summaryrefslogtreecommitdiff
path: root/test/SemaTemplate
diff options
context:
space:
mode:
Diffstat (limited to 'test/SemaTemplate')
-rw-r--r--test/SemaTemplate/alias-templates.cpp6
-rw-r--r--test/SemaTemplate/class-template-spec.cpp45
-rw-r--r--test/SemaTemplate/cxx1z-fold-expressions.cpp15
-rw-r--r--test/SemaTemplate/deduction.cpp47
-rw-r--r--test/SemaTemplate/default-arguments-cxx0x.cpp10
-rw-r--r--test/SemaTemplate/extern-templates.cpp13
-rw-r--r--test/SemaTemplate/instantiate-cast.cpp9
-rw-r--r--test/SemaTemplate/instantiate-expr-4.cpp12
-rw-r--r--test/SemaTemplate/instantiate-member-class.cpp16
-rw-r--r--test/SemaTemplate/instantiate-sizeof.cpp29
-rw-r--r--test/SemaTemplate/member-access-expr.cpp21
-rw-r--r--test/SemaTemplate/ms-delayed-default-template-args.cpp9
-rw-r--r--test/SemaTemplate/ms-function-specialization-class-scope.cpp9
-rw-r--r--test/SemaTemplate/ms-lookup-template-base-classes.cpp61
-rw-r--r--test/SemaTemplate/recovery-crash.cpp14
-rw-r--r--test/SemaTemplate/temp_arg_type.cpp19
-rw-r--r--test/SemaTemplate/template-id-expr.cpp6
-rw-r--r--test/SemaTemplate/undefined-template.cpp139
18 files changed, 446 insertions, 34 deletions
diff --git a/test/SemaTemplate/alias-templates.cpp b/test/SemaTemplate/alias-templates.cpp
index 1849ff64026b..b7078353ff1b 100644
--- a/test/SemaTemplate/alias-templates.cpp
+++ b/test/SemaTemplate/alias-templates.cpp
@@ -221,3 +221,9 @@ namespace PR14858 {
template<typename ...T, typename ...U> void h(X<T...> &) {}
template<typename ...T, typename ...U> void h(X<U...> &) {} // ok, different
}
+
+namespace redecl {
+ template<typename> using A = int;
+ template<typename = void> using A = int;
+ A<> a; // ok
+}
diff --git a/test/SemaTemplate/class-template-spec.cpp b/test/SemaTemplate/class-template-spec.cpp
index 0292c1b8ff20..86cace19dbfb 100644
--- a/test/SemaTemplate/class-template-spec.cpp
+++ b/test/SemaTemplate/class-template-spec.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
template<typename T, typename U = int> struct A; // expected-note {{template is declared here}} \
// expected-note{{explicitly specialized}}
@@ -75,7 +77,10 @@ struct A<double> { }; // expected-error{{template specialization requires 'templ
template<> struct ::A<double>;
namespace N {
- template<typename T> struct B; // expected-note 2{{explicitly specialized}}
+ template<typename T> struct B; // expected-note {{explicitly specialized}}
+#if __cplusplus <= 199711L
+ // expected-note@-2 {{explicitly specialized}}
+#endif
template<> struct ::N::B<char>; // okay
template<> struct ::N::B<short>; // okay
@@ -86,7 +91,11 @@ namespace N {
template<> struct N::B<int> { }; // okay
-template<> struct N::B<float> { }; // expected-warning{{C++11 extension}}
+template<> struct N::B<float> { };
+#if __cplusplus <= 199711L
+// expected-warning@-2 {{first declaration of class template specialization of 'B' outside namespace 'N' is a C++11 extension}}
+#endif
+
namespace M {
template<> struct ::N::B<short> { }; // expected-error{{class template specialization of 'B' not in a namespace enclosing 'N'}}
@@ -142,13 +151,26 @@ namespace PR18009 {
}
namespace PR16519 {
- template<typename T, T...N> struct integer_sequence { typedef T value_type; }; // expected-warning {{extension}}
+ template<typename T, T...N> struct integer_sequence { typedef T value_type; };
+#if __cplusplus <= 199711L
+ // expected-warning@-2 {{variadic templates are a C++11 extension}}
+#endif
template<typename T> struct __make_integer_sequence;
- template<typename T, T N> using make_integer_sequence = typename __make_integer_sequence<T>::template make<N, N % 2>::type; // expected-warning {{extension}}
+ template<typename T, T N> using make_integer_sequence = typename __make_integer_sequence<T>::template make<N, N % 2>::type;
+#if __cplusplus <= 199711L
+ // expected-warning@-2 {{alias declarations are a C++11 extension}}
+#endif
+
+ template<typename T, typename T::value_type ...Extra> struct __make_integer_sequence_impl;
+#if __cplusplus <= 199711L
+ // expected-warning@-2 {{variadic templates are a C++11 extension}}
+#endif
- template<typename T, typename T::value_type ...Extra> struct __make_integer_sequence_impl; // expected-warning {{extension}}
- template<typename T, T ...N, T ...Extra> struct __make_integer_sequence_impl<integer_sequence<T, N...>, Extra...> { // expected-warning 2{{extension}}
+ template<typename T, T ...N, T ...Extra> struct __make_integer_sequence_impl<integer_sequence<T, N...>, Extra...> {
+#if __cplusplus <= 199711L
+ // expected-warning@-2 2 {{variadic templates are a C++11 extension}}
+#endif
typedef integer_sequence<T, N..., sizeof...(N) + N..., Extra...> type;
};
@@ -160,8 +182,15 @@ namespace PR16519 {
template<T N, typename Dummy> struct make<N, 1, Dummy> : __make_integer_sequence_impl<make_integer_sequence<T, N/2>, N - 1> {};
};
- using X = make_integer_sequence<int, 5>; // expected-warning {{extension}}
- using X = integer_sequence<int, 0, 1, 2, 3, 4>; // expected-warning {{extension}}
+ using X = make_integer_sequence<int, 5>;
+#if __cplusplus <= 199711L
+ // expected-warning@-2 {{alias declarations are a C++11 extension}}
+#endif
+
+ using X = integer_sequence<int, 0, 1, 2, 3, 4>;
+#if __cplusplus <= 199711L
+ // expected-warning@-2 {{alias declarations are a C++11 extension}}
+#endif
}
namespace DefaultArgVsPartialSpec {
diff --git a/test/SemaTemplate/cxx1z-fold-expressions.cpp b/test/SemaTemplate/cxx1z-fold-expressions.cpp
index 8bb79113fa9d..aefee92f648a 100644
--- a/test/SemaTemplate/cxx1z-fold-expressions.cpp
+++ b/test/SemaTemplate/cxx1z-fold-expressions.cpp
@@ -25,10 +25,6 @@ constexpr bool check() {
static_assert(check());
template<int ...N> void empty() {
- static_assert((N + ...) == 0);
- static_assert((N * ...) == 1);
- static_assert((N | ...) == 0);
- static_assert((N & ...) == -1);
static_assert((N || ...) == false);
static_assert((N && ...) == true);
(N, ...);
@@ -36,14 +32,19 @@ template<int ...N> void empty() {
template void empty<>();
// An empty fold-expression isn't a null pointer just because it's an integer
-// with value 0.
+// with value 0. (This is no longer an issue since empty pack expansions don't
+// produce integers any more.)
template<int ...N> void null_ptr() {
- void *p = (N + ...); // expected-error {{rvalue of type 'int'}}
- void *q = (N | ...); // expected-error {{rvalue of type 'int'}}
+ void *p = (N || ...); // expected-error {{rvalue of type 'bool'}}
+ void *q = (N , ...); // expected-error {{rvalue of type 'void'}}
}
template void null_ptr<>(); // expected-note {{in instantiation of}}
template<int ...N> void bad_empty() {
+ (N + ...); // expected-error {{empty expansion for operator '+' with no fallback}}
+ (N * ...); // expected-error {{empty expansion for operator '*' with no fallback}}
+ (N | ...); // expected-error {{empty expansion for operator '|' with no fallback}}
+ (N & ...); // expected-error {{empty expansion for operator '&' with no fallback}}
(N - ...); // expected-error {{empty expansion for operator '-' with no fallback}}
(N / ...); // expected-error {{empty expansion for operator '/' with no fallback}}
(N % ...); // expected-error {{empty expansion for operator '%' with no fallback}}
diff --git a/test/SemaTemplate/deduction.cpp b/test/SemaTemplate/deduction.cpp
index 6826774a0020..d024c3147735 100644
--- a/test/SemaTemplate/deduction.cpp
+++ b/test/SemaTemplate/deduction.cpp
@@ -218,3 +218,50 @@ namespace NonDeducedNestedNameSpecifier {
template<typename T> int f(A<T>, typename A<T>::template B<T>);
int k = f(A<int>(), 0);
}
+
+namespace PR27601_RecursivelyInheritedBaseSpecializationsDeductionAmbiguity {
+namespace ns1 {
+
+template<class...> struct B { };
+template<class H, class ... Ts> struct B<H, Ts...> : B<> { };
+template<class ... Ts> struct D : B<Ts...> { };
+
+template<class T, class ... Ts> void f(B<T, Ts...> &) { }
+
+int main() {
+ D<int, char> d;
+ f<int>(d);
+}
+} //end ns1
+
+namespace ns2 {
+
+template <int i, typename... Es> struct tup_impl;
+
+template <int i> struct tup_impl<i> {}; // empty tail
+
+template <int i, typename Head, typename... Tail>
+struct tup_impl<i, Head, Tail...> : tup_impl<i + 1, Tail...> {
+ using value_type = Head;
+ Head head;
+};
+
+template <typename... Es> struct tup : tup_impl<0, Es...> {};
+
+template <typename Head, int i, typename... Tail>
+Head &get_helper(tup_impl<i, Head, Tail...> &t) {
+ return t.head;
+}
+
+template <typename Head, int i, typename... Tail>
+Head const &get_helper(tup_impl<i, Head, Tail...> const &t) {
+ return t.head;
+}
+
+int main() {
+ tup<int, double, char> t;
+ get_helper<double>(t);
+ return 0;
+}
+} // end ns2
+} \ No newline at end of file
diff --git a/test/SemaTemplate/default-arguments-cxx0x.cpp b/test/SemaTemplate/default-arguments-cxx0x.cpp
index 0c97c2056b75..c52899a8e6d1 100644
--- a/test/SemaTemplate/default-arguments-cxx0x.cpp
+++ b/test/SemaTemplate/default-arguments-cxx0x.cpp
@@ -75,3 +75,13 @@ namespace rdar23810407 {
g<int>();
}
}
+
+// rdar://problem/24480205
+namespace PR13986 {
+ constexpr unsigned Dynamic = 0;
+ template <unsigned> class A { template <unsigned = Dynamic> void m_fn1(); };
+ class Test {
+ ~Test() {}
+ A<1> m_target;
+ };
+}
diff --git a/test/SemaTemplate/extern-templates.cpp b/test/SemaTemplate/extern-templates.cpp
index eca64ed595eb..5eb9c9db127c 100644
--- a/test/SemaTemplate/extern-templates.cpp
+++ b/test/SemaTemplate/extern-templates.cpp
@@ -1,4 +1,5 @@
-// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -triple i686-pc-win32 -fsyntax-only -verify %s -DMS
+// RUN: %clang_cc1 -triple x86_64-unknown-linux-gnu-pc-win32 -fsyntax-only -verify %s
template<typename T>
class X0 {
@@ -21,12 +22,20 @@ extern template class X0<int*>;
template<typename T>
void X0<T>::Inner::g(T t) {
- t = 17; // expected-error{{incompatible}}
+#ifdef MS
+ t = 17; // expected-error{{assigning to 'long *' from incompatible}} expected-error{{assigning to 'int *' from incompatible}}
+#else
+ t = 17; // expected-error{{assigning to 'long *' from incompatible}}
+#endif
}
void test_intptr(X0<int*> xi, X0<int*>::Inner xii) {
xi.f(0);
+#ifdef MS
+ xii.g(0); // expected-note {{instantiation}}
+#else
xii.g(0);
+#endif
}
extern template class X0<long*>;
diff --git a/test/SemaTemplate/instantiate-cast.cpp b/test/SemaTemplate/instantiate-cast.cpp
index b3babf12981e..32a1cfdfec9d 100644
--- a/test/SemaTemplate/instantiate-cast.cpp
+++ b/test/SemaTemplate/instantiate-cast.cpp
@@ -1,6 +1,13 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
-struct A { int x; }; // expected-note 2 {{candidate constructor}}
+struct A { int x; };
+// expected-note@-1 {{candidate constructor (the implicit copy constructor) not viable: no known conversion from 'int' to 'const A' for 1st argument}}
+#if __cplusplus >= 201103L
+// expected-note@-3 {{candidate constructor (the implicit move constructor) not viable: no known conversion from 'int' to 'A' for 1st argument}}
+#endif
+// expected-note@-5 {{candidate constructor (the implicit default constructor) not viable: requires 0 arguments, but 1 was provided}}
class Base {
public:
diff --git a/test/SemaTemplate/instantiate-expr-4.cpp b/test/SemaTemplate/instantiate-expr-4.cpp
index d95ccfecd9b5..9a1a1d2bb697 100644
--- a/test/SemaTemplate/instantiate-expr-4.cpp
+++ b/test/SemaTemplate/instantiate-expr-4.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -fsyntax-only -verify -std=c++11 %s
// ---------------------------------------------------------------------
// C++ Functional Casts
@@ -22,6 +24,9 @@ struct FunctionalCast0 {
template struct FunctionalCast0<5>;
struct X { // expected-note 3 {{candidate constructor (the implicit copy constructor)}}
+#if __cplusplus >= 201103L
+// expected-note@-2 3 {{candidate constructor (the implicit move constructor) not viable}}
+#endif
X(int, int); // expected-note 3 {{candidate constructor}}
};
@@ -213,6 +218,10 @@ template<typename T, typename Val1>
struct InitList1 {
void f(Val1 val1) {
T x = { val1 };
+#if __cplusplus >= 201103L
+ // expected-error@-2 {{type 'float' cannot be narrowed to 'int' in initializer list}}
+ // expected-note@-3 {{insert an explicit cast to silence this issue}}
+#endif
}
};
@@ -222,6 +231,9 @@ struct APair {
};
template struct InitList1<int[1], float>;
+#if __cplusplus >= 201103L
+// expected-note@-2 {{instantiation of member function}}
+#endif
template struct InitList1<APair, int*>;
template<typename T, typename Val1, typename Val2>
diff --git a/test/SemaTemplate/instantiate-member-class.cpp b/test/SemaTemplate/instantiate-member-class.cpp
index 3f49606b86e5..159bccb2c992 100644
--- a/test/SemaTemplate/instantiate-member-class.cpp
+++ b/test/SemaTemplate/instantiate-member-class.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
namespace PR8965 {
template<typename T>
@@ -106,7 +108,10 @@ namespace test2 {
namespace AliasTagDef {
template<typename T>
struct F {
- using S = struct U { // expected-warning {{C++11}}
+ using S = struct U {
+#if __cplusplus <= 199711L
+ // expected-warning@-2 {{alias declarations are a C++11 extension}}
+#endif
T g() {
return T();
}
@@ -122,8 +127,13 @@ namespace rdar10397846 {
{
struct B
{
- struct C { C() { int *ptr = I; } }; // expected-error{{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}} \
- expected-warning{{expression which evaluates to zero treated as a null pointer constant of type 'int *'}}
+ struct C { C() { int *ptr = I; } };
+#if __cplusplus >= 201103L
+ // expected-error@-2 {{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}}
+#else
+ // expected-warning@-4 {{expression which evaluates to zero treated as a null pointer constant of type 'int *'}}
+#endif
+ // expected-error@-6 {{cannot initialize a variable of type 'int *' with an rvalue of type 'int'}}
};
};
diff --git a/test/SemaTemplate/instantiate-sizeof.cpp b/test/SemaTemplate/instantiate-sizeof.cpp
index bf66fdc17c65..660e70549e30 100644
--- a/test/SemaTemplate/instantiate-sizeof.cpp
+++ b/test/SemaTemplate/instantiate-sizeof.cpp
@@ -1,5 +1,4 @@
-// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
-// expected-no-diagnostics
+// RUN: %clang_cc1 -triple x86_64-linux-gnu -fsyntax-only -verify -std=c++11 %s
// Make sure we handle contexts correctly with sizeof
template<typename T> void f(T n) {
@@ -9,3 +8,29 @@ template<typename T> void f(T n) {
int main() {
f<int>(1);
}
+
+// Make sure we handle references to non-static data members in unevaluated
+// contexts in class template methods correctly. Previously we assumed these
+// would be valid MemberRefExprs, but they have no 'this' so we need to form a
+// DeclRefExpr to the FieldDecl instead.
+// PR26893
+template <class T>
+struct M {
+ M() {}; // expected-note {{in instantiation of default member initializer 'M<S>::m' requested here}}
+ int m = *T::x; // expected-error {{invalid use of non-static data member 'x'}}
+ void f() {
+ // These are valid.
+ static_assert(sizeof(T::x) == 8, "ptr");
+ static_assert(sizeof(*T::x) == 4, "int");
+ }
+};
+struct S { int *x; };
+template struct M<S>; // expected-note {{in instantiation of member function 'M<S>::M' requested here}}
+
+// Similar test case for PR26893.
+template <typename T=void>
+struct bar {
+ struct foo { int array[10]; };
+ int baz() { return sizeof(foo::array); }
+};
+template struct bar<>;
diff --git a/test/SemaTemplate/member-access-expr.cpp b/test/SemaTemplate/member-access-expr.cpp
index f1aa30ec32a6..8dba2e68d656 100644
--- a/test/SemaTemplate/member-access-expr.cpp
+++ b/test/SemaTemplate/member-access-expr.cpp
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
template<typename T>
void call_f0(T x) {
x.Base::f0();
@@ -28,15 +31,25 @@ void test_f0_through_typedef(X0 x0) {
template<typename TheBase, typename T>
void call_f0_through_typedef2(T x) {
- typedef TheBase CrazyBase; // expected-note{{current scope}}
- x.CrazyBase::f0(); // expected-error{{ambiguous}} \
- // expected-error 2{{no member named}}
+ typedef TheBase CrazyBase;
+#if __cplusplus <= 199711L
+ // expected-note@-2 {{lookup from the current scope refers here}}
+#endif
+
+ x.CrazyBase::f0(); // expected-error 2{{no member named}}
+#if __cplusplus <= 199711L
+ // expected-error@-2 {{lookup of 'CrazyBase' in member access expression is ambiguous}}
+#endif
+
}
struct OtherBase { };
struct X1 : Base, OtherBase {
- typedef OtherBase CrazyBase; // expected-note{{object type}}
+ typedef OtherBase CrazyBase;
+#if __cplusplus <= 199711L
+ // expected-note@-2 {{lookup in the object type 'X1' refers here}}
+#endif
};
void test_f0_through_typedef2(X0 x0, X1 x1) {
diff --git a/test/SemaTemplate/ms-delayed-default-template-args.cpp b/test/SemaTemplate/ms-delayed-default-template-args.cpp
index ca9ddb0d9d15..0c0546942475 100644
--- a/test/SemaTemplate/ms-delayed-default-template-args.cpp
+++ b/test/SemaTemplate/ms-delayed-default-template-args.cpp
@@ -55,6 +55,15 @@ struct Foo {
typedef int Weber;
}
+// MSVC accepts this, but Clang doesn't.
+namespace test_scope_spec {
+template <typename T = ns::Bar> // expected-error {{use of undeclared identifier 'ns'}}
+struct Foo {
+ static_assert(sizeof(T) == 4, "Bar should have gotten int");
+};
+namespace ns { typedef int Bar; }
+}
+
#ifdef __clang__
// These are negative test cases that MSVC doesn't compile either. Try to use
// unique undeclared identifiers so typo correction doesn't find types declared
diff --git a/test/SemaTemplate/ms-function-specialization-class-scope.cpp b/test/SemaTemplate/ms-function-specialization-class-scope.cpp
index 5da00837cc09..3c7111d05838 100644
--- a/test/SemaTemplate/ms-function-specialization-class-scope.cpp
+++ b/test/SemaTemplate/ms-function-specialization-class-scope.cpp
@@ -75,3 +75,12 @@ namespace Duplicates {
// here.
template struct A<int>;
}
+
+namespace PR28082 {
+struct S {
+ template <int>
+ int f(int = 0);
+ template <>
+ int f<0>(int); // expected-warning {{Microsoft extension}}
+};
+}
diff --git a/test/SemaTemplate/ms-lookup-template-base-classes.cpp b/test/SemaTemplate/ms-lookup-template-base-classes.cpp
index 4f3df277d912..6afc7091260d 100644
--- a/test/SemaTemplate/ms-lookup-template-base-classes.cpp
+++ b/test/SemaTemplate/ms-lookup-template-base-classes.cpp
@@ -1,4 +1,4 @@
-// RUN: %clang_cc1 -std=c++1y -fms-compatibility -fno-spell-checking -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fcxx-exceptions -fexceptions -std=c++1y -fms-compatibility -fno-spell-checking -fsyntax-only -verify %s
template <class T>
@@ -573,3 +573,62 @@ void h();
template <typename T> decltype(h(T())) check2(); // expected-note{{candidate template ignored: substitution failure [with T = int]: no matching function for call to 'h'}}
decltype(check2<int>()) y; // expected-error{{no matching function for call to 'check2'}}
}
+
+// We also allow unqualified lookup into bases in contexts where the we know the
+// undeclared identifier *must* be a type, such as a new expression or catch
+// parameter type.
+template <typename T>
+struct UseUnqualifiedTypeNames : T {
+ void foo() {
+ void *P = new TheType; // expected-warning {{unqualified lookup}} expected-error {{no type}}
+ size_t x = __builtin_offsetof(TheType, f2); // expected-warning {{unqualified lookup}} expected-error {{no type}}
+ try {
+ } catch (TheType) { // expected-warning {{unqualified lookup}} expected-error {{no type}}
+ }
+ enum E : IntegerType { E0 = 42 }; // expected-warning {{unqualified lookup}} expected-error {{no type}}
+ _Atomic(TheType) a; // expected-warning {{unqualified lookup}} expected-error {{no type}}
+ }
+ void out_of_line();
+};
+template <typename T>
+void UseUnqualifiedTypeNames<T>::out_of_line() {
+ void *p = new TheType; // expected-warning {{unqualified lookup}} expected-error {{no type}}
+}
+struct Base {
+ typedef int IntegerType;
+ struct TheType {
+ int f1, f2;
+ };
+};
+template struct UseUnqualifiedTypeNames<Base>;
+struct BadBase { };
+template struct UseUnqualifiedTypeNames<BadBase>; // expected-note-re 2 {{in instantiation {{.*}} requested here}}
+
+namespace partial_template_lookup {
+
+class Bar;
+class Spare;
+
+template <class T, class X = Bar>
+class FooTemplated;
+
+class FooBase {
+public:
+ typedef int BaseTypedef;
+};
+
+// Partial template spec (unused)
+template <class T>
+class FooTemplated<T, Spare> {};
+
+// Partial template spec (used)
+template <class T>
+class FooTemplated<T, Bar> : public FooBase {};
+
+// Full template spec
+template <class T, class X>
+class FooTemplated : public FooTemplated<T, Bar> {
+public:
+ BaseTypedef Member; // expected-warning {{unqualified lookup}}
+};
+}
diff --git a/test/SemaTemplate/recovery-crash.cpp b/test/SemaTemplate/recovery-crash.cpp
index 02f80495bb94..c8e783f47b45 100644
--- a/test/SemaTemplate/recovery-crash.cpp
+++ b/test/SemaTemplate/recovery-crash.cpp
@@ -1,4 +1,6 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
// Clang used to crash trying to recover while adding 'this->' before Work(x);
@@ -25,14 +27,20 @@ namespace PR16134 {
namespace PR16225 {
template <typename T> void f();
- template<typename C> void g(C*) {
+ template <typename C> void g(C*) {
struct LocalStruct : UnknownBase<Mumble, C> { }; // expected-error {{unknown template name 'UnknownBase'}} \
// expected-error {{use of undeclared identifier 'Mumble'}}
- f<LocalStruct>(); // expected-warning {{template argument uses local type 'LocalStruct'}}
+ f<LocalStruct>();
+#if __cplusplus <= 199711L
+ // expected-warning@-2 {{template argument uses local type 'LocalStruct'}}
+#endif
}
struct S;
void h() {
- g<S>(0); // expected-note {{in instantiation of function template specialization}}
+ g<S>(0);
+#if __cplusplus <= 199711L
+ // expected-note@-2 {{in instantiation of function template specialization}}
+#endif
}
}
diff --git a/test/SemaTemplate/temp_arg_type.cpp b/test/SemaTemplate/temp_arg_type.cpp
index 637b5637baec..daad61c14292 100644
--- a/test/SemaTemplate/temp_arg_type.cpp
+++ b/test/SemaTemplate/temp_arg_type.cpp
@@ -1,4 +1,7 @@
// RUN: %clang_cc1 -fsyntax-only -verify %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++98 %s
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++11 %s
+
template<typename T> class A; // expected-note 2 {{template parameter is declared here}} expected-note{{template is declared here}}
// [temp.arg.type]p1
@@ -24,11 +27,21 @@ A<ns::B> a8; // expected-error{{use of class template 'ns::B' requires template
// [temp.arg.type]p2
void f() {
class X { };
- A<X> * a = 0; // expected-warning{{template argument uses local type 'X'}}
+ A<X> * a = 0;
+#if __cplusplus <= 199711L
+ // expected-warning@-2 {{template argument uses local type 'X'}}
+#endif
}
-struct { int x; } Unnamed; // expected-note{{unnamed type used in template argument was declared here}}
-A<__typeof__(Unnamed)> *a9; // expected-warning{{template argument uses unnamed type}}
+struct { int x; } Unnamed;
+#if __cplusplus <= 199711L
+// expected-note@-2 {{unnamed type used in template argument was declared here}}
+#endif
+
+A<__typeof__(Unnamed)> *a9;
+#if __cplusplus <= 199711L
+// expected-warning@-2 {{template argument uses unnamed type}}
+#endif
template<typename T, unsigned N>
struct Array {
diff --git a/test/SemaTemplate/template-id-expr.cpp b/test/SemaTemplate/template-id-expr.cpp
index 4416f92723ad..499d289ee675 100644
--- a/test/SemaTemplate/template-id-expr.cpp
+++ b/test/SemaTemplate/template-id-expr.cpp
@@ -96,3 +96,9 @@ void f5() {
}
template void f5<0>(); // expected-note {{in instantiation of function template specialization 'f5<0>' requested here}}
+
+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}}
+};
diff --git a/test/SemaTemplate/undefined-template.cpp b/test/SemaTemplate/undefined-template.cpp
new file mode 100644
index 000000000000..a03d0b7cff62
--- /dev/null
+++ b/test/SemaTemplate/undefined-template.cpp
@@ -0,0 +1,139 @@
+// RUN: %clang_cc1 -fsyntax-only -verify -std=c++14 -Wundefined-func-template %s
+
+template <class T> struct C1 {
+ static char s_var_1; // expected-note{{forward declaration of template entity is here}}
+ static char s_var_2; // expected-note{{forward declaration of template entity is here}}
+ static void s_func_1(); // expected-note{{forward declaration of template entity is here}}
+ static void s_func_2(); // expected-note{{forward declaration of template entity is here}}
+ void meth_1(); // expected-note2{{forward declaration of template entity is here}}
+ void meth_2();
+ template <class T1> static char s_tvar_2; // expected-note{{forward declaration of template entity is here}}
+ template <class T1> static void s_tfunc_2(); // expected-note{{forward declaration of template entity is here}}
+ template<typename T1> struct C2 {
+ static char s_var_2; // expected-note{{forward declaration of template entity is here}}
+ static void s_func_2(); // expected-note{{forward declaration of template entity is here}}
+ void meth_2(); // expected-note{{forward declaration of template entity is here}}
+ template <class T2> static char s_tvar_2; // expected-note{{forward declaration of template entity is here}}
+ template <class T2> void tmeth_2(); // expected-note{{forward declaration of template entity is here}}
+ };
+};
+
+extern template char C1<int>::s_var_2;
+extern template void C1<int>::s_func_2();
+extern template void C1<int>::meth_2();
+extern template char C1<int>::s_tvar_2<char>;
+extern template void C1<int>::s_tfunc_2<char>();
+extern template void C1<int>::C2<long>::s_var_2;
+extern template void C1<int>::C2<long>::s_func_2();
+extern template void C1<int>::C2<long>::meth_2();
+extern template char C1<int>::C2<long>::s_tvar_2<char>;
+extern template void C1<int>::C2<long>::tmeth_2<char>();
+
+char func_01() {
+ return C1<int>::s_var_2;
+}
+
+char func_02() {
+ return C1<int>::s_var_1; // expected-warning{{instantiation of variable 'C1<int>::s_var_1' required here, but no definition is available}}
+ // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::s_var_1' is explicitly instantiated in another translation unit}}
+}
+
+char func_03() {
+ return C1<char>::s_var_2; // expected-warning{{instantiation of variable 'C1<char>::s_var_2' required here, but no definition is available}}
+ // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<char>::s_var_2' is explicitly instantiated in another translation unit}}
+}
+
+void func_04() {
+ C1<int>::s_func_1(); // expected-warning{{instantiation of function 'C1<int>::s_func_1' required here, but no definition is available}}
+ // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::s_func_1' is explicitly instantiated in another translation unit}}
+}
+
+void func_05() {
+ C1<int>::s_func_2();
+}
+
+void func_06() {
+ C1<char>::s_func_2(); // expected-warning{{instantiation of function 'C1<char>::s_func_2' required here, but no definition is available}}
+ // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<char>::s_func_2' is explicitly instantiated in another translation unit}}
+}
+
+void func_07(C1<int> *x) {
+ x->meth_1(); // expected-warning{{instantiation of function 'C1<int>::meth_1' required here, but no definition is available}}
+ // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::meth_1' is explicitly instantiated in another translation unit}}
+}
+
+void func_08(C1<int> *x) {
+ x->meth_2();
+}
+
+void func_09(C1<char> *x) {
+ x->meth_1(); // expected-warning{{instantiation of function 'C1<char>::meth_1' required here, but no definition is available}}
+ // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<char>::meth_1' is explicitly instantiated in another translation unit}}
+}
+
+char func_10() {
+ return C1<int>::s_tvar_2<char>;
+}
+
+char func_11() {
+ return C1<int>::s_tvar_2<long>; // expected-warning{{instantiation of variable 'C1<int>::s_tvar_2<long>' required here, but no definition is available}}
+ // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::s_tvar_2<long>' is explicitly instantiated in another translation unit}}
+}
+
+void func_12() {
+ C1<int>::s_tfunc_2<char>();
+}
+
+void func_13() {
+ C1<int>::s_tfunc_2<long>(); // expected-warning{{instantiation of function 'C1<int>::s_tfunc_2<long>' required here, but no definition is available}}
+ // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::s_tfunc_2<long>' is explicitly instantiated in another translation unit}}
+}
+
+char func_14() {
+ return C1<int>::C2<long>::s_var_2;
+}
+
+char func_15() {
+ return C1<int>::C2<char>::s_var_2; //expected-warning {{instantiation of variable 'C1<int>::C2<char>::s_var_2' required here, but no definition is available}}
+ // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<char>::s_var_2' is explicitly instantiated in another translation unit}}
+}
+
+void func_16() {
+ C1<int>::C2<long>::s_func_2();
+}
+
+void func_17() {
+ C1<int>::C2<char>::s_func_2(); // expected-warning{{instantiation of function 'C1<int>::C2<char>::s_func_2' required here, but no definition is available}}
+ // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<char>::s_func_2' is explicitly instantiated in another translation unit}}
+}
+
+void func_18(C1<int>::C2<long> *x) {
+ x->meth_2();
+}
+
+void func_19(C1<int>::C2<char> *x) {
+ x->meth_2(); // expected-warning{{instantiation of function 'C1<int>::C2<char>::meth_2' required here, but no definition is available}}
+ // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<char>::meth_2' is explicitly instantiated in another translation unit}}
+}
+
+char func_20() {
+ return C1<int>::C2<long>::s_tvar_2<char>;
+}
+
+char func_21() {
+ return C1<int>::C2<long>::s_tvar_2<long>; // expected-warning{{instantiation of variable 'C1<int>::C2<long>::s_tvar_2<long>' required here, but no definition is available}}
+ // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<long>::s_tvar_2<long>' is explicitly instantiated in another translation unit}}
+}
+
+void func_22(C1<int>::C2<long> *x) {
+ x->tmeth_2<char>();
+}
+
+void func_23(C1<int>::C2<long> *x) {
+ x->tmeth_2<int>(); // expected-warning{{instantiation of function 'C1<int>::C2<long>::tmeth_2<int>' required here, but no definition is available}}
+ // expected-note@-1{{add an explicit instantiation declaration to suppress this warning if 'C1<int>::C2<long>::tmeth_2<int>' is explicitly instantiated in another translation unit}}
+}
+
+int main() {
+ return 0;
+}