422 lines · cpp
1// RUN: %clang_cc1 -triple x86_64-linux -verify=both,expected -std=c++11 %s -fexperimental-new-constant-interpreter2// RUN: %clang_cc1 -triple x86_64-linux -verify=both,ref -std=c++11 %s3 4namespace IntOrEnum {5 const int k = 0;6 const int &p = k;7 template<int n> struct S {};8 S<p> s;9}10 11const int cval = 2;12template <int> struct C{};13template struct C<cval>;14 15 16/// FIXME: This example does not get properly diagnosed in the new interpreter.17extern const int recurse1;18const int recurse2 = recurse1; // both-note {{here}}19const int recurse1 = 1;20int array1[recurse1];21int array2[recurse2]; // both-warning {{variable length arrays in C++}} \22 // both-note {{initializer of 'recurse2' is not a constant expression}} \23 // expected-error {{variable length array declaration not allowed at file scope}} \24 // ref-warning {{variable length array folded to constant array as an extension}}25 26constexpr int b = b; // both-error {{must be initialized by a constant expression}} \27 // both-note {{read of object outside its lifetime is not allowed in a constant expression}}28 29 30[[clang::require_constant_initialization]] int c = c; // both-error {{variable does not have a constant initializer}} \31 // both-note {{attribute here}} \32 // both-note {{read of non-const variable}} \33 // both-note {{declared here}}34 35 36struct S {37 int m;38};39constexpr S s = { 5 };40constexpr const int *p = &s.m + 1;41 42constexpr const int *np2 = &(*(int(*)[4])nullptr)[0]; // both-error {{constexpr variable 'np2' must be initialized by a constant expression}} \43 // both-note {{dereferencing a null pointer is not allowed in a constant expression}}44 45constexpr int preDec(int x) { // both-error {{never produces a constant expression}}46 return --x; // both-note {{subexpression}}47}48 49constexpr int postDec(int x) { // both-error {{never produces a constant expression}}50 return x--; // both-note {{subexpression}}51}52 53constexpr int preInc(int x) { // both-error {{never produces a constant expression}}54 return ++x; // both-note {{subexpression}}55}56 57constexpr int postInc(int x) { // both-error {{never produces a constant expression}}58 return x++; // both-note {{subexpression}}59}60 61 62namespace ReferenceToConst {63 template<int n> struct S; // both-note 1{{here}}64 struct LiteralType {65 constexpr LiteralType(int n) : n(n) {}66 int n;67 };68 template<int n> struct T {69 T() {70 static const int ki = 42;71 const int &i2 = ki;72 typename S<i2>::T check5; // both-error {{undefined template}}73 }74 };75}76 77 78 79namespace GH50055 {80// Enums without fixed underlying type81enum E1 {e11=-4, e12=4};82enum E2 {e21=0, e22=4};83enum E3 {e31=-4, e32=1024};84enum E4 {e41=0};85// Empty but as-if it had a single enumerator with value 086enum EEmpty {};87 88// Enum with fixed underlying type because the underlying type is explicitly specified89enum EFixed : int {efixed1=-4, efixed2=4};90// Enum with fixed underlying type because it is scoped91enum class EScoped {escoped1=-4, escoped2=4};92 93enum EMaxInt {emaxint1=-1, emaxint2=__INT_MAX__};94 95enum NumberType {};96 97E2 testDefaultArgForParam(E2 e2Param = (E2)-1) { // ok, not a constant expression context98 E2 e2LocalInit = e2Param; // ok, not a constant expression context99 return e2LocalInit;100}101 102// #include <enum-constexpr-conversion-system-header.h>103 104void testValueInRangeOfEnumerationValues() {105 constexpr E1 x1 = static_cast<E1>(-8);106 constexpr E1 x2 = static_cast<E1>(8);107 // both-error@-1 {{constexpr variable 'x2' must be initialized by a constant expression}}108 // both-note@-2 {{integer value 8 is outside the valid range of values [-8, 7] for the enumeration type 'E1'}}109 E1 x2b = static_cast<E1>(8); // ok, not a constant expression context110 111 constexpr E2 x3 = static_cast<E2>(-8);112 // both-error@-1 {{constexpr variable 'x3' must be initialized by a constant expression}}113 // both-note@-2 {{integer value -8 is outside the valid range of values [0, 7] for the enumeration type 'E2'}}114 constexpr E2 x4 = static_cast<E2>(0);115 constexpr E2 x5 = static_cast<E2>(8);116 // both-error@-1 {{constexpr variable 'x5' must be initialized by a constant expression}}117 // both-note@-2 {{integer value 8 is outside the valid range of values [0, 7] for the enumeration type 'E2'}}118 119 constexpr E3 x6 = static_cast<E3>(-2048);120 constexpr E3 x7 = static_cast<E3>(-8);121 constexpr E3 x8 = static_cast<E3>(0);122 constexpr E3 x9 = static_cast<E3>(8);123 constexpr E3 x10 = static_cast<E3>(2048);124 // both-error@-1 {{constexpr variable 'x10' must be initialized by a constant expression}}125 // both-note@-2 {{integer value 2048 is outside the valid range of values [-2048, 2047] for the enumeration type 'E3'}}126 127 constexpr E4 x11 = static_cast<E4>(0);128 constexpr E4 x12 = static_cast<E4>(1);129 constexpr E4 x13 = static_cast<E4>(2);130 // both-error@-1 {{constexpr variable 'x13' must be initialized by a constant expression}}131 // both-note@-2 {{integer value 2 is outside the valid range of values [0, 1] for the enumeration type 'E4'}}132 133 constexpr EEmpty x14 = static_cast<EEmpty>(0);134 constexpr EEmpty x15 = static_cast<EEmpty>(1);135 constexpr EEmpty x16 = static_cast<EEmpty>(2);136 // both-error@-1 {{constexpr variable 'x16' must be initialized by a constant expression}}137 // both-note@-2 {{integer value 2 is outside the valid range of values [0, 1] for the enumeration type 'EEmpty'}}138 139 constexpr EFixed x17 = static_cast<EFixed>(100);140 constexpr EScoped x18 = static_cast<EScoped>(100);141 142 constexpr EMaxInt x19 = static_cast<EMaxInt>(__INT_MAX__-1);143 constexpr EMaxInt x20 = static_cast<EMaxInt>((long)__INT_MAX__+1);144 // both-error@-1 {{constexpr variable 'x20' must be initialized by a constant expression}}145 // both-note@-2 {{integer value 2147483648 is outside the valid range of values [-2147483648, 2147483647] for the enumeration type 'EMaxInt'}}146 147 const NumberType neg_one = (NumberType) ((NumberType) 0 - (NumberType) 1); // ok, not a constant expression context148}149struct EnumTest {150 enum type {151 Type1,152 BOUND153 };154 static const type binding_completed = type(BOUND + 1); // both-error {{in-class initializer for static data member is not a constant expression}} \155 // both-note {{integer value 2 is outside the valid range of values}}156};157 158template<class T, unsigned size> struct Bitfield {159 static constexpr T max = static_cast<T>((1 << size) - 1);160 // both-error@-1 {{constexpr variable 'max' must be initialized by a constant expression}}161 // both-note@-2 {{integer value 15 is outside the valid range of values [0, 7] for the enumeration type 'E2'}}162};163 164void testValueInRangeOfEnumerationValuesViaTemplate() {165 Bitfield<E2, 3> good;166 Bitfield<E2, 4> bad; // both-note {{in instantiation}}167}168 169enum SortOrder {170 AscendingOrder,171 DescendingOrder172};173 174class A {175 static void f(SortOrder order);176};177 178void A::f(SortOrder order) {179 if (order == SortOrder(-1)) // ok, not a constant expression context180 return;181}182}183 184namespace FinalLtorDiags {185 template<int*> struct A {}; // both-note {{template parameter is declared here}}186 int k;187 int *q = &k; // both-note {{declared here}}188 A<q> c; // both-error {{non-type template argument of type 'int *' is not a constant expression}} \189 // both-note {{read of non-constexpr variable 'q' is not allowed in a constant expression}}190}191 192void lambdas() {193 int d;194 int a9[1] = {[d = 0] = 1}; // both-error {{not an integral constant expression}}195}196 197 198namespace InitLinkToRVO {199 struct A {200 int y = 3;201 int z = 1 + y;202 };203 204 constexpr A make() { return A {}; }205 static_assert(make().z == 4, "");206}207 208namespace DynamicCast {209 struct S { int x, y; } s;210 constexpr S* sptr = &s;211 struct Str {212 int b : reinterpret_cast<S*>(sptr) == reinterpret_cast<S*>(sptr);213 int g : (S*)(void*)(sptr) == sptr;214 };215}216 217namespace GlobalInitializer {218 extern int &g; // both-note {{here}}219 struct S {220 int G : g; // both-error {{constant expression}} \221 // both-note {{initializer of 'g' is unknown}}222 };223}224 225namespace ExternPointer {226 struct S { int a; };227 extern const S pu;228 constexpr const int *pua = &pu.a; // Ok.229}230 231namespace PseudoDtor {232 typedef int I;233 constexpr int f(int a = 1) { // both-error {{never produces a constant expression}} \234 // ref-note {{destroying object 'a' whose lifetime has already ended}}235 return (236 a.~I(), // both-note {{pseudo-destructor call is not permitted}} \237 // expected-note {{pseudo-destructor call is not permitted}}238 0);239 }240 static_assert(f() == 0, ""); // both-error {{constant expression}} \241 // expected-note {{in call to}}242}243 244namespace IntToPtrCast {245 typedef __INTPTR_TYPE__ intptr_t;246 247 constexpr intptr_t f(intptr_t x) {248 return (((x) >> 21) * 8);249 }250 251 extern "C" int foo;252 constexpr intptr_t i = f((intptr_t)&foo - 10); // both-error{{constexpr variable 'i' must be initialized by a constant expression}} \253 // both-note{{reinterpret_cast}}254}255 256namespace Volatile {257 constexpr int f(volatile int &&r) {258 return r; // both-note {{read of volatile-qualified type 'volatile int'}}259 }260 struct S {261 int j : f(0); // both-error {{constant expression}} \262 // both-note {{in call to 'f(0)'}}263 };264}265 266namespace ZeroSizeCmp {267 extern void (*start[])();268 extern void (*end[])();269 static_assert(&start != &end, ""); // both-error {{constant expression}} \270 // both-note {{comparison of pointers '&start' and '&end' to unrelated zero-sized objects}}271}272 273namespace OverlappingStrings {274 static_assert(+"foo" != +"bar", "");275 static_assert(&"xfoo"[1] != &"yfoo"[1], "");276 static_assert(+"foot" != +"foo", "");277 static_assert(+"foo\0bar" != +"foo\0baz", "");278 279 280#define fold(x) (__builtin_constant_p(x) ? (x) : (x))281 static_assert(fold((const char*)u"A" != (const char*)"\0A\0x"), "");282 static_assert(fold((const char*)u"A" != (const char*)"A\0\0x"), "");283 static_assert(fold((const char*)u"AAA" != (const char*)"AAA\0\0x"), "");284 285 constexpr const char *string = "hello";286 constexpr const char *also_string = string;287 static_assert(string == string, "");288 static_assert(string == also_string, "");289 290 291 // These strings may overlap, and so the result of the comparison is unknown.292 constexpr bool may_overlap_1 = +"foo" == +"foo"; // both-error {{}} both-note {{addresses of potentially overlapping literals}}293 constexpr bool may_overlap_2 = +"foo" == +"foo\0bar"; // both-error {{}} both-note {{addresses of potentially overlapping literals}}294 constexpr bool may_overlap_3 = +"foo" == &"bar\0foo"[4]; // both-error {{}} both-note {{addresses of potentially overlapping literals}}295 constexpr bool may_overlap_4 = &"xfoo"[1] == &"xfoo"[1]; // both-error {{}} both-note {{addresses of potentially overlapping literals}}296 297 298 /// Used to crash.299 const bool x = &"ab"[0] == &"ba"[3];300 301}302 303namespace NonConstLocal {304 int a() {305 const int t=t; // both-note {{declared here}}306 307 switch(1) {308 case t:; // both-note {{initializer of 't' is not a constant expression}} \309 // both-error {{case value is not a constant expression}}310 }311 }312}313 314#define ATTR __attribute__((require_constant_initialization))315int somefunc() {316 const int non_global = 42; // both-note {{declared here}}317 ATTR static const int &local_init = non_global; // both-error {{variable does not have a constant initializer}} \318 // both-note {{required by}} \319 // both-note {{reference to 'non_global' is not a constant expression}}320}321 322namespace PR19010 {323 struct Empty {};324 struct Empty2 : Empty {};325 struct Test : Empty2 {326 constexpr Test() {}327 Empty2 array[2];328 };329 void test() { constexpr Test t; }330}331 332namespace ReadMutableInCopyCtor {333 struct G {334 struct X {};335 union U { X a; };336 mutable U u; // both-note {{declared here}}337 };338 constexpr G g1 = {};339 constexpr G g2 = g1; // both-error {{must be initialized by a constant expression}} \340 // both-note {{read of mutable member 'u'}} \341 // both-note {{in call to 'G(g1)'}}342}343 344namespace GH150709 {345 struct C { };346 struct D : C {347 constexpr int f() const { return 1; };348 };349 struct E : C { };350 struct F : D { };351 struct G : E { };352 353 constexpr C c1, c2[2];354 constexpr D d1, d2[2];355 constexpr E e1, e2[2];356 constexpr F f;357 constexpr G g;358 359 constexpr auto mp = static_cast<int (C::*)() const>(&D::f);360 361 // sanity checks for fix of GH150709 (unchanged behavior)362 static_assert((c1.*mp)() == 1, ""); // both-error {{constant expression}}363 static_assert((d1.*mp)() == 1, "");364 static_assert((f.*mp)() == 1, "");365 static_assert((c2[0].*mp)() == 1, ""); // ref-error {{constant expression}}366 static_assert((d2[0].*mp)() == 1, "");367 368 // incorrectly undiagnosed before fix of GH150709369 static_assert((e1.*mp)() == 1, ""); // ref-error {{constant expression}}370 static_assert((e2[0].*mp)() == 1, ""); // ref-error {{constant expression}}371 static_assert((g.*mp)() == 1, ""); // ref-error {{constant expression}}372}373 374namespace DiscardedAddrLabel {375 void foo(void) {376 L:377 *&&L; // both-error {{indirection not permitted on operand of type 'void *'}} \378 // both-warning {{expression result unused}}379 }380}381 382struct Counter {383 int copies;384 constexpr Counter(int copies) : copies(copies) {}385 constexpr Counter(const Counter& other) : copies(other.copies + 1) {}386};387// Passing an lvalue by value makes a non-elidable copy.388constexpr int PassByValue(Counter c) { return c.copies; }389static_assert(PassByValue(Counter(0)) == 0, "expect no copies");390 391namespace PointerCast {392 /// The two interpreters disagree here.393 struct S { int x, y; } s;394 constexpr S* sptr = &s;395 struct U {};396 struct Str {397 int e : (Str*)(sptr) == (Str*)(sptr); // expected-error {{not an integral constant expression}} \398 // expected-note {{cast that performs the conversions of a reinterpret_cast}}399 };400}401 402namespace DummyToGlobalBlockMove {403 struct Baz {404 unsigned int n;405 };406 407 struct AP {408 const AP *p;409 const Baz *lp;410 };411 412 class Bar {413 public:414 static Baz _m[];415 static const AP m;416 };417 418 const AP Bar::m = {0, &Bar::_m[0]};419 Baz Bar::_m[] = {{0}};420 const AP m = {&Bar ::m};421}422