Skip to content

Conversation

foxfromabyss
Copy link

P0615R0 changed the term "decomposition" to "structured binding". Some diagnostic messages were created before this paper. These messages should be updated using "structured binding" to avoid making users confused.

Closes #157880

Copy link

Thank you for submitting a Pull Request (PR) to the LLVM Project!

This PR will be automatically labeled and the relevant teams will be notified.

If you wish to, you can add reviewers by using the "Reviewers" section on this page.

If this is not working for you, it is probably because you do not have write permissions for the repository. In which case you can instead tag reviewers by name in a comment by using @ followed by their GitHub username.

If you have received no comments on your PR for a week, you can request a review by "ping"ing the PR by adding a comment “Ping”. The common courtesy "ping" rate is once a week. Please remember that you are asking for valuable time from other developers.

If you have further questions, they may be answered by the LLVM GitHub User Guide.

You can also ask questions in a comment on this PR, on the LLVM Discord or on the forums.

@llvmbot llvmbot added clang Clang issues not falling into any other category clang:frontend Language frontend issues, e.g. anything involving "Sema" labels Oct 12, 2025
@llvmbot
Copy link
Member

llvmbot commented Oct 12, 2025

@llvm/pr-subscribers-clang-static-analyzer-1

@llvm/pr-subscribers-clang

Author: None (foxfromabyss)

Changes

P0615R0 changed the term "decomposition" to "structured binding". Some diagnostic messages were created before this paper. These messages should be updated using "structured binding" to avoid making users confused.

Closes #157880


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

2 Files Affected:

  • (modified) clang/include/clang/Basic/DiagnosticParseKinds.td (+4-3)
  • (modified) clang/include/clang/Basic/DiagnosticSemaKinds.td (+53-54)
diff --git a/clang/include/clang/Basic/DiagnosticParseKinds.td b/clang/include/clang/Basic/DiagnosticParseKinds.td
index c724136a7fdaf..f1fa98c0bd498 100644
--- a/clang/include/clang/Basic/DiagnosticParseKinds.td
+++ b/clang/include/clang/Basic/DiagnosticParseKinds.td
@@ -504,9 +504,10 @@ def err_expected_end_of_enumerator : Error<
 def err_expected_coloncolon_after_super : Error<
   "expected '::' after '__super'">;
 
-def ext_decomp_decl_empty : ExtWarn<
-  "ISO C++17 does not allow a decomposition group to be empty">,
-  InGroup<DiagGroup<"empty-decomposition">>;
+def ext_decomp_decl_empty
+    : ExtWarn<
+          "ISO C++17 does not allow a structural binding group to be empty">,
+      InGroup<DiagGroup<"empty-structural-binding">>;
 
 def err_function_parameter_limit_exceeded : Error<
   "too many function parameters; subsequent parameters will be ignored">;
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 3df28f2ef3334..2069560284fc6 100644
--- a/clang/include/clang/Basic/DiagnosticSemaKinds.td
+++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td
@@ -31,12 +31,12 @@ defm constexpr_body_multiple_return : CXX14Compat<
 defm variable_template : CXX14Compat<"variable templates are">;
 
 // C++17 compatibility with C++14 and earlier.
-defm decomp_decl : CXX17Compat<"decomposition declarations are">;
+defm decomp_decl : CXX17Compat<"structural binding declarations are">;
 defm inline_variable : CXX17Compat<"inline variables are">;
 
 // C++20 compatibility with C++17 and earlier.
 defm decomp_decl_spec
-    : CXX20Compat<"decomposition declaration declared '%0' is">;
+    : CXX20Compat<"structural binding declaration declared '%0' is">;
 defm constexpr_local_var_no_init : CXX20Compat<
   "uninitialized variable in a constexpr %select{function|constructor}0 is">;
 defm constexpr_function_try_block : CXX20Compat<
@@ -589,60 +589,59 @@ def warn_modifying_shadowing_decl :
           "field of %1">,
   InGroup<ShadowFieldInConstructorModified>, DefaultIgnore;
 
-// C++ decomposition declarations
-def err_decomp_decl_context : Error<
-  "decomposition declaration not permitted in this context">;
+// C++ structured binding declarations
+def err_decomp_decl_context
+    : Error<"structured binding declaration not permitted in this context">;
 def err_decomp_decl_spec
