Skip to content

[clang-tidy] Avoid diagnosing std::array initializations for modernize-use-designated-initializers #134774

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

RiverDave
Copy link
Contributor

@RiverDave RiverDave commented Apr 8, 2025

Edit:
I suggest we avoid diagnosing initializers for std::array type. The fixit provided is incorrect as observed in #133715. The only workaround would require C99-style array designators which don’t really align with the purpose of this check. This would also generate extra compiler warnings.

Fixes #133715

@llvmbot
Copy link
Member

llvmbot commented Apr 8, 2025

@llvm/pr-subscribers-clang-tidy

Author: David Rivera (RiverDave)

Changes

I suggest we avoid diagnosing designated initializers for std::array initializations. The fixit provided is incorrect as observed in #133715. The only workaround would require C99-style array designators which don’t really align with the purpose of this check. This would also generate extra compiler warnings.

Fun fact:
Something I found interesting was the fact that you could access the implementation-defined internal array field. see:

    std::array<int, 3> arr2 = {._M_elems[0] = {3}};

That compiles, however it wouldn’t make sense to provide this as suggestion considering it wouldn’t be portable at all.


Full diff: https://github.com/llvm/llvm-project/pull/134774.diff

2 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp (+6-1)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4)
diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp
index 3132067f3d5ec..9e2ac149d0868 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp
@@ -119,13 +119,18 @@ UseDesignatedInitializersCheck::UseDesignatedInitializersCheck(
 void UseDesignatedInitializersCheck::registerMatchers(MatchFinder *Finder) {
   const auto HasBaseWithFields =
       hasAnyBase(hasType(cxxRecordDecl(has(fieldDecl()))));
+
+  // see #133715
+  const auto IsSTLArray =
+      hasType(qualType(hasDeclaration(recordDecl(hasName("::std::array")))));
+
   Finder->addMatcher(
       initListExpr(
           hasType(cxxRecordDecl(RestrictToPODTypes ? isPOD() : isAggregate(),
                                 unless(HasBaseWithFields))
                       .bind("type")),
           IgnoreSingleElementAggregates ? hasMoreThanOneElement() : anything(),
-          unless(isFullyDesignated()))
+          unless(anyOf(isFullyDesignated(), IsSTLArray)))
           .bind("init"),
       this);
 }
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 6c1f05009df98..44c348f453543 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -171,6 +171,10 @@ Changes in existing checks
   ``constexpr`` and ``static``` values on member initialization and by detecting
   explicit casting of built-in types within member list initialization.
 
+- Improved :doc:`modernize-use-designated-initializers
+  <clang-tidy/checks/modernize/use-designated-initializers>` check by avoiding
+  diagnosing designated initializers for ``std::array`` initializations.
+
 - Improved :doc:`modernize-use-ranges
   <clang-tidy/checks/modernize/use-ranges>` check by updating suppress 
   warnings logic for ``nullptr`` in ``std::find``.

@llvmbot
Copy link
Member

llvmbot commented Apr 8, 2025

@llvm/pr-subscribers-clang-tools-extra

Author: David Rivera (RiverDave)

Changes

I suggest we avoid diagnosing designated initializers for std::array initializations. The fixit provided is incorrect as observed in #133715. The only workaround would require C99-style array designators which don’t really align with the purpose of this check. This would also generate extra compiler warnings.

Fun fact:
Something I found interesting was the fact that you could access the implementation-defined internal array field. see:

    std::array&lt;int, 3&gt; arr2 = {._M_elems[0] = {3}};

That compiles, however it wouldn’t make sense to provide this as suggestion considering it wouldn’t be portable at all.


Full diff: https://github.com/llvm/llvm-project/pull/134774.diff

2 Files Affected:

  • (modified) clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp (+6-1)
  • (modified) clang-tools-extra/docs/ReleaseNotes.rst (+4)
diff --git a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp
index 3132067f3d5ec..9e2ac149d0868 100644
--- a/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp
+++ b/clang-tools-extra/clang-tidy/modernize/UseDesignatedInitializersCheck.cpp
@@ -119,13 +119,18 @@ UseDesignatedInitializersCheck::UseDesignatedInitializersCheck(
 void UseDesignatedInitializersCheck::registerMatchers(MatchFinder *Finder) {
   const auto HasBaseWithFields =
       hasAnyBase(hasType(cxxRecordDecl(has(fieldDecl()))));
+
+  // see #133715
+  const auto IsSTLArray =
+      hasType(qualType(hasDeclaration(recordDecl(hasName("::std::array")))));
+
   Finder->addMatcher(
       initListExpr(
           hasType(cxxRecordDecl(RestrictToPODTypes ? isPOD() : isAggregate(),
                                 unless(HasBaseWithFields))
                       .bind("type")),
           IgnoreSingleElementAggregates ? hasMoreThanOneElement() : anything(),
-          unless(isFullyDesignated()))
+          unless(anyOf(isFullyDesignated(), IsSTLArray)))
           .bind("init"),
       this);
 }
diff --git a/clang-tools-extra/docs/ReleaseNotes.rst b/clang-tools-extra/docs/ReleaseNotes.rst
index 6c1f05009df98..44c348f453543 100644
--- a/clang-tools-extra/docs/ReleaseNotes.rst
+++ b/clang-tools-extra/docs/ReleaseNotes.rst
@@ -171,6 +171,10 @@ Changes in existing checks
   ``constexpr`` and ``static``` values on member initialization and by detecting
   explicit casting of built-in types within member list initialization.
 
