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 | |
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> |
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 | |