1 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -pedantic %s 2 // C++ [expr.const]p1: 3 // In several places, C++ requires expressions that evaluate to an integral 4 // or enumeration constant: as array bounds, as case expressions, as 5 // bit-field lengths, as enumerator initializers, as static member 6 // initializers, and as integral or enumeration non-type template arguments. 7 // An integral constant-expression can involve only literals, enumerators, 8 // const variables or static data members of integral or enumeration types 9 // initialized with constant expressions, and sizeof expressions. Floating 10 // literals can appear only if they are cast to integral or enumeration types. 11 12 enum Enum { eval = 1 }; 13 const int cval = 2; 14 const Enum ceval = eval; 15 struct Struct { 16 static const int sval = 3; 17 static const Enum seval = eval; 18 }; 19 20 template <int itval, Enum etval> struct C { 21 enum E { 22 v1 = 1, 23 v2 = eval, 24 v3 = cval, 25 v4 = ceval, 26 v5 = Struct::sval, 27 v6 = Struct::seval, 28 v7 = itval, 29 v8 = etval, 30 v9 = (int)1.5, 31 v10 = sizeof(Struct), 32 v11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 33 }; 34 unsigned 35 b1 : 1, 36 b2 : eval, 37 b3 : cval, 38 b4 : ceval, 39 b5 : Struct::sval, 40 b6 : Struct::seval, 41 b7 : itval, 42 b8 : etval, 43 b9 : (int)1.5, 44 b10 : sizeof(Struct), 45 b11 : true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 46 ; 47 static const int 48 i1 = 1, 49 i2 = eval, 50 i3 = cval, 51 i4 = ceval, 52 i5 = Struct::sval, 53 i6 = Struct::seval, 54 i7 = itval, 55 i8 = etval, 56 i9 = (int)1.5, 57 i10 = sizeof(Struct), 58 i11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 59 ; 60 void f(int cond) { 61 switch(cond) { 62 case 0 + 1: 63 case 100 + eval: 64 case 200 + cval: 65 case 300 + ceval: 66 case 400 + Struct::sval: 67 case 500 + Struct::seval: 68 case 600 + itval: 69 case 700 + etval: 70 case 800 + (int)1.5: 71 case 900 + sizeof(Struct): 72 case 1000 + (true? 1 + cval * Struct::sval ^ 73 itval / (int)1.5 - sizeof(Struct) : 0): 74 ; 75 } 76 } 77 typedef C<itval, etval> T0; 78 }; 79 80 template struct C<1, eval>; 81 template struct C<cval, ceval>; 82 template struct C<Struct::sval, Struct::seval>; 83 84 enum { 85 a = sizeof(int) == 8, 86 b = a? 8 : 4 87 }; 88 89 void diags(int n) { 90 switch (n) { 91 case (1/0, 1): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} 92 case (int)(1/0, 2.0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} 93 case __imag(1/0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} 94 case (int)__imag((double)(1/0)): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} 95 ; 96 } 97 } 98 99 namespace IntOrEnum { 100 const int k = 0; 101 const int &p = k; 102 template<int n> struct S {}; 103 S<p> s; // expected-error {{not an integral constant expression}} 104 } 105 106 extern const int recurse1; 107 // recurse2 cannot be used in a constant expression because it is not 108 // initialized by a constant expression. The same expression appearing later in 109 // the TU would be a constant expression, but here it is not. 110 const int recurse2 = recurse1; 111 const int recurse1 = 1; 112 int array1[recurse1]; // ok 113 int array2[recurse2]; // expected-warning {{variable length array}} expected-warning {{integer constant expression}} 114 115 namespace FloatConvert { 116 typedef int a[(int)42.3]; 117 typedef int a[(int)42.997]; 118 typedef int b[(long long)4e20]; // expected-warning {{variable length}} expected-error {{variable length}} expected-warning {{'long long' is a C++11 extension}} 119 } 120 121 // PR12626 122 namespace test3 { 123 struct X; // expected-note {{forward declaration of 'test3::X'}} 124 struct Y { bool b; X x; }; // expected-error {{field has incomplete type 'test3::X'}} 125 int f() { return Y().b; } 126 } 127 128 // PR18283 129 namespace test4 { 130 template <int> struct A {}; 131 int const i = { 42 }; 132 // i can be used as non-type template-parameter as "const int x = { 42 };" is 133 // equivalent to "const int x = 42;" as per C++03 8.5/p13. 134 typedef A<i> Ai; // ok 135 } 136 137 // rdar://16064952 138 namespace rdar16064952 { 139 template < typename T > void fn1() { 140 T b; 141 unsigned w = ({int a = b.val[sizeof(0)]; 0; }); // expected-warning {{use of GNU statement expression extension}} 142 } 143 } 144