diff options
Diffstat (limited to 'test/SemaTemplate')
| -rw-r--r-- | test/SemaTemplate/alias-templates.cpp | 6 | ||||
| -rw-r--r-- | test/SemaTemplate/class-template-spec.cpp | 45 | ||||
| -rw-r--r-- | test/SemaTemplate/cxx1z-fold-expressions.cpp | 15 | ||||
| -rw-r--r-- | test/SemaTemplate/deduction.cpp | 47 | ||||
| -rw-r--r-- | test/SemaTemplate/default-arguments-cxx0x.cpp | 10 | ||||
| -rw-r--r-- | test/SemaTemplate/extern-templates.cpp | 13 | ||||
| -rw-r--r-- | test/SemaTemplate/instantiate-cast.cpp | 9 | ||||
| -rw-r--r-- | test/SemaTemplate/instantiate-expr-4.cpp | 12 | ||||
| -rw-r--r-- | test/SemaTemplate/instantiate-member-class.cpp | 16 | ||||
| -rw-r--r-- | test/SemaTemplate/instantiate-sizeof.cpp | 29 | ||||
| -rw-r--r-- | test/SemaTemplate/member-access-expr.cpp | 21 | ||||
| -rw-r--r-- | test/SemaTemplate/ms-delayed-default-template-args.cpp | 9 | ||||
| -rw-r--r-- | test/SemaTemplate/ms-function-specialization-class-scope.cpp | 9 | ||||
| -rw-r--r-- | test/SemaTemplate/ms-lookup-template-base-classes.cpp | 61 | ||||
| -rw-r--r-- | test/SemaTemplate/recovery-crash.cpp | 14 | ||||
| -rw-r--r-- | test/SemaTemplate/temp_arg_type.cpp | 19 | ||||
| -rw-r--r-- | test/SemaTemplate/template-id-expr.cpp | 6 | ||||
| -rw-r--r-- | test/SemaTemplate/undefined-template.cpp | 139 |
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; +} |
