mirror of
https://github.com/llvm/llvm-project.git
synced 2025-04-25 12:36:10 +00:00
Revert "[Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations" (#76876)
Reverts llvm/llvm-project#76677 See discussion here: https://github.com/llvm/llvm-project/pull/76677
This commit is contained in:
parent
49b492048a
commit
3f2e670671
@ -518,7 +518,6 @@ Improvements to Clang's diagnostics
|
||||
- Clang now diagnoses definitions of friend function specializations, e.g. ``friend void f<>(int) {}``.
|
||||
- Clang now diagnoses narrowing conversions involving const references.
|
||||
(`#63151: <https://github.com/llvm/llvm-project/issues/63151>`_).
|
||||
- Clang now diagnoses unexpanded packs within the template argument lists of function template specializations.
|
||||
|
||||
|
||||
Improvements to Clang's time-trace
|
||||
|
@ -9900,15 +9900,15 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
// Match up the template parameter lists with the scope specifier, then
|
||||
// determine whether we have a template or a template specialization.
|
||||
bool Invalid = false;
|
||||
TemplateIdAnnotation *TemplateId =
|
||||
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
|
||||
? D.getName().TemplateId
|
||||
: nullptr;
|
||||
TemplateParameterList *TemplateParams =
|
||||
MatchTemplateParametersToScopeSpecifier(
|
||||
D.getDeclSpec().getBeginLoc(), D.getIdentifierLoc(),
|
||||
D.getCXXScopeSpec(), TemplateId, TemplateParamLists, isFriend,
|
||||
isMemberSpecialization, Invalid);
|
||||
D.getCXXScopeSpec(),
|
||||
D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId
|
||||
? D.getName().TemplateId
|
||||
: nullptr,
|
||||
TemplateParamLists, isFriend, isMemberSpecialization,
|
||||
Invalid);
|
||||
if (TemplateParams) {
|
||||
// Check that we can declare a template here.
|
||||
if (CheckTemplateDeclScope(S, TemplateParams))
|
||||
@ -9921,11 +9921,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
if (Name.getNameKind() == DeclarationName::CXXDestructorName) {
|
||||
Diag(NewFD->getLocation(), diag::err_destructor_template);
|
||||
NewFD->setInvalidDecl();
|
||||
// Function template with explicit template arguments.
|
||||
} else if (TemplateId) {
|
||||
Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec)
|
||||
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
|
||||
NewFD->setInvalidDecl();
|
||||
}
|
||||
|
||||
// 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,
|
||||
<< FixItHint::CreateRemoval(RemoveRange)
|
||||
<< FixItHint::CreateInsertion(InsertLoc, "<>");
|
||||
Invalid = true;
|
||||
|
||||
// Recover by faking up an empty template argument list.
|
||||
HasExplicitTemplateArgs = true;
|
||||
TemplateArgs.setLAngleLoc(InsertLoc);
|
||||
TemplateArgs.setRAngleLoc(InsertLoc);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
@ -9996,33 +9986,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
if (TemplateParamLists.size() > 0)
|
||||
// For source fidelity, store all the template param lists.
|
||||
NewFD->setTemplateParameterListsInfo(Context, TemplateParamLists);
|
||||
|
||||
// "friend void foo<>(int);" is an implicit specialization decl.
|
||||
if (isFriend && TemplateId)
|
||||
isFunctionTemplateSpecialization = true;
|
||||
}
|
||||
|
||||
// If this is a function template specialization and the unqualified-id of
|
||||
// the declarator-id is a template-id, convert the template argument list
|
||||
// into our AST format and check for unexpanded packs.
|
||||
if (isFunctionTemplateSpecialization && TemplateId) {
|
||||
HasExplicitTemplateArgs = true;
|
||||
|
||||
TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
|
||||
TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
|
||||
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
|
||||
TemplateId->NumArgs);
|
||||
translateTemplateArguments(TemplateArgsPtr, TemplateArgs);
|
||||
|
||||
// FIXME: Should we check for unexpanded packs if this was an (invalid)
|
||||
// declaration of a function template partial specialization? Should we
|
||||
// consider the unexpanded pack context to be a partial specialization?
|
||||
for (const TemplateArgumentLoc &ArgLoc : TemplateArgs.arguments()) {
|
||||
if (DiagnoseUnexpandedParameterPack(
|
||||
ArgLoc, isFriend ? UPPC_FriendDeclaration
|
||||
: UPPC_ExplicitSpecialization))
|
||||
NewFD->setInvalidDecl();
|
||||
}
|
||||
}
|
||||
|
||||
if (Invalid) {
|
||||
@ -10475,6 +10438,46 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
|
||||
diag::ext_operator_new_delete_declared_inline)
|
||||
<< NewFD->getDeclName();
|
||||
|
||||
// If the declarator is a template-id, translate the parser's template
|
||||
// argument list into our AST format.
|
||||
if (D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId) {
|
||||
TemplateIdAnnotation *TemplateId = D.getName().TemplateId;
|
||||
TemplateArgs.setLAngleLoc(TemplateId->LAngleLoc);
|
||||
TemplateArgs.setRAngleLoc(TemplateId->RAngleLoc);
|
||||
ASTTemplateArgsPtr TemplateArgsPtr(TemplateId->getTemplateArgs(),
|
||||
TemplateId->NumArgs);
|
||||
translateTemplateArguments(TemplateArgsPtr,
|
||||
TemplateArgs);
|
||||
|
||||
HasExplicitTemplateArgs = true;
|
||||
|
||||
if (NewFD->isInvalidDecl()) {
|
||||
HasExplicitTemplateArgs = false;
|
||||
} else if (FunctionTemplate) {
|
||||
// Function template with explicit template arguments.
|
||||
Diag(D.getIdentifierLoc(), diag::err_function_template_partial_spec)
|
||||
<< SourceRange(TemplateId->LAngleLoc, TemplateId->RAngleLoc);
|
||||
|
||||
HasExplicitTemplateArgs = false;
|
||||
} else if (isFriend) {
|
||||
// "friend void foo<>(int);" is an implicit specialization decl.
|
||||
isFunctionTemplateSpecialization = true;
|
||||
} else {
|
||||
assert(isFunctionTemplateSpecialization &&
|
||||
"should have a 'template<>' for this decl");
|
||||
}
|
||||
} else if (isFriend && isFunctionTemplateSpecialization) {
|
||||
// This combination is only possible in a recovery case; the user
|
||||
// wrote something like:
|
||||
// template <> friend void foo(int);
|
||||
// which we're recovering from as if the user had written:
|
||||
// friend void foo<>(int);
|
||||
// Go ahead and fake up a template id.
|
||||
HasExplicitTemplateArgs = true;
|
||||
TemplateArgs.setLAngleLoc(D.getIdentifierLoc());
|
||||
TemplateArgs.setRAngleLoc(D.getIdentifierLoc());
|
||||
}
|
||||
|
||||
// We do not add HD attributes to specializations here because
|
||||
// they may have different constexpr-ness compared to their
|
||||
// templates and, after maybeAddCUDAHostDeviceAttrs() is applied,
|
||||
|
@ -376,11 +376,6 @@ namespace Specializations {
|
||||
template<typename... Ts>
|
||||
struct PrimaryClass<Ts>; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
|
||||
|
||||
template<typename T, typename... Ts>
|
||||
void PrimaryFunction();
|
||||
template<typename T, typename... Ts>
|
||||
void PrimaryFunction<Ts>(); // expected-error{{function template partial specialization is not allowed}}
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
template<typename T, typename... Ts>
|
||||
constexpr int PrimaryVar = 0;
|
||||
@ -397,13 +392,6 @@ namespace Specializations {
|
||||
template<typename U>
|
||||
struct InnerClass<U, Ts>; // expected-error{{partial specialization contains unexpanded parameter pack 'Ts'}}
|
||||
|
||||
template<typename... Us>
|
||||
void InnerFunction();
|
||||
template<>
|
||||
void InnerFunction<Ts>(); // expected-error{{explicit specialization contains unexpanded parameter pack 'Ts'}}
|
||||
|
||||
friend void PrimaryFunction<Ts>(); // expected-error{{friend declaration contains unexpanded parameter pack 'Ts'}}
|
||||
|
||||
#if __cplusplus >= 201402L
|
||||
template<typename... Us>
|
||||
constexpr static int InnerVar = 0;
|
||||
|
Loading…
x
Reference in New Issue
Block a user