Clang Project

clang_source_code/test/Parser/cxx1z-decomposition.cpp
1// RUN: %clang_cc1 -std=c++1z %s -verify -fcxx-exceptions
2// RUN: not %clang_cc1 -std=c++1z %s -emit-llvm-only -fcxx-exceptions
3
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() {
36    // 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'}}
44
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'}}
72    extern auto &[c] = n; // expected-error {{cannot be declared 'extern'}} expected-error {{cannot have an initializer}}
73    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.
102    int [K] arr = {0}; // expected-error {{expected ';'}} expected-error {{cannot be declared with type 'int'}} expected-error {{decomposition declaration '[K]' requires an initializer}}
103    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}
138
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}}
144    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}}
146    auto &[good1] = arr;
147    auto &&[good2] = S{};
148    const auto &[good3](S{});
149    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}
153