-    : Error<"decomposition declaration cannot be declared '%0'">;
-def err_decomp_decl_type : Error<
-  "decomposition declaration cannot be declared with type %0; "
-  "declared type must be 'auto' or reference to 'auto'">;
-def err_decomp_decl_constraint : Error<
-  "decomposition declaration cannot be declared with constrained 'auto'">;
-def err_decomp_decl_parens : Error<
-  "decomposition declaration cannot be declared with parentheses">;
-def err_decomp_decl_template : Error<
-  "decomposition declaration cannot be a template">;
-def err_decomp_decl_not_alone : Error<
-  "decomposition declaration must be the only declaration in its group">;
-def err_decomp_decl_requires_init : Error<
-  "decomposition declaration %0 requires an initializer">;
-def err_decomp_decl_wrong_number_bindings : Error<
-  "type %0 decomposes into %3 %plural{1:element|:elements}2, but "
-  "%select{%plural{0:no|:only %1}1|%1}4 "
-  "%plural{1:name was|:names were}1 provided">;
-def err_decomp_decl_unbindable_type : Error<
-  "cannot decompose %select{union|non-class, non-array}1 type %2">;
-def err_decomp_decl_multiple_bases_with_members : Error<
-  "cannot decompose class type %1: "
-  "%select{its base classes %2 and|both it and its base class}0 %3 "
-  "have non-static data members">;
-def err_decomp_decl_ambiguous_base : Error<
-  "cannot decompose members of ambiguous base class %1 of %0:%2">;
-def err_decomp_decl_inaccessible_base : Error<
-  "cannot decompose members of inaccessible base class %1 of %0">,
-  AccessControl;
-def err_decomp_decl_inaccessible_field : Error<
-  "cannot decompose %select{private|protected}0 member %1 of %3">,
-  AccessControl;
-def err_decomp_decl_lambda : Error<
-  "cannot decompose lambda closure type">;
-def err_decomp_decl_anon_union_member : Error<
-  "cannot decompose class type %0 because it has an anonymous "
-  "%select{struct|union}1 member">;
-def err_decomp_decl_std_tuple_element_not_specialized : Error<
-  "cannot decompose this type; 'std::tuple_element<%0>::type' "
-  "does not name a type">;
-def err_decomp_decl_std_tuple_size_not_constant : Error<
-  "cannot decompose this type; 'std::tuple_size<%0>::value' "
-  "is not a valid integral constant expression">;
+    : Error<"structured binding declaration cannot be declared '%0'">;
+def err_decomp_decl_type
+    : Error<"structured binding declaration cannot be declared with type %0; "
+            "declared type must be 'auto' or reference to 'auto'">;
+def err_decomp_decl_constraint : Error<"structured binding declaration cannot "
+                                       "be declared with constrained 'auto'">;
+def err_decomp_decl_parens
+    : Error<
+          "structured binding declaration cannot be declared with parentheses">;
+def err_decomp_decl_template
+    : Error<"structured binding declaration cannot be a template">;
+def err_decomp_decl_not_alone : Error<"structured binding declaration must be "
+                                      "the only declaration in its group">;
+def err_decomp_decl_requires_init
+    : Error<"structured binding declaration %0 requires an initializer">;
+def err_decomp_decl_wrong_number_bindings
+    : Error<"type %0 binds to %3 %plural{1:element|:elements}2, but "
+            "%select{%plural{0:no|:only %1}1|%1}4 "
+            "%plural{1:name was|:names were}1 provided">;
+def err_decomp_decl_unbindable_type
+    : Error<"cannot bind %select{union|non-class, non-array}1 type %2">;
+def err_decomp_decl_multiple_bases_with_members
+    : Error<"cannot bind class type %1: "
+            "%select{its base classes %2 and|both it and its base class}0 %3 "
+            "have non-static data members">;
+def err_decomp_decl_ambiguous_base
+    : Error<"cannot bind members of ambiguous base class %1 of %0:%2">;
+def err_decomp_decl_inaccessible_base
+    : Error<"cannot bind members of inaccessible base class %1 of %0">,
+      AccessControl;
+def err_decomp_decl_inaccessible_field
+    : Error<"cannot bind %select{private|protected}0 member %1 of %3">,
+      AccessControl;
+def err_decomp_decl_lambda : Error<"cannot bind lambda closure type">;
+def err_decomp_decl_anon_union_member
+    : Error<"cannot bind class type %0 because it has an anonymous "
+            "%select{struct|union}1 member">;
+def err_decomp_decl_std_tuple_element_not_specialized
+    : Error<"cannot bind this type; 'std::tuple_element<%0>::type' "
+            "does not name a type">;
+def err_decomp_decl_std_tuple_size_not_constant
+    : Error<"cannot bind this type; 'std::tuple_size<%0>::value' "
+            "is not a valid integral constant expression">;
 def err_decomp_decl_std_tuple_size_invalid
