summaryrefslogtreecommitdiff
path: root/clang/test/SemaTemplate/template-id-expr.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/test/SemaTemplate/template-id-expr.cpp')
-rw-r--r--clang/test/SemaTemplate/template-id-expr.cpp98
1 files changed, 98 insertions, 0 deletions
diff --git a/clang/test/SemaTemplate/template-id-expr.cpp b/clang/test/SemaTemplate/template-id-expr.cpp
new file mode 100644
index 0000000..4416f92
--- /dev/null
+++ b/clang/test/SemaTemplate/template-id-expr.cpp
@@ -0,0 +1,98 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// PR5336
+template<typename FromCl>
+struct isa_impl_cl {
+ template<class ToCl>
+ static void isa(const FromCl &Val) { }
+};
+
+template<class X, class Y>
+void isa(const Y &Val) { return isa_impl_cl<Y>::template isa<X>(Val); }
+
+class Value;
+void f0(const Value &Val) { isa<Value>(Val); }
+
+// Implicit template-ids.
+template<typename T>
+struct X0 {
+ template<typename U>
+ void f1();
+
+ template<typename U>
+ void f2(U) {
+ f1<U>();
+ }
+};
+
+void test_X0_int(X0<int> xi, float f) {
+ xi.f2(f);
+}
+
+// Not template-id expressions, but they almost look like it.
+template<typename F>
+struct Y {
+ Y(const F&);
+};
+
+template<int I>
+struct X {
+ X(int, int);
+ void f() {
+ Y<X<I> >(X<I>(0, 0));
+ Y<X<I> >(::X<I>(0, 0));
+ }
+};
+
+template struct X<3>;
+
+// 'template' as a disambiguator.
+// PR7030
+struct Y0 {
+ template<typename U>
+ void f1(U);
+
+ template<typename U>
+ static void f2(U);
+
+ void f3(int);
+
+ static int f4(int);
+ template<typename U>
+ static void f4(U);
+
+ template<typename U>
+ void f() {
+ Y0::template f1<U>(0);
+ Y0::template f1(0);
+ this->template f1(0);
+
+ Y0::template f2<U>(0);
+ Y0::template f2(0);
+
+ Y0::template f3(0); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
+ Y0::template f3(); // expected-error {{'f3' following the 'template' keyword does not refer to a template}}
+
+ int x;
+ x = Y0::f4(0);
+ x = Y0::f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+ x = Y0::template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+
+ x = this->f4(0);
+ x = this->f4<int>(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+ x = this->template f4(0); // expected-error {{assigning to 'int' from incompatible type 'void'}}
+ }
+};
+
+struct A {
+ template<int I>
+ struct B {
+ static void b1();
+ };
+};
+
+template<int I>
+void f5() {
+ A::template B<I>::template b1(); // expected-error {{'b1' following the 'template' keyword does not refer to a template}}
+}
+
+template void f5<0>(); // expected-note {{in instantiation of function template specialization 'f5<0>' requested here}}