xref: /llvm-project/clang/test/CXX/drs/cwg20xx.cpp (revision 14ba3f9d07ea1664497c5d117120fb243ca221aa)
1 // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify=expected,cxx98 -fexceptions -fcxx-exceptions -pedantic-errors
2 // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,cxx11 -fexceptions -fcxx-exceptions -pedantic-errors
3 // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors
4 // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx14 -fexceptions -fcxx-exceptions -pedantic-errors
5 // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors
6 // RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors
7 // RUN: %clang_cc1 -std=c++2c -triple x86_64-unknown-unknown %s -verify=expected,since-cxx11,since-cxx14,since-cxx20 -fexceptions -fcxx-exceptions -pedantic-errors
8 
9 #if __cplusplus == 199711L
10 #define static_assert(...) __extension__ _Static_assert(__VA_ARGS__)
11 // cxx98-error@-1 {{variadic macros are a C99 feature}}
12 #endif
13 
14 namespace cwg2007 { // cwg2007: 3.4
15 template<typename T> struct A { typename T::error e; };
16 template<typename T> struct B { };
17 B<A<void> > b1;
18 B<A<void> > b2 = b1;
19 int a = b2[0];
20 // cxx98-error@-1 {{type 'B<A<void> >' does not provide a subscript operator}}
21 // since-cxx11-error@-2 {{type 'B<A<void>>' does not provide a subscript operator}}
22 int b = __builtin_addressof(b2)->foo;
23 // cxx98-error@-1 {{no member named 'foo' in 'cwg2007::B<cwg2007::A<void> >'}}
24 // since-cxx11-error@-2 {{no member named 'foo' in 'cwg2007::B<cwg2007::A<void>>'}}
25 } // namespace cwg2007
26 
27 // cwg2009: na
28 
29 namespace cwg2026 { // cwg2026: 11
30   template<int> struct X {};
31 
32   const int a = a + 1; // #cwg2026-a
33   // expected-warning@-1 {{variable 'a' is uninitialized when used within its own initialization}}
34   X<a> xa; // #cwg2026-xa
35   // cxx98-error@-1 {{non-type template argument of type 'int' is not an integral constant expression}}
36   //   cxx98-note@-2 {{initializer of 'a' is not a constant expression}}
37   //   cxx98-note@#cwg2026-a {{declared here}}
38   // since-cxx11-error@#cwg2026-xa {{non-type template argument is not a constant expression}}
39   //   since-cxx11-note@#cwg2026-xa {{initializer of 'a' is not a constant expression}}
40   //   since-cxx11-note@#cwg2026-a {{declared here}}
41 
42 #if __cplusplus >= 201103L
43   constexpr int b = b;
44   // since-cxx11-error@-1 {{constexpr variable 'b' must be initialized by a constant expression}}
45   //   since-cxx11-note@-2 {{read of object outside its lifetime is not allowed in a constant expression}}
46   [[clang::require_constant_initialization]] int c = c;
47   // since-cxx11-error@-1 {{variable does not have a constant initializer}}
48   //   since-cxx11-note@-2 {{required by 'require_constant_initialization' attribute here}}
49   //   cxx11-note@-3 {{read of non-const variable 'c' is not allowed in a constant expression}}
50   //   cxx11-note@-4 {{declared here}}
51   //   since-cxx14-note@-5 {{read of object outside its lifetime is not allowed in a constant expression}}
52 #endif
53 
54 #if __cplusplus >= 202002L
55   constinit int d = d;
56   // since-cxx20-error@-1 {{variable does not have a constant initializer}}
57   //   since-cxx20-note@-2 {{required by 'constinit' specifier here}}
58   //   since-cxx20-note@-3 {{read of object outside its lifetime is not allowed in a constant expression}}
59 #endif
60 
61   void f() {
62     static const int e = e + 1; // #cwg2026-e
63     // expected-warning@-1 {{static variable 'e' is suspiciously used within its own initialization}}
64     X<e> xe; // #cwg2026-xe
65     // cxx98-error@-1 {{non-type template argument of type 'int' is not an integral constant expression}}
66     //   cxx98-note@-2 {{initializer of 'e' is not a constant expression}}
67     //   cxx98-note@#cwg2026-e {{declared here}}
68     // since-cxx11-error@#cwg2026-xe {{non-type template argument is not a constant expression}}
69     //   since-cxx11-note@#cwg2026-xe {{initializer of 'e' is not a constant expression}}
70     //   since-cxx11-note@#cwg2026-e {{declared here}}
71 
72 #if __cplusplus >= 201103L
73     static constexpr int f = f;
74     // since-cxx11-error@-1 {{constexpr variable 'f' must be initialized by a constant expression}}
75     //   since-cxx11-note@-2 {{read of object outside its lifetime is not allowed in a constant expression}}
76     [[clang::require_constant_initialization]] static int g = g;
77     // since-cxx11-error@-1 {{variable does not have a constant initializer}}
78     //   since-cxx11-note@-2 {{required by 'require_constant_initialization' attribute here}}
79     //   cxx11-note@-3 {{read of non-const variable 'g' is not allowed in a constant expression}}
80     //   cxx11-note@-4 {{declared here}}
81     //   since-cxx14-note@-5 {{read of object outside its lifetime is not allowed in a constant expression}}
82 #endif
83 
84 #if __cplusplus >= 202002L
85     static constinit int h = h;
86     // since-cxx20-error@-1 {{variable does not have a constant initializer}}
87     //   since-cxx20-note@-2 {{required by 'constinit' specifier here}}
88     //   since-cxx20-note@-3 {{read of object outside its lifetime is not allowed in a constant expression}}
89 #endif
90   }
91 } // namespace cwg2026
92 
93 namespace cwg2049 { // cwg2049: 18
94 #if __cplusplus >= 202302L
95 template <int* x = {}> struct X {};
96 X<> a;
97 X<nullptr> b;
98 static_assert(__is_same(decltype(a), decltype(b)));
99 #endif
100 } // namespace cwg2049
101 
102 namespace cwg2061 { // cwg2061: 2.7
103 #if __cplusplus >= 201103L
104   namespace A {
105     inline namespace b {
106       namespace C {
107         // 'f' is the example from the DR.  'S' is an example where if we didn't
108         // properly handle the two being the same, we would get an incomplete
109         // type error during attempted instantiation.
110         template<typename T> void f();
111         template<typename T> struct S;
112       }
113     }
114   }
115 
116   namespace A {
117     namespace C {
118       template<> void f<int>() { }
119       template<> struct S<int> { };
120     }
121   }
122 
123   void use() {
124     A::C::f<int>();
125     A::C::S<int> s;
126   }
127 #endif // C++11
128 } // namespace cwg2061
129 
130 namespace cwg2076 { // cwg2076: 13
131 #if __cplusplus >= 201103L
132   namespace std_example {
133     struct A { A(int); };
134     struct B { B(A); };
135     B b{{0}};
136 
137     struct Params { int a; int b; };
138     struct Foo {
139       Foo(Params);
140     };
141     Foo foo{{1, 2}};
142   }
143 
144   struct string_view {
145     string_view(int); // not an aggregate
146   };
147   struct string {
148     string(int); // not an aggregate
149     operator string_view() const;
150   };
151 
152   void foo(const string &); // #cwg2076-foo
153   void bar(string_view); // #cwg2076-bar
154 
155   void func(const string &arg) {
156     // An argument in one set of braces is subject to user-defined conversions;
157     // an argument in two sets of braces is not, but an identity conversion is
158     // still OK.
159     foo(arg);
160     foo({arg});
161     foo({{arg}});
162     foo({{{arg}}});
163     // since-cxx11-error@-1 {{no matching function}}
164     //   since-cxx11-note@#cwg2076-foo  {{cannot convert initializer list}}
165     bar(arg);
166     bar({arg});
167     bar({{arg}});
168     // since-cxx11-error@-1 {{no matching function}}
169     //   since-cxx11-note@#cwg2076-bar {{cannot convert initializer list}}
170     bar({{{arg}}});
171     // since-cxx11-error@-1 {{no matching function}}
172     //   since-cxx11-note@#cwg2076-bar {{cannot convert initializer list}}
173   }
174 #endif
175 } // namespace cwg2076
176 
177 namespace cwg2082 { // cwg2082: 11
178   void test1(int x, int = sizeof(x)); // ok
179 #if __cplusplus >= 201103L
180   void test2(int x, int = decltype(x){}); // ok
181 #endif
182 } // namespace cwg2082
183 
184 namespace cwg2083 { // cwg2083: partial
185 #if __cplusplus >= 201103L
186   void non_const_mem_ptr() {
187     struct A {
188       int x;
189       int y;
190     };
191     constexpr A a = {1, 2};
192     struct B {
193       int A::*p;
194       constexpr int g() const {
195         // OK, not an odr-use of 'a'.
196         return a.*p;
197       };
198     };
199     static_assert(B{&A::x}.g() == 1, "");
200     static_assert(B{&A::y}.g() == 2, "");
201   }
202 #endif
203 
204   const int a = 1;
205   int b;
206   // Note, references only get special odr-use / constant initializxer
207   // treatment in C++11 onwards. We continue to apply that even after CWG2083.
208   void ref_to_non_const() {
209     int c;
210     const int &ra = a; // #cwg2083-ra
211     int &rb = b; // #cwg2083-rb
212     int &rc = c; // #cwg2083-rc
213     struct A {
214       int f() {
215         int a = ra;
216         // cxx98-error@-1 {{reference to local variable 'ra' declared in enclosing function 'cwg2083::ref_to_non_const'}}
217         //   cxx98-note@#cwg2083-ra {{'ra' declared here}}
218         int b = rb;
219         // cxx98-error@-1 {{reference to local variable 'rb' declared in enclosing function 'cwg2083::ref_to_non_const'}}
220         //   cxx98-note@#cwg2083-rb {{'rb' declared here}}
221         int c = rc;
222         // expected-error@-1 {{reference to local variable 'rc' declared in enclosing function 'cwg2083::ref_to_non_const'}}
223         //   expected-note@#cwg2083-rc {{'rc' declared here}}
224         return a + b + c;
225       }
226     };
227   }
228 
229 #if __cplusplus >= 201103L
230   struct NoMut1 { int a, b; };
231   struct NoMut2 { NoMut1 m; };
232   struct NoMut3 : NoMut1 {
233     constexpr NoMut3(int a, int b) : NoMut1{a, b} {}
234   };
235   struct Mut1 {
236     int a;
237     mutable int b;
238   };
239   struct Mut2 { Mut1 m; };
240   struct Mut3 : Mut1 {
241     constexpr Mut3(int a, int b) : Mut1{a, b} {}
242   };
243   void mutable_subobjects() {
244     constexpr NoMut1 nm1 = {1, 2};
245     constexpr NoMut2 nm2 = {1, 2};
246     constexpr NoMut3 nm3 = {1, 2};
247     constexpr Mut1 m1 = {1, 2}; // #cwg2083-m1
248     constexpr Mut2 m2 = {1, 2}; // #cwg2083-m2
249     constexpr Mut3 m3 = {1, 2}; // #cwg2083-m3
250     struct A {
251       void f() {
252         static_assert(nm1.a == 1, "");
253         static_assert(nm2.m.a == 1, "");
254         static_assert(nm3.a == 1, "");
255         // Can't even access a non-mutable member of a variable containing mutable fields.
256         static_assert(m1.a == 1, "");
257         // since-cxx11-error@-1 {{reference to local variable 'm1' declared in enclosing function 'cwg2083::mutable_subobjects'}}
258         //   since-cxx11-note@#cwg2083-m1 {{'m1' declared here}}
259         static_assert(m2.m.a == 1, "");
260         // since-cxx11-error@-1 {{reference to local variable 'm2' declared in enclosing function 'cwg2083::mutable_subobjects'}}
261         //   since-cxx11-note@#cwg2083-m2 {{'m2' declared here}}
262         static_assert(m3.a == 1, "");
263         // since-cxx11-error@-1 {{reference to local variable 'm3' declared in enclosing function 'cwg2083::mutable_subobjects'}}
264         //   since-cxx11-note@#cwg2083-m3 {{'m3' declared here}}
265       }
266     };
267   }
268 #endif
269 
270   void ellipsis() {
271     void ellipsis(...);
272     struct A {};
273     const int n = 0;
274 #if __cplusplus >= 201103L
275     constexpr
276 #endif
277       A a = {}; // #cwg2083-a
278     struct B {
279       void f() {
280         ellipsis(n);
281         // Even though this is technically modelled as an lvalue-to-rvalue
282         // conversion, it calls a constructor and binds 'a' to a reference, so
283         // it results in an odr-use.
284         ellipsis(a);
285         // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg2083::ellipsis'}}
286         //   expected-note@#cwg2083-a {{'a' declared here}}
287       }
288     };
289   }
290 
291 #if __cplusplus >= 201103L
292   void volatile_lval() {
293     struct A { int n; };
294     constexpr A a = {0}; // #cwg2083-a2
295     struct B {
296       void f() {
297         // An lvalue-to-rvalue conversion of a volatile lvalue always results
298         // in odr-use.
299         int A::*p = &A::n;
300         int x = a.*p;
301         volatile int A::*q = p;
302         int y = a.*q;
303         // since-cxx11-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg2083::volatile_lval'}}
304         //   since-cxx11-note@#cwg2083-a2 {{'a' declared here}}
305       }
306     };
307   }
308 #endif
309 
310   void discarded_lval() {
311     struct A { int x; mutable int y; volatile int z; };
312     A a; // #cwg2083-a-3
313     int &r = a.x; // #cwg2083-r
314     struct B {
315       void f() {
316         // FIXME: We emit more errors than we should be. They are explicitly
317         // marked below.
318         a.x;
319         // expected-warning@-1 {{expression result unused}}
320         // expected-error@-2 {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} FIXME
321         //   expected-note@#cwg2083-a-3 {{'a' declared here}}
322         a.*&A::x;
323         // expected-warning@-1 {{expression result unused}}
324         // expected-error@-2 {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} FIXME
325         //   expected-note@#cwg2083-a-3 {{'a' declared here}}
326         true ? a.x : a.y; // #cwg2083-ternary
327         // expected-warning@-1 {{expression result unused}}
328         // expected-error@#cwg2083-ternary {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} FIXME
329         //   expected-note@#cwg2083-a-3 {{'a' declared here}}
330         // expected-error@#cwg2083-ternary {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} FIXME
331         //   expected-note@#cwg2083-a-3 {{'a' declared here}}
332         (void)a.x;
333         // expected-error@-1 {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} FIXME
334         //   expected-note@#cwg2083-a-3 {{'a' declared here}}
335         a.x, discarded_lval();
336         // expected-warning@-1 {{left operand of comma operator has no effect}}
337         // expected-error@-2 {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}} FIXME
338         //   expected-note@#cwg2083-a-3 {{'a' declared here}}
339 
340         // 'volatile' qualifier triggers an lvalue-to-rvalue conversion.
341         a.z;
342         // cxx98-warning@-1 {{expression result unused; assign into a variable to force a volatile load}}
343         // expected-error@-2 {{reference to local variable 'a' declared in enclosing function 'cwg2083::discarded_lval'}}
344         //   expected-note@#cwg2083-a-3 {{'a' declared here}}
345 
346         // References always get "loaded" to determine what they reference,
347         // even if the result is discarded.
348         r;
349         // expected-warning@-1 {{expression result unused}}
350         // expected-error@-2 {{reference to local variable 'r' declared in enclosing function 'cwg2083::discarded_lval'}}
351         //   expected-note@#cwg2083-r {{'r' declared here}}
352       }
353     };
354   }
355 
356   namespace dr_example_1 {
357     extern int globx;
358     int main() {
359       const int &x = globx; // #cwg2083-x
360       struct A {
361         const int *foo() { return &x; }
362         // cxx98-error@-1 {{reference to local variable 'x' declared in enclosing function 'cwg2083::dr_example_1::main'}}
363         //   cxx98-note@#cwg2083-x {{'x' declared here}}
364       } a;
365       return *a.foo();
366     }
367   }
368 
369 #if __cplusplus >= 201103L
370   namespace dr_example_2 {
371     struct A {
372       int q;
373       constexpr A(int q) : q(q) {}
374       constexpr A(const A &a) : q(a.q * 2) {} // (note, not called)
375     };
376 
377     int main(void) {
378       constexpr A a(42);
379       constexpr int aq = a.q;
380       struct Q {
381         int foo() { return a.q; }
382       } q;
383       return q.foo();
384     }
385 
386     // Checking odr-use does not invent an lvalue-to-rvalue conversion (and
387     // hence copy construction) on the potential result variable.
388     struct B {
389       int b = 42;
390       constexpr B() {}
391       constexpr B(const B&) = delete;
392     };
393     void f() {
394       constexpr B b;
395       struct Q {
396         constexpr int foo() const { return b.b; }
397       };
398       static_assert(Q().foo() == 42, "");
399     }
400   }
401 #endif
402 } // namespace cwg2083
403 
404 namespace cwg2091 { // cwg2091: 10
405 template<int &> struct X;
406 template<int &N> void f(X<N>&);
407 int n;
408 void g(X<n> &x) { f(x); }
409 
410 namespace GH42233 {
411 enum E { I };
412 
413 class AA { };
414 E EV[1] = {I};
415 
416 template<class ENUM, const ENUM* const VALUES>
417 struct S
418 {
419   template< class E, const E* const V>
420     friend AA& operator<<( AA& os, const S<E,V>& e );
421 };
422 
423 int f()
424 {
425   S< E, EV > x;
426 
427   AA a;
428   a << x;
429   return 0;
430 }
431 } // namespace GH42233
432 } // namespace cwg2091
433 
434 namespace cwg2094 { // cwg2094: 5
435   struct A { int n; };
436   struct B { volatile int n; };
437   static_assert(__is_trivially_copyable(volatile int), "");
438   static_assert(__is_trivially_copyable(const volatile int), "");
439   static_assert(__is_trivially_copyable(const volatile int[]), "");
440   static_assert(__is_trivially_copyable(A), "");
441   static_assert(__is_trivially_copyable(volatile A), "");
442   static_assert(__is_trivially_copyable(const volatile A), "");
443   static_assert(__is_trivially_copyable(const volatile A[]), "");
444   static_assert(__is_trivially_copyable(B), "");
445 
446   static_assert(__is_trivially_constructible(A, A const&), "");
447   static_assert(__is_trivially_constructible(B, B const&), "");
448 
449   static_assert(__is_trivially_assignable(A, const A&), "");
450   static_assert(__is_trivially_assignable(B, const B&), "");
451 } // namespace cwg2094
452 
453 // cwg2096: dup 2598
454