1 // RUN: %clang_cc1 -std=c++17 %s -triple x86_64-unknown-linux-gnu -verify=expected,cxx17,pre2c -fcxx-exceptions 2 // RUN: %clang_cc1 -std=c++2b %s -triple x86_64-unknown-linux-gnu -verify=expected,cxx2b,pre2c,post2b -fcxx-exceptions 3 // RUN: %clang_cc1 -std=c++2c %s -triple x86_64-unknown-linux-gnu -verify=expected,cxx2c,post2b -fcxx-exceptions 4 // RUN: not %clang_cc1 -std=c++17 %s -triple x86_64-unknown-linux-gnu -emit-llvm-only -fcxx-exceptions 5 6 struct S { int a, b, c; }; 7 8 // A simple-declaration can be a decompsition declaration. 9 namespace SimpleDecl { 10 auto [a_x, b_x, c_x] = S(); 11 12 void f(S s) { 13 auto [a, b, c] = S(); 14 { 15 for (auto [a, b, c] = S();;) {} 16 if (auto [a, b, c] = S(); true) {} 17 switch (auto [a, b, c] = S(); 0) { case 0:; } 18 } 19 } 20 } 21 22 // A for-range-declaration can be a decomposition declaration. 23 namespace ForRangeDecl { 24 extern S arr[10]; 25 void h() { 26 for (auto [a, b, c] : arr) { 27 } 28 } 29 } 30 31 // Other kinds of declaration cannot. 32 namespace OtherDecl { 33 // A parameter-declaration is not a simple-declaration. 34 // This parses as an array declaration. 35 void f(auto [a, b, c]); // cxx17-error {{'auto' not allowed in function prototype}} expected-error {{'a'}} 36 37 void g() { 38 // A condition is allowed as a Clang extension. 39 // See commentary in test/Parser/decomposed-condition.cpp 40 for (; auto [a, b, c] = S(); ) {} // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{value of type 'S' is not contextually convertible to 'bool'}} 41 if (auto [a, b, c] = S()) {} // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{value of type 'S' is not contextually convertible to 'bool'}} 42 if (int n; auto [a, b, c] = S()) {} // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{value of type 'S' is not contextually convertible to 'bool'}} 43 switch (auto [a, b, c] = S()) {} // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{statement requires expression of integer type ('S' invalid)}} 44 switch (int n; auto [a, b, c] = S()) {} // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{statement requires expression of integer type ('S' invalid)}} 45 while (auto [a, b, c] = S()) {} // expected-warning {{ISO C++17 does not permit structured binding declaration in a condition}} expected-error {{value of type 'S' is not contextually convertible to 'bool'}} 46 47 // An exception-declaration is not a simple-declaration. 48 try {} 49 catch (auto [a, b, c]) {} // expected-error {{'auto' not allowed in exception declaration}} expected-error {{'a'}} 50 } 51 52 // A member-declaration is not a simple-declaration. 53 class A { 54 auto [a, b, c] = S(); // expected-error {{not permitted in this context}} 55 static auto [a, b, c] = S(); // expected-error {{not permitted in this context}} 56 }; 57 } 58 59 namespace GoodSpecifiers { 60 void f() { 61 int n[1]; 62 const volatile auto &[a] = n; // post2b-warning {{volatile qualifier in structured binding declaration is deprecated}} 63 } 64 } 65 66 namespace BadSpecifiers { 67 typedef int I1[1]; 68 I1 n; 69 struct S { int n; } s; 70 void f() { 71 // storage-class-specifiers 72 static auto &[a] = n; // cxx17-warning {{declared 'static' is a C++20 extension}} 73 thread_local auto &[b] = n; // cxx17-warning {{declared 'thread_local' is a C++20 extension}} 74 extern auto &[c] = n; // expected-error {{cannot be declared 'extern'}} expected-error {{declaration of block scope identifier with linkage cannot have an initializer}} 75 struct S { 76 mutable auto &[d] = n; // expected-error {{not permitted in this context}} 77 78 // function-specifiers 79 virtual auto &[e] = n; // expected-error {{not permitted in this context}} 80 explicit auto &[f] = n; // expected-error {{not permitted in this context}} 81 82 // misc decl-specifiers 83 friend auto &[g] = n; // expected-error {{'auto' not allowed}} expected-error {{friends can only be classes or functions}} 84 }; 85 typedef auto &[h] = n; // expected-error {{cannot be declared 'typedef'}} 86 constexpr auto &[i] = n; // expected-error {{cannot be declared 'constexpr'}} 87 } 88 89 static constexpr inline thread_local auto &[j1] = n; // expected-error {{cannot be declared with 'constexpr inline' specifiers}} 90 static thread_local auto &[j2] = n; // cxx17-warning {{declared with 'static thread_local' specifiers is a C++20 extension}} 91 92 inline auto &[k] = n; // expected-error {{cannot be declared 'inline'}} 93 94 const int K = 5; 95 auto ([c]) = s; // expected-error {{decomposition declaration cannot be declared with parentheses}} 96 void g() { 97 // defining-type-specifiers other than cv-qualifiers and 'auto' 98 S [a] = s; // expected-error {{cannot be declared with type 'S'}} 99 decltype(auto) [b] = s; // expected-error {{cannot be declared with type 'decltype(auto)'}} 100 auto ([c2]) = s; // cxx17-error {{decomposition declaration cannot be declared with parenthese}} \ 101 // post2b-error {{use of undeclared identifier 'c2'}} \ 102 // post2b-error {{expected body of lambda expression}} \ 103 104 // FIXME: This error is not very good. 105 auto [d]() = s; // expected-error {{expected ';'}} expected-error {{expected expression}} 106 auto [e][1] = s; // expected-error {{expected ';'}} expected-error {{requires an initializer}} 107 108 // FIXME: This should fire the 'misplaced array declarator' diagnostic. 109 int [K] arr = {0}; // expected-error {{expected ';'}} expected-error {{cannot be declared with type 'int'}} expected-error {{decomposition declaration '[K]' requires an initializer}} 110 int [5] arr = {0}; // expected-error {{place the brackets after the name}} 111 112 auto *[f] = s; // expected-error {{cannot be declared with type 'auto *'}} expected-error {{incompatible initializer}} 113 auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto S::*'}} expected-error {{incompatible initializer}} 114 115 // ref-qualifiers are OK. 116 auto &&[ok_1] = S(); 117 auto &[ok_2] = s; 118 119 // attributes are OK. 120 [[]] auto [ok_3] = s; 121 alignas(S) auto [ok_4] = s; 122 123 auto [bad_attr_2] [[]] = s; // expected-error {{expected ';'}} expected-error {{}} 124 } 125 } 126 127 namespace MultiDeclarator { 128 struct S { int n; }; 129 void f(S s) { 130 auto [a] = s, [b] = s; // expected-error {{must be the only declaration}} 131 auto [c] = s, d = s; // expected-error {{must be the only declaration}} 132 auto e = s, [f] = s; // expected-error {{must be the only declaration}} 133 auto g = s, h = s, i = s, [j] = s; // expected-error {{must be the only declaration}} 134 } 135 } 136 137 namespace Template { 138 int n[3]; 139 // FIXME: There's no actual rule against this... 140 template<typename T> auto [a, b, c] = n; // expected-error {{decomposition declaration template not supported}} 141 } 142 143 namespace Init { 144 void f() { 145 int arr[1]; 146 struct S { int n; }; 147 auto &[bad1]; // expected-error {{decomposition declaration '[bad1]' requires an initializer}} 148 const auto &[bad2](S{}, S{}); // expected-error {{initializer for variable '[bad2]' with type 'const auto &' contains multiple expressions}} 149 const auto &[bad3](); // expected-error {{expected expression}} 150 auto &[good1] = arr; 151 auto &&[good2] = S{}; 152 const auto &[good3](S{}); 153 S [goodish3] = { 4 }; // expected-error {{cannot be declared with type 'S'}} 154 S [goodish4] { 4 }; // expected-error {{cannot be declared with type 'S'}} 155 } 156 } 157 158 159 namespace attributes { 160 161 struct S{ 162 int a; 163 int b = 0; 164 }; 165 166 void err() { 167 auto [[]] = S{0}; // expected-error {{expected unqualified-id}} 168 auto [ alignas(42) a, foo ] = S{0}; // expected-error {{an attribute list cannot appear here}} 169 auto [ c, [[]] d ] = S{0}; // expected-error {{an attribute list cannot appear here}} 170 auto [ e, alignas(42) f ] = S{0}; // expected-error {{an attribute list cannot appear here}} 171 } 172 173 void ok() { 174 auto [ a alignas(42) [[]], b alignas(42) [[]]] = S{0}; // expected-error 2{{'alignas' attribute only applies to variables, data members and tag types}} \ 175 // pre2c-warning 2{{an attribute specifier sequence attached to a structured binding declaration is a C++2c extension}} 176 auto [ c [[]] alignas(42), d [[]] alignas(42) [[]]] = S{0}; // expected-error 2{{'alignas' attribute only applies to variables, data members and tag types}} \ 177 // pre2c-warning 2{{an attribute specifier sequence attached to a structured binding declaration is a C++2c extension}} 178 } 179 180 181 auto [G1 [[deprecated]], G2 [[deprecated]]] = S{42}; // #deprecated-here 182 // pre2c-warning@-1 2{{an attribute specifier sequence attached to a structured binding declaration is a C++2c extension}} 183 184 int test() { 185 return G1 + G2; // expected-warning {{'G1' is deprecated}} expected-note@#deprecated-here {{here}} \ 186 // expected-warning {{'G2' is deprecated}} expected-note@#deprecated-here {{here}} 187 } 188 189 void invalid_attributes() { 190 // pre2c-warning@+1 {{an attribute specifier sequence attached to a structured binding declaration is a C++2c extension}} 191 auto [a alignas(42) // expected-error {{'alignas' attribute only applies to variables, data members and tag types}} 192 [[assume(true), // expected-error {{'assume' attribute cannot be applied to a declaration}} 193 carries_dependency, // expected-error {{'carries_dependency' attribute only applies to parameters, Objective-C methods, and functions}} 194 fallthrough, // expected-error {{'fallthrough' attribute cannot be applied to a declaration}} 195 likely, // expected-error {{'likely' attribute cannot be applied to a declaration}} 196 unlikely, // expected-error {{'unlikely' attribute cannot be applied to a declaration}} 197 nodiscard, // expected-warning {{'nodiscard' attribute only applies to Objective-C methods, enums, structs, unions, classes, functions, function pointers, and typedefs}} 198 noreturn, // expected-error {{'noreturn' attribute only applies to functions}} 199 no_unique_address]], // expected-error {{'no_unique_address' attribute only applies to non-bit-field non-static data members}} 200 b] = S{0}; 201 } 202 203 } 204