[llvm-branch-commits] [clang] 687396b - Revert "[Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (#76677)"
via llvm-branch-commits
llvm-branch-commits at lists.llvm.org
Wed Jan 3 15:15:44 PST 2024
Author: Erich Keane
Date: 2024-01-03T15:15:38-08:00
New Revision: 687396b5f4ba0713d103ebd172b308e92eb930cc
URL: https://github.com/llvm/llvm-project/commit/687396b5f4ba0713d103ebd172b308e92eb930cc
DIFF: https://github.com/llvm/llvm-project/commit/687396b5f4ba0713d103ebd172b308e92eb930cc.diff
LOG: Revert "[Clang][Sema] Diagnose unexpanded packs in the template argument lists of function template specializations (#76677)"
This reverts commit 7fbc1de9896029636dd572a692ee90ba88285943.
Added:
Modified:
clang/docs/ReleaseNotes.rst
clang/lib/Sema/SemaDecl.cpp
clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
Removed:
################################################################################
diff --git a/clang/docs/ReleaseNotes.rst b/clang/docs/ReleaseNotes.rst
index 778ce0e0e52d06..a3107c4a695321 100644
--- a/clang/docs/ReleaseNotes.rst
+++ b/clang/docs/ReleaseNotes.rst
@@ -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
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp
index 8e46c4984d93dc..2de631941325fa 100644
--- a/clang/lib/Sema/SemaDecl.cpp
+++ b/clang/lib/Sema/SemaDecl.cpp
@@ -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
diff erent constexpr-ness compared to their
// templates and, after maybeAddCUDAHostDeviceAttrs() is applied,
diff --git a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
index 3c500c2c4dc4a7..30ce6b40e1fb5f 100644
--- a/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
+++ b/clang/test/CXX/temp/temp.decls/temp.variadic/p5.cpp
@@ -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;
More information about the llvm-branch-commits
mailing list