Skip to content

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

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 1 commit into from
Nov 16, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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 @@ -8839,6 +8839,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