xref: /aosp_15_r20/external/clang/test/SemaCXX/constant-expression-cxx1y.cpp (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li // RUN: %clang_cc1 -std=c++1y -verify %s -fcxx-exceptions -triple=x86_64-linux-gnu
2*67e74705SXin Li 
3*67e74705SXin Li struct S {
4*67e74705SXin Li   // dummy ctor to make this a literal type
5*67e74705SXin Li   constexpr S(int);
6*67e74705SXin Li 
7*67e74705SXin Li   S();
8*67e74705SXin Li 
9*67e74705SXin Li   int arr[10];
10*67e74705SXin Li 
getS11*67e74705SXin Li   constexpr int &get(int n) { return arr[n]; }
getS12*67e74705SXin Li   constexpr const int &get(int n) const { return arr[n]; }
13*67e74705SXin Li };
14*67e74705SXin Li 
15*67e74705SXin Li S s = S();
16*67e74705SXin Li const S &sr = s;
17*67e74705SXin Li static_assert(&s.get(4) - &sr.get(2) == 2, "");
18*67e74705SXin Li 
19*67e74705SXin Li // Compound-statements can be used in constexpr functions.
e()20*67e74705SXin Li constexpr int e() {{{{}} return 5; }}
21*67e74705SXin Li static_assert(e() == 5, "");
22*67e74705SXin Li 
23*67e74705SXin Li // Types can be defined in constexpr functions.
f()24*67e74705SXin Li constexpr int f() {
25*67e74705SXin Li   enum E { e1, e2, e3 };
26*67e74705SXin Li 
27*67e74705SXin Li   struct S {
28*67e74705SXin Li     constexpr S(E e) : e(e) {}
29*67e74705SXin Li     constexpr int get() { return e; }
30*67e74705SXin Li     E e;
31*67e74705SXin Li   };
32*67e74705SXin Li 
33*67e74705SXin Li   return S(e2).get();
34*67e74705SXin Li }
35*67e74705SXin Li static_assert(f() == 1, "");
36*67e74705SXin Li 
37*67e74705SXin Li // Variables can be declared in constexpr functions.
g(int k)38*67e74705SXin Li constexpr int g(int k) {
39*67e74705SXin Li   const int n = 9;
40*67e74705SXin Li   int k2 = k * k;
41*67e74705SXin Li   int k3 = k2 * k;
42*67e74705SXin Li   return 3 * k3 + 5 * k2 + n * k - 20;
43*67e74705SXin Li }
44*67e74705SXin Li static_assert(g(2) == 42, "");
h(int n)45*67e74705SXin Li constexpr int h(int n) {
46*67e74705SXin Li   static const int m = n; // expected-error {{static variable not permitted in a constexpr function}}
47*67e74705SXin Li   return m;
48*67e74705SXin Li }
i(int n)49*67e74705SXin Li constexpr int i(int n) {
50*67e74705SXin Li   thread_local const int m = n; // expected-error {{thread_local variable not permitted in a constexpr function}}
51*67e74705SXin Li   return m;
52*67e74705SXin Li }
53*67e74705SXin Li 
54*67e74705SXin Li // if-statements can be used in constexpr functions.
j(int k)55*67e74705SXin Li constexpr int j(int k) {
56*67e74705SXin Li   if (k == 5)
57*67e74705SXin Li     return 1;
58*67e74705SXin Li   if (k == 1)
59*67e74705SXin Li     return 5;
60*67e74705SXin Li   else {
61*67e74705SXin Li     if (int n = 2 * k - 4) {
62*67e74705SXin Li       return n + 1;
63*67e74705SXin Li       return 2;
64*67e74705SXin Li     }
65*67e74705SXin Li   }
66*67e74705SXin Li } // expected-note 2{{control reached end of constexpr function}}
67*67e74705SXin Li static_assert(j(0) == -3, "");
68*67e74705SXin Li static_assert(j(1) == 5, "");
69*67e74705SXin Li static_assert(j(2), ""); // expected-error {{constant expression}} expected-note {{in call to 'j(2)'}}
70*67e74705SXin Li static_assert(j(3) == 3, "");
71*67e74705SXin Li static_assert(j(4) == 5, "");
72*67e74705SXin Li static_assert(j(5) == 1, "");
73*67e74705SXin Li 
74*67e74705SXin Li // There can be 0 return-statements.
k()75*67e74705SXin Li constexpr void k() {
76*67e74705SXin Li }
77*67e74705SXin Li 
78*67e74705SXin Li // If the return type is not 'void', no return statements => never a constant
79*67e74705SXin Li // expression, so still diagnose that case.
fn()80*67e74705SXin Li [[noreturn]] constexpr int fn() { // expected-error {{no return statement in constexpr function}}
81*67e74705SXin Li   fn();
82*67e74705SXin Li }
83*67e74705SXin Li 
84*67e74705SXin Li // We evaluate the body of a constexpr constructor, to check for side-effects.
85*67e74705SXin Li struct U {
UU86*67e74705SXin Li   constexpr U(int n) {
87*67e74705SXin Li     if (j(n)) {} // expected-note {{in call to 'j(2)'}}
88*67e74705SXin Li   }
89*67e74705SXin Li };
90*67e74705SXin Li constexpr U u1{1};
91*67e74705SXin Li constexpr U u2{2}; // expected-error {{constant expression}} expected-note {{in call to 'U(2)'}}
92*67e74705SXin Li 
93*67e74705SXin Li // We allow expression-statements.
l(bool b)94*67e74705SXin Li constexpr int l(bool b) {
95*67e74705SXin Li   if (b)
96*67e74705SXin Li     throw "invalid value for b!"; // expected-note {{subexpression not valid}}
97*67e74705SXin Li   return 5;
98*67e74705SXin Li }
99*67e74705SXin Li static_assert(l(false) == 5, "");
100*67e74705SXin Li static_assert(l(true), ""); // expected-error {{constant expression}} expected-note {{in call to 'l(true)'}}
101*67e74705SXin Li 
102*67e74705SXin Li // Potential constant expression checking is still applied where possible.
htonl(int x)103*67e74705SXin Li constexpr int htonl(int x) { // expected-error {{never produces a constant expression}}
104*67e74705SXin Li   typedef unsigned char uchar;
105*67e74705SXin Li   uchar arr[4] = { uchar(x >> 24), uchar(x >> 16), uchar(x >> 8), uchar(x) };
106*67e74705SXin Li   return *reinterpret_cast<int*>(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}}
107*67e74705SXin Li }
108*67e74705SXin Li 
maybe_htonl(bool isBigEndian,int x)109*67e74705SXin Li constexpr int maybe_htonl(bool isBigEndian, int x) {
110*67e74705SXin Li   if (isBigEndian)
111*67e74705SXin Li     return x;
112*67e74705SXin Li 
113*67e74705SXin Li   typedef unsigned char uchar;
114*67e74705SXin Li   uchar arr[4] = { uchar(x >> 24), uchar(x >> 16), uchar(x >> 8), uchar(x) };
115*67e74705SXin Li   return *reinterpret_cast<int*>(arr); // expected-note {{reinterpret_cast is not allowed in a constant expression}}
116*67e74705SXin Li }
117*67e74705SXin Li 
118*67e74705SXin Li constexpr int swapped = maybe_htonl(false, 123); // expected-error {{constant expression}} expected-note {{in call}}
119*67e74705SXin Li 
120*67e74705SXin Li namespace NS {
121*67e74705SXin Li   constexpr int n = 0;
122*67e74705SXin Li }
namespace_alias()123*67e74705SXin Li constexpr int namespace_alias() {
124*67e74705SXin Li   namespace N = NS;
125*67e74705SXin Li   return N::n;
126*67e74705SXin Li }
127*67e74705SXin Li 
128*67e74705SXin Li namespace assign {
129*67e74705SXin Li   constexpr int a = 0;
130*67e74705SXin Li   const int b = 0;
131*67e74705SXin Li   int c = 0; // expected-note {{here}}
132*67e74705SXin Li 
set(const int & a,int b)133*67e74705SXin Li   constexpr void set(const int &a, int b) {
134*67e74705SXin Li     const_cast<int&>(a) = b; // expected-note 3{{constant expression cannot modify an object that is visible outside that expression}}
135*67e74705SXin Li   }
wrap(int a,int b)136*67e74705SXin Li   constexpr int wrap(int a, int b) {
137*67e74705SXin Li     set(a, b);
138*67e74705SXin Li     return a;
139*67e74705SXin Li   }
140*67e74705SXin Li 
141*67e74705SXin Li   static_assert((set(a, 1), a) == 1, ""); // expected-error {{constant expression}} expected-note {{in call to 'set(a, 1)'}}
142*67e74705SXin Li   static_assert((set(b, 1), b) == 1, ""); // expected-error {{constant expression}} expected-note {{in call to 'set(b, 1)'}}
143*67e74705SXin Li   static_assert((set(c, 1), c) == 1, ""); // expected-error {{constant expression}} expected-note {{in call to 'set(c, 1)'}}
144*67e74705SXin Li 
145*67e74705SXin Li   static_assert(wrap(a, 1) == 1, "");
146*67e74705SXin Li   static_assert(wrap(b, 1) == 1, "");
147*67e74705SXin Li   static_assert(wrap(c, 1) == 1, ""); // expected-error {{constant expression}} expected-note {{read of non-const variable 'c'}}
148*67e74705SXin Li }
149*67e74705SXin Li 
150*67e74705SXin Li namespace string_assign {
151*67e74705SXin Li   template<typename T>
swap(T & a,T & b)152*67e74705SXin Li   constexpr void swap(T &a, T &b) {
153*67e74705SXin Li     T tmp = a;
154*67e74705SXin Li     a = b;
155*67e74705SXin Li     b = tmp;
156*67e74705SXin Li   }
157*67e74705SXin Li   template<typename Iterator>
reverse(Iterator begin,Iterator end)158*67e74705SXin Li   constexpr void reverse(Iterator begin, Iterator end) {
159*67e74705SXin Li     while (begin != end && begin != --end)
160*67e74705SXin Li       swap(*begin++, *end);
161*67e74705SXin Li   }
162*67e74705SXin Li   template<typename Iterator1, typename Iterator2>
equal(Iterator1 a,Iterator1 ae,Iterator2 b,Iterator2 be)163*67e74705SXin Li   constexpr bool equal(Iterator1 a, Iterator1 ae, Iterator2 b, Iterator2 be) {
164*67e74705SXin Li     while (a != ae && b != be)
165*67e74705SXin Li       if (*a++ != *b++)
166*67e74705SXin Li         return false;
167*67e74705SXin Li     return a == ae && b == be;
168*67e74705SXin Li   }
test1(int n)169*67e74705SXin Li   constexpr bool test1(int n) {
170*67e74705SXin Li     char stuff[100] = "foobarfoo";
171*67e74705SXin Li     const char stuff2[100] = "oofraboof";
172*67e74705SXin Li     reverse(stuff, stuff + n); // expected-note {{cannot refer to element 101 of array of 100 elements}}
173*67e74705SXin Li     return equal(stuff, stuff + n, stuff2, stuff2 + n);
174*67e74705SXin Li   }
175*67e74705SXin Li   static_assert(!test1(1), "");
176*67e74705SXin Li   static_assert(test1(3), "");
177*67e74705SXin Li   static_assert(!test1(6), "");
178*67e74705SXin Li   static_assert(test1(9), "");
179*67e74705SXin Li   static_assert(!test1(100), "");
180*67e74705SXin Li   static_assert(!test1(101), ""); // expected-error {{constant expression}} expected-note {{in call to 'test1(101)'}}
181*67e74705SXin Li 
f()182*67e74705SXin Li   constexpr void f() { // expected-error{{constexpr function never produces a constant expression}} expected-note@+2{{assignment to dereferenced one-past-the-end pointer is not allowed in a constant expression}}
183*67e74705SXin Li     char foo[10] = { "z" }; // expected-note {{here}}
184*67e74705SXin Li     foo[10] = 'x'; // expected-warning {{past the end}}
185*67e74705SXin Li   }
186*67e74705SXin Li }
187*67e74705SXin Li 
188*67e74705SXin Li namespace array_resize {
do_stuff(int k1,int k2)189*67e74705SXin Li   constexpr int do_stuff(int k1, int k2) {
190*67e74705SXin Li     int arr[1234] = { 1, 2, 3, 4 };
191*67e74705SXin Li     arr[k1] = 5; // expected-note {{past-the-end}} expected-note {{cannot refer to element 1235}} expected-note {{cannot refer to element -1}}
192*67e74705SXin Li     return arr[k2];
193*67e74705SXin Li   }
194*67e74705SXin Li   static_assert(do_stuff(1, 2) == 3, "");
195*67e74705SXin Li   static_assert(do_stuff(0, 0) == 5, "");
196*67e74705SXin Li   static_assert(do_stuff(1233, 1233) == 5, "");
197*67e74705SXin Li   static_assert(do_stuff(1233, 0) == 1, "");
198*67e74705SXin Li   static_assert(do_stuff(1234, 0) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}}
199*67e74705SXin Li   static_assert(do_stuff(1235, 0) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}}
200*67e74705SXin Li   static_assert(do_stuff(-1, 0) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}}
201*67e74705SXin Li }
202*67e74705SXin Li 
203*67e74705SXin Li namespace potential_const_expr {
set(int & n)204*67e74705SXin Li   constexpr void set(int &n) { n = 1; }
div_zero_1()205*67e74705SXin Li   constexpr int div_zero_1() { int z = 0; set(z); return 100 / z; } // no error
div_zero_2()206*67e74705SXin Li   constexpr int div_zero_2() { // expected-error {{never produces a constant expression}}
207*67e74705SXin Li     int z = 0;
208*67e74705SXin Li     return 100 / (set(z), 0); // expected-note {{division by zero}}
209*67e74705SXin Li   }
210*67e74705SXin Li   int n; // expected-note {{declared here}}
ref()211*67e74705SXin Li   constexpr int ref() { // expected-error {{never produces a constant expression}}
212*67e74705SXin Li     int &r = n;
213*67e74705SXin Li     return r; // expected-note {{read of non-const variable 'n'}}
214*67e74705SXin Li   }
215*67e74705SXin Li }
216*67e74705SXin Li 
217*67e74705SXin Li namespace subobject {
A()218*67e74705SXin Li   union A { constexpr A() : y(5) {} int x, y; };
219*67e74705SXin Li   struct B { A a; };
220*67e74705SXin Li   struct C : B {};
D(int n)221*67e74705SXin Li   union D { constexpr D() : c() {} constexpr D(int n) : n(n) {} C c; int n; };
f(D & d)222*67e74705SXin Li   constexpr void f(D &d) {
223*67e74705SXin Li     d.c.a.y = 3;
224*67e74705SXin Li     // expected-note@-1 {{cannot modify an object that is visible outside}}
225*67e74705SXin Li     // expected-note@-2 {{assignment to member 'c' of union with active member 'n'}}
226*67e74705SXin Li   }
check(D & d)227*67e74705SXin Li   constexpr bool check(D &d) { return d.c.a.y == 3; }
228*67e74705SXin Li 
g()229*67e74705SXin Li   constexpr bool g() { D d; f(d); return d.c.a.y == 3; }
230*67e74705SXin Li   static_assert(g(), "");
231*67e74705SXin Li 
232*67e74705SXin Li   D d;
h()233*67e74705SXin Li   constexpr bool h() { f(d); return check(d); } // expected-note {{in call}}
234*67e74705SXin Li   static_assert(h(), ""); // expected-error {{constant expression}} expected-note {{in call}}
235*67e74705SXin Li 
i()236*67e74705SXin Li   constexpr bool i() { D d(0); f(d); return check(d); } // expected-note {{in call}}
237*67e74705SXin Li   static_assert(i(), ""); // expected-error {{constant expression}} expected-note {{in call}}
238*67e74705SXin Li 
j()239*67e74705SXin Li   constexpr bool j() { D d; d.c.a.x = 3; return check(d); } // expected-note {{assignment to member 'x' of union with active member 'y'}}
240*67e74705SXin Li   static_assert(j(), ""); // expected-error {{constant expression}} expected-note {{in call}}
241*67e74705SXin Li }
242*67e74705SXin Li 
243*67e74705SXin Li namespace lifetime {
id(int && n)244*67e74705SXin Li   constexpr int &&id(int &&n) { return static_cast<int&&>(n); }
dead()245*67e74705SXin Li   constexpr int &&dead() { return id(0); } // expected-note {{temporary created here}}
bad()246*67e74705SXin Li   constexpr int bad() { int &&n = dead(); n = 1; return n; } // expected-note {{assignment to temporary whose lifetime has ended}}
247*67e74705SXin Li   static_assert(bad(), ""); // expected-error {{constant expression}} expected-note {{in call}}
248*67e74705SXin Li }
249*67e74705SXin Li 
250*67e74705SXin Li namespace const_modify {
modify(int & n)251*67e74705SXin Li   constexpr int modify(int &n) { return n = 1; } // expected-note 2 {{modification of object of const-qualified type 'const int'}}
test1()252*67e74705SXin Li   constexpr int test1() { int k = 0; return modify(k); }
test2()253*67e74705SXin Li   constexpr int test2() { const int k = 0; return modify(const_cast<int&>(k)); } // expected-note 2 {{in call}}
254*67e74705SXin Li   static_assert(test1() == 1, "");
255*67e74705SXin Li   static_assert(test2() == 1, ""); // expected-error {{constant expression}} expected-note {{in call}}
256*67e74705SXin Li   constexpr int i = test2(); // expected-error {{constant expression}} expected-note {{in call}}
257*67e74705SXin Li }
258*67e74705SXin Li 
259*67e74705SXin Li namespace null {
test(int * p)260*67e74705SXin Li   constexpr int test(int *p) {
261*67e74705SXin Li     return *p = 123; // expected-note {{assignment to dereferenced null pointer}}
262*67e74705SXin Li   }
263*67e74705SXin Li   static_assert(test(0), ""); // expected-error {{constant expression}} expected-note {{in call}}
264*67e74705SXin Li }
265*67e74705SXin Li 
266*67e74705SXin Li namespace incdec {
ref(T && r)267*67e74705SXin Li   template<typename T> constexpr T &ref(T &&r) { return r; }
postinc(T && r)268*67e74705SXin Li   template<typename T> constexpr T postinc(T &&r) { return (r++, r); }
postdec(T && r)269*67e74705SXin Li   template<typename T> constexpr T postdec(T &&r) { return (r--, r); }
270*67e74705SXin Li 
271*67e74705SXin Li   static_assert(++ref(0) == 1, "");
272*67e74705SXin Li   static_assert(ref(0)++ == 0, "");
273*67e74705SXin Li   static_assert(postinc(0) == 1, "");
274*67e74705SXin Li   static_assert(--ref(0) == -1, "");
275*67e74705SXin Li   static_assert(ref(0)-- == 0, "");
276*67e74705SXin Li   static_assert(postdec(0) == -1, "");
277*67e74705SXin Li 
278*67e74705SXin Li   constexpr int overflow_int_inc_1 = ref(0x7fffffff)++; // expected-error {{constant}} expected-note {{2147483648}}
279*67e74705SXin Li   constexpr int overflow_int_inc_1_ok = ref(0x7ffffffe)++;
280*67e74705SXin Li   constexpr int overflow_int_inc_2 = ++ref(0x7fffffff); // expected-error {{constant}} expected-note {{2147483648}}
281*67e74705SXin Li   constexpr int overflow_int_inc_2_ok = ++ref(0x7ffffffe);
282*67e74705SXin Li 
283*67e74705SXin Li   // inc/dec on short can't overflow because we promote to int first
284*67e74705SXin Li   static_assert(++ref<short>(0x7fff) == (int)0xffff8000u, "");
285*67e74705SXin Li   static_assert(--ref<short>(0x8000) == 0x7fff, "");
286*67e74705SXin Li 
287*67e74705SXin Li   // inc on bool sets to true
288*67e74705SXin Li   static_assert(++ref(false), ""); // expected-warning {{deprecated}}
289*67e74705SXin Li   static_assert(++ref(true), ""); // expected-warning {{deprecated}}
290*67e74705SXin Li 
291*67e74705SXin Li   int arr[10];
292*67e74705SXin Li   static_assert(++ref(&arr[0]) == &arr[1], "");
293*67e74705SXin Li   static_assert(++ref(&arr[9]) == &arr[10], "");
294*67e74705SXin Li   static_assert(++ref(&arr[10]) == &arr[11], ""); // expected-error {{constant}} expected-note {{cannot refer to element 11}}
295*67e74705SXin Li   static_assert(ref(&arr[0])++ == &arr[0], "");
296*67e74705SXin Li   static_assert(ref(&arr[10])++ == &arr[10], ""); // expected-error {{constant}} expected-note {{cannot refer to element 11}}
297*67e74705SXin Li   static_assert(postinc(&arr[0]) == &arr[1], "");
298*67e74705SXin Li   static_assert(--ref(&arr[10]) == &arr[9], "");
299*67e74705SXin Li   static_assert(--ref(&arr[1]) == &arr[0], "");
300*67e74705SXin Li   static_assert(--ref(&arr[0]) != &arr[0], ""); // expected-error {{constant}} expected-note {{cannot refer to element -1}}
301*67e74705SXin Li   static_assert(ref(&arr[1])-- == &arr[1], "");
302*67e74705SXin Li   static_assert(ref(&arr[0])-- == &arr[0], ""); // expected-error {{constant}} expected-note {{cannot refer to element -1}}
303*67e74705SXin Li   static_assert(postdec(&arr[1]) == &arr[0], "");
304*67e74705SXin Li 
305*67e74705SXin Li   int x;
306*67e74705SXin Li   static_assert(++ref(&x) == &x + 1, "");
307*67e74705SXin Li 
308*67e74705SXin Li   static_assert(++ref(0.0) == 1.0, "");
309*67e74705SXin Li   static_assert(ref(0.0)++ == 0.0, "");
310*67e74705SXin Li   static_assert(postinc(0.0) == 1.0, "");
311*67e74705SXin Li   static_assert(--ref(0.0) == -1.0, "");
312*67e74705SXin Li   static_assert(ref(0.0)-- == 0.0, "");
313*67e74705SXin Li   static_assert(postdec(0.0) == -1.0, "");
314*67e74705SXin Li 
315*67e74705SXin Li   static_assert(++ref(1e100) == 1e100, "");
316*67e74705SXin Li   static_assert(--ref(1e100) == 1e100, "");
317*67e74705SXin Li 
318*67e74705SXin Li   union U {
319*67e74705SXin Li     int a, b;
320*67e74705SXin Li   };
f(U u)321*67e74705SXin Li   constexpr int f(U u) {
322*67e74705SXin Li     return ++u.b; // expected-note {{increment of member 'b' of union with active member 'a'}}
323*67e74705SXin Li   }
324*67e74705SXin Li   constexpr int wrong_member = f({0}); // expected-error {{constant}} expected-note {{in call to 'f({.a = 0})'}}
325*67e74705SXin Li   constexpr int vol = --ref<volatile int>(0); // expected-error {{constant}} expected-note {{decrement of volatile-qualified}}
326*67e74705SXin Li 
incr(int k)327*67e74705SXin Li   constexpr int incr(int k) {
328*67e74705SXin Li     int x = k;
329*67e74705SXin Li     if (x++ == 100)
330*67e74705SXin Li       return x;
331*67e74705SXin Li     return incr(x);
332*67e74705SXin Li   }
333*67e74705SXin Li   static_assert(incr(0) == 101, "");
334*67e74705SXin Li }
335*67e74705SXin Li 
336*67e74705SXin Li namespace compound_assign {
test_int()337*67e74705SXin Li   constexpr bool test_int() {
338*67e74705SXin Li     int a = 3;
339*67e74705SXin Li     a += 6;
340*67e74705SXin Li     if (a != 9) return false;
341*67e74705SXin Li     a -= 2;
342*67e74705SXin Li     if (a != 7) return false;
343*67e74705SXin Li     a *= 3;
344*67e74705SXin Li     if (a != 21) return false;
345*67e74705SXin Li     if (&(a /= 10) != &a) return false;
346*67e74705SXin Li     if (a != 2) return false;
347*67e74705SXin Li     a <<= 3;
348*67e74705SXin Li     if (a != 16) return false;
349*67e74705SXin Li     a %= 6;
350*67e74705SXin Li     if (a != 4) return false;
351*67e74705SXin Li     a >>= 1;
352*67e74705SXin Li     if (a != 2) return false;
353*67e74705SXin Li     a ^= 10;
354*67e74705SXin Li     if (a != 8) return false;
355*67e74705SXin Li     a |= 5;
356*67e74705SXin Li     if (a != 13) return false;
357*67e74705SXin Li     a &= 14;
358*67e74705SXin Li     if (a != 12) return false;
359*67e74705SXin Li     return true;
360*67e74705SXin Li   }
361*67e74705SXin Li   static_assert(test_int(), "");
362*67e74705SXin Li 
test_float()363*67e74705SXin Li   constexpr bool test_float() {
364*67e74705SXin Li     float f = 123.;
365*67e74705SXin Li     f *= 2;
366*67e74705SXin Li     if (f != 246.) return false;
367*67e74705SXin Li     if ((f -= 0.5) != 245.5) return false;
368*67e74705SXin Li     if (f != 245.5) return false;
369*67e74705SXin Li     f /= 0.5;
370*67e74705SXin Li     if (f != 491.) return false;
371*67e74705SXin Li     f += -40;
372*67e74705SXin Li     if (f != 451.) return false;
373*67e74705SXin Li     return true;
374*67e74705SXin Li   }
375*67e74705SXin Li   static_assert(test_float(), "");
376*67e74705SXin Li 
test_ptr()377*67e74705SXin Li   constexpr bool test_ptr() {
378*67e74705SXin Li     int arr[123] = {};
379*67e74705SXin Li     int *p = arr;
380*67e74705SXin Li     if ((p += 4) != &arr[4]) return false;
381*67e74705SXin Li     if (p != &arr[4]) return false;
382*67e74705SXin Li     p += -1;
383*67e74705SXin Li     if (p != &arr[3]) return false;
384*67e74705SXin Li     if ((p -= -10) != &arr[13]) return false;
385*67e74705SXin Li     if (p != &arr[13]) return false;
386*67e74705SXin Li     p -= 11;
387*67e74705SXin Li     if (p != &arr[2]) return false;
388*67e74705SXin Li     return true;
389*67e74705SXin Li   }
390*67e74705SXin Li   static_assert(test_ptr(), "");
391*67e74705SXin Li 
392*67e74705SXin Li   template<typename T>
test_overflow()393*67e74705SXin Li   constexpr bool test_overflow() {
394*67e74705SXin Li     T a = 1;
395*67e74705SXin Li     while (a != a / 2)
396*67e74705SXin Li       a *= 2; // expected-note {{value 2147483648 is outside the range}} expected-note {{ 9223372036854775808 }} expected-note {{floating point arithmetic produces an infinity}}
397*67e74705SXin Li     return true;
398*67e74705SXin Li   }
399*67e74705SXin Li 
400*67e74705SXin Li   static_assert(test_overflow<int>(), ""); // expected-error {{constant}} expected-note {{call}}
401*67e74705SXin Li   static_assert(test_overflow<unsigned>(), ""); // ok, unsigned overflow is defined
402*67e74705SXin Li   static_assert(test_overflow<short>(), ""); // ok, short is promoted to int before multiplication
403*67e74705SXin Li   static_assert(test_overflow<unsigned short>(), ""); // ok
404*67e74705SXin Li   static_assert(test_overflow<unsigned long long>(), ""); // ok
405*67e74705SXin Li   static_assert(test_overflow<long long>(), ""); // expected-error {{constant}} expected-note {{call}}
406*67e74705SXin Li   static_assert(test_overflow<float>(), ""); // expected-error {{constant}} expected-note {{call}}
407*67e74705SXin Li 
test_promotion(short k)408*67e74705SXin Li   constexpr short test_promotion(short k) {
409*67e74705SXin Li     short s = k;
410*67e74705SXin Li     s *= s;
411*67e74705SXin Li     return s;
412*67e74705SXin Li   }
413*67e74705SXin Li   static_assert(test_promotion(100) == 10000, "");
414*67e74705SXin Li   static_assert(test_promotion(200) == -25536, "");
415*67e74705SXin Li   static_assert(test_promotion(256) == 0, "");
416*67e74705SXin Li 
test_bounds(const char * p,int o)417*67e74705SXin Li   constexpr const char *test_bounds(const char *p, int o) {
418*67e74705SXin Li     return p += o; // expected-note {{element 5 of}} expected-note {{element -1 of}} expected-note {{element 1000 of}}
419*67e74705SXin Li   }
420*67e74705SXin Li   static_assert(test_bounds("foo", 0)[0] == 'f', "");
421*67e74705SXin Li   static_assert(test_bounds("foo", 3)[0] == 0, "");
422*67e74705SXin Li   static_assert(test_bounds("foo", 4)[-3] == 'o', "");
423*67e74705SXin Li   static_assert(test_bounds("foo" + 4, -4)[0] == 'f', "");
424*67e74705SXin Li   static_assert(test_bounds("foo", 5) != 0, ""); // expected-error {{constant}} expected-note {{call}}
425*67e74705SXin Li   static_assert(test_bounds("foo", -1) != 0, ""); // expected-error {{constant}} expected-note {{call}}
426*67e74705SXin Li   static_assert(test_bounds("foo", 1000) != 0, ""); // expected-error {{constant}} expected-note {{call}}
427*67e74705SXin Li }
428*67e74705SXin Li 
429*67e74705SXin Li namespace loops {
fib_loop(int a)430*67e74705SXin Li   constexpr int fib_loop(int a) {
431*67e74705SXin Li     int f_k = 0, f_k_plus_one = 1;
432*67e74705SXin Li     for (int k = 1; k != a; ++k) {
433*67e74705SXin Li       int f_k_plus_two = f_k + f_k_plus_one;
434*67e74705SXin Li       f_k = f_k_plus_one;
435*67e74705SXin Li       f_k_plus_one = f_k_plus_two;
436*67e74705SXin Li     }
437*67e74705SXin Li     return f_k_plus_one;
438*67e74705SXin Li   }
439*67e74705SXin Li   static_assert(fib_loop(46) == 1836311903, "");
440*67e74705SXin Li 
breaks_work()441*67e74705SXin Li   constexpr bool breaks_work() {
442*67e74705SXin Li     int a = 0;
443*67e74705SXin Li     for (int n = 0; n != 100; ++n) {
444*67e74705SXin Li       ++a;
445*67e74705SXin Li       if (a == 5) continue;
446*67e74705SXin Li       if ((a % 5) == 0) break;
447*67e74705SXin Li     }
448*67e74705SXin Li 
449*67e74705SXin Li     int b = 0;
450*67e74705SXin Li     while (b != 17) {
451*67e74705SXin Li       ++b;
452*67e74705SXin Li       if (b == 6) continue;
453*67e74705SXin Li       if ((b % 6) == 0) break;
454*67e74705SXin Li     }
455*67e74705SXin Li 
456*67e74705SXin Li     int c = 0;
457*67e74705SXin Li     do {
458*67e74705SXin Li       ++c;
459*67e74705SXin Li       if (c == 7) continue;
460*67e74705SXin Li       if ((c % 7) == 0) break;
461*67e74705SXin Li     } while (c != 21);
462*67e74705SXin Li 
463*67e74705SXin Li     return a == 10 && b == 12 && c == 14;
464*67e74705SXin Li   }
465*67e74705SXin Li   static_assert(breaks_work(), "");
466*67e74705SXin Li 
467*67e74705SXin Li   void not_constexpr();
no_cont_after_break()468*67e74705SXin Li   constexpr bool no_cont_after_break() {
469*67e74705SXin Li     for (;;) {
470*67e74705SXin Li       break;
471*67e74705SXin Li       not_constexpr();
472*67e74705SXin Li     }
473*67e74705SXin Li     while (true) {
474*67e74705SXin Li       break;
475*67e74705SXin Li       not_constexpr();
476*67e74705SXin Li     }
477*67e74705SXin Li     do {
478*67e74705SXin Li       break;
479*67e74705SXin Li       not_constexpr();
480*67e74705SXin Li     } while (true);
481*67e74705SXin Li     return true;
482*67e74705SXin Li   }
483*67e74705SXin Li   static_assert(no_cont_after_break(), "");
484*67e74705SXin Li 
cond()485*67e74705SXin Li   constexpr bool cond() {
486*67e74705SXin Li     for (int a = 1; bool b = a != 3; ++a) {
487*67e74705SXin Li       if (!b)
488*67e74705SXin Li         return false;
489*67e74705SXin Li     }
490*67e74705SXin Li     while (bool b = true) {
491*67e74705SXin Li       b = false;
492*67e74705SXin Li       break;
493*67e74705SXin Li     }
494*67e74705SXin Li     return true;
495*67e74705SXin Li   }
496*67e74705SXin Li   static_assert(cond(), "");
497*67e74705SXin Li 
range_for()498*67e74705SXin Li   constexpr int range_for() {
499*67e74705SXin Li     int arr[] = { 1, 2, 3, 4, 5 };
500*67e74705SXin Li     int sum = 0;
501*67e74705SXin Li     for (int x : arr)
502*67e74705SXin Li       sum += x;
503*67e74705SXin Li     return sum;
504*67e74705SXin Li   }
505*67e74705SXin Li   static_assert(range_for() == 15, "");
506*67e74705SXin Li 
507*67e74705SXin Li   template<int...N> struct ints {};
508*67e74705SXin Li   template<typename A, typename B> struct join_ints;
509*67e74705SXin Li   template<int...As, int...Bs> struct join_ints<ints<As...>, ints<Bs...>> {
510*67e74705SXin Li     using type = ints<As..., sizeof...(As) + Bs...>;
511*67e74705SXin Li   };
512*67e74705SXin Li   template<unsigned N> struct make_ints {
513*67e74705SXin Li     using type = typename join_ints<typename make_ints<N/2>::type, typename make_ints<(N+1)/2>::type>::type;
514*67e74705SXin Li   };
515*67e74705SXin Li   template<> struct make_ints<0> { using type = ints<>; };
516*67e74705SXin Li   template<> struct make_ints<1> { using type = ints<0>; };
517*67e74705SXin Li 
ignoreloops::ignore518*67e74705SXin Li   struct ignore { template<typename ...Ts> constexpr ignore(Ts &&...) {} };
519*67e74705SXin Li 
520*67e74705SXin Li   template<typename T, unsigned N> struct array {
arrayloops::array521*67e74705SXin Li     constexpr array() : arr{} {}
522*67e74705SXin Li     template<typename ...X>
arrayloops::array523*67e74705SXin Li     constexpr array(X ...x) : arr{} {
524*67e74705SXin Li       init(typename make_ints<sizeof...(X)>::type{}, x...);
525*67e74705SXin Li     }
initloops::array526*67e74705SXin Li     template<int ...I, typename ...X> constexpr void init(ints<I...>, X ...x) {
527*67e74705SXin Li       ignore{arr[I] = x ...};
528*67e74705SXin Li     }
529*67e74705SXin Li     T arr[N];
530*67e74705SXin Li     struct iterator {
531*67e74705SXin Li       T *p;
iteratorloops::array::iterator532*67e74705SXin Li       constexpr explicit iterator(T *p) : p(p) {}
operator !=loops::array::iterator533*67e74705SXin Li       constexpr bool operator!=(iterator o) { return p != o.p; }
operator ++loops::array::iterator534*67e74705SXin Li       constexpr iterator &operator++() { ++p; return *this; }
operator *loops::array::iterator535*67e74705SXin Li       constexpr T &operator*() { return *p; }
536*67e74705SXin Li     };
beginloops::array537*67e74705SXin Li     constexpr iterator begin() { return iterator(arr); }
endloops::array538*67e74705SXin Li     constexpr iterator end() { return iterator(arr + N); }
539*67e74705SXin Li   };
540*67e74705SXin Li 
range_for_2()541*67e74705SXin Li   constexpr int range_for_2() {
542*67e74705SXin Li     array<int, 5> arr { 1, 2, 3, 4, 5 };
543*67e74705SXin Li     int sum = 0;
544*67e74705SXin Li     for (int k : arr) {
545*67e74705SXin Li       sum += k;
546*67e74705SXin Li       if (sum > 8) break;
547*67e74705SXin Li     }
548*67e74705SXin Li     return sum;
549*67e74705SXin Li   }
550*67e74705SXin Li   static_assert(range_for_2() == 10, "");
551*67e74705SXin Li }
552*67e74705SXin Li 
553*67e74705SXin Li namespace assignment_op {
554*67e74705SXin Li   struct A {
Aassignment_op::A555*67e74705SXin Li     constexpr A() : n(5) {}
556*67e74705SXin Li     int n;
557*67e74705SXin Li     struct B {
558*67e74705SXin Li       int k = 1;
559*67e74705SXin Li       union U {
U()560*67e74705SXin Li         constexpr U() : y(4) {}
561*67e74705SXin Li         int x;
562*67e74705SXin Li         int y;
563*67e74705SXin Li       } u;
564*67e74705SXin Li     } b;
565*67e74705SXin Li   };
testA()566*67e74705SXin Li   constexpr bool testA() {
567*67e74705SXin Li     A a, b;
568*67e74705SXin Li     a.n = 7;
569*67e74705SXin Li     a.b.u.y = 5;
570*67e74705SXin Li     b = a;
571*67e74705SXin Li     return b.n == 7 && b.b.u.y == 5 && b.b.k == 1;
572*67e74705SXin Li   }
573*67e74705SXin Li   static_assert(testA(), "");
574*67e74705SXin Li 
575*67e74705SXin Li   struct B {
576*67e74705SXin Li     bool assigned = false;
operator =assignment_op::B577*67e74705SXin Li     constexpr B &operator=(const B&) {
578*67e74705SXin Li       assigned = true;
579*67e74705SXin Li       return *this;
580*67e74705SXin Li     }
581*67e74705SXin Li   };
582*67e74705SXin Li   struct C : B {
583*67e74705SXin Li     B b;
584*67e74705SXin Li     int n = 5;
585*67e74705SXin Li   };
testC()586*67e74705SXin Li   constexpr bool testC() {
587*67e74705SXin Li     C c, d;
588*67e74705SXin Li     c.n = 7;
589*67e74705SXin Li     d = c;
590*67e74705SXin Li     c.n = 3;
591*67e74705SXin Li     return d.n == 7 && d.assigned && d.b.assigned;
592*67e74705SXin Li   }
593*67e74705SXin Li   static_assert(testC(), "");
594*67e74705SXin Li }
595*67e74705SXin Li 
596*67e74705SXin Li namespace switch_stmt {
f(char k)597*67e74705SXin Li   constexpr int f(char k) {
598*67e74705SXin Li     bool b = false;
599*67e74705SXin Li     int z = 6;
600*67e74705SXin Li     switch (k) {
601*67e74705SXin Li       return -1;
602*67e74705SXin Li     case 0:
603*67e74705SXin Li       if (false) {
604*67e74705SXin Li       case 1:
605*67e74705SXin Li         z = 1;
606*67e74705SXin Li         for (; b;) {
607*67e74705SXin Li           return 5;
608*67e74705SXin Li           while (0)
609*67e74705SXin Li             case 2: return 2;
610*67e74705SXin Li           case 7: z = 7;
611*67e74705SXin Li           do case 6: {
612*67e74705SXin Li             return z;
613*67e74705SXin Li             if (false)
614*67e74705SXin Li               case 3: return 3;
615*67e74705SXin Li             case 4: z = 4;
616*67e74705SXin Li           } while (1);
617*67e74705SXin Li           case 5: b = true;
618*67e74705SXin Li           case 9: z = 9;
619*67e74705SXin Li         }
620*67e74705SXin Li         return z;
621*67e74705SXin Li       } else if (false) case 8: z = 8;
622*67e74705SXin Li       else if (false) {
623*67e74705SXin Li       case 10:
624*67e74705SXin Li         z = -10;
625*67e74705SXin Li         break;
626*67e74705SXin Li       }
627*67e74705SXin Li       else z = 0;
628*67e74705SXin Li       return z;
629*67e74705SXin Li     default:
630*67e74705SXin Li       return -1;
631*67e74705SXin Li     }
632*67e74705SXin Li     return -z;
633*67e74705SXin Li   }
634*67e74705SXin Li   static_assert(f(0) == 0, "");
635*67e74705SXin Li   static_assert(f(1) == 1, "");
636*67e74705SXin Li   static_assert(f(2) == 2, "");
637*67e74705SXin Li   static_assert(f(3) == 3, "");
638*67e74705SXin Li   static_assert(f(4) == 4, "");
639*67e74705SXin Li   static_assert(f(5) == 5, "");
640*67e74705SXin Li   static_assert(f(6) == 6, "");
641*67e74705SXin Li   static_assert(f(7) == 7, "");
642*67e74705SXin Li   static_assert(f(8) == 8, "");
643*67e74705SXin Li   static_assert(f(9) == 9, "");
644*67e74705SXin Li   static_assert(f(10) == 10, "");
645*67e74705SXin Li 
646*67e74705SXin Li   // Check that we can continue an outer loop from within a switch.
contin()647*67e74705SXin Li   constexpr bool contin() {
648*67e74705SXin Li     for (int n = 0; n != 10; ++n) {
649*67e74705SXin Li       switch (n) {
650*67e74705SXin Li       case 0:
651*67e74705SXin Li         ++n;
652*67e74705SXin Li         continue;
653*67e74705SXin Li       case 1:
654*67e74705SXin Li         return false;
655*67e74705SXin Li       case 2:
656*67e74705SXin Li         return true;
657*67e74705SXin Li       }
658*67e74705SXin Li     }
659*67e74705SXin Li     return false;
660*67e74705SXin Li   }
661*67e74705SXin Li   static_assert(contin(), "");
662*67e74705SXin Li 
switch_into_for()663*67e74705SXin Li   constexpr bool switch_into_for() {
664*67e74705SXin Li     int n = 0;
665*67e74705SXin Li     switch (n) {
666*67e74705SXin Li       for (; n == 1; ++n) {
667*67e74705SXin Li         return n == 1;
668*67e74705SXin Li       case 0: ;
669*67e74705SXin Li       }
670*67e74705SXin Li     }
671*67e74705SXin Li     return false;
672*67e74705SXin Li   }
673*67e74705SXin Li   static_assert(switch_into_for(), "");
674*67e74705SXin Li 
duff_copy(char * a,const char * b,int n)675*67e74705SXin Li   constexpr void duff_copy(char *a, const char *b, int n) {
676*67e74705SXin Li     switch ((n - 1) % 8 + 1) {
677*67e74705SXin Li       for ( ; n; n = (n - 1) & ~7) {
678*67e74705SXin Li       case 8: a[n-8] = b[n-8];
679*67e74705SXin Li       case 7: a[n-7] = b[n-7];
680*67e74705SXin Li       case 6: a[n-6] = b[n-6];
681*67e74705SXin Li       case 5: a[n-5] = b[n-5];
682*67e74705SXin Li       case 4: a[n-4] = b[n-4];
683*67e74705SXin Li       case 3: a[n-3] = b[n-3];
684*67e74705SXin Li       case 2: a[n-2] = b[n-2];
685*67e74705SXin Li       case 1: a[n-1] = b[n-1];
686*67e74705SXin Li       }
687*67e74705SXin Li       case 0: ;
688*67e74705SXin Li     }
689*67e74705SXin Li   }
690*67e74705SXin Li 
test_copy(const char * str,int n)691*67e74705SXin Li   constexpr bool test_copy(const char *str, int n) {
692*67e74705SXin Li     char buffer[16] = {};
693*67e74705SXin Li     duff_copy(buffer, str, n);
694*67e74705SXin Li     for (int i = 0; i != sizeof(buffer); ++i)
695*67e74705SXin Li       if (buffer[i] != (i < n ? str[i] : 0))
696*67e74705SXin Li         return false;
697*67e74705SXin Li     return true;
698*67e74705SXin Li   }
699*67e74705SXin Li   static_assert(test_copy("foo", 0), "");
700*67e74705SXin Li   static_assert(test_copy("foo", 1), "");
701*67e74705SXin Li   static_assert(test_copy("foo", 2), "");
702*67e74705SXin Li   static_assert(test_copy("hello world", 0), "");
703*67e74705SXin Li   static_assert(test_copy("hello world", 7), "");
704*67e74705SXin Li   static_assert(test_copy("hello world", 8), "");
705*67e74705SXin Li   static_assert(test_copy("hello world", 9), "");
706*67e74705SXin Li   static_assert(test_copy("hello world", 10), "");
707*67e74705SXin Li   static_assert(test_copy("hello world", 10), "");
708*67e74705SXin Li }
709*67e74705SXin Li 
710*67e74705SXin Li namespace deduced_return_type {
f()711*67e74705SXin Li   constexpr auto f() { return 0; }
g(T t)712*67e74705SXin Li   template<typename T> constexpr auto g(T t) { return t; }
713*67e74705SXin Li   static_assert(f() == 0, "");
714*67e74705SXin Li   static_assert(g(true), "");
715*67e74705SXin Li }
716*67e74705SXin Li 
717*67e74705SXin Li namespace modify_temporary_during_construction {
718*67e74705SXin Li   struct A { int &&temporary; int x; int y; };
f(int & r)719*67e74705SXin Li   constexpr int f(int &r) { r *= 9; return r - 12; }
720*67e74705SXin Li   constexpr A a = { 6, f(a.temporary), a.temporary }; // expected-note {{temporary created here}}
721*67e74705SXin Li   static_assert(a.x == 42, "");
722*67e74705SXin Li   static_assert(a.y == 54, "");
723*67e74705SXin Li   constexpr int k = a.temporary++; // expected-error {{constant expression}} expected-note {{outside the expression that created the temporary}}
724*67e74705SXin Li }
725*67e74705SXin Li 
726*67e74705SXin Li namespace std {
727*67e74705SXin Li   typedef decltype(sizeof(int)) size_t;
728*67e74705SXin Li 
729*67e74705SXin Li   template <class _E>
730*67e74705SXin Li   class initializer_list
731*67e74705SXin Li   {
732*67e74705SXin Li     const _E* __begin_;
733*67e74705SXin Li     size_t    __size_;
734*67e74705SXin Li 
initializer_list(const _E * __b,size_t __s)735*67e74705SXin Li     constexpr initializer_list(const _E* __b, size_t __s)
736*67e74705SXin Li       : __begin_(__b),
737*67e74705SXin Li         __size_(__s)
738*67e74705SXin Li     {}
739*67e74705SXin Li 
740*67e74705SXin Li   public:
741*67e74705SXin Li     typedef _E        value_type;
742*67e74705SXin Li     typedef const _E& reference;
743*67e74705SXin Li     typedef const _E& const_reference;
744*67e74705SXin Li     typedef size_t    size_type;
745*67e74705SXin Li 
746*67e74705SXin Li     typedef const _E* iterator;
747*67e74705SXin Li     typedef const _E* const_iterator;
748*67e74705SXin Li 
initializer_list()749*67e74705SXin Li     constexpr initializer_list() : __begin_(nullptr), __size_(0) {}
750*67e74705SXin Li 
size() const751*67e74705SXin Li     constexpr size_t    size()  const {return __size_;}
begin() const752*67e74705SXin Li     constexpr const _E* begin() const {return __begin_;}
end() const753*67e74705SXin Li     constexpr const _E* end()   const {return __begin_ + __size_;}
754*67e74705SXin Li   };
755*67e74705SXin Li }
756*67e74705SXin Li 
757*67e74705SXin Li namespace InitializerList {
sum(std::initializer_list<int> ints)758*67e74705SXin Li   constexpr int sum(std::initializer_list<int> ints) {
759*67e74705SXin Li     int total = 0;
760*67e74705SXin Li     for (int n : ints) total += n;
761*67e74705SXin Li     return total;
762*67e74705SXin Li   }
763*67e74705SXin Li   static_assert(sum({1, 2, 3, 4, 5}) == 15, "");
764*67e74705SXin Li }
765*67e74705SXin Li 
766*67e74705SXin Li namespace StmtExpr {
f(int k)767*67e74705SXin Li   constexpr int f(int k) {
768*67e74705SXin Li     switch (k) {
769*67e74705SXin Li     case 0:
770*67e74705SXin Li       return 0;
771*67e74705SXin Li 
772*67e74705SXin Li       ({
773*67e74705SXin Li         case 1: // expected-note {{not supported}}
774*67e74705SXin Li           return 1;
775*67e74705SXin Li       });
776*67e74705SXin Li     }
777*67e74705SXin Li   }
778*67e74705SXin Li   static_assert(f(1) == 1, ""); // expected-error {{constant expression}} expected-note {{in call}}
779*67e74705SXin Li 
g()780*67e74705SXin Li   constexpr int g() { // expected-error {{never produces a constant}}
781*67e74705SXin Li     return ({ int n; n; }); // expected-note {{object of type 'int' is not initialized}}
782*67e74705SXin Li   }
783*67e74705SXin Li 
784*67e74705SXin Li   // FIXME: We should handle the void statement expression case.
h()785*67e74705SXin Li   constexpr int h() { // expected-error {{never produces a constant}}
786*67e74705SXin Li     ({ if (true) {} }); // expected-note {{not supported}}
787*67e74705SXin Li     return 0;
788*67e74705SXin Li   }
789*67e74705SXin Li }
790*67e74705SXin Li 
791*67e74705SXin Li namespace VirtualFromBase {
792*67e74705SXin Li   struct S1 {
793*67e74705SXin Li     virtual int f() const;
794*67e74705SXin Li   };
795*67e74705SXin Li   struct S2 {
796*67e74705SXin Li     virtual int f();
797*67e74705SXin Li   };
798*67e74705SXin Li   template <typename T> struct X : T {
XVirtualFromBase::X799*67e74705SXin Li     constexpr X() {}
800*67e74705SXin Li     double d = 0.0;
fVirtualFromBase::X801*67e74705SXin Li     constexpr int f() { return sizeof(T); }
802*67e74705SXin Li   };
803*67e74705SXin Li 
804*67e74705SXin Li   // Non-virtual f(), OK.
805*67e74705SXin Li   constexpr X<X<S1>> xxs1;
806*67e74705SXin Li   constexpr X<S1> *p = const_cast<X<X<S1>>*>(&xxs1);
807*67e74705SXin Li   static_assert(p->f() == sizeof(S1), "");
808*67e74705SXin Li 
809*67e74705SXin Li   // Virtual f(), not OK.
810*67e74705SXin Li   constexpr X<X<S2>> xxs2;
811*67e74705SXin Li   constexpr X<S2> *q = const_cast<X<X<S2>>*>(&xxs2);
812*67e74705SXin Li   static_assert(q->f() == sizeof(X<S2>), ""); // expected-error {{constant expression}} expected-note {{virtual function call}}
813*67e74705SXin Li }
814*67e74705SXin Li 
815*67e74705SXin Li namespace Lifetime {
get(int && r)816*67e74705SXin Li   constexpr int &get(int &&r) { return r; }
f()817*67e74705SXin Li   constexpr int f() {
818*67e74705SXin Li     int &r = get(123);
819*67e74705SXin Li     return r; // expected-note {{read of object outside its lifetime}}
820*67e74705SXin Li   }
821*67e74705SXin Li   static_assert(f() == 123, ""); // expected-error {{constant expression}} expected-note {{in call}}
822*67e74705SXin Li 
g()823*67e74705SXin Li   constexpr int g() {
824*67e74705SXin Li     int *p = 0;
825*67e74705SXin Li     {
826*67e74705SXin Li       int n = 0;
827*67e74705SXin Li       p = &n;
828*67e74705SXin Li       n = 42;
829*67e74705SXin Li     }
830*67e74705SXin Li     *p = 123; // expected-note {{assignment to object outside its lifetime}}
831*67e74705SXin Li     return *p;
832*67e74705SXin Li   }
833*67e74705SXin Li   static_assert(g() == 42, ""); // expected-error {{constant expression}} expected-note {{in call}}
834*67e74705SXin Li 
h(int n)835*67e74705SXin Li   constexpr int h(int n) {
836*67e74705SXin Li     int *p[4] = {};
837*67e74705SXin Li     int &&r = 1;
838*67e74705SXin Li     p[0] = &r;
839*67e74705SXin Li     while (int a = 1) {
840*67e74705SXin Li       p[1] = &a;
841*67e74705SXin Li       for (int b = 1; int c = 1; ) {
842*67e74705SXin Li         p[2] = &b, p[3] = &c;
843*67e74705SXin Li         break;
844*67e74705SXin Li       }
845*67e74705SXin Li       break;
846*67e74705SXin Li     }
847*67e74705SXin Li     *p[n] = 0; // expected-note 3{{assignment to object outside its lifetime}}
848*67e74705SXin Li     return *p[n];
849*67e74705SXin Li   }
850*67e74705SXin Li   static_assert(h(0) == 0, ""); // ok, lifetime-extended
851*67e74705SXin Li   static_assert(h(1) == 0, ""); // expected-error {{constant expression}} expected-note {{in call}}
852*67e74705SXin Li   static_assert(h(2) == 0, ""); // expected-error {{constant expression}} expected-note {{in call}}
853*67e74705SXin Li   static_assert(h(3) == 0, ""); // expected-error {{constant expression}} expected-note {{in call}}
854*67e74705SXin Li 
855*67e74705SXin Li   // FIXME: This function should be treated as non-constant.
lifetime_versus_loops()856*67e74705SXin Li   constexpr void lifetime_versus_loops() {
857*67e74705SXin Li     int *p = 0;
858*67e74705SXin Li     for (int i = 0; i != 2; ++i) {
859*67e74705SXin Li       int *q = p;
860*67e74705SXin Li       int n = 0;
861*67e74705SXin Li       p = &n;
862*67e74705SXin Li       if (i)
863*67e74705SXin Li         // This modifies the 'n' from the previous iteration of the loop outside
864*67e74705SXin Li         // its lifetime.
865*67e74705SXin Li         ++*q;
866*67e74705SXin Li     }
867*67e74705SXin Li   }
868*67e74705SXin Li   static_assert((lifetime_versus_loops(), true), "");
869*67e74705SXin Li }
870*67e74705SXin Li 
871*67e74705SXin Li namespace Bitfields {
872*67e74705SXin Li   struct A {
873*67e74705SXin Li     bool b : 1;
874*67e74705SXin Li     int n : 4;
875*67e74705SXin Li     unsigned u : 5;
876*67e74705SXin Li   };
test()877*67e74705SXin Li   constexpr bool test() {
878*67e74705SXin Li     A a {};
879*67e74705SXin Li     a.b += 2;
880*67e74705SXin Li     --a.n;
881*67e74705SXin Li     --a.u;
882*67e74705SXin Li     a.n = -a.n * 3;
883*67e74705SXin Li     return a.b == false && a.n == 3 && a.u == 31;
884*67e74705SXin Li   }
885*67e74705SXin Li   static_assert(test(), "");
886*67e74705SXin Li }
887*67e74705SXin Li 
888*67e74705SXin Li namespace PR17615 {
889*67e74705SXin Li   struct A {
890*67e74705SXin Li     int &&r;
APR17615::A891*67e74705SXin Li     constexpr A(int &&r) : r(static_cast<int &&>(r)) {}
APR17615::A892*67e74705SXin Li     constexpr A() : A(0) {
893*67e74705SXin Li       (void)+r; // expected-note {{outside its lifetime}}
894*67e74705SXin Li     }
895*67e74705SXin Li   };
896*67e74705SXin Li   constexpr int k = A().r; // expected-error {{constant expression}} expected-note {{in call to}}
897*67e74705SXin Li }
898*67e74705SXin Li 
899*67e74705SXin Li namespace PR17331 {
900*67e74705SXin Li   template<typename T, unsigned int N>
sum(const T (& arr)[N])901*67e74705SXin Li   constexpr T sum(const T (&arr)[N]) {
902*67e74705SXin Li     T result = 0;
903*67e74705SXin Li     for (T i : arr)
904*67e74705SXin Li       result += i;
905*67e74705SXin Li     return result;
906*67e74705SXin Li   }
907*67e74705SXin Li 
908*67e74705SXin Li   constexpr int ARR[] = { 1, 2, 3, 4, 5 };
909*67e74705SXin Li   static_assert(sum(ARR) == 15, "");
910*67e74705SXin Li }
911*67e74705SXin Li 
912*67e74705SXin Li namespace EmptyClass {
913*67e74705SXin Li   struct E1 {} e1;
914*67e74705SXin Li   union E2 {} e2; // expected-note 4{{here}}
915*67e74705SXin Li   struct E3 : E1 {} e3;
916*67e74705SXin Li 
917*67e74705SXin Li   template<typename E>
f(E & a,int kind)918*67e74705SXin Li   constexpr int f(E &a, int kind) {
919*67e74705SXin Li     switch (kind) {
920*67e74705SXin Li     case 0: { E e(a); return 0; } // expected-note {{read}} expected-note {{in call}}
921*67e74705SXin Li     case 1: { E e(static_cast<E&&>(a)); return 0; } // expected-note {{read}} expected-note {{in call}}
922*67e74705SXin Li     case 2: { E e; e = a; return 0; } // expected-note {{read}} expected-note {{in call}}
923*67e74705SXin Li     case 3: { E e; e = static_cast<E&&>(a); return 0; } // expected-note {{read}} expected-note {{in call}}
924*67e74705SXin Li     }
925*67e74705SXin Li   }
926*67e74705SXin Li   constexpr int test1 = f(e1, 0);
927*67e74705SXin Li   constexpr int test2 = f(e2, 0); // expected-error {{constant expression}} expected-note {{in call}}
928*67e74705SXin Li   constexpr int test3 = f(e3, 0);
929*67e74705SXin Li   constexpr int test4 = f(e1, 1);
930*67e74705SXin Li   constexpr int test5 = f(e2, 1); // expected-error {{constant expression}} expected-note {{in call}}
931*67e74705SXin Li   constexpr int test6 = f(e3, 1);
932*67e74705SXin Li   constexpr int test7 = f(e1, 2);
933*67e74705SXin Li   constexpr int test8 = f(e2, 2); // expected-error {{constant expression}} expected-note {{in call}}
934*67e74705SXin Li   constexpr int test9 = f(e3, 2);
935*67e74705SXin Li   constexpr int testa = f(e1, 3);
936*67e74705SXin Li   constexpr int testb = f(e2, 3); // expected-error {{constant expression}} expected-note {{in call}}
937*67e74705SXin Li   constexpr int testc = f(e3, 3);
938*67e74705SXin Li }
939*67e74705SXin Li 
940*67e74705SXin Li namespace SpeculativeEvalWrites {
941*67e74705SXin Li   // Ensure that we don't try to speculatively evaluate writes.
f()942*67e74705SXin Li   constexpr int f() {
943*67e74705SXin Li     int i = 0;
944*67e74705SXin Li     int a = 0;
945*67e74705SXin Li     // __builtin_object_size speculatively evaluates its first argument.
946*67e74705SXin Li     __builtin_object_size((i = 1, &a), 0);
947*67e74705SXin Li     return i;
948*67e74705SXin Li   }
949*67e74705SXin Li 
950*67e74705SXin Li   static_assert(!f(), "");
951*67e74705SXin Li }
952*67e74705SXin Li 
953*67e74705SXin Li namespace PR27989 {
f(int n)954*67e74705SXin Li   constexpr int f(int n) {
955*67e74705SXin Li     int a = (n = 1, 0);
956*67e74705SXin Li     return n;
957*67e74705SXin Li   }
958*67e74705SXin Li   static_assert(f(0) == 1, "");
959*67e74705SXin Li }
960