constant-expression-cxx11.cpp revision 0b4072f42f4c94c6c396b43ed3db4d1deecef9c3
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 const int MaybeReturnNonstaticRef(bool b, const int a) {
106    // If ObscureTheTruth returns a reference to 'a', the result is not a
107    // constant expression even though 'a' is still in scope.
108    return ObscureTheTruth(b ? a : k);
109  }
110  constexpr int n1a = MaybeReturnNonstaticRef(false, 0); // ok
111  constexpr int n2a = MaybeReturnNonstaticRef(true, 0); // expected-error {{must be initialized by a constant expression}}
112
113  constexpr int InternalReturnJunk(int n) {
114    // FIXME: We should reject this: it never produces a constant expression.
115    return MaybeReturnJunk(true, n);
116  }
117  constexpr int n3 = InternalReturnJunk(0); // expected-error {{must be initialized by a constant expression}}
118
119  constexpr int LToR(int &n) { return n; }
120  constexpr int GrabCallersArgument(bool which, int a, int b) {
121    return LToR(which ? b : a);
122  }
123  constexpr int n4 = GrabCallersArgument(false, 1, 2);
124  constexpr int n5 = GrabCallersArgument(true, 4, 8);
125  // FIXME: this isn't an ICE yet.
126  using check_value = int[n4 + n5];
127  using check_value = int[9];
128
129}
130
131#if 0
132namespace Pointers {
133
134  constexpr int f(int n, const int *a, const int *b, const int *c) {
135    return n == 0 ? 0 : *a + f(n-1, b, c, a);
136  }
137
138  const int x = 1, y = 10, z = 100;
139  constexpr int n1 = f(23, &x, &y, &z);
140  // FIXME: this isn't an ICE yet.
141  using check_value_1 = int[n1];
142  using check_value_1 = int[788];
143
144  constexpr int g(int n, int a, int b, int c) {
145    return f(n, &a, &b, &c);
146  }
147  constexpr int n2 = g(23, x, y, z);
148  using check_value_1 = int[n2];
149
150}
151
152namespace FunctionPointers {
153
154  constexpr int Double(int n) { return 2 * n; }
155  constexpr int Triple(int n) { return 3 * n; }
156  constexpr int Twice(int (*F)(int), int n) { return F(F(n)); }
157  constexpr int Quadruple(int n) { return Twice(Double, n); }
158  constexpr auto Select(int n) -> int (*)(int) {
159    return n == 2 ? &Double : n == 3 ? &Triple : n == 4 ? &Quadruple : 0;
160  }
161  constexpr int Apply(int (*F)(int), int n) { return F(n); }
162
163  using check_value = int[1 + Apply(Select(4), 5) + Apply(Select(3), 7)];
164  using check_value = int[42];
165
166  constexpr int Invalid = Apply(Select(0), 0); // xpected-error {{must be initialized by a constant expression}}
167
168}
169#endif
170
171namespace PointerComparison {
172
173int x, y;
174constexpr bool g1 = &x == &y;
175constexpr bool g2 = &x != &y;
176constexpr bool g3 = &x <= &y; // expected-error {{must be initialized by a constant expression}}
177constexpr bool g4 = &x >= &y; // expected-error {{must be initialized by a constant expression}}
178constexpr bool g5 = &x < &y; // expected-error {{must be initialized by a constant expression}}
179constexpr bool g6 = &x > &y; // expected-error {{must be initialized by a constant expression}}
180
181struct S { int x, y; } s;
182constexpr bool m1 = &s.x == &s.y;
183constexpr bool m2 = &s.x != &s.y;
184constexpr bool m3 = &s.x <= &s.y;
185constexpr bool m4 = &s.x >= &s.y;
186constexpr bool m5 = &s.x < &s.y;
187constexpr bool m6 = &s.x > &s.y;
188
189constexpr bool n1 = 0 == &y;
190constexpr bool n2 = 0 != &y;
191constexpr bool n3 = 0 <= &y; // expected-error {{must be initialized by a constant expression}}
192constexpr bool n4 = 0 >= &y; // expected-error {{must be initialized by a constant expression}}
193constexpr bool n5 = 0 < &y; // expected-error {{must be initialized by a constant expression}}
194constexpr bool n6 = 0 > &y; // expected-error {{must be initialized by a constant expression}}
195
196constexpr bool n7 = &x == 0;
197constexpr bool n8 = &x != 0;
198constexpr bool n9 = &x <= 0; // expected-error {{must be initialized by a constant expression}}
199constexpr bool n10 = &x >= 0; // expected-error {{must be initialized by a constant expression}}
200constexpr bool n11 = &x < 0; // expected-error {{must be initialized by a constant expression}}
201constexpr bool n12 = &x > 0; // expected-error {{must be initialized by a constant expression}}
202
203constexpr bool s1 = &x == &x;
204constexpr bool s2 = &x != &x;
205constexpr bool s3 = &x <= &x;
206constexpr bool s4 = &x >= &x;
207constexpr bool s5 = &x < &x;
208constexpr bool s6 = &x > &x;
209
210#if 0
211constexpr S* sptr = &s;
212constexpr bool dyncast = sptr == dynamic_cast<S*>(sptr);
213#endif
214
215extern char externalvar[];
216constexpr bool constaddress = (void *)externalvar == (void *)0x4000UL;  // expected-error {{must be initialized by a constant expression}}
217
218using check = int[m1 + (m2<<1) + (m3<<2) + (m4<<3) + (m5<<4) + (m6<<5) +
219                  (n1<<6) + (n2<<7) + (n7<<8) + (n8<<9) + (g1<<10) + (g2<<11) +
220               (s1<<12) + (s2<<13) + (s3<<14) + (s4<<15) + (s5<<16) + (s6<<17)];
221using check = int[2+4+16+128+512+2048+4096+16384+32768];
222
223}
224
225namespace MaterializeTemporary {
226
227constexpr int f(const int &r) { return r; }
228constexpr int n = f(1);
229
230constexpr bool same(const int &a, const int &b) { return &a == &b; }
231constexpr bool sameTemporary(const int &n) { return same(n, n); }
232
233using check_value = int[1];
234using check_value = int[n];
235using check_value = int[!same(4, 4)];
236using check_value = int[same(n, n)];
237using check_value = int[sameTemporary(9)];
238
239}
240