Clang Project

clang_source_code/test/SemaTemplate/constexpr-instantiate.cpp
1// RUN: %clang_cc1 -std=c++11 -verify %s
2
3namespace UseBeforeDefinition {
4  struct A {
5    template<typename T> static constexpr T get() { return T(); }
6    // ok, not a constant expression.
7    int n = get<int>();
8  };
9
10  // ok, constant expression.
11  constexpr int j = A::get<int>();
12
13  template<typename T> constexpr int consume(T);
14  // ok, not a constant expression.
15  const int k = consume(0); // expected-note {{here}}
16
17  template<typename T> constexpr int consume(T) { return 0; }
18  // ok, constant expression.
19  constexpr int l = consume(0);
20
21  constexpr int m = k; // expected-error {{constant expression}} expected-note {{initializer of 'k'}}
22}
23
24namespace IntegralConst {
25  template<typename T> constexpr T f(T n) { return n; }
26  enum E {
27    v = f(0), w = f(1) // ok
28  };
29  static_assert(w == 1, "");
30
31  char arr[f('x')]; // ok
32  static_assert(sizeof(arr) == 'x', "");
33}
34
35namespace ConvertedConst {
36  template<typename T> constexpr T f(T n) { return n; }
37  int f() {
38    switch (f()) {
39      case f(4): return 0;
40    }
41    return 1;
42  }
43}
44
45namespace OverloadResolution {
46  template<typename T> constexpr T f(T t) { return t; }
47
48  template<int n> struct S { };
49
50  template<typename T> auto g(T t) -> S<f(sizeof(T))> &;
51  char &f(...);
52
53  template<typename T> auto h(T t[f(sizeof(T))]) -> decltype(&*t) {
54    return t;
55  }
56
57  S<4> &k = g(0);
58  int *p, *q = h(p);
59}
60
61namespace DataMember {
62  template<typename T> struct S { static const int k; };
63  const int n = S<int>::k; // expected-note {{here}}
64  template<typename T> const int S<T>::k = 0;
65  constexpr int m = S<int>::k; // ok
66  constexpr int o = n; // expected-error {{constant expression}} expected-note {{initializer of 'n'}}
67}
68
69namespace Reference {
70  const int k = 5;
71  template<typename T> struct S {
72    static volatile int &r;
73  };
74  template<typename T> volatile int &S<T>::r = const_cast<volatile int&>(k);
75  constexpr int n = const_cast<int&>(S<int>::r);
76  static_assert(n == 5, "");
77}
78
79namespace Unevaluated {
80  // We follow the current proposed resolution of core issue 1581: a constexpr
81  // function template specialization requires a definition if:
82  //  * it is odr-used, or would be odr-used except that it appears within the
83  //    definition of a template, or
84  //  * it is used within a braced-init-list, where it may be necessary for
85  //    detecting narrowing conversions.
86  //
87  // We apply this both for instantiating constexpr function template
88  // specializations and for implicitly defining defaulted constexpr special
89  // member functions.
90  //
91  // FIXME: None of this is required by the C++ standard yet. The rules in this
92  //        area are subject to change.
93  namespace NotConstexpr {
94    template<typename T> struct S {
95      S() : n(0) {}
96      S(const S&) : n(T::error) {}
97      int n;
98    };
99    struct U : S<int> {};
100    decltype(U(U())) u;
101  }
102  namespace Constexpr {
103    template<typename T> struct S {
104      constexpr S() : n(0) {}
105      constexpr S(const S&) : n(T::error) {}
106      int n;
107    };
108    struct U : S<int> {};
109    decltype(U(U())) u;
110  }
111  namespace ConstexprList {
112    template<int N> struct S {
113      constexpr S() : n(0) {
114        static_assert(N >= 0, "");
115      }
116      constexpr operator int() const { return 0; }
117      int n;
118    };
119    struct U : S<0> {};
120    // ok, trigger instantiation within a list
121    decltype(char{U()}) t0;
122    decltype(new char{S<1>()}) t1; // expected-warning {{side effects}}
123    decltype((char){S<2>()}) t2;
124    decltype(+(char[1]){{S<3>()}}) t3;
125    // do not trigger instantiation outside a list
126    decltype(char(S<-1>())) u1;
127    decltype(new char(S<-2>())) u2; // expected-warning {{side effects}}
128    decltype((char)(S<-3>())) u3;
129  }
130
131  namespace PR11851_Comment0 {
132    template<int x> constexpr int f() { return x; }
133    template<int i> void ovf(int (&x)[f<i>()]);
134    void f() { int x[10]; ovf<10>(x); }
135  }
136
137  namespace PR11851_Comment1 {
138    template<typename T>
139    constexpr bool Integral() {
140      return true;
141    }
142    template<typename T, bool Int = Integral<T>()>
143    struct safe_make_unsigned {
144      typedef T type;
145    };
146    template<typename T>
147    using Make_unsigned = typename safe_make_unsigned<T>::type;
148    template <typename T>
149    struct get_distance_type {
150      using type = int;
151    };
152    template<typename R>
153    auto size(R) -> Make_unsigned<typename get_distance_type<R>::type>;
154    auto check() -> decltype(size(0));
155  }
156
157  namespace PR11851_Comment6 {
158    template<int> struct foo {};
159    template<class> constexpr int bar() { return 0; }
160    template<class T> foo<bar<T>()> foobar();
161    auto foobar_ = foobar<int>();
162  }
163
164  namespace PR11851_Comment9 {
165    struct S1 {
166      constexpr S1() {}
167      constexpr operator int() const { return 0; }
168    };
169    int k1 = sizeof(short{S1(S1())});
170
171    struct S2 {
172      constexpr S2() {}
173      constexpr operator int() const { return 123456; }
174    };
175    int k2 = sizeof(short{S2(S2())}); // expected-error {{cannot be narrowed}} expected-note {{insert an explicit cast to silence this issue}}
176  }
177
178  namespace PR12288 {
179    template <typename> constexpr bool foo() { return true; }
180    template <bool> struct bar {};
181    template <typename T> bar<foo<T>()> baz() { return bar<foo<T>()>(); }
182    int main() { baz<int>(); }
183  }
184
185  namespace PR13423 {
186    template<bool, typename> struct enable_if {};
187    template<typename T> struct enable_if<true, T> { using type = T; };
188
189    template<typename T> struct F {
190      template<typename U>
191      static constexpr bool f() { return sizeof(T) < U::size; }
192
193      template<typename U>
194      static typename enable_if<f<U>(), void>::type g() {} // expected-note {{requirement 'f<Unevaluated::PR13423::U>()' was not satisfied}}
195    };
196
197    struct U { static constexpr int size = 2; };
198
199    void h() { F<char>::g<U>(); }
200    void i() { F<int>::g<U>(); } // expected-error {{no matching function}}
201  }
202
203  namespace PR14203 {
204    struct duration { constexpr duration() {} };
205
206    template <typename>
207    void sleep_for() {
208      constexpr duration max = duration();
209    }
210  }
211
212  // For variables, we instantiate when they are used in a context in which
213  // evaluation could be required (odr-used, used in a template whose
214  // instantiations would odr-use, or used in list initialization), if they
215  // can be used as a constant (const integral or constexpr).
216  namespace Variables {
217    template<int N> struct A {
218      static const int k;
219      static int n;
220    };
221    template<const int *N> struct B {};
222    template<int N> constexpr int A<N>::k = *(int[N]){N}; // expected-error 1+{{negative}}
223    template<int N> int A<N>::n = *(int[N]){0};
224
225    template <typename> void f() {
226      (void)A<-1>::n; // ok
227      (void)A<-1>::k; // expected-note {{instantiation of }}
228      B<&A<-2>::n> b1; // ok
229      B<&A<-2>::k> b2; // expected-note {{instantiation of }}
230    };
231
232    decltype(A<-3>::k) d1 = 0; // ok
233    decltype(char{A<-4>::k}) d2 = 0; // expected-note {{instantiation of }} expected-error {{narrow}} expected-note {{cast}}
234    decltype(char{A<1>::k}) d3 = 0; // ok
235    decltype(char{A<1 + (unsigned char)-1>::k}) d4 = 0; // expected-error {{narrow}} expected-note {{cast}}
236  }
237}
238
239namespace NoInstantiationWhenSelectingOverload {
240  // Check that we don't instantiate conversion functions when we're checking
241  // for the existence of an implicit conversion sequence, only when a function
242  // is actually chosen by overload resolution.
243  struct S {
244    template<typename T> constexpr S(T) : n(T::error) {} // expected-error {{no members}}
245    int n;
246  };
247
248  constexpr int f(S) { return 0; }
249  constexpr int f(int) { return 0; }
250
251  void g() { f(0); }
252  void h() { (void)sizeof(char{f(0)}); }
253  void i() { (void)sizeof(char{f("oops")}); } // expected-note {{instantiation of}}
254}
255
256namespace PR20090 {
257  template <typename T> constexpr T fact(T n) {
258    return n == 0 ? 1 : [=] { return n * fact(n - 1); }();
259  }
260  static_assert(fact(0) == 1, "");
261}
262