1// RUN: %clang_cc1 -fsyntax-only -verify %s
2// PR5336
3template<typename FromCl>
4struct isa_impl_cl {
5 template<class ToCl>
6 static void isa(const FromCl &Val) { }
7};
8
9template<class X, class Y>
10void isa(const Y &Val) {   return isa_impl_cl<Y>::template isa<X>(Val); }
11
12class Value;
13void f0(const Value &Val) { isa<Value>(Val); }
14
15// Implicit template-ids.
16template<typename T>
17struct X0 {
18  template<typename U>
19  void f1();
20
21  template<typename U>
22  void f2(U) {
23    f1<U>();
24  }
25};
26
27void test_X0_int(X0<int> xi, float f) {
28  xi.f2(f);
29}
30
31// Not template-id expressions, but they almost look like it.
32template<typename F>
33struct Y {
34  Y(const F&);
35};
36
37template<int I>
38struct X {
39  X(int, int);
40  void f() {
41    Y<X<I> >(X<I>(0, 0));
42    Y<X<I> >(::X<I>(0, 0));
43  }
44};
45
46template struct X<3>;
47
48// 'template' as a disambiguator.
49// PR7030
50struct Y0 {
51  template<typename U>
52  void f1(U);
53
54  template<typename U>
55  static void f2(U);
56
57  void f3(int);
58
59  static int f4(int);
60  template<typename U>
61  static void f4(U);
62
63  template<typename U>
64  void f() {
65    Y0::template f1<U>(0);
66    Y0::template f1(0);
67    this->template f1(0);
68
69    Y0::template f2<U>(0);
70    Y0::template f2(0);
71
72    Y0::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
73    Y0::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
74
75    int x;
76    x = Y0::f4(0);
77    x = Y0::f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
78    x = Y0::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
79
80    x = this->f4(0);
81    x = this->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
82    x = this->template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
83  }
84};
85
86struct A {
87  template<int I>
88  struct B {
89    static void b1();
90  };
91};
92
93template<int I>
94void f5() {
95  A::template B<I>::template b1(); // expected-error {{'b1' following the 'template' keyword does not refer to a template}}
96}
97
98template void f5<0>(); // expected-note {{in instantiation of function template specialization 'f5<0>' requested here}}
99