Skip to content
Merged
Show file tree
Hide file tree
Changes from 3 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions clang/docs/ReleaseNotes.rst
Original file line number Diff line number Diff line change
Expand Up @@ -297,6 +297,8 @@ Attribute Changes in Clang

Improvements to Clang's diagnostics
-----------------------------------
- Diagnostics messages now refer to ``structured binding`` instead of ``decomposition``,
to align with `P0615R0 <https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2017/p0615r0.html>`_ changing the term.
- Added a separate diagnostic group ``-Wfunction-effect-redeclarations``, for the more pedantic
diagnostics for function effects (``[[clang::nonblocking]]`` and ``[[clang::nonallocating]]``).
Moved the warning for a missing (though implied) attribute on a redeclaration into this group.
Expand Down
7 changes: 4 additions & 3 deletions clang/include/clang/Basic/DiagnosticParseKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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 structured binding group to be empty">,
InGroup<DiagGroup<"empty-structured-binding">>;

def err_function_parameter_limit_exceeded : Error<
"too many function parameters; subsequent parameters will be ignored">;
Expand Down
107 changes: 53 additions & 54 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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<"structured 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<"structured 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<
Expand Down Expand Up @@ -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: "
Expand Down Expand Up @@ -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 "
"structured binding declaration">;
def err_new_array_of_auto : Error<
"cannot allocate array of 'auto'">;
def err_auto_not_allowed : Error<
Expand Down
2 changes: 1 addition & 1 deletion clang/test/Analysis/zero-size-non-pod-array.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ void zeroSizeArrayBinding() {
// Note: This is an error in gcc but a warning in clang.
// In MSVC the declaration of 'S arr[0]' is already an error
// and it doesn't recognize this syntax as a structured binding.
auto [] = arr; //expected-warning{{ISO C++17 does not allow a decomposition group to be empty}}
auto [] = arr; //expected-warning{{ISO C++17 does not allow a structured binding group to be empty}}

clang_analyzer_eval(S::CtorInvocationCount == 0); //expected-warning{{TRUE}}
}
Expand Down
4 changes: 2 additions & 2 deletions clang/test/CXX/dcl.decl/dcl.decomp/p2.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -16,8 +16,8 @@ int array() {
using X3 = X[3];
auto [a3, b3, c3] = X3{1, 2, 3};

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

auto &[r0, r1, r2] = arr;
const auto &[cr0, cr1, cr2] = arr;
Expand Down
10 changes: 5 additions & 5 deletions clang/test/CXX/dcl.decl/dcl.decomp/p3.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -5,26 +5,26 @@ using size_t = decltype(sizeof(0));
struct A { int x, y; };
struct B { int x, y; };

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

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

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

struct Bad2 {};
template<> struct std::tuple_size<Bad2> { const int value = 5; };
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}}
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}}

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

void no_get_1() {
{
auto [a0, a1] = A(); // expected-error {{decomposes into 3 elements}}
auto [b0, b1] = B(); // expected-error {{decomposes into 3 elements}}
auto [a0, a1] = A(); // expected-error {{binds to 3 elements}}
auto [b0, b1] = B(); // expected-error {{binds to 3 elements}}
}
auto [a0, a1, a2] = A(); // expected-error {{undeclared identifier 'get'}} expected-note {{in implicit initialization of binding declaration 'a0'}}
}
Expand Down
26 changes: 13 additions & 13 deletions clang/test/CXX/dcl.decl/dcl.decomp/p4.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -25,10 +25,10 @@ namespace NonPublicMembers {
struct NonPublic4 : NonPublic2 {};

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

Expand All @@ -46,8 +46,8 @@ namespace AnonymousMember {
};

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

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

void test() {
auto [b] = B(); // expected-error {{cannot decompose class type 'B': both it and its base class 'A' have non-static data members}}
auto [d] = D(); // expected-error {{cannot decompose class type 'D': its base classes 'A' and 'C' have non-static data members}}
auto [b] = B(); // expected-error {{cannot bind class type 'B': both it and its base class 'A' have non-static data members}}
auto [d] = D(); // expected-error {{cannot bind class type 'D': its base classes 'A' and 'C' have non-static data members}}
auto [e] = E();
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}}
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}}
auto [h] = H(); // ok, only one (virtual) base subobject even though there are two paths to it
auto [k] = K(); // expected-error {{cannot decompose members of ambiguous base class 'I'}}
auto [k] = K(); // expected-error {{cannot bind members of ambiguous base class 'I'}}
auto [m] = M(); // ok, all paths to I are through the same virtual base subobject J

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

