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