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