[clang] [Clang][Sema] Differentiate between partial/explicit specializations when diagnosing unexpanded packs (PR #72015)
Krystian Stasiowski via cfe-commits
cfe-commits at lists.llvm.org
Fri Nov 10 18:30:40 PST 2023
https://github.com/sdkrystian created https://github.com/llvm/llvm-project/pull/72015
None
>From 394e2e0eed84f0102d194174a7c60048556c56dc Mon Sep 17 00:00:00 2001
From: Krystian Stasiowski <sdkrystian at gmail.com>
Date: Fri, 10 Nov 2023 20:51:12 -0500
Subject: [PATCH] [Clang] Differentiate between partial/explicit
specializations when diagnosing unexpanded packs
---
.../clang/Basic/DiagnosticSemaKinds.td | 6 ++--
clang/include/clang/Sema/Sema.h | 3 ++
clang/lib/Sema/SemaTemplate.cpp | 8 +++--
.../CXX/temp/temp.decls/temp.variadic/p5.cpp | 35 +++++++++++++++++--
4 files changed, 44 insertions(+), 8 deletions(-)
diff --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index 4614324babb1c91..0c8f07b095b1eaa 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 f69f366c1750918..e59827b8c281ea1 100644
--- a/clang/include/clang/Sema/Sema.h
+++ b/clang/include/clang/Sema/Sema.h
@@ -8839,6 +8839,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 6865e04b94b2050..766ebd90fded0c4 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 7536339c14a2e08..d00630b0258a734 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,38 @@ 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<typename ...Types>
-struct TestUnexpandedDecls<int, Types>; // expected-error{{partial specialization contains unexpanded parameter pack 'Types'}}
+// Test unexpanded parameter packs in partial/explicit specializations.
+namespace Specializations {
+ template<typename T, typename... Ts>
+ struct PrimaryClass;
+
+ template<typename T, typename... Ts>
+ constexpr int PrimaryVar = 0;
+
+ template<typename... Ts>
+ struct PrimaryClass<Ts>; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
+
+ template<typename... Ts>
+ constexpr int PrimaryVar<Ts> = 0; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
+
+ template<typename... Ts>
+ struct OuterClass {
+ template<typename... Us>
+ struct InnerClass;
+ template<typename... Us>
+ constexpr static int InnerVar = 0;
+
+ template<>
+ struct InnerClass<Ts>; // expected-error{{explicit specialization contains unexpanded parameter pack 'Ts'}}
+ template<>
+ constexpr static int InnerVar<Ts> = 0; // expected-error{{explicit specialization contains unexpanded parameter pack 'Ts'}}
+
+ template<typename U>
+ struct InnerClass<U, Ts>; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
+ template<typename U>
+ constexpr static int InnerVar<U, Ts> = 0; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
+ };
+}
// Test for diagnostics in the presence of multiple unexpanded
// parameter packs.
More information about the cfe-commits
mailing list