blob: cf4ba77723ad2aaaf34ef1f9eee58b03adaa12da [file] [log] [blame]
Richard Smithbdb84f32016-07-22 23:36:59 +00001// RUN: %clang_cc1 -std=c++1z %s -verify -fcxx-exceptions
2
3struct S { int a, b, c; };
4
5// A simple-declaration can be a decompsition declaration.
6namespace 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.
20namespace 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.
29namespace 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() {
Zhihao Yuanc81f4532017-12-07 07:03:15 +000035 // A condition is allowed as a Clang extension.
36 // See commentary in test/Parser/decomposed-condition.cpp
37 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'}}
38 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'}}
39 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'}}
40 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)}}
41 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)}}
42 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'}}
Richard Smithbdb84f32016-07-22 23:36:59 +000043
44 // An exception-declaration is not a simple-declaration.
45 try {}
46 catch (auto [a, b, c]) {} // expected-error {{'auto' not allowed in exception declaration}} expected-error {{'a'}}
47 }
48
49 // A member-declaration is not a simple-declaration.
50 class A {
51 auto [a, b, c] = S(); // expected-error {{not permitted in this context}}
52 static auto [a, b, c] = S(); // expected-error {{not permitted in this context}}
53 };
54}
55
56namespace GoodSpecifiers {
57 void f() {
58 int n[1];
59 const volatile auto &[a] = n;
60 }
61}
62
63namespace BadSpecifiers {
64 typedef int I1[1];
65 I1 n;
66 struct S { int n; } s;
67 void f() {
68 // storage-class-specifiers
69 static auto &[a] = n; // expected-error {{cannot be declared 'static'}}
70 thread_local auto &[b] = n; // expected-error {{cannot be declared 'thread_local'}}
Richard Smith7873de02016-08-11 22:25:46 +000071 extern auto &[c] = n; // expected-error {{cannot be declared 'extern'}} expected-error {{cannot have an initializer}}
Richard Smithbdb84f32016-07-22 23:36:59 +000072 struct S {
73 mutable auto &[d] = n; // expected-error {{not permitted in this context}}
74
75 // function-specifiers
76 virtual auto &[e] = n; // expected-error {{not permitted in this context}}
77 explicit auto &[f] = n; // expected-error {{not permitted in this context}}
78
79 // misc decl-specifiers
80 friend auto &[g] = n; // expected-error {{'auto' not allowed}} expected-error {{friends can only be classes or functions}}
81 };
82 typedef auto &[h] = n; // expected-error {{cannot be declared 'typedef'}}
83 constexpr auto &[i] = n; // expected-error {{cannot be declared 'constexpr'}}
84
85 static constexpr thread_local auto &[j] = n; // expected-error {{cannot be declared with 'static thread_local constexpr' specifiers}}
86 }
87 inline auto &[k] = n; // expected-error {{cannot be declared 'inline'}}
88
89 const int K = 5;
90 void g() {
91 // defining-type-specifiers other than cv-qualifiers and 'auto'
92 S [a] = s; // expected-error {{cannot be declared with type 'BadSpecifiers::S'}}
93 decltype(auto) [b] = s; // expected-error {{cannot be declared with type 'decltype(auto)'}}
94 auto ([c]) = s; // expected-error {{cannot be declared with parentheses}}
95
96 // FIXME: This error is not very good.
97 auto [d]() = s; // expected-error {{expected ';'}} expected-error {{expected expression}}
98 auto [e][1] = s; // expected-error {{expected ';'}} expected-error {{requires an initializer}}
99
100 // FIXME: This should fire the 'misplaced array declarator' diagnostic.
Richard Smith7873de02016-08-11 22:25:46 +0000101 int [K] arr = {0}; // expected-error {{expected ';'}} expected-error {{cannot be declared with type 'int'}} expected-error {{decomposition declaration '[K]' requires an initializer}}
Richard Smithbdb84f32016-07-22 23:36:59 +0000102 int [5] arr = {0}; // expected-error {{place the brackets after the name}}
103
104 auto *[f] = s; // expected-error {{cannot be declared with type 'auto *'}} expected-error {{incompatible initializer}}
105 auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto BadSpecifiers::S::*'}} expected-error {{incompatible initializer}}
106
107 // ref-qualifiers are OK.
108 auto &&[ok_1] = S();
109 auto &[ok_2] = s;
110
111 // attributes are OK.
112 [[]] auto [ok_3] = s;
113 alignas(S) auto [ok_4] = s;
114
115 // ... but not after the identifier or declarator.
116 // FIXME: These errors are not very good.
117 auto [bad_attr_1 [[]]] = s; // expected-error {{attribute list cannot appear here}} expected-error 2{{}}
118 auto [bad_attr_2] [[]] = s; // expected-error {{expected ';'}} expected-error {{}}
119 }
120}
121
122namespace MultiDeclarator {
123 struct S { int n; };
124 void f(S s) {
125 auto [a] = s, [b] = s; // expected-error {{must be the only declaration}}
126 auto [c] = s, d = s; // expected-error {{must be the only declaration}}
127 auto e = s, [f] = s; // expected-error {{must be the only declaration}}
128 auto g = s, h = s, i = s, [j] = s; // expected-error {{must be the only declaration}}
129 }
130}
131
132namespace Template {
133 int n[3];
134 // FIXME: There's no actual rule against this...
135 template<typename T> auto [a, b, c] = n; // expected-error {{decomposition declaration template not supported}}
136}
Richard Smith7873de02016-08-11 22:25:46 +0000137
138namespace Init {
139 void f() {
140 int arr[1];
141 struct S { int n; };
142 auto &[bad1]; // expected-error {{decomposition declaration '[bad1]' requires an initializer}}
Richard Smith4b46cb92016-12-09 22:56:20 +0000143 const auto &[bad2](S{}, S{}); // expected-error {{initializer for variable '[bad2]' with type 'const auto &' contains multiple expressions}}
144 const auto &[bad3](); // expected-error {{expected expression}}
Richard Smith7873de02016-08-11 22:25:46 +0000145 auto &[good1] = arr;
146 auto &&[good2] = S{};
Richard Smith4b46cb92016-12-09 22:56:20 +0000147 const auto &[good3](S{});
Richard Smith7873de02016-08-11 22:25:46 +0000148 S [goodish3] = { 4 }; // expected-error {{cannot be declared with type 'S'}}
149 S [goodish4] { 4 }; // expected-error {{cannot be declared with type 'S'}}
150 }
151}