diff options
Diffstat (limited to 'test/Parser/cxx1z-decomposition.cpp')
-rw-r--r-- | test/Parser/cxx1z-decomposition.cpp | 150 |
1 files changed, 150 insertions, 0 deletions
diff --git a/test/Parser/cxx1z-decomposition.cpp b/test/Parser/cxx1z-decomposition.cpp new file mode 100644 index 000000000000..9cbe70e3c69b --- /dev/null +++ b/test/Parser/cxx1z-decomposition.cpp @@ -0,0 +1,150 @@ +// RUN: %clang_cc1 -std=c++1z %s -verify -fcxx-exceptions + +struct S { int a, b, c; }; + +// A simple-declaration can be a decompsition declaration. +namespace SimpleDecl { + auto [a_x, b_x, c_x] = S(); + + void f(S s) { + auto [a, b, c] = S(); + { + for (auto [a, b, c] = S();;) {} + if (auto [a, b, c] = S(); true) {} + switch (auto [a, b, c] = S(); 0) { case 0:; } + } + } +} + +// A for-range-declaration can be a decomposition declaration. +namespace ForRangeDecl { + extern S arr[10]; + void h() { + for (auto [a, b, c] : arr) { + } + } +} + +// Other kinds of declaration cannot. +namespace OtherDecl { + // A parameter-declaration is not a simple-declaration. + // This parses as an array declaration. + void f(auto [a, b, c]); // expected-error {{'auto' not allowed in function prototype}} expected-error {{'a'}} + + void g() { + // A condition is not a simple-declaration. + for (; auto [a, b, c] = S(); ) {} // expected-error {{not permitted in this context}} + if (auto [a, b, c] = S()) {} // expected-error {{not permitted in this context}} + if (int n; auto [a, b, c] = S()) {} // expected-error {{not permitted in this context}} + switch (auto [a, b, c] = S()) {} // expected-error {{not permitted in this context}} + switch (int n; auto [a, b, c] = S()) {} // expected-error {{not permitted in this context}} + while (auto [a, b, c] = S()) {} // expected-error {{not permitted in this context}} + + // An exception-declaration is not a simple-declaration. + try {} + catch (auto [a, b, c]) {} // expected-error {{'auto' not allowed in exception declaration}} expected-error {{'a'}} + } + + // A member-declaration is not a simple-declaration. + class A { + auto [a, b, c] = S(); // expected-error {{not permitted in this context}} + static auto [a, b, c] = S(); // expected-error {{not permitted in this context}} + }; +} + +namespace GoodSpecifiers { + void f() { + int n[1]; + const volatile auto &[a] = n; + } +} + +namespace BadSpecifiers { + typedef int I1[1]; + I1 n; + struct S { int n; } s; + void f() { + // storage-class-specifiers + static auto &[a] = n; // expected-error {{cannot be declared 'static'}} + thread_local auto &[b] = n; // expected-error {{cannot be declared 'thread_local'}} + extern auto &[c] = n; // expected-error {{cannot be declared 'extern'}} expected-error {{cannot have an initializer}} + struct S { + mutable auto &[d] = n; // expected-error {{not permitted in this context}} + + // function-specifiers + virtual auto &[e] = n; // expected-error {{not permitted in this context}} + explicit auto &[f] = n; // expected-error {{not permitted in this context}} + + // misc decl-specifiers + friend auto &[g] = n; // expected-error {{'auto' not allowed}} expected-error {{friends can only be classes or functions}} + }; + typedef auto &[h] = n; // expected-error {{cannot be declared 'typedef'}} + constexpr auto &[i] = n; // expected-error {{cannot be declared 'constexpr'}} + + static constexpr thread_local auto &[j] = n; // expected-error {{cannot be declared with 'static thread_local constexpr' specifiers}} + } + inline auto &[k] = n; // expected-error {{cannot be declared 'inline'}} + + const int K = 5; + void g() { + // defining-type-specifiers other than cv-qualifiers and 'auto' + S [a] = s; // expected-error {{cannot be declared with type 'BadSpecifiers::S'}} + decltype(auto) [b] = s; // expected-error {{cannot be declared with type 'decltype(auto)'}} + auto ([c]) = s; // expected-error {{cannot be declared with parentheses}} + + // FIXME: This error is not very good. + auto [d]() = s; // expected-error {{expected ';'}} expected-error {{expected expression}} + auto [e][1] = s; // expected-error {{expected ';'}} expected-error {{requires an initializer}} + + // FIXME: This should fire the 'misplaced array declarator' diagnostic. + int [K] arr = {0}; // expected-error {{expected ';'}} expected-error {{cannot be declared with type 'int'}} expected-error {{decomposition declaration '[K]' requires an initializer}} + int [5] arr = {0}; // expected-error {{place the brackets after the name}} + + auto *[f] = s; // expected-error {{cannot be declared with type 'auto *'}} expected-error {{incompatible initializer}} + auto S::*[g] = s; // expected-error {{cannot be declared with type 'auto BadSpecifiers::S::*'}} expected-error {{incompatible initializer}} + + // ref-qualifiers are OK. + auto &&[ok_1] = S(); + auto &[ok_2] = s; + + // attributes are OK. + [[]] auto [ok_3] = s; + alignas(S) auto [ok_4] = s; + + // ... but not after the identifier or declarator. + // FIXME: These errors are not very good. + auto [bad_attr_1 [[]]] = s; // expected-error {{attribute list cannot appear here}} expected-error 2{{}} + auto [bad_attr_2] [[]] = s; // expected-error {{expected ';'}} expected-error {{}} + } +} + +namespace MultiDeclarator { + struct S { int n; }; + void f(S s) { + auto [a] = s, [b] = s; // expected-error {{must be the only declaration}} + auto [c] = s, d = s; // expected-error {{must be the only declaration}} + auto e = s, [f] = s; // expected-error {{must be the only declaration}} + auto g = s, h = s, i = s, [j] = s; // expected-error {{must be the only declaration}} + } +} + +namespace Template { + int n[3]; + // FIXME: There's no actual rule against this... + template<typename T> auto [a, b, c] = n; // expected-error {{decomposition declaration template not supported}} +} + +namespace Init { + void f() { + int arr[1]; + struct S { int n; }; + auto &[bad1]; // expected-error {{decomposition declaration '[bad1]' requires an initializer}} + const auto &[bad2](S{}, S{}); // expected-error {{initializer for variable '[bad2]' with type 'const auto &' contains multiple expressions}} + const auto &[bad3](); // expected-error {{expected expression}} + auto &[good1] = arr; + auto &&[good2] = S{}; + const auto &[good3](S{}); + S [goodish3] = { 4 }; // expected-error {{cannot be declared with type 'S'}} + S [goodish4] { 4 }; // expected-error {{cannot be declared with type 'S'}} + } +} |