constant-expression-cxx11.cpp revision ffbda40a1fb7169591dc01771f3511178a2f727c
1// RUN: %clang_cc1 -triple i686-linux -fsyntax-only -verify -std=c++11 %s
2
3// FIXME: support const T& parameters here.
4//template<typename T> constexpr T id(const T &t) { return t; }
5template<typename T> constexpr T id(T t) { return t; }
6// FIXME: support templates here.
7//template<typename T> constexpr T min(const T &a, const T &b) {
8//  return a < b ? a : b;
9//}
10//template<typename T> constexpr T max(const T &a, const T &b) {
11//  return a < b ? b : a;
12//}
13constexpr int min(const int &a, const int &b) { return a < b ? a : b; }
14constexpr int max(const int &a, const int &b) { return a < b ? b : a; }
15
16struct MemberZero {
17  constexpr int zero() { return 0; }
18};
19
20namespace TemplateArgumentConversion {
21  template<int n> struct IntParam {};
22
23  using IntParam0 = IntParam<0>;
24  // FIXME: This should be accepted once we do constexpr function invocation.
25  using IntParam0 = IntParam<id(0)>; // expected-error {{not an integral constant expression}}
26  using IntParam0 = IntParam<MemberZero().zero>; // expected-error {{did you mean to call it with no arguments?}} expected-error {{not an integral constant expression}}
27}
28
29namespace CaseStatements {
30  void f(int n) {
31    switch (n) {
32    // FIXME: Produce the 'add ()' fixit for this.
33    case MemberZero().zero: // desired-error {{did you mean to call it with no arguments?}} expected-error {{not an integer constant expression}}
34    // FIXME: This should be accepted once we do constexpr function invocation.
35    case id(1): // expected-error {{not an integer constant expression}}
36      return;
37    }
38  }
39}
40
41extern int &Recurse1;
42int &Recurse2 = Recurse1, &Recurse1 = Recurse2;
43constexpr int &Recurse3 = Recurse2; // expected-error {{must be initialized by a constant expression}}
44
45namespace MemberEnum {
46  struct WithMemberEnum {
47    enum E { A = 42 };
48  } wme;
49  // FIXME: b's initializer is not treated as a constant expression yet, but we
50  // can at least fold it.
51  constexpr bool b = wme.A == 42;
52  int n[b];
53}
54
55namespace Recursion {
56  constexpr int fib(int n) { return n > 1 ? fib(n-1) + fib(n-2) : n; }
57  // FIXME: this isn't an ICE yet.
58  using check_fib = int[fib(11)];
59  using check_fib = int[89];
60
61  constexpr int gcd_inner(int a, int b) {
62    return b == 0 ? a : gcd_inner(b, a % b);
63  }
64  constexpr int gcd(int a, int b) {
65    return gcd_inner(max(a, b), min(a, b));
66  }
67
68  // FIXME: this isn't an ICE yet.
69  using check_gcd = int[gcd(1749237, 5628959)];
70  using check_gcd = int[7];
71}
72
73namespace FunctionCast {
74  // When folding, we allow functions to be cast to different types. Such
75  // cast functions cannot be called, even if they're constexpr.
76  constexpr int f() { return 1; }
77  typedef double (*DoubleFn)();
78  typedef int (*IntFn)();
79  int a[(int)DoubleFn(f)()]; // expected-error {{variable length array}}
80  int b[(int)IntFn(f)()];    // ok
81}
82
83namespace StaticMemberFunction {
84  struct S {
85    static constexpr int k = 42;
86    static constexpr int f(int n) { return n * k + 2; }
87  } s;
88  // FIXME: this isn't an ICE yet.
89  using check_static_call = int[S::f(19)];
90  constexpr int n = s.f(19);
91  using check_static_call = int[s.f(19)];
92  using check_static_call = int[800];
93}
94
95namespace ParameterScopes {
96
97  const int k = 42;
98  constexpr const int &ObscureTheTruth(const int &a) { return a; }
99  constexpr const int &MaybeReturnJunk(bool b, const int a) {
100    return ObscureTheTruth(b ? a : k);
101  }
102  constexpr int n1 = MaybeReturnJunk(false, 0); // ok
103  constexpr int n2 = MaybeReturnJunk(true, 0); // expected-error {{must be initialized by a constant expression}}
104
105  constexpr int InternalReturnJunk(int n) {
106    // FIXME: We should reject this: it never produces a constant expression.
107    return MaybeReturnJunk(true, n);
108  }
109  constexpr int n3 = InternalReturnJunk(0); // expected-error {{must be initialized by a constant expression}}
110
111  constexpr int LToR(int &n) { return n; }
112  constexpr int GrabCallersArgument(bool which, int a, int b) {
113    return LToR(which ? b : a);
114  }
115  constexpr int n4 = GrabCallersArgument(false, 1, 2);
116  constexpr int n5 = GrabCallersArgument(true, 4, 8);
117  // FIXME: this isn't an ICE yet.
118  using check_value = int[n4 + n5];
119  using check_value = int[9];
120
121}
122
123namespace Pointers {
124
125  constexpr int f(int n, const int *a, const int *b, const int *c) {
126    return n == 0 ? 0 : *a + f(n-1, b, c, a);
127  }
128
129  const int x = 1, y = 10, z = 100;
130  constexpr int n1 = f(23, &x, &y, &z);
131  // FIXME: this isn't an ICE yet.
132  using check_value_1 = int[n1];
133  using check_value_1 = int[788];
134
135  constexpr int g(int n, int a, int b, int c) {
136    return f(n, &a, &b, &c);
137  }
138  constexpr int n2 = g(23, x, y, z);
139  using check_value_1 = int[n2];
140
141}
142
143namespace FunctionPointers {
144
145  constexpr int Double(int n) { return 2 * n; }
146  constexpr int Triple(int n) { return 3 * n; }
147  constexpr int Twice(int (*F)(int), int n) { return F(F(n)); }
148  constexpr int Quadruple(int n) { return Twice(Double, n); }
149  constexpr auto Select(int n) -> int (*)(int) {
150    return n == 2 ? &Double : n == 3 ? &Triple : n == 4 ? &Quadruple : 0;
151  }
152  constexpr int Apply(int (*F)(int), int n) { return F(n); }
153
154  using check_value = int[1 + Apply(Select(4), 5) + Apply(Select(3), 7)];
155  using check_value = int[42];
156
157  constexpr int Invalid = Apply(Select(0), 0); // expected-error {{must be initialized by a constant expression}}
158
159}
160
161namespace PointerComparison {
162
163int x, y;
164constexpr bool g1 = &x == &y;
165constexpr bool g2 = &x != &y;
166constexpr bool g3 = &x <= &y; // expected-error {{must be initialized by a constant expression}}
167constexpr bool g4 = &x >= &y; // expected-error {{must be initialized by a constant expression}}
168constexpr bool g5 = &x < &y; // expected-error {{must be initialized by a constant expression}}
169constexpr bool g6 = &x > &y; // expected-error {{must be initialized by a constant expression}}
170
171struct S { int x, y; } s;
172constexpr bool m1 = &s.x == &s.y;
173constexpr bool m2 = &s.x != &s.y;
174constexpr bool m3 = &s.x <= &s.y;
175constexpr bool m4 = &s.x >= &s.y;
176constexpr bool m5 = &s.x < &s.y;
177constexpr bool m6 = &s.x > &s.y;
178
179constexpr bool n1 = 0 == &y;
180constexpr bool n2 = 0 != &y;
181constexpr bool n3 = 0 <= &y; // expected-error {{must be initialized by a constant expression}}
182constexpr bool n4 = 0 >= &y; // expected-error {{must be initialized by a constant expression}}
183constexpr bool n5 = 0 < &y; // expected-error {{must be initialized by a constant expression}}
184constexpr bool n6 = 0 > &y; // expected-error {{must be initialized by a constant expression}}
185
186constexpr bool n7 = &x == 0;
187constexpr bool n8 = &x != 0;
188constexpr bool n9 = &x <= 0; // expected-error {{must be initialized by a constant expression}}
189constexpr bool n10 = &x >= 0; // expected-error {{must be initialized by a constant expression}}
190constexpr bool n11 = &x < 0; // expected-error {{must be initialized by a constant expression}}
191constexpr bool n12 = &x > 0; // expected-error {{must be initialized by a constant expression}}
192
193constexpr bool s1 = &x == &x;
194constexpr bool s2 = &x != &x;
195constexpr bool s3 = &x <= &x;
196constexpr bool s4 = &x >= &x;
197constexpr bool s5 = &x < &x;
198constexpr bool s6 = &x > &x;
199
200constexpr S* sptr = &s;
201constexpr bool dyncast = sptr == dynamic_cast<S*>(sptr);
202
203extern char externalvar[];
204constexpr bool constaddress = (void *)externalvar == (void *)0x4000UL;  // expected-error {{must be initialized by a constant expression}}
205
206using check = int[m1 + (m2<<1) + (m3<<2) + (m4<<3) + (m5<<4) + (m6<<5) +
207                  (n1<<6) + (n2<<7) + (n7<<8) + (n8<<9) + (g1<<10) + (g2<<11) +
208               (s1<<12) + (s2<<13) + (s3<<14) + (s4<<15) + (s5<<16) + (s6<<17)];
209using check = int[2+4+16+128+512+2048+4096+16384+32768];
210
211}
212
213namespace MaterializeTemporary {
214
215constexpr int f(const int &r) { return r; }
216constexpr int n = f(1);
217
218constexpr bool same(const int &a, const int &b) { return &a == &b; }
219constexpr bool sameTemporary(const int &n) { return same(n, n); }
220
221using check_value = int[1];
222using check_value = int[n];
223using check_value = int[!same(4, 4)];
224using check_value = int[same(n, n)];
225using check_value = int[sameTemporary(9)];
226
227}
228