xref: /llvm-project/clang/test/SemaCXX/cxx2c-placeholder-vars.cpp (revision e48d8f9fea69095757d3593a567316197ec70450)
1 // RUN: %clang_cc1 -fsyntax-only -verify -ast-dump -std=c++2c -Wunused-parameter -Wunused -Wpre-c++26-compat %s | FileCheck %s
2 
3 void static_var() {
4     static int _; // expected-note {{previous definition is here}} \
5                   // expected-note {{candidate}}
6     static int _; // expected-error {{redefinition of '_'}}
7     int _;        // expected-warning {{placeholder variables are incompatible with C++ standards before C++2c}} \
8                   // expected-note {{candidate}}
9     _++; // expected-error{{reference to '_' is ambiguous}}
10 }
11 
12 void static_var_2() {
13     int _; // expected-note {{previous definition is here}}
14     static int _; // expected-error {{redefinition of '_'}}
15 }
16 
17 void bindings() {
18     int arr[4] = {0, 1, 2, 3};
19     auto [_, _, _, _] = arr; // expected-warning 3{{placeholder variables are incompatible with C++ standards before C++2c}} \
20                              // expected-note 4{{placeholder declared here}}
21     _ == 42; // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}}
22     {
23         // no extension warning as we only introduce a single placeholder.
24         auto [_, a, b, c] = arr; // expected-warning {{unused variable '[_, a, b, c]'}}
25     }
26     {
27         auto [_, _, b, c] = arr; // expected-warning {{unused variable '[_, _, b, c]'}} \
28                                  // expected-warning {{placeholder variables are incompatible with C++ standards before C++2c}}
29     }
30     {
31         // There are only 3 extension warnings because the first
32         // introduction of `_` is valid in all C++ standards
33         auto [_, _, _, _] = arr; // expected-warning 3{{placeholder variables are incompatible with C++ standards before C++2c}}
34     }
35 }
36 
37 namespace StaticBindings {
38 
39 int arr[2] = {0, 1};
40 static auto [_, _] = arr; // expected-error {{redefinition of '_'}} \
41                           // expected-note  {{previous definition is here}}
42 
43 void f() {
44     int arr[2] = {0, 1};
45     static auto [_, _] = arr; // expected-error {{redefinition of '_'}} \
46                             // expected-note  {{previous definition is here}}
47 }
48 
49 }
50 
51 void lambda() {
52     (void)[_ = 0, _ = 1] { // expected-warning {{placeholder variables are incompatible with C++ standards before C++2c}} \
53                            // expected-note 2{{placeholder declared here}}
54         (void)_++; // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}}
55     };
56 
57     {
58         int _ = 12;
59         (void)[_ = 0]{ return _;}; // no warning (different scope)
60     }
61 
62     auto GH107024 = [_ = 42]() { return _; }();
63 }
64 
65 namespace global_var {
66     int _; // expected-note {{previous definition is here}}
67     int _; // expected-error {{redefinition of '_'}}
68 }
69 
70 namespace {
71     int _; // expected-note {{previous definition is here}}
72     int _; // expected-error {{redefinition of '_'}}
73 }
74 
75 
76 namespace global_fun {
77 void _();
78 void _();
79 
80 void _() {} // expected-note {{previous definition is here}}
81 void _() {} // expected-error {{redefinition of '_'}}
82 void _(int){}
83 }
84 
85 typedef int _;
86 typedef int _; // Type redeclaration, nothing to do with placeholders
87 
88 void extern_test() {
89     extern int _;
90     extern int _; // expected-note {{candidate}}
91     int _; //expected-note {{candidate}}
92     _++; // expected-error {{reference to '_' is ambiguous}}
93 }
94 
95 
96 struct Members {
97     int _; // expected-note 2{{placeholder declared here}}
98     int _; // expected-warning{{placeholder variables are incompatible with C++ standards before C++2c}} \
99            // expected-note 2{{placeholder declared here}}
100     void f() {
101         _++; // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}}
102     }
103     void attributes() __attribute__((diagnose_if(_ != 0, "oh no!", "warning"))); // expected-error{{ambiguous reference to placeholder '_', which is defined multiple times}}
104 };
105 
106 namespace using_ {
107 int _; // expected-note {{target of using declaration}}
108 void f() {
109     int _; // expected-note {{conflicting declaration}}
110     _ = 0;
111     using using_::_; // expected-error {{target of using declaration conflicts with declaration already in scope}}
112 }
113 }
114 
115 
116 void call(int);
117 void test_param(int _) {}
118 void test_params(int _, int _); // expected-error {{redefinition of parameter '_'}} \
119                                 // expected-note {{previous declaration is here}}
120 
121 template <auto _, auto _> // expected-error {{declaration of '_' shadows template parameter}} \
122                           // expected-note  {{template parameter is declared here}}
123 auto i = 0;
124 
125 template <typename T>
126 concept C = requires(T _, T _) {  // expected-error {{redefinition of parameter '_'}} \
127                                 // expected-note {{previous declaration is here}}
128     T{};
129 };
130 
131 struct S {
132     int a;
133 };
134 
135 void f(S a, S _) { // expected-warning {{unused parameter 'a'}}
136 
137 }
138 
139 void unused_warning() {
140   int _ = 12; // placeholder variable, no unused-but-set warning
141   int x = 12; // expected-warning {{unused variable 'x'}}
142   int _ = 12; // expected-warning {{placeholder variables are incompatible with C++ standards before C++2c}}
143 }
144 
145 struct ShadowMembers {
146   int _;
147   void f() {
148     int _;
149     _ = 12; // Ok, access the local variable
150     (void)({ int _ = 12; _;}); // Ok, inside a different scope
151   }
152 };
153 
154 struct MemberPtrs {
155   int _, _; // expected-warning {{placeholder variables are incompatible with C++ standards before C++2c}} \
156             // expected-note 4{{placeholder declared here}}
157 };
158 constexpr int oh_no = __builtin_offsetof(MemberPtrs, _); // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}}
159 int MemberPtrs::* ref = &MemberPtrs::_; // expected-error{{ambiguous reference to placeholder '_', which is defined multiple times}}
160 
161 
162 struct MemberInitializer {
163   MemberInitializer() : _(0) {}  // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}}
164   int _, _; // expected-note 2{{placeholder declared here}} \
165             // expected-warning {{placeholder variables are incompatible with C++ standards before C++2c}}
166 };
167 
168 struct MemberAndUnion {
169   int _; // expected-note {{placeholder declared here}}
170   union { int _; int _; }; // expected-note 2 {{placeholder declared here}} \
171                            // expected-warning 2{{placeholder variables are incompatible with C++ standards before C++2c}}
172 
173 
174   MemberAndUnion() : _(0) {} // expected-error {{ambiguous reference to placeholder '_', which is defined multiple time}}
175 };
176 
177 struct Union { union { int _, _, _; }; };   // expected-note 3{{placeholder declared here}} \
178                                             // expected-warning 2{{placeholder variables are incompatible with C++ standards before C++2c}}
179 
180 void TestUnion() {
181    Union c;
182    c._ = 0; // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}}
183 }
184 
185 void AnonymousLocals() {
186     union  {int _, _;}; // expected-warning {{placeholder variables are incompatible with C++ standards before C++2c}}  \
187                         // expected-note 2{{placeholder declared here}}
188     union  {int _, _;}; // expected-warning 2{{placeholder variables are incompatible with C++ standards before C++2c}} \
189                         // expected-note 2{{placeholder declared here}}
190     _. = 0; // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}}
191 }
192 
193 namespace StaticUnions {
194 
195 static union { int _ = 42; }; // expected-note {{previous declaration is here}}
196 static union { int _ = 43; }; // expected-error {{member of anonymous union redeclares '_'}}
197 
198 inline void StaticUnion() {
199   static union { int _{}; };  // expected-note {{previous declaration is here}}
200   static union { int _{}; }; // expected-error {{member of anonymous union redeclares '_'}}
201 }
202 
203 }
204 
205 namespace TagVariables {
206 
207 [[maybe_unused]] struct {
208     int _, _, _;  // expected-warning 2{{placeholder variables are incompatible with C++ standards before C++2c}}
209 } a;
210 
211 [[maybe_unused]] union {
212     int _, _, _; // expected-warning 2{{placeholder variables are incompatible with C++ standards before C++2c}}
213 } b;
214 
215 }
216 
217 namespace MemberLookupTests {
218 
219 struct S {
220     int _, _; // expected-warning {{placeholder variables are incompatible with C++ standards before C++2c}} \
221               // expected-note 8{{placeholder declared here}}
222 
223     void f() {
224         _ ++ ; // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}}
225     }
226 };
227 
228 struct T : S {
229 
230 };
231 
232 void Test() {
233     S s{._ =0}; // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}}
234     S{}._; // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}}
235     T{}._; // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}}
236 };
237 
238 };
239 
240 namespace Bases {
241     struct S {
242         int _, _; // expected-warning {{placeholder variables are incompatible with C++ standards before C++2c}} \
243                   // expected-note   2{{placeholder declared here}}
244         int a;
245     };
246     struct T : S{
247         int _, _; // expected-warning {{placeholder variables are incompatible with C++ standards before C++2c}} \
248                   // expected-note   2{{placeholder declared here}}
249         int a;
250         void f() {
251             _; // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}}
252             S::_; // expected-error {{ambiguous reference to placeholder '_', which is defined multiple times}} \
253                   // expected-error {{a type specifier is required for all declarations}}
254         }
255     };
256 }
257 
258 namespace GH114069 {
259 
260 template <class T>
261 struct A {
262     T _ = 1;
263     T _ = 2;
264     T : 1;
265     T a = 3;
266     T _ = 4;
267 };
268 
269 void f() {
270     [[maybe_unused]] A<int> a;
271 }
272 
273 // CHECK: NamespaceDecl {{.*}} GH114069
274 // CHECK: ClassTemplateSpecializationDecl {{.*}} struct A definition
275 // CHECK: CXXConstructorDecl {{.*}} implicit used constexpr A 'void () noexcept'
276 // CHECK-NEXT: CXXCtorInitializer Field {{.*}} '_' 'int'
277 // CHECK-NEXT: CXXDefaultInitExpr {{.*}} 'int' has rewritten init
278 // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 1
279 // CHECK-NEXT: CXXCtorInitializer Field {{.*}} '_' 'int'
280 // CHECK-NEXT: CXXDefaultInitExpr {{.*}} 'int' has rewritten init
281 // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 2
282 // CHECK-NEXT: CXXCtorInitializer Field {{.*}} 'a' 'int'
283 // CHECK-NEXT: CXXDefaultInitExpr {{.*}} 'int' has rewritten init
284 // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 3
285 // CHECK-NEXT: CXXCtorInitializer Field {{.*}} '_' 'int'
286 // CHECK-NEXT: CXXDefaultInitExpr {{.*}} 'int' has rewritten init
287 // CHECK-NEXT: IntegerLiteral {{.*}} 'int' 4
288 // CHECK-NEXT: CompoundStmt {{.*}}
289 
290 }
291