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); // 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> 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 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> 110 void f() { 111 Y1::template f1<U>(0); 112 Y1::template f1(0); 113 this->template f1(0); 114 115 Y1::template f2<U>(0); 116 Y1::template f2(0); 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 {{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 {{assigning to 'int' from incompatible type 'void'}} 129 } 130 }; 131 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> 139 void f(Y1 *p) { 140 Y1::template f1<U>(0); 141 Y1::template f1(0); 142 p->template f1(0); 143 144 Y1::template f2<U>(0); 145 Y1::template f2(0); 146 147 Y1::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}} 148 Y1::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}} 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'}} 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'}} 158 } 159 }; 160 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> 171 void f5() { 172 A::template B<I>::template b1(); // expected-error {{'b1' following the 'template' keyword does not refer to a template}} 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 {{type alias template 'D' cannot be referenced with a 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