1a5728872c7702ddd09537c95bc3cbd20e1f2fb09Daniel Dunbar// RUN: %clang_cc1 -fsyntax-only -verify %s
2fd2300e1ee0eab6c51862a92d3f3c72540b36b23Douglas Gregor// PR5336
3fd2300e1ee0eab6c51862a92d3f3c72540b36b23Douglas Gregortemplate<typename FromCl>
4fd2300e1ee0eab6c51862a92d3f3c72540b36b23Douglas Gregorstruct isa_impl_cl {
5fd2300e1ee0eab6c51862a92d3f3c72540b36b23Douglas Gregor template<class ToCl>
6fd2300e1ee0eab6c51862a92d3f3c72540b36b23Douglas Gregor static void isa(const FromCl &Val) { }
7fd2300e1ee0eab6c51862a92d3f3c72540b36b23Douglas Gregor};
8fd2300e1ee0eab6c51862a92d3f3c72540b36b23Douglas Gregor
9fd2300e1ee0eab6c51862a92d3f3c72540b36b23Douglas Gregortemplate<class X, class Y>
10fd2300e1ee0eab6c51862a92d3f3c72540b36b23Douglas Gregorvoid isa(const Y &Val) {   return isa_impl_cl<Y>::template isa<X>(Val); }
11fd2300e1ee0eab6c51862a92d3f3c72540b36b23Douglas Gregor
12fd2300e1ee0eab6c51862a92d3f3c72540b36b23Douglas Gregorclass Value;
13fd2300e1ee0eab6c51862a92d3f3c72540b36b23Douglas Gregorvoid f0(const Value &Val) { isa<Value>(Val); }
148a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregor
158a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregor// Implicit template-ids.
168a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregortemplate<typename T>
178a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregorstruct X0 {
188a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregor  template<typename U>
198a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregor  void f1();
208a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregor
218a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregor  template<typename U>
228a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregor  void f2(U) {
238a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregor    f1<U>();
248a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregor  }
258a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregor};
268a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregor
278a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregorvoid test_X0_int(X0<int> xi, float f) {
288a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregor  xi.f2(f);
298a4386b3634065b96d08f94736bc1f953e385f50Douglas Gregor}
30ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregor
31ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregor// Not template-id expressions, but they almost look like it.
32ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregortemplate<typename F>
33ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregorstruct Y {
34ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregor  Y(const F&);
35ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregor};
36ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregor
37ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregortemplate<int I>
38ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregorstruct X {
39ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregor  X(int, int);
40ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregor  void f() {
41ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregor    Y<X<I> >(X<I>(0, 0));
42ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregor    Y<X<I> >(::X<I>(0, 0));
43ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregor  }
44ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregor};
45ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregor
46ae4c77dc8a77ee89e5b2de8003283249e38075c3Douglas Gregortemplate struct X<3>;
470278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor
480278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor// 'template' as a disambiguator.
490278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor// PR7030
500278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregorstruct Y0 {
510278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor  template<typename U>
520278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor  void f1(U);
530278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor
540278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor  template<typename U>
550278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor  static void f2(U);
560278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor
570278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor  void f3(int);
580278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor
590278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor  static int f4(int);
600278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor  template<typename U>
610278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor  static void f4(U);
620278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor
630278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor  template<typename U>
640278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor  void f() {
651a15dae8be2b28e02b6639aa92b832465c5be420Douglas Gregor    Y0::template f1<U>(0);
661a15dae8be2b28e02b6639aa92b832465c5be420Douglas Gregor    Y0::template f1(0);
670278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor    this->template f1(0);
680278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor
691a15dae8be2b28e02b6639aa92b832465c5be420Douglas Gregor    Y0::template f2<U>(0);
701a15dae8be2b28e02b6639aa92b832465c5be420Douglas Gregor    Y0::template f2(0);
710278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor
720278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor    Y0::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
730278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor    Y0::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
740278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor
750278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor    int x;
760278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor    x = Y0::f4(0);
770278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor    x = Y0::f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
781a15dae8be2b28e02b6639aa92b832465c5be420Douglas Gregor    x = Y0::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
790278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor
800278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor    x = this->f4(0);
810278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor    x = this->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
820278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor    x = this->template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
830278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor  }
840278e123b4606ea15dbfa717e9c5a76a5ef2bc7dDouglas Gregor};
859d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnara
869d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnarastruct A {
879d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnara  template<int I>
889d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnara  struct B {
899d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnara    static void b1();
909d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnara  };
919d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnara};
929d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnara
939d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnaratemplate<int I>
949d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnaravoid f5() {
959d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnara  A::template B<I>::template b1(); // expected-error {{'b1' following the 'template' keyword does not refer to a template}}
969d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnara}
979d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnara
989d9922af13edf3ddf8804a41a98d997324fdd58eAbramo Bagnaratemplate void f5<0>(); // expected-note {{in instantiation of function template specialization 'f5<0>' requested here}}
99