+- Improved :doc:`modernize-use-designated-initializers
+  <clang-tidy/checks/modernize/use-designated-initializers>` check by avoiding
+  diagnosing designated initializers for ``std::array`` initializations.
+
 - Improved :doc:`modernize-use-ranges
   <clang-tidy/checks/modernize/use-ranges>` check by updating suppress 
   warnings logic for ``nullptr`` in ``std::find``.

@carlosgalvezp
Copy link
Contributor

I found interesting was the fact that you could access the implementation-defined internal array field

Yes, this is required in order for std::array to be an aggregate type.

@carlosgalvezp
Copy link
Contributor

Actually, it seems to me that IgnoreSingleElementAggregates should already be handling this situation. If it doesn't, there's a bug there that should be fixed, instead of patching it for std::array?

Copy link
Contributor

@carlosgalvezp carlosgalvezp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We should fix IgnoreSingleElementAggregates instead.

@RiverDave
Copy link
Contributor Author

RiverDave commented Apr 9, 2025

We should fix IgnoreSingleElementAggregates instead.

Just to be clear, I suppose we're looking to fix std::array + IgnoreSingleElementAggregates = false as It's the only problematic combination I could analyze. The fixit this check provides on aggregate types with a single field of array type, seem to be correct to me: https://godbolt.org/z/zx4aofaso

@carlosgalvezp
Copy link
Contributor

Ok, I see, let's disable for ::std::array then, generalize in the future if we come across a similar use case.

@RiverDave
Copy link
Contributor Author

Ok, I see, let's disable for ::std::array then, generalize in the future if we come across a similar use case.

Thanks, your feedback has been addressed.

@RiverDave
Copy link
Contributor Author

Ping

@@ -182,6 +182,11 @@ Changes in existing checks
``constexpr`` and ``static``` values on member initialization and by detecting
explicit casting of built-in types within member list initialization.

- Improved :doc:`modernize-use-designated-initializers
<clang-tidy/checks/modernize/use-designated-initializers>` check by avoiding
diagnosing designated initializers for ``std::array`` initializations when
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please document this exception also in IgnoreSingleElementAggregates

Copy link
Contributor Author

@RiverDave RiverDave Apr 22, 2025

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Done, let me know if my explanation is not clear enough

Copy link
Contributor

@carlosgalvezp carlosgalvezp left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please add a unit test demonstrating that the related issue is fixed.

@RiverDave
Copy link
Contributor Author

Please add a unit test demonstrating that the related issue is fixed.

Added 👍

Copy link
Contributor

@HerrCai0907 HerrCai0907 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exclude std::array don't resolve root problem here. It can also happen in user defined class.
e.g. https://godbolt.org/z/cn46MT5Mn

But maybe it could be handled in another PR? since std::array is a special case that we don't know the detail member name in std::array.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
4 participants