diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td index f9dec60cf9907..a9dde041bc22a 100644 --- a/clang/include/clang/Basic/DiagnosticSemaKinds.td +++ b/clang/include/clang/Basic/DiagnosticSemaKinds.td @@ -5655,9 +5655,9 @@ def err_unexpanded_parameter_pack : Error< "%select{expression|base type|declaration type|data member type|bit-field " "size|static assertion|fixed underlying type|enumerator value|" "using declaration|friend declaration|qualifier|initializer|default argument|" - "non-type template parameter type|exception type|partial specialization|" - "__if_exists name|__if_not_exists name|lambda|block|type constraint|" - "requirement|requires clause}0 " + "non-type template parameter type|exception type|explicit specialization|" + "partial specialization|__if_exists name|__if_not_exists name|lambda|block|" + "type constraint|requirement|requires clause}0 " "contains%plural{0: an|:}1 unexpanded parameter pack" "%plural{0:|1: %2|2:s %2 and %3|:s %2, %3, ...}1">; diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index a35a3c2c26c22..731d0886a7367 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/include/clang/Sema/Sema.h @@ -8842,6 +8842,9 @@ class Sema final { /// The type of an exception. UPPC_ExceptionType, + /// Explicit specialization. + UPPC_ExplicitSpecialization, + /// Partial specialization. UPPC_PartialSpecialization, diff --git a/clang/lib/Sema/SemaTemplate.cpp b/clang/lib/Sema/SemaTemplate.cpp index 6865e04b94b20..766ebd90fded0 100644 --- a/clang/lib/Sema/SemaTemplate.cpp +++ b/clang/lib/Sema/SemaTemplate.cpp @@ -4559,7 +4559,9 @@ DeclResult Sema::ActOnVarTemplateSpecialization( // Check for unexpanded parameter packs in any of the template arguments. for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) if (DiagnoseUnexpandedParameterPack(TemplateArgs[I], - UPPC_PartialSpecialization)) + IsPartialSpecialization + ? UPPC_PartialSpecialization + : UPPC_ExplicitSpecialization)) return true; // Check that the template argument list is well-formed for this @@ -8744,7 +8746,9 @@ DeclResult Sema::ActOnClassTemplateSpecialization( // Check for unexpanded parameter packs in any of the template arguments. for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I) if (DiagnoseUnexpandedParameterPack(TemplateArgs[I], - UPPC_PartialSpecialization)) + isPartialSpecialization + ? UPPC_PartialSpecialization + : UPPC_ExplicitSpecialization)) return true; // Check that the template argument list is well-formed for this diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp index 7536339c14a2e..30ce6b40e1fb5 100644 --- a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp +++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp @@ -369,9 +369,39 @@ void test_unexpanded_exprs(Types ...values) { void f(int arg = values); // expected-error{{default argument contains unexpanded parameter pack 'values'}} } -// Test unexpanded parameter packs in partial specializations. -template -struct TestUnexpandedDecls; // expected-error{{partial specialization contains unexpanded parameter pack 'Types'}} +// Test unexpanded parameter packs in partial/explicit specializations. +namespace Specializations { + template + struct PrimaryClass; + template + struct PrimaryClass; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}} + +#if __cplusplus >= 201402L + template + constexpr int PrimaryVar = 0; + template + constexpr int PrimaryVar = 0; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}} +#endif + + template + struct OuterClass { + template + struct InnerClass; + template<> + struct InnerClass; // expected-error{{explicit specialization contains unexpanded parameter pack 'Ts'}} + template + struct InnerClass; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}} + +#if __cplusplus >= 201402L + template + constexpr static int InnerVar = 0; + template<> + constexpr static int InnerVar = 0; // expected-error{{explicit specialization contains unexpanded parameter pack 'Ts'}} + template + constexpr static int InnerVar = 0; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}} +#endif + }; +} // Test for diagnostics in the presence of multiple unexpanded // parameter packs.