Skip to content

Commit 979eb55

Browse files
authored
[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.
1 parent e8fe15c commit 979eb55

File tree

4 files changed

+45
-8
lines changed

4 files changed

+45
-8
lines changed

clang/include/clang/Basic/DiagnosticSemaKinds.td

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5655,9 +5655,9 @@ def err_unexpanded_parameter_pack : Error<
56555655
"%select{expression|base type|declaration type|data member type|bit-field "
56565656
"size|static assertion|fixed underlying type|enumerator value|"
56575657
"using declaration|friend declaration|qualifier|initializer|default argument|"
5658-
"non-type template parameter type|exception type|partial specialization|"
5659-
"__if_exists name|__if_not_exists name|lambda|block|type constraint|"
5660-
"requirement|requires clause}0 "
5658+
"non-type template parameter type|exception type|explicit specialization|"
5659+
"partial specialization|__if_exists name|__if_not_exists name|lambda|block|"
5660+
"type constraint|requirement|requires clause}0 "
56615661
"contains%plural{0: an|:}1 unexpanded parameter pack"
56625662
"%plural{0:|1: %2|2:s %2 and %3|:s %2, %3, ...}1">;
56635663

clang/include/clang/Sema/Sema.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -8842,6 +8842,9 @@ class Sema final {
88428842
/// The type of an exception.
88438843
UPPC_ExceptionType,
88448844

8845+
/// Explicit specialization.
8846+
UPPC_ExplicitSpecialization,
8847+
88458848
/// Partial specialization.
88468849
UPPC_PartialSpecialization,
88478850

clang/lib/Sema/SemaTemplate.cpp

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4559,7 +4559,9 @@ DeclResult Sema::ActOnVarTemplateSpecialization(
45594559
// Check for unexpanded parameter packs in any of the template arguments.
45604560
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
45614561
if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
4562-
UPPC_PartialSpecialization))
4562+
IsPartialSpecialization
4563+
? UPPC_PartialSpecialization
4564+
: UPPC_ExplicitSpecialization))
45634565
return true;
45644566

45654567
// Check that the template argument list is well-formed for this
@@ -8744,7 +8746,9 @@ DeclResult Sema::ActOnClassTemplateSpecialization(
87448746
// Check for unexpanded parameter packs in any of the template arguments.
87458747
for (unsigned I = 0, N = TemplateArgs.size(); I != N; ++I)
87468748
if (DiagnoseUnexpandedParameterPack(TemplateArgs[I],
8747-
UPPC_PartialSpecialization))
8749+
isPartialSpecialization
8750+
? UPPC_PartialSpecialization
8751+
: UPPC_ExplicitSpecialization))
87488752
return true;
87498753

87508754
// Check that the template argument list is well-formed for this

clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp

Lines changed: 33 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -369,9 +369,39 @@ void test_unexpanded_exprs(Types ...values) {
369369
void f(int arg = values); // expected-error{{default argument contains unexpanded parameter pack 'values'}}
370370
}
371371

372-
// Test unexpanded parameter packs in partial specializations.
373-
template<typename ...Types>
374-
struct TestUnexpandedDecls<int, Types>; // expected-error{{partial specialization contains unexpanded parameter pack 'Types'}}
372+
// Test unexpanded parameter packs in partial/explicit specializations.
373+
namespace Specializations {
374+
template<typename T, typename... Ts>
375+
struct PrimaryClass;
376+
template<typename... Ts>
377+
struct PrimaryClass<Ts>; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
378+
379+
#if __cplusplus >= 201402L
380+
template<typename T, typename... Ts>
381+
constexpr int PrimaryVar = 0;
382+
template<typename... Ts>
383+
constexpr int PrimaryVar<Ts> = 0; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
384+
#endif
385+
386+
template<typename... Ts>
387+
struct OuterClass {
388+
template<typename... Us>
389+
struct InnerClass;
390+
template<>
391+
struct InnerClass<Ts>; // expected-error{{explicit specialization contains unexpanded parameter pack 'Ts'}}
392+
template<typename U>
393+
struct InnerClass<U, Ts>; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
394+
395+
#if __cplusplus >= 201402L
396+
template<typename... Us>
397+
constexpr static int InnerVar = 0;
398+
template<>
399+
constexpr static int InnerVar<Ts> = 0; // expected-error{{explicit specialization contains unexpanded parameter pack 'Ts'}}
400+
template<typename U>
401+
constexpr static int InnerVar<U, Ts> = 0; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
402+
#endif
403+
};
404+
}
375405

376406
// Test for diagnostics in the presence of multiple unexpanded
377407
// parameter packs.

0 commit comments

Comments
 (0)