1 // RUN: %clang_cc1 -std=c++17 %s -verify -fcxx-exceptions 2 // RUN: not %clang_cc1 -std=c++17 %s -emit-llvm-only -fcxx-exceptions 3 4 struct S { int a, b, c; }; 5 6 // A simple-declaration can be a decompsition declaration. 7 namespace SimpleDecl { 8 auto [a_x, b_x, c_x] = S(); 9 f(S s)10 void f(S s) { 11 auto [a, b, c] = S(); 12 { 13 for (auto [a, b, c] = S();;) {} 14 if (auto [a, b, c] = S(); true) {} 15 switch (auto [a, b, c] = S(); 0) { case 0:; } 16 } 17 } 18 } 19 20 // A for-range-declaration can be a decomposition declaration. 21 namespace ForRangeDecl { 22 extern S arr[10]; h()23 void h() { 24 for (auto [a, b, c] : arr) { 25 } 26 } 27 } 28 29 // Other kinds of declaration cannot. 30 namespace OtherDecl { 31 // A parameter-declaration is not a simple-declaration. 32 // This parses as an array declaration. 33 void f(auto [a, b, c]); // expected-error {{'auto' not allowed in function prototype}} expected-error {{'a'}} 34 g()35 void g() { 36 // A condition is allowed as a Clang extension. 37 // See commentary in test/Parser/decomposed-condition.cpp 38 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'}} 39 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'}} 40 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'}} 41 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)}} 42 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)}} 43 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'}} 44 45 // An exception-declaration is not a simple-declaration. 46 try {} 47 catch (auto [a, b, c]) {} // expected-error {{'auto' not allowed in exception declaration}} expected-error {{'a'}} 48 } 49 50 // A member-declaration is not a simple-declaration. 51 class A { 52 auto [a, b, c] = S(); // expected-error {{not permitted in this context}} 53 static auto [a, b, c] = S(); // expected-error {{not permitted in this context}} 54 }; 55 } 56 57 namespace GoodSpecifiers { f()58 void f() { 59 int n[1]; 60 const volatile auto &[a] = n; 61 } 62 } 63 64 namespace BadSpecifiers { 65 typedef int I1[1]; 66 I1 n; 67 struct S { int n; } s; f()68 void f() { 69 // storage-class-specifiers 70 static auto &[a] = n; // expected-warning {{declared 'static' is a C++20 extension}} 71 thread_local auto &[b] = n; // expected-warning {{declared 'thread_local' is a C++20 extension}} 72 extern auto &[c] = n; // expected-error {{cannot be declared 'extern'}} expected-error {{cannot have an initializer}} 73 struct S { 74 mutable auto &[d] = n; // expected-error {{not permitted in this context}} 75 76 // function-specifiers 77 virtual auto &[e] = n; // expected-error {{not permitted in this context}} 78 explicit auto &[f] = n; // expected-error {{not permitted in this context}} 79 80 // misc decl-specifiers 81 friend auto &[g] = n; // expected-error {{'auto' not allowed}} expected-error {{friends can only be classes or functions}} 82 }; 83 typedef auto &[h] = n; // expected-error {{cannot be declared 'typedef'}} 84 constexpr auto &[i] = n; // expected-error {{cannot be declared 'constexpr'}} 85 } 86 87 static constexpr inline thread_local auto &[j1] = n; // expected-error {{cannot be declared with 'constexpr inline' specifiers}} 88 static thread_local auto &[j2] = n; // expected-warning {{declared with 'static thread_local' specifiers is a C++20 extension}} 89 90 inline auto &[k] = n; // expected-error {{cannot be declared 'inline'}} 91 92 const int K = 5; g()93 void g() { 94 // defining-type-specifiers other than cv-qualifiers and 'auto' 95 S [a] = s; // expected-error {{cannot be declared with type 'BadSpecifiers::S'}} 96 decltype(auto) [b] = s; // expected-error {{cannot be declared with type 'decltype(auto)'}} 97 auto ([c]) = s; // expected-error {{cannot be declared with parentheses}} 98 99 // FIXME: This error is not very good. 100 auto [d]() = s; // expected-error {{expected ';'}} expected-error {{expected expression}} 101 auto [e][1] = s; // expected-error {{expected ';'}} expected-error {{requires an initializer}} 102 103 // FIXME: This should fire the 'misplaced array declarator' diagnostic. 104 int [K] arr = {0}; // expected-error {{expected ';'}} expected-error {{cannot be declared with type 'int'}} expected-error {{decomposition declaration '[K]' requires an initializer}} 105 int [5] arr = {0}; // expected-error {{place the brackets after the name}} 106 107 auto *[f] = s; // expected-error {{cannot be declared with type 'auto *'}} expected-error {{incompatible initializer}} 108 auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto BadSpecifiers::S::*'}} expected-error {{incompatible initializer}} 109 110 // ref-qualifiers are OK. 111 auto &&[ok_1] = S(); 112 auto &[ok_2] = s; 113 114 // attributes are OK. 115 [[]] auto [ok_3] = s; 116 alignas(S) auto [ok_4] = s; 117 118 // ... but not after the identifier or declarator. 119 // FIXME: These errors are not very good. 120 auto [bad_attr_1 [[]]] = s; // expected-error {{attribute list cannot appear here}} expected-error 2{{}} 121 auto [bad_attr_2] [[]] = s; // expected-error {{expected ';'}} expected-error {{}} 122 } 123 } 124 125 namespace MultiDeclarator { 126 struct S { int n; }; f(S s)127 void f(S s) { 128 auto [a] = s, [b] = s; // expected-error {{must be the only declaration}} 129 auto [c] = s, d = s; // expected-error {{must be the only declaration}} 130 auto e = s, [f] = s; // expected-error {{must be the only declaration}} 131 auto g = s, h = s, i = s, [j] = s; // expected-error {{must be the only declaration}} 132 } 133 } 134 135 namespace Template { 136 int n[3]; 137 // FIXME: There's no actual rule against this... 138 template<typename T> auto [a, b, c] = n; // expected-error {{decomposition declaration template not supported}} 139 } 140 141 namespace Init { f()142 void f() { 143 int arr[1]; 144 struct S { int n; }; 145 auto &[bad1]; // expected-error {{decomposition declaration '[bad1]' requires an initializer}} 146 const auto &[bad2](S{}, S{}); // expected-error {{initializer for variable '[bad2]' with type 'const auto &' contains multiple expressions}} 147 const auto &[bad3](); // expected-error {{expected expression}} 148 auto &[good1] = arr; 149 auto &&[good2] = S{}; 150 const auto &[good3](S{}); 151 S [goodish3] = { 4 }; // expected-error {{cannot be declared with type 'S'}} 152 S [goodish4] { 4 }; // expected-error {{cannot be declared with type 'S'}} 153 } 154 } 155