Skip to content

Commit

Permalink
[Clang][Sema] Differentiate between partial/explicit specializations …
Browse files Browse the repository at this point in the history
…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.
  • Loading branch information
sdkrystian committed Nov 16, 2023
1 parent e8fe15c commit 979eb55
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 8 deletions.
6 changes: 3 additions & 3 deletions clang/include/clang/Basic/DiagnosticSemaKinds.td
Original file line number Diff line number Diff line change
Expand Up @@ -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">;

Expand Down
3 changes: 3 additions & 0 deletions clang/include/clang/Sema/Sema.h
Original file line number Diff line number Diff line change
Expand Up @@ -8842,6 +8842,9 @@ class Sema final {
/// The type of an exception.
UPPC_ExceptionType,

/// Explicit specialization.
UPPC_ExplicitSpecialization,

/// Partial specialization.
UPPC_PartialSpecialization,

Expand Down
8 changes: 6 additions & 2 deletions clang/lib/Sema/SemaTemplate.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down
36 changes: 33 additions & 3 deletions clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down

0 comments on commit 979eb55

Please sign in to comment.