aboutsummaryrefslogtreecommitdiff
path: root/test/SemaTemplate
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaTemplate')
-rw-r--r--test/SemaTemplate/alias-templates.cpp17
-rw-r--r--test/SemaTemplate/array-redeclaration.cpp33
-rw-r--r--test/SemaTemplate/class-template-decl.cpp6
-rw-r--r--test/SemaTemplate/class-template-spec.cpp47
-rw-r--r--test/SemaTemplate/cxx1z-decomposition.cpp33
-rw-r--r--test/SemaTemplate/cxx1z-using-declaration.cpp230
-rw-r--r--test/SemaTemplate/deduction.cpp85
-rw-r--r--test/SemaTemplate/default-expr-arguments-3.cpp55
-rw-r--r--test/SemaTemplate/dependent-type-identity.cpp9
-rw-r--r--test/SemaTemplate/instantiate-exception-spec-cxx11.cpp18
-rw-r--r--test/SemaTemplate/instantiation-default-1.cpp2
-rw-r--r--test/SemaTemplate/instantiation-depth-default.cpp17
-rw-r--r--test/SemaTemplate/ms-class-specialization-class-scope.cpp2
-rw-r--r--test/SemaTemplate/temp_arg_enum_printing.cpp6
-rw-r--r--test/SemaTemplate/temp_arg_nontype.cpp87
-rw-r--r--test/SemaTemplate/temp_arg_nontype_cxx11.cpp13
-rw-r--r--test/SemaTemplate/temp_arg_nontype_cxx1z.cpp179
-rw-r--r--test/SemaTemplate/temp_arg_template.cpp4
-rw-r--r--test/SemaTemplate/temp_arg_template_cxx1z.cpp102
-rw-r--r--test/SemaTemplate/temp_class_spec_neg.cpp6
-rw-r--r--test/SemaTemplate/temp_explicit.cpp2
-rw-r--r--test/SemaTemplate/template-id-expr.cpp2
22 files changed, 917 insertions, 38 deletions
diff --git a/test/SemaTemplate/alias-templates.cpp b/test/SemaTemplate/alias-templates.cpp
index b7078353ff1b3..bcdc84e19f7e7 100644
--- a/test/SemaTemplate/alias-templates.cpp
+++ b/test/SemaTemplate/alias-templates.cpp
@@ -220,6 +220,23 @@ namespace PR14858 {
template<typename ...T, typename ...U> void h(X<T...> &) {}
template<typename ...T, typename ...U> void h(X<U...> &) {} // ok, different
+
+ template<typename ...T> void i(auto (T ...t) -> int(&)[sizeof...(t)]);
+ auto mk_arr(int, int) -> int(&)[2];
+ void test_i() { i<int, int>(mk_arr); }
+
+#if 0 // FIXME: This causes clang to assert.
+ template<typename ...T> using Z = auto (T ...p) -> int (&)[sizeof...(p)];
+ template<typename ...T, typename ...U> void j(Z<T..., U...> &) {}
+ void test_j() { j<int, int>(mk_arr); }
+#endif
+
+ template<typename ...T> struct Q {
+ template<typename ...U> using V = int[sizeof...(U)];
+ template<typename ...U> void f(V<typename U::type..., typename T::type...> *);
+ };
+ struct B { typedef int type; };
+ void test_q(int (&a)[5]) { Q<B, B, B>().f<B, B>(&a); }
}
namespace redecl {
diff --git a/test/SemaTemplate/array-redeclaration.cpp b/test/SemaTemplate/array-redeclaration.cpp
new file mode 100644
index 0000000000000..4edee701cfc46
--- /dev/null
+++ b/test/SemaTemplate/array-redeclaration.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -fsyntax-only -verify %s
+// expected-no-diagnostics
+
+extern int array[1];
+
+template <typename>
+class C {
+ enum { D };
+public:
+ template <typename A> void foo1() {
+ extern int array[((int)C<A>::k > (int)D) ? 1 : -1];
+ }
+};
+
+template<>
+class C<int> {
+public:
+ const static int k = 2;
+};
+
+void foo2() {
+ C<char> c;
+ c.foo1<int>();
+}
+
+template<int n>
+void foo3() {
+ extern int array[n ? 1 : -1];
+}
+
+void foo4() {
+ foo3<5>();
+}
diff --git a/test/SemaTemplate/class-template-decl.cpp b/test/SemaTemplate/class-template-decl.cpp
index 63482d84df0c9..2e36cae14f600 100644
--- a/test/SemaTemplate/class-template-decl.cpp
+++ b/test/SemaTemplate/class-template-decl.cpp
@@ -10,11 +10,11 @@ namespace N {
template<typename T> class C;
}
-extern "C" {
+extern "C" { // expected-note {{extern "C" language linkage specification begins here}}
template<typename T> class D; // expected-error{{templates must have C++ linkage}}
}
-extern "C" {
+extern "C" { // expected-note 2 {{extern "C" language linkage specification begins here}}
class PR17968 {
template<typename T> class D; // expected-error{{templates must have C++ linkage}}
template<typename T> void f(); // expected-error{{templates must have C++ linkage}}
@@ -148,7 +148,7 @@ namespace redecl {
}
extern "C" template <typename T> // expected-error{{templates must have C++ linkage}}
-void DontCrashOnThis() {
+void DontCrashOnThis() { // expected-note@-1 {{extern "C" language linkage specification begins here}}
T &pT = T();
pT;
}
diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp
index 86cace19dbfbc..518ec78e6f7d0 100644
--- a/test/SemaTemplate/class-template-spec.cpp
+++ b/test/SemaTemplate/class-template-spec.cpp
@@ -137,12 +137,16 @@ namespace PR18009 {
A<int>::S<8, sizeof(int)> a; // ok
template <typename T> struct B {
- template <int N, int M> struct S; // expected-note {{declared here}}
- template <int N> struct S<N, sizeof(T) +
- N // expected-error {{non-type template argument depends on a template parameter of the partial specialization}}
- > {};
+ template <int N, int M> struct S;
+ template <int N> struct S<N, sizeof(T) + N> {}; // ok (dr1315)
};
- B<int>::S<8, sizeof(int) + 8> s; // expected-error {{undefined}}
+ B<int>::S<8, sizeof(int) + 8> b;
+
+ template <typename T> struct C {
+ template <int N, int M> struct S;
+ template <int N> struct S<N, N ? **(T(*)[N])0 : 0> {}; // expected-error {{depends on a template parameter of the partial specialization}}
+ };
+ C<int> c; // expected-note {{in instantiation of}}
template<int A> struct outer {
template<int B, int C> struct inner {};
@@ -167,10 +171,16 @@ namespace PR16519 {
// expected-warning@-2 {{variadic templates are a C++11 extension}}
#endif
- template<typename T, T ...N, T ...Extra> struct __make_integer_sequence_impl<integer_sequence<T, N...>, Extra...> {
+ // Note that the following seemingly-equivalent template parameter list is
+ // not OK; it would result in a partial specialization that is not more
+ // specialized than the primary template. (See NTTPTypeVsPartialOrder below.)
+ //
+ // template<typename T, T ...N, T ...Extra>
+ template<typename T, T ...N, typename integer_sequence<T, N...>::value_type ...Extra>
#if __cplusplus <= 199711L
- // expected-warning@-2 2 {{variadic templates are a C++11 extension}}
+ // expected-warning@-2 2{{variadic templates are a C++11 extension}}
#endif
+ struct __make_integer_sequence_impl<integer_sequence<T, N...>, Extra...> {
typedef integer_sequence<T, N..., sizeof...(N) + N..., Extra...> type;
};
@@ -193,13 +203,32 @@ namespace PR16519 {
#endif
}
+namespace NTTPTypeVsPartialOrder {
+ struct X { typedef int value_type; };
+ template<typename T> struct Y { typedef T value_type; };
+
+ template<typename T, typename T::value_type N> struct A; // expected-note {{template}}
+ template<int N> struct A<X, N> {};
+ template<typename T, T N> struct A<Y<T>, N> {}; // expected-error {{not more specialized}} expected-note {{'T' vs 'typename Y<type-parameter-0-0>::value_type'}}
+ A<X, 0> ax;
+ A<Y<int>, 0> ay;
+
+
+ template<int, typename T, typename T::value_type> struct B; // expected-note {{template}}
+ template<typename T, typename T::value_type N> struct B<0, T, N>; // expected-note {{matches}}
+ template<int N> struct B<0, X, N> {};
+ template<typename T, T N> struct B<0, Y<T>, N> {}; // expected-error {{not more specialized}} expected-note {{'T' vs 'typename Y<type-parameter-0-0>::value_type'}} expected-note {{matches}}
+ B<0, X, 0> bx;
+ B<0, Y<int>, 0> by; // expected-error {{ambiguous}}
+}
+
namespace DefaultArgVsPartialSpec {
// Check that the diagnostic points at the partial specialization, not just at
// the default argument.
template<typename T, int N =
- sizeof(T) // expected-note {{template parameter is used in default argument declared here}}
+ sizeof(T) // ok (dr1315)
> struct X {};
- template<typename T> struct X<T> {}; // expected-error {{non-type template argument depends on a template parameter of the partial specialization}}
+ template<typename T> struct X<T> {};
template<typename T,
T N = 0 // expected-note {{template parameter is declared here}}
diff --git a/test/SemaTemplate/cxx1z-decomposition.cpp b/test/SemaTemplate/cxx1z-decomposition.cpp
new file mode 100644
index 0000000000000..779c4cf75e9db
--- /dev/null
+++ b/test/SemaTemplate/cxx1z-decomposition.cpp
@@ -0,0 +1,33 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+struct A { int x, y; };
+typedef int B[2];
+struct C { template<int> int get(); };
+struct D { int x, y, z; };
+struct E { int *p, n; };
+
+namespace std {
+ using size_t = decltype(sizeof(0));
+ template<typename> struct tuple_size;
+ template<size_t, typename> struct tuple_element { using type = int; };
+}
+
+template<> struct std::tuple_size<C> { enum { value = 2 }; };
+
+template<typename T> int decomp(T &t) {
+ auto &[a, b] = t; // expected-error {{type 'D' decomposes into 3 elements, but only 2 names were provided}}
+ return a + b; // expected-error {{cannot initialize return object of type 'int' with an rvalue of type 'int *'}}
+}
+
+void test() {
+ A a;
+ B b;
+ C c;
+ D d;
+ E e;
+ decomp(a);
+ decomp(b);
+ decomp(c);
+ decomp(d); // expected-note {{in instantiation of}}
+ decomp(e); // expected-note {{in instantiation of}}
+}
diff --git a/test/SemaTemplate/cxx1z-using-declaration.cpp b/test/SemaTemplate/cxx1z-using-declaration.cpp
new file mode 100644
index 0000000000000..7bef36db1f47a
--- /dev/null
+++ b/test/SemaTemplate/cxx1z-using-declaration.cpp
@@ -0,0 +1,230 @@
+// RUN: %clang_cc1 -std=c++1z -verify %s
+
+// Test that we cope with failure to expand a pack.
+template<typename ...T> struct Unexpanded : T... {
+ using T::f; // expected-error {{unexpanded}}
+ using typename T::type; // expected-error {{unexpanded}}
+ template<typename ...U> void g(U ...u) { f(u...); } // expected-error {{undeclared identifier 'f'}}
+ void h() {
+ Unexpanded<type...> *p; // expected-error {{undeclared identifier 'type'}}
+ }
+};
+void test_Unexpanded() {
+ struct A { void f(); }; // expected-note {{must qualify}}
+ struct B { void f(int); }; // expected-note {{must qualify}}
+ Unexpanded<A, B>().g(0); // expected-note {{instantiation of}}
+}
+
+// Test using non-type members from pack of base classes.
+template<typename ...T> struct A : T... { // expected-note 2{{candidate}}
+ using T::T ...; // expected-note 6{{inherited here}}
+ using T::operator() ...;
+ using T::operator T* ...;
+ using T::h ...;
+
+ void f(int n) { h(n); } // expected-error {{ambiguous}}
+ void f(int n, int m) { h(n, m); } // expected-error {{member using declaration 'h' instantiates to an empty pack}}
+ void g(int n) { (*this)(n); } // expected-error {{ambiguous}}
+ void g(int n, int m) { (*this)(n, m); } // expected-error {{does not provide a call operator}}
+};
+
+namespace test_A {
+ struct X { // expected-note 2{{candidate}}
+ X();
+ X(int); // expected-note {{candidate}}
+ void operator()(int); // expected-note 2{{candidate}}
+ operator X *();
+ void h(int); // expected-note {{candidate}}
+ };
+ struct Y {
+ Y();
+ Y(int, int);
+ void operator()(int, int);
+ operator Y *();
+ void h(int, int); // expected-note {{not viable}}
+ };
+ struct Z { // expected-note 2{{candidate}}
+ Z();
+ Z(int); // expected-note {{candidate}}
+ void operator()(int); // expected-note 2{{candidate}}
+ operator Z *();
+ void h(int); // expected-note {{candidate}}
+ };
+
+ void f() {
+ A<> a;
+ a.f(0, 0); // expected-note {{instantiation of}}
+ a.g(0, 0); // expected-note {{instantiation of}}
+
+ A<X, Y> axy(0);
+ A<X, Y>(0, 0);
+ axy.f(0);
+ axy.f(0, 0);
+ axy.g(0);
+ axy.g(0, 0);
+ axy(0);
+ axy(0, 0);
+
+ A<X, Y, Z>(0); // expected-error {{ambiguous}}
+ A<X, Y, Z> axyz(0, 0);
+ axyz.f(0); // expected-note {{instantiation of}}
+ axyz.f(0, 0);
+ axyz.g(0); // expected-note {{instantiation of}}
+ axyz.g(0, 0);
+ axyz(0); // expected-error {{ambiguous}}
+ axyz(0, 0);
+
+ X *x;
+ x = a; // expected-error {{incompatible}}
+ x = axy;
+ x = axyz;
+ x = a.operator X*(); // expected-error {{no member}}
+ x = axy.operator X*();
+ x = axyz.operator X*();
+
+ Z *z;
+ z = axyz;
+ z = axyz.operator Z*();
+ }
+}
+
+// Test using pack of non-type members from single base class.
+template<typename X, typename Y, typename ...T> struct B : X, Y {
+ using X::operator T* ...;
+};
+
+namespace test_B {
+ struct X { operator int*(); operator float*(); operator char*(); }; // expected-note {{candidate}}
+ struct Y { operator int*(); operator float*(); operator char*(); }; // expected-note {{candidate}}
+ B<X, Y, int, float> bif;
+ int *pi = bif;
+ float *pf = bif;
+ char *pc = bif; // expected-error {{ambiguous}}
+}
+
+// Test using type member from pack of base classes.
+template<typename ...T> struct C : T... {
+ using typename T::type ...; // expected-error {{target of using declaration conflicts}}
+ void f() { type value; } // expected-error {{member using declaration 'type' instantiates to an empty pack}}
+};
+
+namespace test_C {
+ struct X { typedef int type; };
+ struct Y { typedef int type; }; // expected-note {{conflicting}}
+ struct Z { typedef float type; }; // expected-note {{target}}
+
+ void f() {
+ C<> c;
+ c.f(); // expected-note {{instantiation of}}
+
+ C<X, Y> cxy;
+ cxy.f();
+
+ C<X, Y, Z> cxyz; // expected-note {{instantiation of}}
+ cxyz.f();
+ }
+}
+
+// Test using pack of non-types at block scope.
+template<typename ...T> int fn1() {
+ using T::e ...; // expected-error 2{{class member}} expected-note 2{{instead}}
+ // expected-error@-1 2{{produces multiple values}}
+ return e; // expected-error {{using declaration 'e' instantiates to an empty pack}}
+}
+
+namespace test_fn1 {
+ struct X { static int e; };
+ struct Y { typedef int e; };
+ inline namespace P { enum E { e }; }
+ inline namespace Q { enum F { e }; }
+ void f() {
+ fn1<>(); // expected-note {{instantiation of}}
+ fn1<X>(); // expected-note {{instantiation of}}
+ fn1<Y>(); // expected-note {{instantiation of}}
+ fn1<E>();
+ fn1<E, F>(); // expected-note {{instantiation of}}
+ fn1<E, X>(); // expected-note {{instantiation of}}
+ }
+}
+
+// Test using pack of types at block scope.
+template<typename ...T> void fn2() {
+ // This cannot ever be valid: in order for T::type to be a type, T must be a
+ // class, and a class member cannot be named by a block-scope using declaration.
+ using typename T::type ...; // expected-error {{class member}}
+ type x; // expected-error {{unknown type name 'type'}}
+}
+
+// Test partial substitution into class-scope pack.
+template<typename ...T> auto lambda1() {
+ return [](auto x) {
+ struct A : T::template X<decltype(x)>... { // expected-note 1+{{instantiation of}}
+ using T::template X<decltype(x)>::f ...;
+ using typename T::template X<decltype(x)>::type ...;
+ void g(int n) { f(n); } // expected-error {{empty pack}} expected-error {{expected 2, have 1}} expected-error {{ambiguous}}
+ void h() { type value; } // expected-error {{empty pack}}
+ };
+ return A();
+ };
+}
+
+namespace test_lambda1 {
+ struct A {
+ template<typename> struct X {
+ void f(int); // expected-note {{candidate}}
+ using type = int;
+ };
+ };
+ struct B {
+ template<typename> struct X {
+ void f(int, int); // expected-note {{declared here}} expected-note {{not viable}}
+ using type = int;
+ };
+ };
+ struct C {
+ template<typename> struct X {
+ void f(int); // expected-note {{candidate}}
+ void f(int, int); // expected-note {{not viable}}
+ using type = int;
+ };
+ };
+
+ void f() {
+ lambda1<>() // expected-note 2{{instantiation of}}
+ (0)
+ // FIXME: This is poor error recovery
+ .g(0); // expected-error {{no member named 'g'}}
+ lambda1<A>()
+ (0)
+ .g(0);
+ lambda1<B>()
+ (0) // expected-note {{instantiation of}}
+ .g(0);
+ lambda1<A, B, C>()
+ (0) // expected-note {{instantiation of}}
+ .g(0);
+ }
+}
+
+namespace p0195r2_example {
+ template<typename ...Ts>
+ struct Overloader : Ts... {
+ using Ts::operator() ...;
+ };
+
+ template<typename ...Ts>
+ constexpr auto make_overloader(Ts &&...ts) {
+ return Overloader<Ts...>{static_cast<Ts&&>(ts)...};
+ }
+
+ void test() {
+ auto o = make_overloader(
+ [&](int &r) -> int & { return r; }, // expected-note {{candidate function}}
+ [&](float &r) -> float & { return r; } // expected-note {{candidate function}}
+ );
+ int a; float f; double d;
+ int &ra = o(a);
+ float &rf = o(f);
+ double &rd = o(d); // expected-error {{no matching function}}
+ }
+}
diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp
index d024c3147735a..9471bac91c308 100644
--- a/test/SemaTemplate/deduction.cpp
+++ b/test/SemaTemplate/deduction.cpp
@@ -1,4 +1,5 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++11
+// RUN: %clang_cc1 -fsyntax-only -verify %s -std=c++1z
// Template argument deduction with template template parameters.
template<typename T, template<T> class A>
@@ -264,4 +265,86 @@ int main() {
return 0;
}
} // end ns2
-} \ No newline at end of file
+}
+
+namespace multiple_deduction_different_type {
+ template<typename T, T v> struct X {};
+ template<template<typename T, T> class X, typename T, typename U, int N>
+ void f(X<T, N>, X<U, N>) {} // expected-note 2{{values of conflicting types}}
+ template<template<typename T, T> class X, typename T, typename U, const int *N>
+ void g(X<T, N>, X<U, N>) {} // expected-note 0-2{{values of conflicting types}}
+ int n;
+ void h() {
+ f(X<int, 1+1>(), X<unsigned int, 3-1>()); // expected-error {{no matching function}}
+ f(X<unsigned int, 1+1>(), X<int, 3-1>()); // expected-error {{no matching function}}
+#if __cplusplus > 201402L
+ g(X<const int*, &n>(), X<int*, &n + 1 - 1>()); // expected-error {{no matching function}}
+ g(X<int*, &n>(), X<const int*, &n + 1 - 1>()); // expected-error {{no matching function}}
+#endif
+ }
+
+ template<template<typename T, T> class X, typename T, typename U, T N>
+ void x(X<T, N>, int(*)[N], X<U, N>) {} // expected-note 1+{{candidate}}
+ template<template<typename T, T> class X, typename T, typename U, T N>
+ void x(int(*)[N], X<T, N>, X<U, N>) {} // expected-note 1+{{candidate}}
+ int arr[3];
+ void y() {
+ x(X<int, 3>(), &arr, X<int, 3>());
+ x(&arr, X<int, 3>(), X<int, 3>());
+
+ x(X<int, 3>(), &arr, X<char, 3>()); // expected-error {{no matching function}}
+ x(&arr, X<int, 3>(), X<char, 3>()); // expected-error {{no matching function}}
+
+ x(X<char, 3>(), &arr, X<char, 3>());
+ x(&arr, X<char, 3>(), X<char, 3>());
+ }
+}
+
+namespace nullptr_deduction {
+ using nullptr_t = decltype(nullptr);
+
+ template<typename T, T v> struct X {};
+ template<typename T, T v> void f(X<T, v>) {
+ static_assert(!v, "");
+ }
+ void g() {
+ f(X<int*, nullptr>());
+ f(X<nullptr_t, nullptr>());
+ }
+
+ template<template<typename T, T> class X, typename T, typename U, int *P>
+ void f1(X<T, P>, X<U, P>) {} // expected-note 2{{values of conflicting types}}
+ void h() {
+ f1(X<int*, nullptr>(), X<nullptr_t, nullptr>()); // expected-error {{no matching function}}
+ f1(X<nullptr_t, nullptr>(), X<int*, nullptr>()); // expected-error {{no matching function}}
+ }
+
+ template<template<typename T, T> class X, typename T, typename U, nullptr_t P>
+ void f2(X<T, P>, X<U, P>) {} // expected-note 2{{values of conflicting types}}
+ void i() {
+ f2(X<int*, nullptr>(), X<nullptr_t, nullptr>()); // expected-error {{no matching function}}
+ f2(X<nullptr_t, nullptr>(), X<int*, nullptr>()); // expected-error {{no matching function}}
+ }
+}
+
+namespace member_pointer {
+ struct A { void f(int); };
+ template<typename T, void (A::*F)(T)> struct B;
+ template<typename T> struct C;
+ template<typename T, void (A::*F)(T)> struct C<B<T, F>> {
+ C() { A a; T t; (a.*F)(t); }
+ };
+ C<B<int, &A::f>> c;
+}
+
+namespace deduction_substitution_failure {
+ template<typename T> struct Fail { typedef typename T::error error; }; // expected-error 2{{prior to '::'}}
+
+ template<typename T, typename U> struct A {};
+ template<typename T> struct A<T, typename Fail<T>::error> {}; // expected-note {{instantiation of}}
+ A<int, int> ai; // expected-note {{during template argument deduction for class template partial specialization 'A<T, typename Fail<T>::error>' [with T = int]}}
+
+ template<typename T, typename U> int B; // expected-warning 0-1 {{extension}}
+ template<typename T> int B<T, typename Fail<T>::error> {}; // expected-note {{instantiation of}}
+ int bi = B<char, char>; // expected-note {{during template argument deduction for variable template partial specialization 'B<T, typename Fail<T>::error>' [with T = char]}}
+}
diff --git a/test/SemaTemplate/default-expr-arguments-3.cpp b/test/SemaTemplate/default-expr-arguments-3.cpp
new file mode 100644
index 0000000000000..9dc3b134300ac
--- /dev/null
+++ b/test/SemaTemplate/default-expr-arguments-3.cpp
@@ -0,0 +1,55 @@
+// RUN: %clang_cc1 -std=c++14 -verify -ast-dump %s | FileCheck %s
+// expected-no-diagnostics
+
+// CHECK: FunctionDecl {{.*}} used func 'void (void)'
+// CHECK-NEXT: TemplateArgument type 'int'
+// CHECK: LambdaExpr {{.*}} 'class (lambda at
+// CHECK: ParmVarDecl {{.*}} used f 'enum foo' cinit
+// CHECK-NEXT: DeclRefExpr {{.*}} 'enum foo' EnumConstant {{.*}} 'a' 'enum foo'
+
+namespace PR28795 {
+ template<typename T>
+ void func() {
+ enum class foo { a, b };
+ auto bar = [](foo f = foo::a) { return f; };
+ bar();
+ }
+
+ void foo() {
+ func<int>();
+ }
+}
+
+// CHECK: ClassTemplateSpecializationDecl {{.*}} struct class2 definition
+// CHECK-NEXT: TemplateArgument type 'int'
+// CHECK: LambdaExpr {{.*}} 'class (lambda at
+// CHECK: ParmVarDecl {{.*}} used f 'enum foo' cinit
+// CHECK-NEXT: DeclRefExpr {{.*}} 'enum foo' EnumConstant {{.*}} 'a' 'enum foo'
+
+// Template struct case:
+template <class T> struct class2 {
+ void bar() {
+ enum class foo { a, b };
+ [](foo f = foo::a) { return f; }();
+ }
+};
+
+template struct class2<int>;
+
+// CHECK: FunctionTemplateDecl {{.*}} f1
+// CHECK-NEXT: TemplateTypeParmDecl {{.*}} typename T
+// CHECK-NEXT: FunctionDecl {{.*}} f1 'void (void)'
+// CHECK: FunctionDecl {{.*}} f1 'void (void)'
+// CHECK-NEXT: TemplateArgument type 'int'
+// CHECK: ParmVarDecl {{.*}} n 'enum foo' cinit
+// CHECK-NEXT: DeclRefExpr {{.*}} 'enum foo' EnumConstant {{.*}} 'a' 'enum foo'
+
+template<typename T>
+void f1() {
+ enum class foo { a, b };
+ struct S {
+ int g1(foo n = foo::a);
+ };
+}
+
+template void f1<int>();
diff --git a/test/SemaTemplate/dependent-type-identity.cpp b/test/SemaTemplate/dependent-type-identity.cpp
index 6b23a38f84863..c826268c864c4 100644
--- a/test/SemaTemplate/dependent-type-identity.cpp
+++ b/test/SemaTemplate/dependent-type-identity.cpp
@@ -80,11 +80,20 @@ namespace PR6851 {
S< S<w>::cond && 1 > foo();
};
+ struct Arrow { Arrow *operator->(); int n; };
+ template<typename T> struct M {
+ Arrow a;
+ auto f() -> M<decltype(a->n)>;
+ };
+
struct Alien;
bool operator&&(const Alien&, const Alien&);
template <bool w>
S< S<w>::cond && 1 > N::foo() { }
+
+ template<typename T>
+ auto M<T>::f() -> M<decltype(a->n)> {}
}
namespace PR7460 {
diff --git a/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp b/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
index 6e8323d1ee2ca..c5290efafc1ab 100644
--- a/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
+++ b/test/SemaTemplate/instantiate-exception-spec-cxx11.cpp
@@ -30,8 +30,6 @@ template<unsigned N> struct S {
// expected-error {{no member named 'recurse'}} \
// expected-note 9{{instantiation of exception spec}}
};
-decltype(S<0>::recurse()) *pVoid1 = 0; // ok, exception spec not needed
-decltype(&S<0>::recurse) pFn = 0; // ok, exception spec not needed
template<> struct S<10> {};
void (*pFn2)() noexcept = &S<0>::recurse; // expected-note {{instantiation of exception spec}} expected-error {{not superset}}
@@ -39,7 +37,7 @@ void (*pFn2)() noexcept = &S<0>::recurse; // expected-note {{instantiation of ex
namespace dr1330_example {
template <class T> struct A {
- void f(...) throw (typename T::X); // expected-error {{'int'}}
+ void f(...) throw (typename T::X);
void f(int);
};
@@ -48,16 +46,14 @@ namespace dr1330_example {
}
struct S {
- template<typename T>
- static int f() noexcept(noexcept(A<T>().f("boo!"))) { return 0; } // \
- // expected-note {{instantiation of exception spec}}
- typedef decltype(f<S>()) X;
+ template<typename T> static void f() throw(typename T::X);
+ typedef decltype(f<S>()) X; // expected-error {{exception specification is not available}}
};
- int test2() {
- S().f<S>(); // ok
- S().f<int>(); // expected-note {{instantiation of exception spec}}
- }
+ struct T {
+ template<typename T> static void f() throw(T**);
+ typedef decltype(f<S>()) X; // expected-error {{exception specification is not available}}
+ };
template<typename T>
struct U {
diff --git a/test/SemaTemplate/instantiation-default-1.cpp b/test/SemaTemplate/instantiation-default-1.cpp
index 99154a5cc4606..ab9eca75e239b 100644
--- a/test/SemaTemplate/instantiation-default-1.cpp
+++ b/test/SemaTemplate/instantiation-default-1.cpp
@@ -36,7 +36,7 @@ typedef int& int_ref_t;
Def2<int_ref_t> *d2; // expected-note{{in instantiation of default argument for 'Def2<int &>' required here}}
-template<> struct Def1<const int, const int> { }; // expected-error{{redefinition of 'Def1<const int>'}}
+template<> struct Def1<const int> { }; // expected-error{{redefinition of 'Def1<const int, const int>'}}
template<typename T, typename T2 = T&> struct Def3;
diff --git a/test/SemaTemplate/instantiation-depth-default.cpp b/test/SemaTemplate/instantiation-depth-default.cpp
new file mode 100644
index 0000000000000..3d89aa18ca438
--- /dev/null
+++ b/test/SemaTemplate/instantiation-depth-default.cpp
@@ -0,0 +1,17 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -ftemplate-backtrace-limit 2 %s
+//
+// FIXME: Disable this test when Clang was built with ASan, because ASan
+// increases our per-frame stack usage enough that this test no longer fits
+// within our normal stack space allocation.
+// REQUIRES: not_asan
+
+template<int N, typename T> struct X : X<N+1, T*> {};
+// expected-error-re@8 {{recursive template instantiation exceeded maximum depth of 1024{{$}}}}
+// expected-note@8 {{instantiation of template class}}
+// expected-note@8 {{skipping 1023 contexts in backtrace}}
+// expected-note@8 {{use -ftemplate-depth=N to increase recursive template instantiation depth}}
+
+X<0, int> x; // expected-note {{in instantiation of}}
+
+// FIXME: It crashes. Investigating.
+// UNSUPPORTED: mingw32
diff --git a/test/SemaTemplate/ms-class-specialization-class-scope.cpp b/test/SemaTemplate/ms-class-specialization-class-scope.cpp
index 3ebb1c9c555ea..fc51c23a34e91 100644
--- a/test/SemaTemplate/ms-class-specialization-class-scope.cpp
+++ b/test/SemaTemplate/ms-class-specialization-class-scope.cpp
@@ -19,7 +19,7 @@ public:
X<double>::y c;
template<> struct X<float> {}; // expected-note {{previous definition is here}}
- template<> struct X<float> {}; // expected-error {{redefinition of 'A::X<float>'}}
+ template<> struct X<float> {}; // expected-error {{redefinition of 'X<float>'}}
};
A::X<void>::x axv;
diff --git a/test/SemaTemplate/temp_arg_enum_printing.cpp b/test/SemaTemplate/temp_arg_enum_printing.cpp
index a788975b20dd9..bdf277d308c3d 100644
--- a/test/SemaTemplate/temp_arg_enum_printing.cpp
+++ b/test/SemaTemplate/temp_arg_enum_printing.cpp
@@ -13,11 +13,11 @@ template <NamedEnum E>
void foo();
void test() {
- // CHECK: template <NamedEnumNS::NamedEnum E = NamedEnumNS::NamedEnum::Val0>
+ // CHECK: template<> void foo<NamedEnumNS::NamedEnum::Val0>()
NamedEnumNS::foo<Val0>();
- // CHECK: template <NamedEnumNS::NamedEnum E = NamedEnumNS::NamedEnum::Val1>
+ // CHECK: template<> void foo<NamedEnumNS::NamedEnum::Val1>()
NamedEnumNS::foo<(NamedEnum)1>();
- // CHECK: template <NamedEnumNS::NamedEnum E = 2>
+ // CHECK: template<> void foo<2>()
NamedEnumNS::foo<(NamedEnum)2>();
}
diff --git a/test/SemaTemplate/temp_arg_nontype.cpp b/test/SemaTemplate/temp_arg_nontype.cpp
index 91b0c6e765088..93f11b5657d03 100644
--- a/test/SemaTemplate/temp_arg_nontype.cpp
+++ b/test/SemaTemplate/temp_arg_nontype.cpp
@@ -364,3 +364,90 @@ namespace PR17696 {
b<&a::i> c; // okay
}
+
+namespace partial_order_different_types {
+ // These are unordered because the type of the final argument doesn't match.
+ template<int, int, typename T, typename, T> struct A; // expected-note {{here}}
+ template<int N, typename T, typename U, T V> struct A<0, N, T, U, V> {}; // expected-note {{matches}}
+ template<typename T, typename U, U V> struct A<0, 0, T, U, V> {}; // expected-note {{matches}}
+ // expected-error@-1 {{not more specialized than the primary}}
+ // expected-note@-2 {{deduced non-type template argument does not have the same type as the corresponding template parameter ('U' vs 'type-parameter-0-0')}}
+ A<0, 0, int, int, 0> a; // expected-error {{ambiguous partial specializations}}
+}
+
+namespace partial_order_references {
+ // FIXME: The standard does not appear to consider the second specialization
+ // to be more more specialized than the first! The problem is that deducing
+ // an 'int&' parameter from an argument 'R' results in a type mismatch,
+ // because the parameter has a reference type and the argument is an
+ // expression and thus does not have reference type. We resolve this by
+ // matching the type of an expression corresponding to the parameter rather
+ // than matching the parameter itself.
+ template <int, int, int &> struct A {};
+ template <int N, int &R> struct A<N, 0, R> {};
+ template <int &R> struct A<0, 0, R> {};
+ int N;
+ A<0, 0, N> a;
+
+ template<int, int &R> struct B; // expected-note 2{{template}}
+ template<const int &R> struct B<0, R> {};
+ // expected-error@-1 {{not more specialized than the primary}}
+ // expected-note@-2 {{'const int' vs 'int &'}}
+ B<0, N> b; // expected-error {{undefined}}
+
+ template<int, const int &R> struct C; // expected-note 2{{template}}
+ template<int &R> struct C<0, R> {};
+ // expected-error@-1 {{not more specialized than the primary}}
+ // expected-note@-2 {{'int' vs 'const int &'}}
+ C<0, N> c; // expected-error {{undefined}}
+
+ template<int, const int &R> struct D; // expected-note 2{{template}}
+ template<int N> struct D<0, N> {};
+ // expected-error@-1 {{not more specialized than the primary}}
+ // expected-note@-2 {{'int' vs 'const int &'}}
+ extern const int K = 5;
+ D<0, K> d; // expected-error {{undefined}}
+}
+
+namespace dependent_nested_partial_specialization {
+ template<typename> using X = int; // expected-warning {{C++11}}
+ template<typename T> using Y = T*; // expected-warning {{C++11}}
+ int n;
+
+ template<template<typename> class X> struct A {
+ template<typename T, X<T> N> struct B; // expected-note 2{{here}}
+ template<typename T> struct B<T, 0> {}; // expected-error {{specializes a template parameter with dependent type 'Y<T>'}}
+ };
+ A<X>::B<int, 0> ax;
+ A<Y>::B<int, &n> ay; // expected-error {{undefined}} expected-note {{instantiation of}}
+
+ template<template<typename> class X> struct C {
+ template<typename T, int N, int M> struct D; // expected-note {{here}}
+ template<typename T, X<T> N> struct D<T*, N, N + 1> {}; // expected-error {{type of specialized non-type template argument depends on}}
+ };
+ C<X>::D<int*, 0, 1> cx;
+ C<Y>::D<int*, 0, 1> cy; // expected-error {{undefined}} expected-note {{instantiation of}}
+
+ template<typename T> struct E {
+ template<typename U, U V> struct F; // expected-note {{template}}
+ template<typename W, T V> struct F<W, V> {}; // expected-error {{not more specialized than the primary}} expected-note {{does not have the same type}}
+ };
+ E<int>::F<int, 0> e1; // expected-note {{instantiation of}}
+}
+
+namespace nondependent_default_arg_ordering {
+ int n, m;
+ template<typename A, A B = &n> struct X {};
+ template<typename A> void f(X<A>); // expected-note {{candidate}}
+ template<typename A> void f(X<A, &m>); // expected-note {{candidate}}
+ template<typename A, A B> void f(X<A, B>); // expected-note 2{{candidate}}
+ template<template<typename U, U> class T, typename A, int *B> void f(T<A, B>); // expected-note 2{{candidate}}
+ void g() {
+ // FIXME: The first and second function templates above should be
+ // considered more specialized than the last two, but during partial
+ // ordering we fail to check that we actually deduced template arguments
+ // that make the deduced A identical to A.
+ X<int *, &n> x; f(x); // expected-error {{ambiguous}}
+ X<int *, &m> y; f(y); // expected-error {{ambiguous}}
+ }
+}
diff --git a/test/SemaTemplate/temp_arg_nontype_cxx11.cpp b/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
index 15c9c2560a964..cfaad0cd0c96f 100644
--- a/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
+++ b/test/SemaTemplate/temp_arg_nontype_cxx11.cpp
@@ -23,3 +23,16 @@ namespace CanonicalNullptr {
B<int> b = MakeB<int>();
C<int> c = MakeC<int>();
}
+
+namespace Auto {
+ template<auto> struct A { }; // expected-error {{until C++1z}}
+}
+
+namespace check_conversion_early {
+ struct X {};
+ template<int> struct A {};
+ template<X &x> struct A<x> {}; // expected-error {{not implicitly convertible}}
+
+ struct Y { constexpr operator int() const { return 0; } };
+ template<Y &y> struct A<y> {}; // expected-error {{cannot be deduced}} expected-note {{'y'}}
+}
diff --git a/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp b/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
index 548f7f8f34fbe..c1fcedd58d134 100644
--- a/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
+++ b/test/SemaTemplate/temp_arg_nontype_cxx1z.cpp
@@ -122,13 +122,13 @@ namespace DeduceDifferentType {
int a_exp = a<3>(A<3>());
template<decltype(nullptr)> struct B {};
- template<int *P> int b(B<P>); // expected-note {{could not match}} expected-note {{not implicitly convertible}}
+ template<int *P> int b(B<P>); // expected-error {{value of type 'int *' is not implicitly convertible to 'decltype(nullptr)'}}
int b_imp = b(B<nullptr>()); // expected-error {{no matching function}}
int b_exp = b<nullptr>(B<nullptr>()); // expected-error {{no matching function}}
struct X { constexpr operator int() { return 0; } } x;
template<X &> struct C {};
- template<int N> int c(C<N>); // expected-note {{does not have the same type}} expected-note {{not implicitly convertible}}
+ template<int N> int c(C<N>); // expected-error {{value of type 'int' is not implicitly convertible to 'DeduceDifferentType::X &'}}
int c_imp = c(C<x>()); // expected-error {{no matching function}}
int c_exp = c<x>(C<x>()); // expected-error {{no matching function}}
@@ -137,7 +137,7 @@ namespace DeduceDifferentType {
struct Z { constexpr operator Y&() { return y; } } z;
constexpr Y::operator Z&() { return z; }
template<Y &> struct D {};
- template<Z &z> int d(D<z>); // expected-note {{does not have the same type}}
+ template<Z &z> int d(D<z>); // expected-note {{couldn't infer template argument 'z'}}
int d_imp = d(D<y>()); // expected-error {{no matching function}}
int d_exp = d<y>(D<y>());
}
@@ -155,3 +155,176 @@ namespace PR24921 {
template<int> void f(int);
template<> void f<e>() {}
}
+
+namespace Auto {
+ namespace Basic {
+ // simple auto
+ template<auto x> constexpr auto constant = x; // expected-note {{declared here}}
+
+ auto v1 = constant<5>;
+ auto v2 = constant<true>;
+ auto v3 = constant<'a'>;
+ auto v4 = constant<2.5>; // expected-error {{cannot have type 'double'}}
+
+ using T1 = decltype(v1);
+ using T1 = int;
+ using T2 = decltype(v2);
+ using T2 = bool;
+ using T3 = decltype(v3);
+ using T3 = char;
+
+ // pointers
+ template<auto v> class B { };
+ template<auto* p> class B<p> { }; // expected-note {{matches}}
+ template<auto** pp> class B<pp> { };
+ template<auto* p0> int &f(B<p0> b); // expected-note {{candidate}}
+ template<auto** pp0> float &f(B<pp0> b); // expected-note {{candidate}}
+
+ int a, *b = &a;
+ int &r = f(B<&a>());
+ float &s = f(B<&b>());
+
+ // pointers to members
+ template<typename T, auto *T::*p> struct B<p> {};
+ template<typename T, auto **T::*p> struct B<p> {};
+ template<typename T, auto *T::*p0> char &f(B<p0> b); // expected-note {{candidate}}
+ template<typename T, auto **T::*pp0> short &f(B<pp0> b); // expected-note {{candidate}}
+
+ struct X { int n; int *p; int **pp; typedef int a, b; };
+ auto t = f(B<&X::n>()); // expected-error {{no match}}
+ char &u = f(B<&X::p>());
+ short &v = f(B<&X::pp>());
+
+ // A case where we need to do auto-deduction, and check whether the
+ // resulting dependent types match during partial ordering. These
+ // templates are not ordered due to the mismatching function parameter.
+ template<typename T, auto *(*f)(T, typename T::a)> struct B<f> {}; // expected-note {{matches}}
+ template<typename T, auto **(*f)(T, typename T::b)> struct B<f> {}; // expected-note {{matches}}
+ int **g(X, int);
+ B<&g> bg; // expected-error {{ambiguous}}
+ }
+
+ namespace Chained {
+ // chained template argument deduction
+ template<long n> struct C { };
+ template<class T> struct D;
+ template<class T, T n> struct D<C<n>>
+ {
+ using Q = T;
+ };
+ using DQ = long;
+ using DQ = D<C<short(2)>>::Q;
+
+ // chained template argument deduction from an array bound
+ template<typename T> struct E;
+ template<typename T, T n> struct E<int[n]> {
+ using Q = T;
+ };
+ using EQ = E<int[short(42)]>::Q;
+ using EQ = decltype(sizeof 0);
+
+ template<int N> struct F;
+ template<typename T, T N> int foo(F<N> *) = delete; // expected-note {{explicitly deleted}}
+ void foo(void *); // expected-note {{candidate function}}
+ void bar(F<0> *p) {
+ foo(p); // expected-error {{deleted function}}
+ }
+ }
+
+ namespace ArrayToPointer {
+ constexpr char s[] = "test";
+ template<const auto* p> struct S { };
+ S<s> p;
+ }
+
+ namespace DecltypeAuto {
+ template<auto v> struct A { };
+ template<decltype(auto) v> struct DA { };
+ template<auto&> struct R { };
+
+ auto n = 0; // expected-note + {{declared here}}
+ A<n> a; // expected-error {{not a constant}} expected-note {{non-const variable 'n'}}
+ DA<n> da1; // expected-error {{not a constant}} expected-note {{non-const variable 'n'}}
+ DA<(n)> da2;
+ R<n> r;
+ }
+
+ namespace Decomposition {
+ // Types of deduced non-type template arguments must match exactly, so
+ // partial ordering fails in both directions here.
+ template<auto> struct Any;
+ template<int N> struct Any<N> { typedef int Int; }; // expected-note 3{{match}}
+ template<short N> struct Any<N> { typedef int Short; }; // expected-note 3{{match}}
+ Any<0>::Int is_int; // expected-error {{ambiguous}}
+ Any<(short)0>::Short is_short; // expected-error {{ambiguous}}
+ Any<(char)0>::Short is_char; // expected-error {{ambiguous}}
+
+ template<int, auto> struct NestedAny;
+ template<auto N> struct NestedAny<0, N>; // expected-note 3{{match}}
+ template<int N> struct NestedAny<0, N> { typedef int Int; }; // expected-note 3{{match}}
+ template<short N> struct NestedAny<0, N> { typedef int Short; }; // expected-note 3{{match}}
+ NestedAny<0, 0>::Int nested_int; // expected-error {{ambiguous}}
+ NestedAny<0, (short)0>::Short nested_short; // expected-error {{ambiguous}}
+ NestedAny<0, (char)0>::Short nested_char; // expected-error {{ambiguous}}
+
+ double foo(int, bool);
+ template<auto& f> struct fn_result_type;
+
+ template<class R, class... Args, R (& f)(Args...)>
+ struct fn_result_type<f>
+ {
+ using type = R;
+ };
+
+ using R1 = fn_result_type<foo>::type;
+ using R1 = double;
+
+ template<int, auto &f> struct fn_result_type_partial_order;
+ template<auto &f> struct fn_result_type_partial_order<0, f>;
+ template<class R, class... Args, R (& f)(Args...)>
+ struct fn_result_type_partial_order<0, f> {};
+ fn_result_type_partial_order<0, foo> frtpo;
+ }
+
+ namespace Variadic {
+ template<auto... vs> struct value_list { };
+
+ using size_t = decltype(sizeof 0);
+ template<size_t n, class List> struct nth_element;
+ template<size_t n, class List> constexpr auto nth_element_v = nth_element<n, List>::value;
+
+ template<size_t n, auto v0, auto... vs>
+ struct nth_element<n, value_list<v0, vs...>>
+ {
+ static constexpr auto value = nth_element<n - 1, value_list<vs...>>::value;
+ };
+ template<auto v0, auto... vs>
+ struct nth_element<0, value_list<v0, vs...>>
+ {
+ static constexpr auto value = v0;
+ };
+
+ static_assert(nth_element_v<2, value_list<'a', 27U, false>> == false, "value mismatch");
+ }
+}
+
+namespace Nested {
+ template<typename T> struct A {
+ template<auto X> struct B;
+ template<auto *P> struct B<P>;
+ template<auto **P> struct B<P> { using pointee = decltype(+**P); };
+ template<auto (*P)(T)> struct B<P> { using param = T; };
+ template<typename U, auto (*P)(T, U)> struct B<P> { using param2 = U; };
+ };
+
+ using Int = int;
+
+ int *n;
+ using Int = A<int>::B<&n>::pointee;
+
+ void f(int);
+ using Int = A<int>::B<&f>::param;
+
+ void g(int, int);
+ using Int = A<int>::B<&g>::param2;
+}
diff --git a/test/SemaTemplate/temp_arg_template.cpp b/test/SemaTemplate/temp_arg_template.cpp
index 6d93f1504a469..67cde53c928b3 100644
--- a/test/SemaTemplate/temp_arg_template.cpp
+++ b/test/SemaTemplate/temp_arg_template.cpp
@@ -6,11 +6,12 @@ template<template<typename T> class X> struct A; // expected-note 2{{previous te
template<template<typename T, int I> class X> struct B; // expected-note{{previous template template parameter is here}}
-template<template<int I> class X> struct C; // expected-note{{previous non-type template parameter with type 'int' is here}}
+template<template<int I> class X> struct C; // expected-note 2{{previous non-type template parameter with type 'int' is here}}
template<class> struct X; // expected-note{{too few template parameters in template template argument}}
template<int N> struct Y; // expected-note{{template parameter has a different kind in template argument}}
template<long N> struct Ylong; // expected-note{{template non-type parameter has a different type 'long' in template argument}}
+template<const int &N> struct Yref; // expected-note{{template non-type parameter has a different type 'const int &' in template argument}}
namespace N {
template<class> struct Z;
@@ -27,6 +28,7 @@ A<TooMany> *a5; // expected-error{{template template argument has different temp
B<X> *a6; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
C<Y> *a7;
C<Ylong> *a8; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
+C<Yref> *a9; // expected-error{{template template argument has different template parameters than its corresponding template template parameter}}
template<typename T> void f(int);
diff --git a/test/SemaTemplate/temp_arg_template_cxx1z.cpp b/test/SemaTemplate/temp_arg_template_cxx1z.cpp
new file mode 100644
index 0000000000000..b6b283b53c6be
--- /dev/null
+++ b/test/SemaTemplate/temp_arg_template_cxx1z.cpp
@@ -0,0 +1,102 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++1z -frelaxed-template-template-args %s
+
+// expected-note@temp_arg_template_cxx1z.cpp:* 1+{{}}
+
+template<template<int> typename> struct Ti;
+template<template<int...> typename> struct TPi;
+template<template<int, int...> typename> struct TiPi;
+template<template<int..., int...> typename> struct TPiPi; // FIXME: Why is this not ill-formed?
+
+template<typename T, template<T> typename> struct tT0;
+template<template<typename T, T> typename> struct Tt0;
+
+template<template<typename> typename> struct Tt;
+template<template<typename, typename...> typename> struct TtPt;
+
+template<int> struct i;
+template<int, int = 0> struct iDi;
+template<int, int> struct ii;
+template<int...> struct Pi;
+template<int, int, int...> struct iiPi;
+
+template<int, typename = int> struct iDt;
+template<int, typename> struct it;
+
+template<typename T, T v> struct t0;
+
+template<typename...> struct Pt;
+
+namespace IntParam {
+ using ok = Pt<Ti<i>,
+ Ti<iDi>,
+ Ti<Pi>,
+ Ti<iDt>>;
+ using err1 = Ti<ii>; // expected-error {{different template parameters}}
+ using err2 = Ti<iiPi>; // expected-error {{different template parameters}}
+ using err3 = Ti<t0>; // expected-error {{different template parameters}}
+ using err4 = Ti<it>; // expected-error {{different template parameters}}
+}
+
+// These are accepted by the backwards-compatibility "parameter pack in
+// parameter matches any number of parameters in arguments" rule.
+namespace IntPackParam {
+ using ok = TPi<Pi>;
+ using ok_compat = Pt<TPi<i>, TPi<iDi>, TPi<ii>, TPi<iiPi>>;
+ using err1 = TPi<t0>; // expected-error {{different template parameters}}
+ using err2 = TPi<iDt>; // expected-error {{different template parameters}}
+ using err3 = TPi<it>; // expected-error {{different template parameters}}
+}
+
+namespace IntAndPackParam {
+ using ok = TiPi<Pi>;
+ using ok_compat = Pt<TiPi<ii>, TiPi<iDi>, TiPi<iiPi>>;
+ using err = TiPi<iDi>;
+}
+
+namespace DependentType {
+ using ok = Pt<tT0<int, i>, tT0<int, iDi>>;
+ using err1 = tT0<int, ii>; // expected-error {{different template parameters}}
+ using err2 = tT0<short, i>; // FIXME: should this be OK?
+ using err2a = tT0<long long, i>; // FIXME: should this be OK (if long long is larger than int)?
+ using err2b = tT0<void*, i>; // expected-error {{different template parameters}}
+ using err3 = tT0<short, t0>; // expected-error {{different template parameters}}
+
+ using ok2 = Tt0<t0>;
+ using err4 = Tt0<it>; // expected-error {{different template parameters}}
+}
+
+namespace Auto {
+ template<template<int> typename T> struct TInt {};
+ template<template<int*> typename T> struct TIntPtr {};
+ template<template<auto> typename T> struct TAuto {};
+ template<template<auto*> typename T> struct TAutoPtr {};
+ template<auto> struct Auto;
+ template<auto*> struct AutoPtr;
+ template<int> struct Int;
+ template<int*> struct IntPtr;
+
+ TInt<Auto> ia;
+ TInt<AutoPtr> iap; // FIXME: ill-formed
+ TInt<Int> ii;
+ TInt<IntPtr> iip; // expected-error {{different template parameters}}
+
+ TIntPtr<Auto> ipa;
+ TIntPtr<AutoPtr> ipap;
+ TIntPtr<Int> ipi; // expected-error {{different template parameters}}
+ TIntPtr<IntPtr> ipip;
+
+ TAuto<Auto> aa;
+ TAuto<AutoPtr> aap; // FIXME: ill-formed
+ TAuto<Int> ai; // FIXME: ill-formed
+ TAuto<IntPtr> aip; // FIXME: ill-formed
+
+ TAutoPtr<Auto> apa;
+ TAutoPtr<AutoPtr> apap;
+ TAutoPtr<Int> api; // FIXME: ill-formed
+ TAutoPtr<IntPtr> apip; // FIXME: ill-formed
+
+ int n;
+ template<auto A, decltype(A) B = &n> struct SubstFailure;
+ TInt<SubstFailure> isf; // expected-error {{different template parameters}}
+ TIntPtr<SubstFailure> ipsf; // expected-error {{different template parameters}}
+}
diff --git a/test/SemaTemplate/temp_class_spec_neg.cpp b/test/SemaTemplate/temp_class_spec_neg.cpp
index 1c77038ab8a9a..6366a528ff530 100644
--- a/test/SemaTemplate/temp_class_spec_neg.cpp
+++ b/test/SemaTemplate/temp_class_spec_neg.cpp
@@ -20,9 +20,9 @@ struct N::M::A<T*> { };
#endif
// C++ [temp.class.spec]p9
-// bullet 1
+// bullet 1, as amended by DR1315
template <int I, int J> struct A {};
-template <int I> struct A<I+5, I*2> {}; // expected-error{{depends on}}
+template <int I> struct A<I+5, I*2> {}; // expected-error{{cannot be deduced}} expected-note {{'I'}}
template <int I, int J> struct B {};
template <int I> struct B<I, I> {}; //OK
@@ -50,4 +50,4 @@ template<typename T = int, // expected-error{{default template argument}}
template<typename T> struct Test1;
template<typename T, typename U> // expected-note{{non-deducible}}
- struct Test1<T*> { }; // expected-warning{{never be used}}
+ struct Test1<T*> { }; // expected-error{{never be used}}
diff --git a/test/SemaTemplate/temp_explicit.cpp b/test/SemaTemplate/temp_explicit.cpp
index 80c90d0cfcd20..e8c9dfb5f5d2c 100644
--- a/test/SemaTemplate/temp_explicit.cpp
+++ b/test/SemaTemplate/temp_explicit.cpp
@@ -26,7 +26,7 @@ template class X0<double> { }; // expected-error{{explicit specialization}}
template class X0<int, int>; // expected-error{{duplicate}}
template<> class X0<char> { }; // expected-note{{previous}}
-template class X0<char>; // expected-warning{{ignored}}
+template class X0<char>; // expected-warning{{has no effect}}
void foo(X0<short>) { }
template class X0<short>;
diff --git a/test/SemaTemplate/template-id-expr.cpp b/test/SemaTemplate/template-id-expr.cpp
index 499d289ee6754..e311b5832d0d2 100644
--- a/test/SemaTemplate/template-id-expr.cpp
+++ b/test/SemaTemplate/template-id-expr.cpp
@@ -100,5 +100,5 @@ template void f5<0>(); // expected-note {{in instantiation of function template
class C {};
template <template <typename> class D> // expected-note{{previous use is here}}
class E {
- template class D<C>; // expected-error {{elaborated type refers to a template template argument}}
+ template class D<C>; // expected-error {{template template argument 'D' cannot be referenced with a class specifier}}
};