1 // UNSUPPORTED: target={{.*}}-zos{{.*}} 2 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=ref,ref20,all,all20 %s 3 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=ref,ref23,all,all23 %s 4 // RUN: %clang_cc1 -std=c++20 -fsyntax-only -fcxx-exceptions -verify=expected20,all,all20 %s -fexperimental-new-constant-interpreter 5 // RUN: %clang_cc1 -std=c++23 -fsyntax-only -fcxx-exceptions -verify=expected23,all,all23 %s -fexperimental-new-constant-interpreter 6 7 constexpr int f(int n) { // all20-error {{constexpr function never produces a constant expression}} 8 static const int m = n; // all-note {{control flows through the definition of a static variable}} \ 9 // all20-note {{control flows through the definition of a static variable}} \ 10 // all20-warning {{is a C++23 extension}} 11 12 return m; 13 } 14 static_assert(f(0) == 0, ""); // all-error {{not an integral constant expression}} \ 15 // all-note {{in call to}} 16 17 constexpr int g(int n) { // all20-error {{constexpr function never produces a constant expression}} 18 thread_local const int m = n; // all-note {{control flows through the definition of a thread_local variable}} \ 19 // all20-note {{control flows through the definition of a thread_local variable}} \ 20 // all20-warning {{is a C++23 extension}} 21 return m; 22 } 23 static_assert(g(0) == 0, ""); // all-error {{not an integral constant expression}} \ 24 // all-note {{in call to}} 25 26 constexpr int c_thread_local(int n) { // all20-error {{constexpr function never produces a constant expression}} 27 static _Thread_local int m = 0; // all20-note 2{{control flows through the definition of a thread_local variable}} \ 28 // all23-note {{control flows through the definition of a thread_local variable}} \ 29 // all20-warning {{is a C++23 extension}} 30 return m; 31 } 32 static_assert(c_thread_local(0) == 0, ""); // all-error {{not an integral constant expression}} \ 33 // all-note {{in call to}} 34 35 36 constexpr int gnu_thread_local(int n) { // all20-error {{constexpr function never produces a constant expression}} 37 static __thread int m = 0; // all20-note 2{{control flows through the definition of a thread_local variable}} \ 38 // all23-note {{control flows through the definition of a thread_local variable}} \ 39 // all20-warning {{is a C++23 extension}} 40 return m; 41 } 42 static_assert(gnu_thread_local(0) == 0, ""); // all-error {{not an integral constant expression}} \ 43 // all-note {{in call to}} 44 45 constexpr int h(int n) { // all20-error {{constexpr function never produces a constant expression}} 46 static const int m = n; // all20-note {{control flows through the definition of a static variable}} \ 47 // all20-warning {{is a C++23 extension}} 48 return &m - &m; 49 } 50 51 constexpr int i(int n) { // all20-error {{constexpr function never produces a constant expression}} 52 thread_local const int m = n; // all20-note {{control flows through the definition of a thread_local variable}} \ 53 // all20-warning {{is a C++23 extension}} 54 return &m - &m; 55 } 56 57 constexpr int j(int n) { 58 if (!n) 59 return 0; 60 static const int m = n; // ref20-warning {{is a C++23 extension}} \ 61 // expected20-warning {{is a C++23 extension}} 62 return m; 63 } 64 constexpr int j0 = j(0); 65 66 constexpr int k(int n) { 67 if (!n) 68 return 0; 69 thread_local const int m = n; // ref20-warning {{is a C++23 extension}} \ 70 // expected20-warning {{is a C++23 extension}} 71 72 return m; 73 } 74 constexpr int k0 = k(0); 75 76 namespace StaticLambdas { 77 constexpr auto static_capture_constexpr() { 78 char n = 'n'; 79 return [n] static { return n; }(); // expected23-error {{a static lambda cannot have any captures}} \ 80 // expected20-error {{a static lambda cannot have any captures}} \ 81 // expected20-warning {{are a C++23 extension}} \ 82 // expected20-warning {{is a C++23 extension}} \ 83 // ref23-error {{a static lambda cannot have any captures}} \ 84 // ref20-error {{a static lambda cannot have any captures}} \ 85 // ref20-warning {{are a C++23 extension}} \ 86 // ref20-warning {{is a C++23 extension}} 87 } 88 static_assert(static_capture_constexpr()); // expected23-error {{static assertion expression is not an integral constant expression}} \ 89 // expected20-error {{static assertion expression is not an integral constant expression}} \ 90 // ref23-error {{static assertion expression is not an integral constant expression}} \ 91 // ref20-error {{static assertion expression is not an integral constant expression}} 92 93 constexpr auto capture_constexpr() { 94 char n = 'n'; 95 return [n] { return n; }(); 96 } 97 static_assert(capture_constexpr()); 98 } 99 100 namespace StaticOperators { 101 auto lstatic = []() static { return 3; }; // ref20-warning {{C++23 extension}} \ 102 // expected20-warning {{C++23 extension}} 103 static_assert(lstatic() == 3, ""); 104 constexpr int (*f2)(void) = lstatic; 105 static_assert(f2() == 3); 106 107 struct S1 { 108 constexpr S1() { // all20-error {{never produces a constant expression}} 109 throw; // all-note {{not valid in a constant expression}} \ 110 // all20-note {{not valid in a constant expression}} 111 } 112 static constexpr int operator()() { return 3; } // ref20-warning {{C++23 extension}} \ 113 // expected20-warning {{C++23 extension}} 114 }; 115 static_assert(S1{}() == 3, ""); // all-error {{not an integral constant expression}} \ 116 // all-note {{in call to}} 117 118 119 120 } 121 122 int test_in_lambdas() { 123 auto c = [](int n) constexpr { 124 if (n == 0) 125 return 0; 126 else 127 goto test; // all-note {{subexpression not valid in a constant expression}} \ 128 // all20-warning {{use of this statement in a constexpr function is a C++23 extension}} 129 test: 130 return 1; 131 }; 132 c(0); 133 constexpr auto A = c(1); // all-error {{must be initialized by a constant expression}} \ 134 // all-note {{in call to}} 135 return 0; 136 } 137 138 /// PackIndexExpr. 139 template <auto... p> 140 struct check_ice { 141 enum e { 142 x = p...[0] // all-warning {{is a C++2c extension}} 143 }; 144 }; 145 static_assert(check_ice<42>::x == 42); 146 147 148 namespace VirtualBases { 149 namespace One { 150 struct U { int n; }; 151 struct V : U { int n; }; 152 struct A : virtual V { int n; }; 153 struct Aa { int n; }; 154 struct B : virtual A, Aa {}; 155 struct C : virtual A, Aa {}; 156 struct D : B, C {}; 157 158 /// Calls the constructor of D. 159 D d; 160 } 161 162 #if __cplusplus >= 202302L 163 struct VBase {}; 164 struct HasVBase : virtual VBase {}; // all23-note 1{{virtual base class declared here}} 165 struct Derived : HasVBase { 166 constexpr Derived() {} // all23-error {{constexpr constructor not allowed in struct with virtual base class}} 167 }; 168 template<typename T> struct DerivedFromVBase : T { 169 constexpr DerivedFromVBase(); 170 }; 171 constexpr int f(DerivedFromVBase<HasVBase>) {} 172 template<typename T> constexpr DerivedFromVBase<T>::DerivedFromVBase() : T() {} 173 constexpr int nVBase = (DerivedFromVBase<HasVBase>(), 0); // all23-error {{constant expression}} \ 174 // all23-note {{cannot construct object of type 'DerivedFromVBase<VirtualBases::HasVBase>' with virtual base class in a constant expression}} 175 #endif 176 } 177 178 namespace LabelGoto { 179 constexpr int foo() { // all20-error {{never produces a constant expression}} 180 a: // all20-warning {{use of this statement in a constexpr function is a C++23 extension}} 181 goto a; // all20-note 2{{subexpression not valid in a constant expression}} \ 182 // ref23-note {{subexpression not valid in a constant expression}} \ 183 // expected23-note {{subexpression not valid in a constant expression}} 184 185 return 1; 186 } 187 static_assert(foo() == 1, ""); // all-error {{not an integral constant expression}} \ 188 // all-note {{in call to}} 189 } 190 191 namespace ExplicitLambdaThis { 192 constexpr auto f = [x = 3]<typename Self>(this Self self) { // all20-error {{explicit object parameters are incompatible with C++ standards before C++2b}} 193 return x; 194 }; 195 static_assert(f()); 196 } 197 198 namespace std { 199 struct strong_ordering { 200 int n; 201 constexpr operator int() const { return n; } 202 static const strong_ordering less, equal, greater; 203 }; 204 constexpr strong_ordering strong_ordering::less = {-1}; 205 constexpr strong_ordering strong_ordering::equal = {0}; 206 constexpr strong_ordering strong_ordering::greater = {1}; 207 } 208 209 namespace UndefinedThreeWay { 210 struct A { 211 friend constexpr std::strong_ordering operator<=>(const A&, const A&) = default; // all-note {{declared here}} 212 }; 213 214 constexpr std::strong_ordering operator<=>(const A&, const A&) noexcept; 215 constexpr std::strong_ordering (*test_a_threeway)(const A&, const A&) = &operator<=>; 216 static_assert(!(*test_a_threeway)(A(), A())); // all-error {{static assertion expression is not an integral constant expression}} \ 217 // all-note {{undefined function 'operator<=>' cannot be used in a constant expression}} 218 } 219 220 /// FIXME: The new interpreter is missing the "initializer of q is not a constant expression" diagnostics.a 221 /// That's because the cast from void* to int* is considered fine, but diagnosed. So we don't consider 222 /// q to be uninitialized. 223 namespace VoidCast { 224 constexpr void* p = nullptr; 225 constexpr int* q = static_cast<int*>(p); // all-error {{must be initialized by a constant expression}} \ 226 // all-note {{cast from 'void *' is not allowed in a constant expression}} \ 227 // ref-note {{declared here}} 228 static_assert(q == nullptr); // ref-error {{not an integral constant expression}} \ 229 // ref-note {{initializer of 'q' is not a constant expression}} 230 } 231 232 namespace ExplicitLambdaInstancePointer { 233 struct C { 234 constexpr C(auto) { } 235 }; 236 void foo() { 237 constexpr auto b = [](this C) { return 1; }; // all20-error {{explicit object parameters are incompatible with C++ standards before C++2b}} 238 constexpr int (*fp)(C) = b; 239 static_assert(fp(1) == 1, ""); 240 } 241 } 242 243 namespace TwosComplementShifts { 244 using uint32 = __UINT32_TYPE__; 245 using int32 = __INT32_TYPE__; 246 static_assert(uint32(int32(0x1234) << 16) == 0x12340000); 247 static_assert(uint32(int32(0x1234) << 19) == 0x91a00000); 248 static_assert(uint32(int32(0x1234) << 20) == 0x23400000); 249 static_assert(uint32(int32(0x1234) << 24) == 0x34000000); 250 static_assert(uint32(int32(-1) << 31) == 0x80000000); 251 252 static_assert(-2 >> 1 == -1); 253 static_assert(-3 >> 1 == -2); 254 static_assert(-7 >> 1 == -4); 255 } 256 257 namespace AnonUnionDtor { 258 struct A { 259 A (); 260 ~A(); 261 }; 262 263 template <class T> 264 struct opt 265 { 266 union { 267 char c; 268 T data; 269 }; 270 271 constexpr opt() {} 272 273 constexpr ~opt() { 274 if (engaged) 275 data.~T(); 276 } 277 278 bool engaged = false; 279 }; 280 281 consteval void foo() { 282 opt<A> a; 283 } 284 285 void bar() { foo(); } 286 } 287 288 /// FIXME: The two interpreters disagree about there to diagnose the non-constexpr destructor call. 289 namespace NonLiteralDtorInParam { 290 class NonLiteral { // all20-note {{is not an aggregate and has no constexpr constructors other than copy or move constructors}} 291 public: 292 NonLiteral() {} 293 ~NonLiteral() {} // all23-note {{declared here}} 294 }; 295 constexpr int F2(NonLiteral N) { // all20-error {{constexpr function's 1st parameter type 'NonLiteral' is not a literal type}} \ 296 // ref23-note {{non-constexpr function '~NonLiteral' cannot be used in a constant expression}} 297 return 8; 298 } 299 300 301 void test() { 302 NonLiteral L; 303 constexpr auto D = F2(L); // all23-error {{must be initialized by a constant expression}} \ 304 // expected23-note {{non-constexpr function '~NonLiteral' cannot be used in a constant expression}} 305 } 306 } 307