]>
Commit | Line | Data |
---|---|---|
223e47cc LB |
1 | // RUN: %clang_cc1 -std=c++11 -verify %s |
2 | ||
3 | // Check that we deal with cases where the instantiation of a class template | |
4 | // recursively requires the instantiation of the same template. | |
5 | namespace test1 { | |
6 | template<typename T> struct A { | |
7 | struct B { // expected-note {{not complete until the closing '}'}} | |
8 | B b; // expected-error {{has incomplete type 'test1::A<int>::B'}} | |
9 | }; | |
10 | B b; // expected-note {{in instantiation of}} | |
11 | }; | |
12 | A<int> a; // expected-note {{in instantiation of}} | |
13 | } | |
14 | ||
15 | namespace test2 { | |
16 | template<typename T> struct A { | |
17 | struct B { | |
18 | struct C {}; | |
19 | char c[1 + C()]; // expected-error {{invalid operands to binary expression}} | |
20 | friend constexpr int operator+(int, C) { return 4; } | |
21 | }; | |
22 | B b; // expected-note {{in instantiation of}} | |
23 | }; | |
24 | A<int> a; // expected-note {{in instantiation of}} | |
25 | } | |
26 | ||
27 | namespace test3 { | |
28 | // PR12317 | |
29 | template<typename T> struct A { | |
30 | struct B { | |
31 | enum { Val = 1 }; | |
32 | char c[1 + Val]; // ok | |
33 | }; | |
34 | B b; | |
35 | }; | |
36 | A<int> a; | |
37 | } | |
38 | ||
39 | namespace test4 { | |
40 | template<typename T> struct M { typedef int type; }; | |
41 | template<typename T> struct A { | |
42 | struct B { // expected-note {{not complete until the closing '}'}} | |
43 | int k[typename A<typename M<T>::type>::B().k[0] + 1]; // expected-error {{incomplete type}} | |
44 | }; | |
45 | B b; // expected-note {{in instantiation of}} | |
46 | }; | |
47 | A<int> a; // expected-note {{in instantiation of}} | |
48 | } | |
49 | ||
50 | // FIXME: PR12298: Recursive constexpr function template instantiation leads to | |
51 | // stack overflow. | |
52 | #if 0 | |
53 | namespace test5 { | |
54 | template<typename T> struct A { | |
55 | constexpr T f(T k) { return g(k); } | |
56 | constexpr T g(T k) { | |
57 | return k ? f(k-1)+1 : 0; | |
58 | } | |
59 | }; | |
60 | // This should be accepted. | |
61 | constexpr int x = A<int>().f(5); | |
62 | } | |
63 | ||
64 | namespace test6 { | |
65 | template<typename T> constexpr T f(T); | |
66 | template<typename T> constexpr T g(T t) { | |
67 | typedef int arr[f(T())]; | |
68 | return t; | |
69 | } | |
70 | template<typename T> constexpr T f(T t) { | |
71 | typedef int arr[g(T())]; | |
72 | return t; | |
73 | } | |
74 | // This should be ill-formed. | |
75 | int n = f(0); | |
76 | } | |
77 | ||
78 | namespace test7 { | |
79 | template<typename T> constexpr T g(T t) { | |
80 | return t; | |
81 | } | |
82 | template<typename T> constexpr T f(T t) { | |
83 | typedef int arr[g(T())]; | |
84 | return t; | |
85 | } | |
86 | // This should be accepted. | |
87 | int n = f(0); | |
88 | } | |
89 | #endif |