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

Merged
merged 1 commit into from
Apr 28, 2025

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.

@RiverDave
Copy link
Contributor Author

Ping @carlosgalvezp :)

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.

LGTM!

@carlosgalvezp
Copy link
Contributor

It can also happen in user defined class.

Yes. But it's unclear what the behavior of the check should be. For std::array, it's clear, because one must not touch the internal element. For a user-defined type, "it depends" on how the user wants to design their struct.

If the need comes, I envision we will need some sort of option so people can add other types on top std::array to be excluded from the check. But let's cross that bridge when we get there :)

@carlosgalvezp
Copy link
Contributor

@RiverDave Do you have permissions to land the PR, or shall I do it for you?

@RiverDave
Copy link
Contributor Author

RiverDave commented Apr 28, 2025

@RiverDave Do you have permissions to land the PR, or shall I do it for you?

Don't have permissions yet.... But Yes! You can merge it for me.

@carlosgalvezp carlosgalvezp merged commit 45411ac into llvm:main Apr 28, 2025
12 checks passed
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…e-use-designated-initializers (llvm#134774)

**Edit:**
I suggest we avoid diagnosing initializers for `std::array` type. The
fixit provided is incorrect as observed in **llvm#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 llvm#133715
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…e-use-designated-initializers (llvm#134774)

**Edit:**
I suggest we avoid diagnosing initializers for `std::array` type. The
fixit provided is incorrect as observed in **llvm#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 llvm#133715
IanWood1 pushed a commit to IanWood1/llvm-project that referenced this pull request May 6, 2025
…e-use-designated-initializers (llvm#134774)

**Edit:**
I suggest we avoid diagnosing initializers for `std::array` type. The
fixit provided is incorrect as observed in **llvm#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 llvm#133715
GeorgeARM pushed a commit to GeorgeARM/llvm-project that referenced this pull request May 7, 2025
…e-use-designated-initializers (llvm#134774)

**Edit:**
I suggest we avoid diagnosing initializers for `std::array` type. The
fixit provided is incorrect as observed in **llvm#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 llvm#133715
Ankur-0429 pushed a commit to Ankur-0429/llvm-project that referenced this pull request May 9, 2025
…e-use-designated-initializers (llvm#134774)

**Edit:**
I suggest we avoid diagnosing initializers for `std::array` type. The
fixit provided is incorrect as observed in **llvm#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 llvm#133715
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

modernize-use-designated-initializers Clang-Tidy check reports std::array when IgnoreSingleElementAggregates is false
4 participants