Run DCE after a LoopFlatten test to reduce spurious output [nfc]
[llvm-project.git] / clang / test / CXX / drs / dr20xx.cpp
blobdd60af14bb6b71dfaee5ae74162e1b419dd97b73
1 // RUN: %clang_cc1 -std=c++98 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors \
2 // RUN: -Wno-variadic-macros -Wno-c11-extensions
3 // RUN: %clang_cc1 -std=c++11 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
4 // RUN: %clang_cc1 -std=c++14 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
5 // RUN: %clang_cc1 -std=c++17 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
6 // RUN: %clang_cc1 -std=c++20 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
7 // RUN: %clang_cc1 -std=c++23 -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors
9 #if __cplusplus < 201103L
10 #define static_assert(...) _Static_assert(__VA_ARGS__)
11 #endif
13 namespace dr2007 { // dr2007: 3.4
14 template<typename T> struct A { typename T::error e; };
15 template<typename T> struct B { };
16 B<A<void> > b1;
17 B<A<void> > b2 = b1;
18 int a = b2[0]; // expected-error {{does not provide a subscript operator}}
19 int b = __builtin_addressof(b2)->foo; // expected-error {{no member}}
22 // dr2009: na
24 namespace dr2026 { // dr2026: 11
25 template<int> struct X {};
27 const int a = a + 1; // expected-warning {{uninitialized}} expected-note {{here}} expected-note 0-1{{outside its lifetime}}
28 X<a> xa; // expected-error {{constant expression}} expected-note {{initializer of 'a'}}
30 #if __cplusplus >= 201103L
31 constexpr int b = b; // expected-error {{constant expression}} expected-note {{outside its lifetime}}
32 [[clang::require_constant_initialization]] int c = c; // expected-error {{constant initializer}} expected-note {{attribute}}
33 #if __cplusplus == 201103L
34 // expected-note@-2 {{read of non-const variable}} expected-note@-2 {{declared here}}
35 #else
36 // expected-note@-4 {{outside its lifetime}}
37 #endif
38 #endif
40 #if __cplusplus > 201703L
41 constinit int d = d; // expected-error {{constant initializer}} expected-note {{outside its lifetime}} expected-note {{'constinit'}}
42 #endif
44 void f() {
45 static const int e = e + 1; // expected-warning {{suspicious}} expected-note {{here}} expected-note 0-1{{outside its lifetime}}
46 X<e> xe; // expected-error {{constant expression}} expected-note {{initializer of 'e'}}
48 #if __cplusplus >= 201103L
49 static constexpr int f = f; // expected-error {{constant expression}} expected-note {{outside its lifetime}}
50 [[clang::require_constant_initialization]] static int g = g; // expected-error {{constant initializer}} expected-note {{attribute}}
51 #if __cplusplus == 201103L
52 // expected-note@-2 {{read of non-const variable}} expected-note@-2 {{declared here}}
53 #else
54 // expected-note@-4 {{outside its lifetime}}
55 #endif
56 #endif
58 #if __cplusplus > 201703L
59 static constinit int h = h; // expected-error {{constant initializer}} expected-note {{outside its lifetime}} expected-note {{'constinit'}}
60 #endif
64 namespace dr2061 { // dr2061: yes
65 #if __cplusplus >= 201103L
66 namespace A {
67 inline namespace b {
68 namespace C {
69 // 'f' is the example from the DR. 'S' is an example where if we didn't
70 // properly handle the two being the same, we would get an incomplete
71 // type error during attempted instantiation.
72 template<typename T> void f();
73 template<typename T> struct S;
78 namespace A {
79 namespace C {
80 template<> void f<int>() { }
81 template<> struct S<int> { };
85 void use() {
86 A::C::f<int>();
87 A::C::S<int> s;
89 #endif // C++11
92 namespace dr2076 { // dr2076: 13
93 #if __cplusplus >= 201103L
94 namespace std_example {
95 struct A { A(int); };
96 struct B { B(A); };
97 B b{{0}};
99 struct Params { int a; int b; };
100 struct Foo {
101 Foo(Params);
103 Foo foo{{1, 2}};
106 struct string_view {
107 string_view(int); // not an aggregate
109 struct string {
110 string(int); // not an aggregate
111 operator string_view() const;
114 void foo(const string &); // expected-note {{cannot convert initializer list}}
115 void bar(string_view); // expected-note 2{{cannot convert initializer list}}
117 void func(const string &arg) {
118 // An argument in one set of braces is subject to user-defined conversions;
119 // an argument in two sets of braces is not, but an identity conversion is
120 // still OK.
121 foo(arg);
122 foo({arg});
123 foo({{arg}});
124 foo({{{arg}}}); // expected-error {{no matching function}}
125 bar(arg);
126 bar({arg});
127 bar({{arg}}); // expected-error {{no matching function}}
128 bar({{{arg}}}); // expected-error {{no matching function}}
130 #endif
133 namespace dr2082 { // dr2082: 11
134 void test1(int x, int = sizeof(x)); // ok
135 #if __cplusplus >= 201103L
136 void test2(int x, int = decltype(x){}); // ok
137 #endif
140 namespace dr2083 { // dr2083: partial
141 #if __cplusplus >= 201103L
142 void non_const_mem_ptr() {
143 struct A {
144 int x;
145 int y;
147 constexpr A a = {1, 2};
148 struct B {
149 int A::*p;
150 constexpr int g() const {
151 // OK, not an odr-use of 'a'.
152 return a.*p;
155 static_assert(B{&A::x}.g() == 1, "");
156 static_assert(B{&A::y}.g() == 2, "");
158 #endif
160 const int a = 1;
161 int b;
162 // Note, references only get special odr-use / constant initializxer
163 // treatment in C++11 onwards. We continue to apply that even after DR2083.
164 void ref_to_non_const() {
165 int c;
166 const int &ra = a; // expected-note 0-1{{here}}
167 int &rb = b; // expected-note 0-1{{here}}
168 int &rc = c; // expected-note {{here}}
169 struct A {
170 int f() {
171 int a = ra;
172 int b = rb;
173 #if __cplusplus < 201103L
174 // expected-error@-3 {{in enclosing function}}
175 // expected-error@-3 {{in enclosing function}}
176 #endif
177 int c = rc; // expected-error {{in enclosing function}}
178 return a + b + c;
183 #if __cplusplus >= 201103L
184 struct NoMut1 { int a, b; };
185 struct NoMut2 { NoMut1 m; };
186 struct NoMut3 : NoMut1 {
187 constexpr NoMut3(int a, int b) : NoMut1{a, b} {}
189 struct Mut1 {
190 int a;
191 mutable int b;
193 struct Mut2 { Mut1 m; };
194 struct Mut3 : Mut1 {
195 constexpr Mut3(int a, int b) : Mut1{a, b} {}
197 void mutable_subobjects() {
198 constexpr NoMut1 nm1 = {1, 2};
199 constexpr NoMut2 nm2 = {1, 2};
200 constexpr NoMut3 nm3 = {1, 2};
201 constexpr Mut1 m1 = {1, 2}; // expected-note {{declared here}}
202 constexpr Mut2 m2 = {1, 2}; // expected-note {{declared here}}
203 constexpr Mut3 m3 = {1, 2}; // expected-note {{declared here}}
204 struct A {
205 void f() {
206 static_assert(nm1.a == 1, "");
207 static_assert(nm2.m.a == 1, "");
208 static_assert(nm3.a == 1, "");
209 // Can't even access a non-mutable member of a variable containing mutable fields.
210 static_assert(m1.a == 1, ""); // expected-error {{enclosing function}}
211 static_assert(m2.m.a == 1, ""); // expected-error {{enclosing function}}
212 static_assert(m3.a == 1, ""); // expected-error {{enclosing function}}
216 #endif
218 void ellipsis() {
219 void ellipsis(...);
220 struct A {};
221 const int n = 0;
222 #if __cplusplus >= 201103L
223 constexpr
224 #endif
225 A a = {}; // expected-note {{here}}
226 struct B {
227 void f() {
228 ellipsis(n);
229 // Even though this is technically modelled as an lvalue-to-rvalue
230 // conversion, it calls a constructor and binds 'a' to a reference, so
231 // it results in an odr-use.
232 ellipsis(a); // expected-error {{enclosing function}}
237 #if __cplusplus >= 201103L
238 void volatile_lval() {
239 struct A { int n; };
240 constexpr A a = {0}; // expected-note {{here}}
241 struct B {
242 void f() {
243 // An lvalue-to-rvalue conversion of a volatile lvalue always results
244 // in odr-use.
245 int A::*p = &A::n;
246 int x = a.*p;
247 volatile int A::*q = p;
248 int y = a.*q; // expected-error {{enclosing function}}
252 #endif
254 void discarded_lval() {
255 struct A { int x; mutable int y; volatile int z; };
256 A a; // expected-note 1+{{here}}
257 int &r = a.x; // expected-note {{here}}
258 struct B {
259 void f() {
260 a.x; // expected-warning {{unused}}
261 a.*&A::x; // expected-warning {{unused}}
262 true ? a.x : a.y; // expected-warning {{unused}}
263 (void)a.x;
264 a.x, discarded_lval(); // expected-warning {{left operand of comma operator has no effect}}
265 #if 1 // FIXME: These errors are all incorrect; the above code is valid.
266 // expected-error@-6 {{enclosing function}}
267 // expected-error@-6 {{enclosing function}}
268 // expected-error@-6 2{{enclosing function}}
269 // expected-error@-6 {{enclosing function}}
270 // expected-error@-6 {{enclosing function}}
271 #endif
273 // 'volatile' qualifier triggers an lvalue-to-rvalue conversion.
274 a.z; // expected-error {{enclosing function}}
275 #if __cplusplus < 201103L
276 // expected-warning@-2 {{assign into a variable}}
277 #endif
279 // References always get "loaded" to determine what they reference,
280 // even if the result is discarded.
281 r; // expected-error {{enclosing function}} expected-warning {{unused}}
286 namespace dr_example_1 {
287 extern int globx;
288 int main() {
289 const int &x = globx;
290 struct A {
291 #if __cplusplus < 201103L
292 // expected-error@+2 {{enclosing function}} expected-note@-3 {{here}}
293 #endif
294 const int *foo() { return &x; }
295 } a;
296 return *a.foo();
300 #if __cplusplus >= 201103L
301 namespace dr_example_2 {
302 struct A {
303 int q;
304 constexpr A(int q) : q(q) {}
305 constexpr A(const A &a) : q(a.q * 2) {} // (note, not called)
308 int main(void) {
309 constexpr A a(42);
310 constexpr int aq = a.q;
311 struct Q {
312 int foo() { return a.q; }
313 } q;
314 return q.foo();
317 // Checking odr-use does not invent an lvalue-to-rvalue conversion (and
318 // hence copy construction) on the potential result variable.
319 struct B {
320 int b = 42;
321 constexpr B() {}
322 constexpr B(const B&) = delete;
324 void f() {
325 constexpr B b;
326 struct Q {
327 constexpr int foo() const { return b.b; }
329 static_assert(Q().foo() == 42, "");
332 #endif
335 namespace dr2094 { // dr2094: 5
336 struct A { int n; };
337 struct B { volatile int n; };
338 static_assert(__is_trivially_copyable(volatile int), "");
339 static_assert(__is_trivially_copyable(const volatile int), "");
340 static_assert(__is_trivially_copyable(const volatile int[]), "");
341 static_assert(__is_trivially_copyable(A), "");
342 static_assert(__is_trivially_copyable(volatile A), "");
343 static_assert(__is_trivially_copyable(const volatile A), "");
344 static_assert(__is_trivially_copyable(const volatile A[]), "");
345 static_assert(__is_trivially_copyable(B), "");
347 static_assert(__is_trivially_constructible(A, A const&), "");
348 static_assert(__is_trivially_constructible(B, B const&), "");
350 static_assert(__is_trivially_assignable(A, const A&), "");
351 static_assert(__is_trivially_assignable(B, const B&), "");