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++2a -triple x86_64-unknown-unknown %s -verify -fexceptions -fcxx-exceptions -pedantic-errors 7 8 #if __cplusplus < 201103L 9 #define static_assert(...) _Static_assert(__VA_ARGS__) 10 #endif 11 12 namespace dr2026 { // dr2026: 11 13 template<int> struct X {}; 14 15 const int a = a + 1; // expected-warning {{uninitialized}} expected-note {{here}} expected-note 0-1{{outside its lifetime}} 16 X<a> xa; // expected-error {{constant expression}} expected-note {{initializer of 'a'}} 17 18 #if __cplusplus >= 201103L 19 constexpr int b = b; // expected-error {{constant expression}} expected-note {{outside its lifetime}} 20 [[clang::require_constant_initialization]] int c = c; // expected-error {{constant initializer}} expected-note {{attribute}} 21 #if __cplusplus == 201103L 22 // expected-note@-2 {{read of non-const variable}} expected-note@-2 {{declared here}} 23 #else 24 // expected-note@-4 {{outside its lifetime}} 25 #endif 26 #endif 27 28 #if __cplusplus > 201703L 29 constinit int d = d; // expected-error {{constant initializer}} expected-note {{outside its lifetime}} expected-note {{'constinit'}} 30 #endif 31 f()32 void f() { 33 static const int e = e + 1; // expected-warning {{suspicious}} expected-note {{here}} expected-note 0-1{{outside its lifetime}} 34 X<e> xe; // expected-error {{constant expression}} expected-note {{initializer of 'e'}} 35 36 #if __cplusplus >= 201103L 37 static constexpr int f = f; // expected-error {{constant expression}} expected-note {{outside its lifetime}} 38 [[clang::require_constant_initialization]] static int g = g; // expected-error {{constant initializer}} expected-note {{attribute}} 39 #if __cplusplus == 201103L 40 // expected-note@-2 {{read of non-const variable}} expected-note@-2 {{declared here}} 41 #else 42 // expected-note@-4 {{outside its lifetime}} 43 #endif 44 #endif 45 46 #if __cplusplus > 201703L 47 static constinit int h = h; // expected-error {{constant initializer}} expected-note {{outside its lifetime}} expected-note {{'constinit'}} 48 #endif 49 } 50 } 51 52 namespace dr2082 { // dr2082: 11 53 void test1(int x, int = sizeof(x)); // ok 54 #if __cplusplus >= 201103L 55 void test2(int x, int = decltype(x){}); // ok 56 #endif 57 } 58 59 namespace dr2083 { // dr2083: partial 60 #if __cplusplus >= 201103L non_const_mem_ptr()61 void non_const_mem_ptr() { 62 struct A { 63 int x; 64 int y; 65 }; 66 constexpr A a = {1, 2}; 67 struct B { 68 int A::*p; 69 constexpr int g() const { 70 // OK, not an odr-use of 'a'. 71 return a.*p; 72 }; 73 }; 74 static_assert(B{&A::x}.g() == 1, ""); 75 static_assert(B{&A::y}.g() == 2, ""); 76 } 77 #endif 78 79 const int a = 1; 80 int b; 81 // Note, references only get special odr-use / constant initializxer 82 // treatment in C++11 onwards. We continue to apply that even after DR2083. ref_to_non_const()83 void ref_to_non_const() { 84 int c; 85 const int &ra = a; // expected-note 0-1{{here}} 86 int &rb = b; // expected-note 0-1{{here}} 87 int &rc = c; // expected-note {{here}} 88 struct A { 89 int f() { 90 int a = ra; 91 int b = rb; 92 #if __cplusplus < 201103L 93 // expected-error@-3 {{in enclosing function}} 94 // expected-error@-3 {{in enclosing function}} 95 #endif 96 int c = rc; // expected-error {{in enclosing function}} 97 return a + b + c; 98 } 99 }; 100 } 101 102 #if __cplusplus >= 201103L 103 struct NoMut1 { int a, b; }; 104 struct NoMut2 { NoMut1 m; }; 105 struct NoMut3 : NoMut1 { NoMut3dr2083::NoMut3106 constexpr NoMut3(int a, int b) : NoMut1{a, b} {} 107 }; 108 struct Mut1 { 109 int a; 110 mutable int b; 111 }; 112 struct Mut2 { Mut1 m; }; 113 struct Mut3 : Mut1 { Mut3dr2083::Mut3114 constexpr Mut3(int a, int b) : Mut1{a, b} {} 115 }; mutable_subobjects()116 void mutable_subobjects() { 117 constexpr NoMut1 nm1 = {1, 2}; 118 constexpr NoMut2 nm2 = {1, 2}; 119 constexpr NoMut3 nm3 = {1, 2}; 120 constexpr Mut1 m1 = {1, 2}; // expected-note {{declared here}} 121 constexpr Mut2 m2 = {1, 2}; // expected-note {{declared here}} 122 constexpr Mut3 m3 = {1, 2}; // expected-note {{declared here}} 123 struct A { 124 void f() { 125 static_assert(nm1.a == 1, ""); 126 static_assert(nm2.m.a == 1, ""); 127 static_assert(nm3.a == 1, ""); 128 // Can't even access a non-mutable member of a variable containing mutable fields. 129 static_assert(m1.a == 1, ""); // expected-error {{enclosing function}} 130 static_assert(m2.m.a == 1, ""); // expected-error {{enclosing function}} 131 static_assert(m3.a == 1, ""); // expected-error {{enclosing function}} 132 } 133 }; 134 } 135 #endif 136 ellipsis()137 void ellipsis() { 138 void ellipsis(...); 139 struct A {}; 140 const int n = 0; 141 #if __cplusplus >= 201103L 142 constexpr 143 #endif 144 A a = {}; // expected-note {{here}} 145 struct B { 146 void f() { 147 ellipsis(n); 148 // Even though this is technically modelled as an lvalue-to-rvalue 149 // conversion, it calls a constructor and binds 'a' to a reference, so 150 // it results in an odr-use. 151 ellipsis(a); // expected-error {{enclosing function}} 152 } 153 }; 154 } 155 156 #if __cplusplus >= 201103L volatile_lval()157 void volatile_lval() { 158 struct A { int n; }; 159 constexpr A a = {0}; // expected-note {{here}} 160 struct B { 161 void f() { 162 // An lvalue-to-rvalue conversion of a volatile lvalue always results 163 // in odr-use. 164 int A::*p = &A::n; 165 int x = a.*p; 166 volatile int A::*q = p; 167 int y = a.*q; // expected-error {{enclosing function}} 168 } 169 }; 170 } 171 #endif 172 discarded_lval()173 void discarded_lval() { 174 struct A { int x; mutable int y; volatile int z; }; 175 A a; // expected-note 1+{{here}} 176 int &r = a.x; // expected-note {{here}} 177 struct B { 178 void f() { 179 a.x; // expected-warning {{unused}} 180 a.*&A::x; // expected-warning {{unused}} 181 true ? a.x : a.y; // expected-warning {{unused}} 182 (void)a.x; 183 a.x, discarded_lval(); // expected-warning {{unused}} 184 #if 1 // FIXME: These errors are all incorrect; the above code is valid. 185 // expected-error@-6 {{enclosing function}} 186 // expected-error@-6 {{enclosing function}} 187 // expected-error@-6 2{{enclosing function}} 188 // expected-error@-6 {{enclosing function}} 189 // expected-error@-6 {{enclosing function}} 190 #endif 191 192 // 'volatile' qualifier triggers an lvalue-to-rvalue conversion. 193 a.z; // expected-error {{enclosing function}} 194 #if __cplusplus < 201103L 195 // expected-warning@-2 {{assign into a variable}} 196 #endif 197 198 // References always get "loaded" to determine what they reference, 199 // even if the result is discarded. 200 r; // expected-error {{enclosing function}} expected-warning {{unused}} 201 } 202 }; 203 } 204 205 namespace dr_example_1 { 206 extern int globx; main()207 int main() { 208 const int &x = globx; 209 struct A { 210 #if __cplusplus < 201103L 211 // expected-error@+2 {{enclosing function}} expected-note@-3 {{here}} 212 #endif 213 const int *foo() { return &x; } 214 } a; 215 return *a.foo(); 216 } 217 } 218 219 #if __cplusplus >= 201103L 220 namespace dr_example_2 { 221 struct A { 222 int q; Adr2083::dr_example_2::A223 constexpr A(int q) : q(q) {} Adr2083::dr_example_2::A224 constexpr A(const A &a) : q(a.q * 2) {} // (note, not called) 225 }; 226 main(void)227 int main(void) { 228 constexpr A a(42); 229 constexpr int aq = a.q; 230 struct Q { 231 int foo() { return a.q; } 232 } q; 233 return q.foo(); 234 } 235 236 // Checking odr-use does not invent an lvalue-to-rvalue conversion (and 237 // hence copy construction) on the potential result variable. 238 struct B { 239 int b = 42; Bdr2083::dr_example_2::B240 constexpr B() {} 241 constexpr B(const B&) = delete; 242 }; f()243 void f() { 244 constexpr B b; 245 struct Q { 246 constexpr int foo() const { return b.b; } 247 }; 248 static_assert(Q().foo() == 42, ""); 249 } 250 } 251 #endif 252 } 253 254 namespace dr2094 { // dr2094: 5 255 struct A { int n; }; 256 struct B { volatile int n; }; 257 static_assert(__is_trivially_copyable(volatile int), ""); 258 static_assert(__is_trivially_copyable(const volatile int), ""); 259 static_assert(__is_trivially_copyable(const volatile int[]), ""); 260 static_assert(__is_trivially_copyable(A), ""); 261 static_assert(__is_trivially_copyable(volatile A), ""); 262 static_assert(__is_trivially_copyable(const volatile A), ""); 263 static_assert(__is_trivially_copyable(const volatile A[]), ""); 264 static_assert(__is_trivially_copyable(B), ""); 265 266 static_assert(__is_trivially_constructible(A, A const&), ""); 267 static_assert(__is_trivially_constructible(B, B const&), ""); 268 269 static_assert(__is_trivially_assignable(A, const A&), ""); 270 static_assert(__is_trivially_assignable(B, const B&), ""); 271 } 272