blob: 1e184a7fac540a4a504347944083e7ced6971312 [file] [log] [blame]
Richard Smithbdb84f32016-07-22 23:36:59 +00001// RUN: %clang_cc1 -std=c++1z %s -verify -fcxx-exceptions
Richard Smith7c7e5312018-10-26 03:21:20 +00002// RUN: not %clang_cc1 -std=c++1z %s -emit-llvm-only -fcxx-exceptions
Richard Smithbdb84f32016-07-22 23:36:59 +00003
4struct S { int a, b, c; };
5
6// A simple-declaration can be a decompsition declaration.
7namespace SimpleDecl {
8 auto [a_x, b_x, c_x] = S();
9
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.
21namespace ForRangeDecl {
22 extern S arr[10];
23 void h() {
24 for (auto [a, b, c] : arr) {
25 }
26 }
27}
28
29// Other kinds of declaration cannot.
30namespace 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
35 void g() {
Zhihao Yuanc81f4532017-12-07 07:03:15 +000036 // 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'}}
Richard Smithbdb84f32016-07-22 23:36:59 +000044
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
57namespace GoodSpecifiers {
58 void f() {
59 int n[1];
60 const volatile auto &[a] = n;
61 }
62}
63
64namespace BadSpecifiers {
65 typedef int I1[1];
66 I1 n;
67 struct S { int n; } s;
68 void f() {
69 // storage-class-specifiers
70 static auto &[a] = n; // expected-error {{cannot be declared 'static'}}
71 thread_local auto &[b] = n; // expected-error {{cannot be declared 'thread_local'}}
Richard Smith7873de02016-08-11 22:25:46 +000072 extern auto &[c] = n; // expected-error {{cannot be declared 'extern'}} expected-error {{cannot have an initializer}}
Richard Smithbdb84f32016-07-22 23:36:59 +000073 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 static constexpr thread_local auto &[j] = n; // expected-error {{cannot be declared with 'static thread_local constexpr' specifiers}}
87 }
88 inline auto &[k] = n; // expected-error {{cannot be declared 'inline'}}
89
90 const int K = 5;
91 void g() {
92 // defining-type-specifiers other than cv-qualifiers and 'auto'
93 S [a] = s; // expected-error {{cannot be declared with type 'BadSpecifiers::S'}}
94 decltype(auto) [b] = s; // expected-error {{cannot be declared with type 'decltype(auto)'}}
95 auto ([c]) = s; // expected-error {{cannot be declared with parentheses}}
96
97 // FIXME: This error is not very good.
98 auto [d]() = s; // expected-error {{expected ';'}} expected-error {{expected expression}}
99 auto [e][1] = s; // expected-error {{expected ';'}} expected-error {{requires an initializer}}
100
101 // FIXME: This should fire the 'misplaced array declarator' diagnostic.
Richard Smith7873de02016-08-11 22:25:46 +0000102 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 +0000103 int [5] arr = {0}; // expected-error {{place the brackets after the name}}
104
105 auto *[f] = s; // expected-error {{cannot be declared with type 'auto *'}} expected-error {{incompatible initializer}}
106 auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto BadSpecifiers::S::*'}} expected-error {{incompatible initializer}}
107
108 // ref-qualifiers are OK.
109 auto &&[ok_1] = S();
110 auto &[ok_2] = s;
111
112 // attributes are OK.
113 [[]] auto [ok_3] = s;
114 alignas(S) auto [ok_4] = s;
115
116 // ... but not after the identifier or declarator.
117 // FIXME: These errors are not very good.
118 auto [bad_attr_1 [[]]] = s; // expected-error {{attribute list cannot appear here}} expected-error 2{{}}
119 auto [bad_attr_2] [[]] = s; // expected-error {{expected ';'}} expected-error {{}}
120 }
121}
122
123namespace MultiDeclarator {
124 struct S { int n; };
125 void f(S s) {
126 auto [a] = s, [b] = s; // expected-error {{must be the only declaration}}
127 auto [c] = s, d = s; // expected-error {{must be the only declaration}}
128 auto e = s, [f] = s; // expected-error {{must be the only declaration}}
129 auto g = s, h = s, i = s, [j] = s; // expected-error {{must be the only declaration}}
130 }
131}
132
133namespace Template {
134 int n[3];
135 // FIXME: There's no actual rule against this...
136 template<typename T> auto [a, b, c] = n; // expected-error {{decomposition declaration template not supported}}
137}
Richard Smith7873de02016-08-11 22:25:46 +0000138
139namespace Init {
140 void f() {
141 int arr[1];
142 struct S { int n; };
143 auto &[bad1]; // expected-error {{decomposition declaration '[bad1]' requires an initializer}}
Richard Smith4b46cb92016-12-09 22:56:20 +0000144 const auto &[bad2](S{}, S{}); // expected-error {{initializer for variable '[bad2]' with type 'const auto &' contains multiple expressions}}
145 const auto &[bad3](); // expected-error {{expected expression}}
Richard Smith7873de02016-08-11 22:25:46 +0000146 auto &[good1] = arr;
147 auto &&[good2] = S{};
Richard Smith4b46cb92016-12-09 22:56:20 +0000148 const auto &[good3](S{});
Richard Smith7873de02016-08-11 22:25:46 +0000149 S [goodish3] = { 4 }; // expected-error {{cannot be declared with type 'S'}}
150 S [goodish4] { 4 }; // expected-error {{cannot be declared with type 'S'}}
151 }
152}