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     ;
fC60   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 
diags(int n)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; // expected-note {{declared here}}
102   template<int n> struct S {};
103   S<p> s; // expected-error {{not an integral constant expression}} expected-note {{read of variable 'p' of non-integral, non-enumeration type 'const int &'}}
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; // expected-note {{here}}
111 const int recurse1 = 1;
112 int array1[recurse1]; // ok
113 int array2[recurse2]; // expected-warning 2{{variable length array}} expected-note {{initializer of 'recurse2' is not a 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}} expected-note {{value 4.0E+20 is outside the range of representable values}}
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'}}
f()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 {
fn1()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 
145 char PR17381_ice = 1000000 * 1000000; // expected-warning {{overflow}} expected-warning {{changes value}}
146 
147 namespace PR31701 {
148   struct C {
149     template<int i> static int n; // expected-warning {{extension}}
150   };
151   template <int M> class D;
152   template <int M>
set()153   template<int i> void D<M>::set() { // expected-error {{from class 'D<M>' without definition}}
154     const C c = C::n<i>;
155   }
156 }
157