Home | History | Annotate | Download | only in SemaCXX
      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