[clang] 979eb55 - [Clang][Sema] Differentiate between partial/explicit specializations when diagnosing unexpanded packs (#72015)

via cfe-commits cfe-commits at lists.llvm.org
Thu Nov 16 01:46:49 PST 2023


Author: Krystian Stasiowski
Date: 2023-11-16T10:46:44+01:00
New Revision: 979eb558dd7c203be10fa24ab2b0d7cb93c3443b

URL: https://github.com/llvm/llvm-project/commit/979eb558dd7c203be10fa24ab2b0d7cb93c3443b
DIFF: https://github.com/llvm/llvm-project/commit/979eb558dd7c203be10fa24ab2b0d7cb93c3443b.diff

LOG: [Clang][Sema] Differentiate between partial/explicit specializations when diagnosing unexpanded packs (#72015)

This adds `UnexpandedParameterPackContext::UPPC_ExplicitSpecialization`
and passes it to `DiagnoseUnexpandedParameterPack` when checking
class/variable template explicit specializations.

Right now we don't check for unexpanded packs in function template
explicit specializations at all, so I will be addressing that in a
followup PR.

Added: 
    

Modified: 
    clang/include/clang/Basic/DiagnosticSemaKinds.td
    clang/include/clang/Sema/Sema.h
    clang/lib/Sema/SemaTemplate.cpp
    clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp

Removed: 
    


################################################################################
diff  --git a/clang/include/clang/Basic/DiagnosticSemaKinds.td b/clang/include/clang/Basic/DiagnosticSemaKinds.td
index f9dec60cf990784..a9dde041bc22a6d 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 a35a3c2c26c22ad..731d0886a7367dc 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 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..30ce6b40e1fb5f0 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<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... Ts>
+  struct PrimaryClass<Ts>; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
+
+#if __cplusplus >= 201402L
+  template<typename T, typename... Ts>
+  constexpr int PrimaryVar = 0;
+  template<typename... Ts>
+  constexpr int PrimaryVar<Ts> = 0; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
+#endif
+
+  template<typename... Ts>
+  struct OuterClass {
+    template<typename... Us>
+    struct InnerClass;
+    template<>
+    struct InnerClass<Ts>; // 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'}}
+
+#if __cplusplus >= 201402L
+    template<typename... Us>
+    constexpr static int InnerVar = 0;
+    template<>
+    constexpr static int InnerVar<Ts> = 0; // expected-error{{explicit 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'}}
+#endif
+  };
+}
 
 // Test for diagnostics in the presence of multiple unexpanded
 // parameter packs.


        


More information about the cfe-commits mailing list