Skip to content

Commit 3f2e670

Browse files
authored
Revert "[Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations" (#76876)
Reverts #76677 See discussion here: #76677
1 parent 49b4920 commit 3f2e670

File tree

3 files changed

+46
-56
lines changed

3 files changed

+46
-56
lines changed

clang/docs/ReleaseNotes.rst

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -518,7 +518,6 @@ Improvements to Clang's diagnostics
518518
- Clang now diagnoses definitions of friend function specializations, e.g. ``friend void f<>(int) {}``.
519519
- Clang now diagnoses narrowing conversions involving const references.
520520
(`#63151: <https://github.com/llvm/llvm-project/issues/63151>`_).
521-
- Clang now diagnoses unexpanded packs within the template argument lists of function template specializations.
522521

523522

524523
Improvements to Clang's time-trace

clang/lib/Sema/SemaDecl.cpp

Lines changed: 46 additions & 43 deletions
Original file line numberDiff line numberDiff line change
@@ -9900,15 +9900,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
99009900
// Match up the template parameter lists with the scope specifier, then
99019901
// determine whether we have a template or a template specialization.
99029902
bool Invalid = false;
9903-
TemplateIdAnnotation *TemplateId =
9904-
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
9905-
? D.getName().TemplateId
9906-
: nullptr;
99079903
TemplateParameterList *TemplateParams =
99089904
MatchTemplateParametersToScopeSpecifier(
99099905
D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
9910-
D.getCXXScopeSpec(), TemplateId, TemplateParamLists, isFriend,
9911-
isMemberSpecialization, Invalid);
9906+
D.getCXXScopeSpec(),
9907+
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
9908+
? D.getName().TemplateId
9909+
: nullptr,
9910+
TemplateParamLists, isFriend, isMemberSpecialization,
9911+
Invalid);
99129912
if (TemplateParams) {
99139913
// Check that we can declare a template here.
99149914
if (CheckTemplateDeclScope(S, TemplateParams))
@@ -9921,11 +9921,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
99219921
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
99229922
Diag(NewFD->getLocation(), diag::err_destructor_template);
99239923
NewFD->setInvalidDecl();
9924-
// Function template with explicit template arguments.
9925-
} else if (TemplateId) {
9926-
Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec)
9927-
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
9928-
NewFD->setInvalidDecl();
99299924
}
99309925

99319926
// If we're adding a template to a dependent context, we may need to
@@ -9978,11 +9973,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
99789973
<< FixItHint::CreateRemoval(RemoveRange)
99799974
<< FixItHint::CreateInsertion(InsertLoc, "<>");
99809975
Invalid = true;
9981-
9982-
// Recover by faking up an empty template argument list.
9983-
HasExplicitTemplateArgs = true;
9984-
TemplateArgs.setLAngleLoc(InsertLoc);
9985-
TemplateArgs.setRAngleLoc(InsertLoc);
99869976
}
99879977
}
99889978
} else {
@@ -9996,33 +9986,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
99969986
if (TemplateParamLists.size() > 0)
99979987
// For source fidelity, store all the template param lists.
99989988
NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists);
9999-
10000-
// "friend void foo<>(int);" is an implicit specialization decl.
10001-
if (isFriend && TemplateId)
10002-
isFunctionTemplateSpecialization = true;
10003-
}
10004-
10005-
// If this is a function template specialization and the unqualified-id of
10006-
// the declarator-id is a template-id, convert the template argument list
10007-
// into our AST format and check for unexpanded packs.
10008-
if (isFunctionTemplateSpecialization && TemplateId) {
10009-
HasExplicitTemplateArgs = true;
10010-
10011-
TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
10012-
TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
10013-
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
10014-
TemplateId->NumArgs);
10015-
translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
10016-
10017-
// FIXME: Should we check for unexpanded packs if this was an (invalid)
10018-
// declaration of a function template partial specialization? Should we
10019-
// consider the unexpanded pack context to be a partial specialization?
10020-
for (const TemplateArgumentLoc &ArgLoc : TemplateArgs.arguments()) {
10021-
if (DiagnoseUnexpandedParameterPack(
10022-
ArgLoc, isFriend ? UPPC_FriendDeclaration
10023-
: UPPC_ExplicitSpecialization))
10024-
NewFD->setInvalidDecl();
10025-
}
100269989
}
100279990

100289991
if (Invalid) {
@@ -10475,6 +10438,46 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
1047510438
diag::ext_operator_new_delete_declared_inline)
1047610439
<< NewFD->getDeclName();
1047710440

10441+
// If the declarator is a template-id, translate the parser's template
10442+
// argument list into our AST format.
10443+
if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
10444+
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
10445+
TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
10446+
TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
10447+
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
10448+
TemplateId->NumArgs);
10449+
translateTemplateArguments(TemplateArgsPtr,
10450+
TemplateArgs);
10451+
10452+
HasExplicitTemplateArgs = true;
10453+
10454+
if (NewFD->isInvalidDecl()) {
10455+
HasExplicitTemplateArgs = false;
10456+
} else if (FunctionTemplate) {
10457+
// Function template with explicit template arguments.
10458+
Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec)
10459+
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
10460+
10461+
HasExplicitTemplateArgs = false;
10462+
} else if (isFriend) {
10463+
// "friend void foo<>(int);" is an implicit specialization decl.
10464+
isFunctionTemplateSpecialization = true;
10465+
} else {
10466+
assert(isFunctionTemplateSpecialization &&
10467+
"should have a 'template<>' for this decl");
10468+
}
10469+
} else if (isFriend && isFunctionTemplateSpecialization) {
10470+
// This combination is only possible in a recovery case; the user
10471+
// wrote something like:
10472+
// template <> friend void foo(int);
10473+
// which we're recovering from as if the user had written:
10474+
// friend void foo<>(int);
10475+
// Go ahead and fake up a template id.
10476+
HasExplicitTemplateArgs = true;
10477+
TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
10478+
TemplateArgs.setRAngleLoc(D.getIdentifierLoc());
10479+
}
10480+
1047810481
// We do not add HD attributes to specializations here because
1047910482
// they may have different constexpr-ness compared to their
1048010483
// templates and, after maybeAddCUDAHostDeviceAttrs() is applied,

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

Lines changed: 0 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -376,11 +376,6 @@ namespace Specializations {
376376
template<typename... Ts>
377377
struct PrimaryClass<Ts>; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
378378

379-
template<typename T, typename... Ts>
380-
void PrimaryFunction();
381-
template<typename T, typename... Ts>
382-
void PrimaryFunction<Ts>(); // expected-error{{function template partial specialization is not allowed}}
383-
384379
#if __cplusplus >= 201402L
385380
template<typename T, typename... Ts>
386381
constexpr int PrimaryVar = 0;
@@ -397,13 +392,6 @@ namespace Specializations {
397392
template<typename U>
398393
struct InnerClass<U, Ts>; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
399394

400-
template<typename... Us>
401-
void InnerFunction();
402-
template<>
403-
void InnerFunction<Ts>(); // expected-error{{explicit specialization contains unexpanded parameter pack 'Ts'}}
404-
405-
friend void PrimaryFunction<Ts>(); // expected-error{{friend declaration contains unexpanded parameter pack 'Ts'}}
406-
407395
#if __cplusplus >= 201402L
408396
template<typename... Us>
409397
constexpr static int InnerVar = 0;

0 commit comments

Comments
 (0)