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>
8  static void isa(const FromCl &Val) { }
9 };
10 
11 template<class X, class Y>
12 void isa(const Y &Val) {   return isa_impl_cl<Y>::template isa<X>(Val); }
13 
14 class Value;
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>
24   void f2(U) {
25     f1<U>();
26   }
27 };
28 
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);
42   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);
60 
61   static int f4(int);
62   template<typename U>
63   static void f4(U);
64 
65   template<typename U>
66   void f() {
67     Y0::template f1<U>(0);
68     Y0::template f1(0);
69     this->template f1(0);
70 
71     Y0::template f2<U>(0);
72     Y0::template f2(0);
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 {{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 {{assigning to 'int' from incompatible type 'void'}}
85   }
86 };
87 
88 struct A {
89   template<int I>
90   struct B {
91     static void b1();
92   };
93 };
94 
95 template<int I>
96 void f5() {
97   A::template B<I>::template b1(); // expected-error {{'b1' following the 'template' keyword does not refer to a template}}
98 }
99 
100 template void f5<0>(); // expected-note {{in instantiation of function template specialization 'f5<0>' requested here}}
101 
102 class C {};
103 template <template <typename> class D>
104 class E {
105   template class D<C>;  // expected-error {{expected '<' after 'template'}}
106   template<> class D<C>;  // expected-error {{cannot specialize a template template parameter}}
107   friend class D<C>; // expected-error {{type alias template 'D' cannot be referenced with a class specifier}}
108 };
109 #if __cplusplus <= 199711L
110 // expected-warning@+2 {{extension}}
111 #endif
112 template<typename T> using D = int; // expected-note {{declared here}}
113 E<D> ed; // expected-note {{instantiation of}}
114