1 | // RUN: %clang_cc1 -std=c++11 -verify %s |
2 | |
3 | // The implicit specialization of a class template specialuzation causes the |
4 | // implicit instantiation of the declarations, but not the definitions or |
5 | // default arguments, of: |
6 | |
7 | // FIXME: Many omitted cases |
8 | |
9 | // - scoped member enumerations |
10 | namespace ScopedEnum { |
11 | template<typename T> struct ScopedEnum1 { |
12 | enum class E { |
13 | e = T::error // expected-error {{'double' cannot be used prior to '::'}} |
14 | }; |
15 | }; |
16 | ScopedEnum1<int> se1; // ok |
17 | |
18 | template<typename T> struct ScopedEnum2 { |
19 | enum class E : T { // expected-error {{non-integral type 'void *' is an invalid underlying type}} |
20 | e = 0 |
21 | }; |
22 | }; |
23 | ScopedEnum2<void*> se2; // expected-note {{here}} |
24 | |
25 | template<typename T> struct UnscopedEnum3 { |
26 | enum class E : T { |
27 | e = 4 |
28 | }; |
29 | int arr[(int)E::e]; |
30 | }; |
31 | UnscopedEnum3<int> ue3; // ok |
32 | |
33 | ScopedEnum1<double>::E e1; // ok |
34 | ScopedEnum1<double>::E e2 = decltype(e2)::e; // expected-note {{in instantiation of enumeration 'ScopedEnum::ScopedEnum1<double>::E' requested here}} |
35 | |
36 | // DR1484 specifies that enumerations cannot be separately instantiated, |
37 | // they will be instantiated with the rest of the template declaration. |
38 | template<typename T> |
39 | int f() { |
40 | enum class E { |
41 | e = T::error // expected-error {{has no members}} |
42 | }; |
43 | return (int)E(); |
44 | } |
45 | int test1 = f<int>(); // expected-note {{here}} |
46 | |
47 | template<typename T> |
48 | int g() { |
49 | enum class E { |
50 | e = T::error // expected-error {{has no members}} |
51 | }; |
52 | return E::e; |
53 | } |
54 | int test2 = g<int>(); // expected-note {{here}} |
55 | } |
56 | |
57 | // - static data members |
58 | namespace StaticDataMembers { |
59 | template<typename T> |
60 | struct A { |
61 | static const int n = T::error; // expected-error {{has no members}} |
62 | static inline int m = T::error; // expected-warning {{extension}} |
63 | }; |
64 | A<int> ai; // expected-note {{here}} |
65 | } |
66 | |
67 | // And it cases the implicit instantiations of the definitions of: |
68 | |
69 | // - unscoped member enumerations |
70 | namespace UnscopedEnum { |
71 | template<typename T> struct UnscopedEnum1 { |
72 | enum E { |
73 | e = T::error // expected-error {{'int' cannot be used prior to '::'}} |
74 | }; |
75 | }; |
76 | UnscopedEnum1<int> ue1; // expected-note {{here}} |
77 | |
78 | template<typename T> struct UnscopedEnum2 { |
79 | enum E : T { // expected-error {{non-integral type 'void *' is an invalid underlying type}} |
80 | e = 0 |
81 | }; |
82 | }; |
83 | UnscopedEnum2<void*> ue2; // expected-note {{here}} |
84 | |
85 | template<typename T> struct UnscopedEnum3 { |
86 | enum E : T { |
87 | e = 4 |
88 | }; |
89 | int arr[E::e]; |
90 | }; |
91 | UnscopedEnum3<int> ue3; // ok |
92 | |
93 | template<typename T> |
94 | int f() { |
95 | enum E { |
96 | e = T::error // expected-error {{has no members}} |
97 | }; |
98 | return (int)E(); |
99 | } |
100 | int test1 = f<int>(); // expected-note {{here}} |
101 | |
102 | template<typename T> |
103 | int g() { |
104 | enum E { |
105 | e = T::error // expected-error {{has no members}} |
106 | }; |
107 | return E::e; |
108 | } |
109 | int test2 = g<int>(); // expected-note {{here}} |
110 | } |
111 | |
112 | // FIXME: |
113 | //- - member anonymous unions |
114 | |