Skip to content

Commit 32cb4b2

Browse files
foxfromabyssfoxfromabyssSirraide
authored
[Clang][Diagnostics] Use "structured binding" instead of "decomposition" (#163101)
[P0615R0](https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0615r0.html) 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 --------- Co-authored-by: foxfromabyss <[email protected]> Co-authored-by: Sirraide <[email protected]>
1 parent be3aa41 commit 32cb4b2

26 files changed

+122
-120
lines changed

clang-tools-extra/test/clang-tidy/checkers/misc/misplaced-const-cxx17.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
// This test previously would cause a failed assertion because the structured
44
// binding declaration had no valid type associated with it. This ensures the
55
// expected clang diagnostic is generated instead.
6-
// CHECK-MESSAGES: :[[@LINE+1]]:6: error: decomposition declaration '[x]' requires an initializer [clang-diagnostic-error]
6+
// CHECK-MESSAGES: :[[@LINE+1]]:6: error: structured binding declaration '[x]' requires an initializer [clang-diagnostic-error]
77
auto [x];
88

99
struct S { int a; };

clang/docs/ReleaseNotes.rst

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -304,6 +304,8 @@ Attribute Changes in Clang
304304

305305
Improvements to Clang's diagnostics
306306
-----------------------------------
307+
- Diagnostics messages now refer to ``structured binding`` instead of ``decomposition``,
308+
to align with `P0615R0 <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0615r0.html>`_ changing the term. (#GH157880)
307309
- Added a separate diagnostic group ``-Wfunction-effect-redeclarations``, for the more pedantic
308310
diagnostics for function effects (``[[clang::nonblocking]]`` and ``[[clang::nonallocating]]``).
309311
Moved the warning for a missing (though implied) attribute on a redeclaration into this group.

clang/include/clang/Basic/DiagnosticParseKinds.td

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -505,7 +505,7 @@ def err_expected_coloncolon_after_super : Error<
505505
"expected '::' after '__super'">;
506506

507507
def ext_decomp_decl_empty : ExtWarn<
508-
"ISO C++17 does not allow a decomposition group to be empty">,
508+
"ISO C++17 does not allow a structured binding group to be empty">,
509509
InGroup<DiagGroup<"empty-decomposition">>;
510510

511511
def err_function_parameter_limit_exceeded : Error<

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 23 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,12 @@ defm constexpr_body_multiple_return : CXX14Compat<
3131
defm variable_template : CXX14Compat<"variable templates are">;
3232

3333
// C++17 compatibility with C++14 and earlier.
34-
defm decomp_decl : CXX17Compat<"decomposition declarations are">;
34+
defm decomp_decl : CXX17Compat<"structured binding declarations are">;
3535
defm inline_variable : CXX17Compat<"inline variables are">;
3636

3737
// C++20 compatibility with C++17 and earlier.
3838
defm decomp_decl_spec
39-
: CXX20Compat<"decomposition declaration declared '%0' is">;
39+
: CXX20Compat<"structured binding declaration declared '%0' is">;
4040
defm constexpr_local_var_no_init : CXX20Compat<
4141
"uninitialized variable in a constexpr %select{function|constructor}0 is">;
4242
defm constexpr_function_try_block : CXX20Compat<
@@ -591,58 +591,58 @@ def warn_modifying_shadowing_decl :
591591

592592
// C++ decomposition declarations
593593
def err_decomp_decl_context : Error<
594-
"decomposition declaration not permitted in this context">;
594+
"structured binding declaration not permitted in this context">;
595595
def err_decomp_decl_spec
596-
: Error<"decomposition declaration cannot be declared '%0'">;
596+
: Error<"structured binding declaration cannot be declared '%0'">;
597597
def err_decomp_decl_type : Error<
598-
"decomposition declaration cannot be declared with type %0; "
598+
"structured binding declaration cannot be declared with type %0; "
599599
"declared type must be 'auto' or reference to 'auto'">;
600600
def err_decomp_decl_constraint : Error<
601-
"decomposition declaration cannot be declared with constrained 'auto'">;
601+
"structured binding declaration cannot be declared with constrained 'auto'">;
602602
def err_decomp_decl_parens : Error<
603-
"decomposition declaration cannot be declared with parentheses">;
603+
"structured binding declaration cannot be declared with parentheses">;
604604
def err_decomp_decl_template : Error<
605-
"decomposition declaration cannot be a template">;
605+
"structured binding declaration cannot be a template">;
606606
def err_decomp_decl_not_alone : Error<
607-
"decomposition declaration must be the only declaration in its group">;
607+
"structured binding declaration must be the only declaration in its group">;
608608
def err_decomp_decl_requires_init : Error<
609-
"decomposition declaration %0 requires an initializer">;
609+
"structured binding declaration %0 requires an initializer">;
610610
def err_decomp_decl_wrong_number_bindings : Error<
611-
"type %0 decomposes into %3 %plural{1:element|:elements}2, but "
611+
"type %0 binds to %3 %plural{1:element|:elements}2, but "
612612
"%select{%plural{0:no|:only %1}1|%1}4 "
613613
"%plural{1:name was|:names were}1 provided">;
614614
def err_decomp_decl_unbindable_type : Error<
615-
"cannot decompose %select{union|non-class, non-array}1 type %2">;
615+
"cannot bind %select{union|non-class, non-array}1 type %2">;
616616
def err_decomp_decl_multiple_bases_with_members : Error<
617-
"cannot decompose class type %1: "
617+
"cannot bind class type %1: "
618618
"%select{its base classes %2 and|both it and its base class}0 %3 "
619619
"have non-static data members">;
620620
def err_decomp_decl_ambiguous_base : Error<
621-
"cannot decompose members of ambiguous base class %1 of %0:%2">;
621+
"cannot bind members of ambiguous base class %1 of %0:%2">;
622622
def err_decomp_decl_inaccessible_base : Error<
623-
"cannot decompose members of inaccessible base class %1 of %0">,
623+
"cannot bind members of inaccessible base class %1 of %0">,
624624
AccessControl;
625625
def err_decomp_decl_inaccessible_field : Error<
626-
"cannot decompose %select{private|protected}0 member %1 of %3">,
626+
"cannot bind %select{private|protected}0 member %1 of %3">,
627627
AccessControl;
628628
def err_decomp_decl_lambda : Error<
629-
"cannot decompose lambda closure type">;
629+
"cannot bind lambda closure type">;
630630
def err_decomp_decl_anon_union_member : Error<
631-
"cannot decompose class type %0 because it has an anonymous "
631+
"cannot bind class type %0 because it has an anonymous "
632632
"%select{struct|union}1 member">;
633633
def err_decomp_decl_std_tuple_element_not_specialized : Error<
634-
"cannot decompose this type; 'std::tuple_element<%0>::type' "
634+
"cannot bind this type; 'std::tuple_element<%0>::type' "
635635
"does not name a type">;
636636
def err_decomp_decl_std_tuple_size_not_constant : Error<
637-
"cannot decompose this type; 'std::tuple_size<%0>::value' "
637+
"cannot bind this type; 'std::tuple_size<%0>::value' "
638638
"is not a valid integral constant expression">;
639639
def err_decomp_decl_std_tuple_size_invalid
640-
: Error<"cannot decompose this type; 'std::tuple_size<%0>::value' "
640+
: Error<"cannot bind this type; 'std::tuple_size<%0>::value' "
641641
"is not a valid size: %1">;
642642
def note_in_binding_decl_init : Note<
643643
"in implicit initialization of binding declaration %0">;
644644
def err_arg_is_not_destructurable : Error<
645-
"type %0 cannot be decomposed">;
645+
"type %0 cannot be bound">;
646646

647647
def err_std_type_trait_not_class_template : Error<
648648
"unsupported standard library implementation: "
@@ -2620,7 +2620,7 @@ def err_auto_variable_cannot_appear_in_own_initializer
26202620
"declared with deduced type %2 cannot appear in its own initializer">;
26212621
def err_binding_cannot_appear_in_own_initializer : Error<
26222622
"binding %0 cannot appear in the initializer of its own "
2623-
"decomposition declaration">;
2623+
"structured binding declaration">;
26242624
def err_new_array_of_auto : Error<
26252625
"cannot allocate array of 'auto'">;
26262626
def err_auto_not_allowed : Error<

clang/test/Analysis/zero-size-non-pod-array.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,7 @@ void zeroSizeArrayBinding() {
9595
// Note: This is an error in gcc but a warning in clang.
9696
// In MSVC the declaration of 'S arr[0]' is already an error
9797
// and it doesn't recognize this syntax as a structured binding.
98-
auto [] = arr; //expected-warning{{ISO C++17 does not allow a decomposition group to be empty}}
98+
auto [] = arr; //expected-warning{{ISO C++17 does not allow a structured binding group to be empty}}
9999

100100
clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
101101
}

clang/test/CXX/dcl.decl/dcl.decomp/p2.cpp

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -16,8 +16,8 @@ int array() {
1616
using X3 = X[3];
1717
auto [a3, b3, c3] = X3{1, 2, 3};
1818

19-
auto &[d, e] = arr; // expected-error {{type 'int[3]' decomposes into 3 elements, but only 2 names were provided}}
20-
auto &[f, g, h, i] = arr; // expected-error {{type 'int[3]' decomposes into 3 elements, but 4 names were provided}}
19+
auto &[d, e] = arr; // expected-error {{type 'int[3]' binds to 3 elements, but only 2 names were provided}}
20+
auto &[f, g, h, i] = arr; // expected-error {{type 'int[3]' binds to 3 elements, but 4 names were provided}}
2121

2222
auto &[r0, r1, r2] = arr;
2323
const auto &[cr0, cr1, cr2] = arr;

clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -5,26 +5,26 @@ using size_t = decltype(sizeof(0));
55
struct A { int x, y; };
66
struct B { int x, y; };
77

8-
void no_tuple_size_1() { auto [x, y] = A(); } // ok, decompose elementwise
8+
void no_tuple_size_1() { auto [x, y] = A(); } // ok, bind elementwise
99

1010
namespace std { template<typename T> struct tuple_size; }
11-
void no_tuple_size_2() { auto [x, y] = A(); } // ok, decompose elementwise
11+
void no_tuple_size_2() { auto [x, y] = A(); } // ok, bind elementwise
1212

1313
struct Bad1 { int a, b; };
1414
template<> struct std::tuple_size<Bad1> {};
1515
void no_tuple_size_3() { auto [x, y] = Bad1(); } // ok, omitting value is valid after DR2386
1616

1717
struct Bad2 {};
1818
template<> struct std::tuple_size<Bad2> { const int value = 5; };
19-
void no_tuple_size_4() { auto [x, y] = Bad2(); } // expected-error {{cannot decompose this type; 'std::tuple_size<Bad2>::value' is not a valid integral constant expression}}
19+
void no_tuple_size_4() { auto [x, y] = Bad2(); } // expected-error {{cannot bind this type; 'std::tuple_size<Bad2>::value' is not a valid integral constant expression}}
2020

2121
template<> struct std::tuple_size<A> { static const int value = 3; };
2222
template<> struct std::tuple_size<B> { enum { value = 3 }; };
2323

2424
void no_get_1() {
2525
{
26-
auto [a0, a1] = A(); // expected-error {{decomposes into 3 elements}}
27-
auto [b0, b1] = B(); // expected-error {{decomposes into 3 elements}}
26+
auto [a0, a1] = A(); // expected-error {{binds to 3 elements}}
27+
auto [b0, b1] = B(); // expected-error {{binds to 3 elements}}
2828
}
2929
auto [a0, a1, a2] = A(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit initialization of binding declaration 'a0'}}
3030
}

clang/test/CXX/dcl.decl/dcl.decomp/p4.cpp

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,10 @@ namespace NonPublicMembers {
2525
struct NonPublic4 : NonPublic2 {};
2626

2727
void test() {
28-
auto [a1] = NonPublic1(); // expected-error {{cannot decompose protected member 'a' of 'NonPublicMembers::NonPublic1'}}
29-
auto [a2] = NonPublic2(); // expected-error {{cannot decompose private member 'a' of 'NonPublicMembers::NonPublic2'}}
30-
auto [a3] = NonPublic3(); // expected-error {{cannot decompose members of inaccessible base class 'A' of 'NonPublicMembers::NonPublic3'}}
31-
auto [a4] = NonPublic4(); // expected-error {{cannot decompose private member 'a' of 'NonPublicMembers::NonPublic2'}}
28+
auto [a1] = NonPublic1(); // expected-error {{cannot bind protected member 'a' of 'NonPublicMembers::NonPublic1'}}
29+
auto [a2] = NonPublic2(); // expected-error {{cannot bind private member 'a' of 'NonPublicMembers::NonPublic2'}}
30+
auto [a3] = NonPublic3(); // expected-error {{cannot bind members of inaccessible base class 'A' of 'NonPublicMembers::NonPublic3'}}
31+
auto [a4] = NonPublic4(); // expected-error {{cannot bind private member 'a' of 'NonPublicMembers::NonPublic2'}}
3232
}
3333
}
3434

@@ -46,8 +46,8 @@ namespace AnonymousMember {
4646
};
4747

4848
void test() {
49-
auto [a1] = Struct(); // expected-error {{cannot decompose class type 'Struct' because it has an anonymous struct member}}
50-
auto [a2] = Union(); // expected-error {{cannot decompose class type 'Union' because it has an anonymous union member}}
49+
auto [a1] = Struct(); // expected-error {{cannot bind class type 'Struct' because it has an anonymous struct member}}
50+
auto [a2] = Union(); // expected-error {{cannot bind class type 'Union' because it has an anonymous union member}}
5151
}
5252
}
5353

@@ -73,12 +73,12 @@ namespace MultipleClasses {
7373
struct M : virtual J, L {};
7474

7575
void test() {
76-
auto [b] = B(); // expected-error {{cannot decompose class type 'B': both it and its base class 'A' have non-static data members}}
77-
auto [d] = D(); // expected-error {{cannot decompose class type 'D': its base classes 'A' and 'C' have non-static data members}}
76+
auto [b] = B(); // expected-error {{cannot bind class type 'B': both it and its base class 'A' have non-static data members}}
77+
auto [d] = D(); // expected-error {{cannot bind class type 'D': its base classes 'A' and 'C' have non-static data members}}
7878
auto [e] = E();
79-
auto [f] = F(); // expected-error-re {{cannot decompose members of ambiguous base class 'A' of 'F':{{.*}}struct MultipleClasses::F -> A{{.*}}struct MultipleClasses::F -> E -> A}}
79+
auto [f] = F(); // expected-error-re {{cannot bind members of ambiguous base class 'A' of 'F':{{.*}}struct MultipleClasses::F -> A{{.*}}struct MultipleClasses::F -> E -> A}}
8080
auto [h] = H(); // ok, only one (virtual) base subobject even though there are two paths to it
81-
auto [k] = K(); // expected-error {{cannot decompose members of ambiguous base class 'I'}}
81+
auto [k] = K(); // expected-error {{cannot bind members of ambiguous base class 'I'}}
8282
auto [m] = M(); // ok, all paths to I are through the same virtual base subobject J
8383

8484
same<decltype(m), int>();
@@ -214,7 +214,7 @@ namespace p0969r0 {
214214
auto &[x, y] = b;
215215
}
216216
void test_external(B b) {
217-
auto &[x, y] = b; // expected-error {{cannot decompose members of inaccessible base class 'A' of 'p0969r0::B'}}
217+
auto &[x, y] = b; // expected-error {{cannot bind members of inaccessible base class 'A' of 'p0969r0::B'}}
218218
}
219219

220220
struct C {
@@ -229,13 +229,13 @@ namespace p0969r0 {
229229
struct D : C {
230230
static void test_member(D d, C c) {
231231
auto &[x1, y1] = d;
232-
auto &[x2, y2] = c; // expected-error {{cannot decompose protected member 'y' of 'p0969r0::C'}}
232+
auto &[x2, y2] = c; // expected-error {{cannot bind protected member 'y' of 'p0969r0::C'}}
233233
}
234234
};
235235
void test_friend(D d) {
236236
auto &[x, y] = d;
237237
}
238238
void test_external(D d) {
239-
auto &[x, y] = d; // expected-error {{cannot decompose protected member 'y' of 'p0969r0::C'}}
239+
auto &[x, y] = d; // expected-error {{cannot bind protected member 'y' of 'p0969r0::C'}}
240240
}
241241
}

clang/test/CXX/drs/cwg22xx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -202,7 +202,7 @@ namespace cwg2285 { // cwg2285: 4
202202
void test() {
203203
using T = int[1];
204204
auto [a] = T{a};
205-
// since-cxx17-error@-1 {{binding 'a' cannot appear in the initializer of its own decomposition declaration}}
205+
// since-cxx17-error@-1 {{binding 'a' cannot appear in the initializer of its own structured binding declaration}}
206206
}
207207
#endif
208208
} // namespace cwg2285

clang/test/CXX/drs/cwg23xx.cpp

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -440,7 +440,7 @@ template <> struct tuple_size<cwg2386::Bad2> {
440440
namespace cwg2386 {
441441
void no_value() { auto [x, y] = Bad1(); }
442442
void wrong_value() { auto [x, y] = Bad2(); }
443-
// since-cxx17-error@-1 {{type 'Bad2' decomposes into 42 elements, but only 2 names were provided}}
443+
// since-cxx17-error@-1 {{type 'Bad2' binds to 42 elements, but only 2 names were provided}}
444444
#endif
445445
} // namespace cwg2386
446446

0 commit comments

Comments
 (0)