-    : Error<"cannot decompose this type; 'std::tuple_size<%0>::value' "
+    : Error<"cannot bind this type; 'std::tuple_size<%0>::value' "
             "is not a valid size: %1">;
 def note_in_binding_decl_init : Note<
   "in implicit initialization of binding declaration %0">;
-def err_arg_is_not_destructurable : Error<
-  "type %0 cannot be decomposed">;
+def err_arg_is_not_destructurable : Error<"type %0 cannot be bound">;
 
 def err_std_type_trait_not_class_template : Error<
   "unsupported standard library implementation: "
@@ -2618,9 +2617,9 @@ def err_auto_variable_cannot_appear_in_own_initializer
           "%VarTemplateExplicitSpec{variable template explicit "
           "specialization}}0 %1 "
           "declared with deduced type %2 cannot appear in its own initializer">;
-def err_binding_cannot_appear_in_own_initializer : Error<
-  "binding %0 cannot appear in the initializer of its own "
-  "decomposition declaration">;
+def err_binding_cannot_appear_in_own_initializer
+    : Error<"binding %0 cannot appear in the initializer of its own "
+            "structural binding declaration">;
 def err_new_array_of_auto : Error<
   "cannot allocate array of 'auto'">;
 def err_auto_not_allowed : Error<

@zwuis
Copy link
Contributor

zwuis commented Oct 13, 2025

Thank you for your patch!

Did you run regression tests locally? Regression tests of Clang are in the folder "clang/test". You can visit https://llvm.org/docs/GettingStarted.html and https://llvm.org/docs/TestingGuide.html for how to run tests.

Please add a release note entry to "clang/docs/ReleaseNotes.rst" so that users can know the improvement.

Copy link
Member

@Sirraide Sirraide left a comment

Choose a reason for hiding this comment

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

This still needs a release note (in clang/docs/ReleaseNotes.rst, in the section ‘Improvements to Clang’s Diagnostics’), and you’ll also have to update a bunch of tests around these diagnostics

P0615R0 changed the term "decomposition" to "structured binding".
Some diagnostic messages were created before this paper.
These messages should be updated using "structured binding" to avoid making users confused.

See for context:
https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0615r0.html
Copy link
Contributor

@Endilll Endilll left a comment

Choose a reason for hiding this comment

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

Changes to C++ DR tests LGTM

@foxfromabyss
Copy link
Author

Must've missed the test output the first time.
Thank you for the review!

Updated the release notes as well, should be good to go now

Comment on lines 507 to 510
def ext_decomp_decl_empty
: ExtWarn<
"ISO C++17 does not allow a structured binding group to be empty">,
InGroup<DiagGroup<"empty-structured-binding">>;
Copy link
Member

Choose a reason for hiding this comment

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

Suggested change
def ext_decomp_decl_empty
: ExtWarn<
"ISO C++17 does not allow a structured binding group to be empty">,
InGroup<DiagGroup<"empty-structured-binding">>;
def ext_decomp_decl_empty : ExtWarn<
"ISO C++17 does not allow a structured binding group to be empty">,
InGroup<DiagGroup<"empty-structured-binding">>;

Our formatter doesn’t format these properly (I regularly have to deal w/ this too...)

Copy link
Member

Choose a reason for hiding this comment

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

Also, one thing I only noticed just now, I’m not sure if we also want to rename the diagnostic group since that might be a breaking change for some people.

CC @AaronBallman @cor3ntin

Copy link
Author

Choose a reason for hiding this comment

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

I'll restore the formatting to the way it was then. Regarding the diagnostic group, I only did this since the full text search for "empty-decomposition" over the entire project gave 0 matches.
In retrospect, should've highlighted said change either way.

Copy link
Author

Choose a reason for hiding this comment

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

Formatting has been restored

Copy link
Contributor

Choose a reason for hiding this comment

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

I see no reason to rename the diagnostic group

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

clang:frontend Language frontend issues, e.g. anything involving "Sema" clang:static analyzer clang Clang issues not falling into any other category

Projects

None yet

Development

Successfully merging this pull request may close these issues.

[Clang][Diagnostics] Use "structured binding" instead of "decomposition"

6 participants