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