struct C {
Expand All @@ -229,13 +229,13 @@ namespace p0969r0 {
struct D : C {
static void test_member(D d, C c) {
auto &[x1, y1] = d;
auto &[x2, y2] = c; // expected-error {{cannot decompose protected member 'y' of 'p0969r0::C'}}
auto &[x2, y2] = c; // expected-error {{cannot bind protected member 'y' of 'p0969r0::C'}}
}
};
void test_friend(D d) {
auto &[x, y] = d;
}
void test_external(D d) {
auto &[x, y] = d; // expected-error {{cannot decompose protected member 'y' of 'p0969r0::C'}}
auto &[x, y] = d; // expected-error {{cannot bind protected member 'y' of 'p0969r0::C'}}
}
}
2 changes: 1 addition & 1 deletion clang/test/CXX/drs/cwg22xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -202,7 +202,7 @@ namespace cwg2285 { // cwg2285: 4
void test() {
using T = int[1];
auto [a] = T{a};
// since-cxx17-error@-1 {{binding 'a' cannot appear in the initializer of its own decomposition declaration}}
// since-cxx17-error@-1 {{binding 'a' cannot appear in the initializer of its own structured binding declaration}}
}
#endif
} // namespace cwg2285
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CXX/drs/cwg23xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -440,7 +440,7 @@ template <> struct tuple_size<cwg2386::Bad2> {
namespace cwg2386 {
void no_value() { auto [x, y] = Bad1(); }
void wrong_value() { auto [x, y] = Bad2(); }
// since-cxx17-error@-1 {{type 'Bad2' decomposes into 42 elements, but only 2 names were provided}}
// since-cxx17-error@-1 {{type 'Bad2' binds to 42 elements, but only 2 names were provided}}
#endif
} // namespace cwg2386

Expand Down
8 changes: 4 additions & 4 deletions clang/test/CXX/drs/cwg26xx.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -183,17 +183,17 @@ T get_T();

void use() {
UnaryC auto [a, b] = get_S();
// since-cxx20-error@-1 {{decomposition declaration cannot be declared with constrained 'auto'}}
// since-cxx20-error@-1 {{structured binding declaration cannot be declared with constrained 'auto'}}
BinaryC<int> auto [c, d] = get_S();
// since-cxx20-error@-1 {{decomposition declaration cannot be declared with constrained 'auto'}}
// since-cxx20-error@-1 {{structured binding declaration cannot be declared with constrained 'auto'}}
}

template<typename T>
void TemplUse() {
UnaryC auto [a, b] = get_T<T>();
// since-cxx20-error@-1 {{decomposition declaration cannot be declared with constrained 'auto'}}
// since-cxx20-error@-1 {{structured binding declaration cannot be declared with constrained 'auto'}}
BinaryC<T> auto [c, d] = get_T<T>();
// since-cxx20-error@-1 {{decomposition declaration cannot be declared with constrained 'auto'}}
// since-cxx20-error@-1 {{structured binding declaration cannot be declared with constrained 'auto'}}
}
#endif
} // namespace cwg2635
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CXX/stmt.stmt/stmt.iter/stmt.ranged/p1.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,7 @@ namespace X {
void test_D() {
#if __cplusplus >= 201703L
for (extern auto [x, y] : D()) {
} // expected-error@-1 {{decomposition declaration cannot be declared 'extern'}}
} // expected-error@-1 {{structured binding declaration cannot be declared 'extern'}}
// expected-error@-2 {{loop variable '[x, y]' may not be declared 'extern'}}
#endif
}
Expand Down
2 changes: 1 addition & 1 deletion clang/test/CXX/temp/temp.res/temp.local/p6.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -165,7 +165,7 @@ A<0>::B a;

template <typename T> int shadow() { // expected-note{{template parameter is declared here}}
using arr = int[1];
// expected-warning@+1 {{decomposition declarations are a C++17 extension}}
// expected-warning@+1 {{structured binding declarations are a C++17 extension}}
auto [
T // expected-error {{declaration of 'T' shadows template parameter}}
] = arr{};
Expand Down
8 changes: 4 additions & 4 deletions clang/test/FixIt/fixit-constrained-structured-binding.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -14,20 +14,20 @@ T get_T();

void use() {
UnaryC auto [a, b] = get_S();
// CHECK: error: decomposition declaration cannot be declared with constrained 'auto'
// CHECK: error: structured binding declaration cannot be declared with constrained 'auto'
// CHECK: fix-it:{{.*}}:{16:3-16:10}:""
BinaryC<int> auto [c, d] = get_S();
// CHECK: error: decomposition declaration cannot be declared with constrained 'auto'
// CHECK: error: structured binding declaration cannot be declared with constrained 'auto'
// CHECK: fix-it:{{.*}}:{19:3-19:16}:""
}

template<typename T>
void TemplUse() {
UnaryC auto [a, b] = get_T<T>();
// CHECK: error: decomposition declaration cannot be declared with constrained 'auto'
// CHECK: error: structured binding declaration cannot be declared with constrained 'auto'
// XCHECK: fix-it:{{.*}}:{26:3-26:10}:""
BinaryC<T> auto [c, d] = get_T<T>();
// CHECK: error: decomposition declaration cannot be declared with constrained 'auto'
// CHECK: error: structured binding declaration cannot be declared with constrained 'auto'
// XCHECK: fix-it:{{.*}}:{29:3-29:14}:""
}

4 changes: 2 additions & 2 deletions clang/test/PCH/cxx1z-decomposition.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@ constexpr int foo(Q &&q) {
return a * 10 + b;
}

auto [noinit]; // expected-error{{decomposition declaration '[noinit]' requires an initializer}}
auto [noinit]; // expected-error{{structured binding declaration '[noinit]' requires an initializer}}

#else

Expand All @@ -31,7 +31,7 @@ int k = decomp(arr);

static_assert(foo({1, 2}) == 12);

// expected-error@15 {{cannot decompose non-class, non-array type 'const int'}}
// expected-error@15 {{cannot bind non-class, non-array type 'const int'}}
int z = decomp(10); // expected-note {{instantiation of}}

#endif
Loading
Loading