xref: /llvm-project/clang/test/SemaTemplate/template-id-expr.cpp (revision bbddedb3bf7b17c5caa4732c4a94dde8824c5e3a)
1 // RUN: %clang_cc1 -fsyntax-only -verify %s
2 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++03 %s
3 // RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
4 // PR5336
5 template<typename FromCl>
6 struct isa_impl_cl {
7  template<class ToCl>
isaisa_impl_cl8  static void isa(const FromCl &Val) { }
9 };
10 
11 template<class X, class Y>
isa(const Y & Val)12 void isa(const Y &Val) {   return isa_impl_cl<Y>::template isa<X>(Val); }
13 
14 class Value;
f0(const Value & Val)15 void f0(const Value &Val) { isa<Value>(Val); }
16 
17 // Implicit template-ids.
18 template<typename T>
19 struct X0 {
20   template<typename U>
21   void f1();
22 
23   template<typename U>
f2X024   void f2(U) {
25     f1<U>();
26   }
27 };
28 
test_X0_int(X0<int> xi,float f)29 void test_X0_int(X0<int> xi, float f) {
30   xi.f2(f);
31 }
32 
33 // Not template-id expressions, but they almost look like it.
34 template<typename F>
35 struct Y {
36   Y(const F&);
37 };
38 
39 template<int I>
40 struct X {
41   X(int, int);
fX42   void f() {
43     Y<X<I> >(X<I>(0, 0));
44     Y<X<I> >(::X<I>(0, 0));
45   }
46 };
47 
48 template struct X<3>;
49 
50 // 'template' as a disambiguator.
51 // PR7030
52 struct Y0 {
53   template<typename U>
54   void f1(U);
55 
56   template<typename U>
57   static void f2(U);
58 
59   void f3(int); // expected-note 2{{declared as a non-template here}}
60 
61   static int f4(int);
62   template<typename U>
63   static void f4(U);
64 
65   template<typename U>
fY066   void f() {
67     Y0::template f1<U>(0);
68     Y0::template f1(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
69     this->template f1(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
70 
71     Y0::template f2<U>(0);
72     Y0::template f2(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
73 
74     Y0::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
75     Y0::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
76 
77     int x;
78     x = Y0::f4(0);
79     x = Y0::f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
80     x = Y0::template f4(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} expected-error {{assigning to 'int' from incompatible type 'void'}}
81 
82     x = this->f4(0);
83     x = this->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
84     x = this->template f4(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} expected-error {{assigning to 'int' from incompatible type 'void'}}
85   }
86 };
87 
88 template<typename U> void Y0
89   ::template // expected-error {{expected unqualified-id}}
90     f1(U) {}
91 
92 // FIXME: error recovery is awful without this.
93     ;
94 
95 template<typename T>
96 struct Y1 {
97   template<typename U>
98   void f1(U);
99 
100   template<typename U>
101   static void f2(U);
102 
103   void f3(int); // expected-note 4{{declared as a non-template here}}
104 
105   static int f4(int);
106   template<typename U>
107   static void f4(U);
108 
109   template<typename U>
fY1110   void f() {
111     Y1::template f1<U>(0);
112     Y1::template f1(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
113     this->template f1(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
114 
115     Y1::template f2<U>(0);
116     Y1::template f2(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
117 
118     Y1::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
119     Y1::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
120 
121     int x;
122     x = Y1::f4(0);
123     x = Y1::f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
124     x = Y1::template f4(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} expected-error {{assigning to 'int' from incompatible type 'void'}}
125 
126     x = this->f4(0);
127     x = this->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
128     x = this->template f4(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}} expected-error {{assigning to 'int' from incompatible type 'void'}}
129   }
130 };
131 
use_Y1(Y1<int> y1)132 void use_Y1(Y1<int> y1) { y1.f<int>(); } // expected-note {{in instantiation of}}
133 
134 template<typename T>
135 struct Y2 : Y1<T> {
136   typedef ::Y1<T> Y1;
137 
138   template<typename U>
fY2139   void f(Y1 *p) {
140     Y1::template f1<U>(0);
141     Y1::template f1(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
142     p->template f1(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
143 
144     Y1::template f2<U>(0);
145     Y1::template f2(0); // expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
146 
147     Y1::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
148     Y1::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
149 
150     int x;
151     x = Y1::f4(0);
152     x = Y1::f4<int>(0); // expected-error {{use 'template'}} expected-error {{assigning to 'int' from incompatible type 'void'}}
153     x = Y1::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
154 
155     x = p->f4(0);
156     x = p->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} expected-error {{use 'template'}}
157     x = p->template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
158   }
159 };
160 
use_Y2(Y2<int> y2)161 void use_Y2(Y2<int> y2) { y2.f<int>(0); } // expected-note {{in instantiation of}}
162 
163 struct A {
164   template<int I>
165   struct B {
166     static void b1(); // expected-note {{declared as a non-template here}}
167   };
168 };
169 
170 template<int I>
f5()171 void f5() {
172   A::template B<I>::template b1(); // expected-error {{'b1' following the 'template' keyword does not refer to a template}} expected-error {{a template argument list is expected after a name prefixed by the template keyword}}
173 }
174 
175 template void f5<0>(); // expected-note {{in instantiation of function template specialization 'f5<0>' requested here}}
176 
177 class C {};
178 template <template <typename> class D>
179 class E {
180   template class D<C>;  // expected-error {{expected '<' after 'template'}}
181   template<> class D<C>;  // expected-error {{cannot specialize a template template parameter}}
182   friend class D<C>; // expected-error {{alias template 'D' cannot be referenced with the 'class' specifier}}
183 };
184 #if __cplusplus <= 199711L
185 // expected-warning@+2 {{extension}}
186 #endif
187 template<typename T> using D = int; // expected-note {{declared here}}
188 E<D> ed; // expected-note {{instantiation of}}
189 
190 namespace non_functions {
191 
192 #if __cplusplus >= 201103L
193 namespace PR88832 {
194 template <typename T> struct O {
195   static const T v = 0;
196 };
197 
198 struct P {
199   template <typename T> using I = typename O<T>::v; // #TypeAlias
200 };
201 
202 struct Q {
foonon_functions::PR88832::Q203   template <typename T> int foo() {
204     return T::template I<int>;
205     // expected-error@-1 {{'P::I' is expected to be a non-type template, but instantiated to a type alias template}}
206     // expected-note@#TypeAlias {{type alias template declared here}}
207   }
208 };
209 
bar()210 int bar() {
211   return Q().foo<P>(); // expected-note-re {{function template specialization {{.*}} requested here}}
212 }
213 
214 } // namespace PR88832
215 #endif
216 
217 namespace PR63243 {
218 
219 namespace std {
220 template <class T> struct add_pointer { // #add_pointer
221 };
222 } // namespace std
223 
224 class A {};
225 
main()226 int main() {
227   std::__add_pointer<A>::type ptr;
228   // expected-warning@-1 {{keyword '__add_pointer' will be made available as an identifier here}}
229   // expected-error@-2 {{no template named '__add_pointer'}}
230   // expected-note@#add_pointer {{'add_pointer' declared here}}
231   // expected-error-re@-4 {{no type named 'type' in '{{.*}}std::add_pointer<{{.*}}A>'}}
232 
233   __add_pointer<A>::type ptr2;
234   // expected-error@-1 {{no template named '__add_pointer'}}
235   // expected-error-re@-2 {{no type named 'type' in '{{.*}}std::add_pointer<{{.*}}A>'}}
236   // expected-note@#add_pointer {{'std::add_pointer' declared here}}
237 }
238 
239 } // namespace PR63243
240 
241 namespace PR48673 {
242 
243 template <typename T> struct C {
244   template <int TT> class Type {}; // #ClassTemplate
245 };
246 
247 template <typename T1> struct A {
248 
249   template <typename T2>
foonon_functions::PR48673::A250   void foo(T2) {}
251 
foonon_functions::PR48673::A252   void foo() {
253     C<T1>::template Type<2>;
254     // expected-error@-1 {{'C<float>::Type' is expected to be a non-type template, but instantiated to a class template}}}
255     // expected-note@#ClassTemplate {{class template declared here}}
256 
257     foo(C<T1>::Type<2>); // expected-error {{expected expression}}
258 
259     foo(C<T1>::template Type<2>);
260     // expected-error@-1 {{'C<float>::Type' is expected to be a non-type template, but instantiated to a class template}}
261     // expected-note@#ClassTemplate {{class template declared here}}
262 
263     foo(C<T1>::template Type<2>());
264     // expected-error@-1 {{'C<float>::Type' is expected to be a non-type template, but instantiated to a class template}}
265     // expected-error@-2 {{called object type '<dependent type>' is not a function or function pointer}}
266     // expected-note@#ClassTemplate {{class template declared here}}
267 
268     foo(typename C<T1>::template Type<2>());
269   }
270 };
271 
test()272 void test() {
273   A<float>().foo(); // expected-note-re {{instantiation of member function {{.*}} requested here}}
274 }
275 
276 } // namespace PR48673
277 
278 }
279