Clang Project

clang_source_code/test/SemaTemplate/template-id-expr.cpp
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
5template<typename FromCl>
6struct isa_impl_cl {
7 template<class ToCl>
8 static void isa(const FromCl &Val) { }
9};
10
11template<class X, class Y>
12void isa(const Y &Val) {   return isa_impl_cl<Y>::template isa<X>(Val); }
13
14class Value;
15void f0(const Value &Val) { isa<Value>(Val); }
16
17// Implicit template-ids.
18template<typename T>
19struct X0 {
20  template<typename U>
21  void f1();
22  
23  template<typename U>
24  void f2(U) {
25    f1<U>();
26  }
27};
28
29void 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.
34template<typename F>
35struct Y {
36  Y(const F&);
37};
38
39template<int I>
40struct 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
48template struct X<3>;
49
50// 'template' as a disambiguator.
51// PR7030
52struct 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
88template<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
95template<typename T>
96struct 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
132void use_Y1(Y1<int> y1) { y1.f<int>(); } // expected-note {{in instantiation of}}
133
134template<typename T>
135struct 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
161void use_Y2(Y2<int> y2) { y2.f<int>(0); } // expected-note {{in instantiation of}}
162
163struct A {
164  template<int I>
165  struct B {
166    static void b1(); // expected-note {{declared as a non-template here}}
167  };
168};
169
170template<int I>
171void f5() {
172  A::template B<I>::template b1(); // expected-error {{'b1' following the 'template' keyword does not refer to a template}}
173}
174
175template void f5<0>(); // expected-note {{in instantiation of function template specialization 'f5<0>' requested here}}
176
177class C {};
178template <template <typename> class D>
179class 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
187template<typename T> using D = int; // expected-note {{declared here}} 
188E<D> ed; // expected-note {{instantiation of}}
189