constant-expression-cxx11.cpp revision b78c0b66481a59dbef7ac2a454e4f89448909749
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