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