| // RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 -pedantic %s |
| // C++ [expr.const]p1: |
| // In several places, C++ requires expressions that evaluate to an integral |
| // or enumeration constant: as array bounds, as case expressions, as |
| // bit-field lengths, as enumerator initializers, as static member |
| // initializers, and as integral or enumeration non-type template arguments. |
| // An integral constant-expression can involve only literals, enumerators, |
| // const variables or static data members of integral or enumeration types |
| // initialized with constant expressions, and sizeof expressions. Floating |
| // literals can appear only if they are cast to integral or enumeration types. |
| |
| enum Enum { eval = 1 }; |
| const int cval = 2; |
| const Enum ceval = eval; |
| struct Struct { |
| static const int sval = 3; |
| static const Enum seval = eval; |
| }; |
| |
| template <int itval, Enum etval> struct C { |
| enum E { |
| v1 = 1, |
| v2 = eval, |
| v3 = cval, |
| v4 = ceval, |
| v5 = Struct::sval, |
| v6 = Struct::seval, |
| v7 = itval, |
| v8 = etval, |
| v9 = (int)1.5, |
| v10 = sizeof(Struct), |
| v11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 |
| }; |
| unsigned |
| b1 : 1, |
| b2 : eval, |
| b3 : cval, |
| b4 : ceval, |
| b5 : Struct::sval, |
| b6 : Struct::seval, |
| b7 : itval, |
| b8 : etval, |
| b9 : (int)1.5, |
| b10 : sizeof(Struct), |
| b11 : true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 |
| ; |
| static const int |
| i1 = 1, |
| i2 = eval, |
| i3 = cval, |
| i4 = ceval, |
| i5 = Struct::sval, |
| i6 = Struct::seval, |
| i7 = itval, |
| i8 = etval, |
| i9 = (int)1.5, |
| i10 = sizeof(Struct), |
| i11 = true? 1 + cval * Struct::sval ^ itval / (int)1.5 - sizeof(Struct) : 0 |
| ; |
| void f(int cond) { |
| switch(cond) { |
| case 0 + 1: |
| case 100 + eval: |
| case 200 + cval: |
| case 300 + ceval: |
| case 400 + Struct::sval: |
| case 500 + Struct::seval: |
| case 600 + itval: |
| case 700 + etval: |
| case 800 + (int)1.5: |
| case 900 + sizeof(Struct): |
| case 1000 + (true? 1 + cval * Struct::sval ^ |
| itval / (int)1.5 - sizeof(Struct) : 0): |
| ; |
| } |
| } |
| typedef C<itval, etval> T0; |
| }; |
| |
| template struct C<1, eval>; |
| template struct C<cval, ceval>; |
| template struct C<Struct::sval, Struct::seval>; |
| |
| enum { |
| a = sizeof(int) == 8, |
| b = a? 8 : 4 |
| }; |
| |
| void diags(int n) { |
| switch (n) { |
| case (1/0, 1): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} |
| case (int)(1/0, 2.0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} |
| case __imag(1/0): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} |
| case (int)__imag((double)(1/0)): // expected-error {{not an integral constant expression}} expected-note {{division by zero}} |
| ; |
| } |
| } |
| |
| namespace IntOrEnum { |
| const int k = 0; |
| const int &p = k; |
| template<int n> struct S {}; |
| S<p> s; // expected-error {{not an integral constant expression}} |
| } |
| |
| extern const int recurse1; |
| // recurse2 cannot be used in a constant expression because it is not |
| // initialized by a constant expression. The same expression appearing later in |
| // the TU would be a constant expression, but here it is not. |
| const int recurse2 = recurse1; |
| const int recurse1 = 1; |
| int array1[recurse1]; // ok |
| int array2[recurse2]; // expected-warning {{variable length array}} expected-warning {{integer constant expression}} |
| |
| namespace FloatConvert { |
| typedef int a[(int)42.3]; |
| typedef int a[(int)42.997]; |
| typedef int b[(int)4e10]; // expected-warning {{variable length}} expected-error {{variable length}} |
| } |