[clang] [clang] remove ClassScopeFunctionSpecializationDecl (PR #66636)
Krystian Stasiowski via cfe-commits
cfe-commits at lists.llvm.org
Mon Sep 18 08:58:04 PDT 2023
================
@@ -10442,32 +10441,54 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC,
if (getLangOpts().CUDA && !isFunctionTemplateSpecialization)
maybeAddCUDAHostDeviceAttrs(NewFD, Previous);
- // If it's a friend (and only if it's a friend), it's possible
- // that either the specialized function type or the specialized
- // template is dependent, and therefore matching will fail. In
- // this case, don't check the specialization yet.
- if (isFunctionTemplateSpecialization && isFriend &&
- (NewFD->getType()->isDependentType() || DC->isDependentContext() ||
- TemplateSpecializationType::anyInstantiationDependentTemplateArguments(
- TemplateArgs.arguments()))) {
- assert(HasExplicitTemplateArgs &&
- "friend function specialization without template args");
- if (CheckDependentFunctionTemplateSpecialization(NewFD, TemplateArgs,
- Previous))
- NewFD->setInvalidDecl();
- } else if (isFunctionTemplateSpecialization) {
- if (CurContext->isDependentContext() && CurContext->isRecord()
- && !isFriend) {
- isDependentClassScopeExplicitSpecialization = true;
- } else if (!NewFD->isInvalidDecl() &&
- CheckFunctionTemplateSpecialization(
- NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr),
- Previous))
- NewFD->setInvalidDecl();
+ // Handle explict specializations of function templates
+ // and friend function declarations with an explicit
+ // template argument list.
+ if (isFunctionTemplateSpecialization) {
+ bool isDependentSpecialization = false;
+ if (isFriend) {
+ // For friend function specializations, this is a dependent
+ // specialization if its semantic context is dependent, its
+ // type is dependent, or if its template-id is dependent.
+ isDependentSpecialization =
+ DC->isDependentContext() || NewFD->getType()->isDependentType() ||
+ (HasExplicitTemplateArgs &&
+ TemplateSpecializationType::
+ anyInstantiationDependentTemplateArguments(
+ TemplateArgs.arguments()));
+ assert(!isDependentSpecialization ||
+ (HasExplicitTemplateArgs == isDependentSpecialization) &&
+ "dependent friend function specialization without template "
+ "args");
+ } else {
+ // For class-scope explicit specializations of function templates,
+ // if the lexical context is dependent, then the specialization
+ // is dependent.
+ isDependentSpecialization =
+ CurContext->isRecord() && CurContext->isDependentContext();
+ }
+
+ TemplateArgumentListInfo *ExplicitTemplateArgs =
+ HasExplicitTemplateArgs ? &TemplateArgs : nullptr;
+ if (isDependentSpecialization) {
+ // If it's a dependent specialization, it may not be possible
+ // to determine the primary template (for explicit specializations)
+ // or befriended declaration (for friends) until the enclosing
+ // template is instantiated. In such cases, we store the declarations
+ // found by name lookup and defer resolution until instantiation.
+ if (CheckDependentFunctionTemplateSpecialization(
+ NewFD, ExplicitTemplateArgs, Previous))
+ NewFD->setInvalidDecl();
+ } else if (!NewFD->isInvalidDecl()) {
+ if (CheckFunctionTemplateSpecialization(NewFD, ExplicitTemplateArgs,
+ Previous))
+ NewFD->setInvalidDecl();
+ }
// C++ [dcl.stc]p1:
// A storage-class-specifier shall not be specified in an explicit
// specialization (14.7.3)
+ // FIXME: We should be checking this for dependent specializations.
----------------
sdkrystian wrote:
I opted to not fix it in this commit to minimize unrelated changes. We _should_ be doing this check if `!isFriend` (since we already diagnose storage class specifiers on friend declarations elsewhere). Furthermore, the check for inconsistent storage class should happen in `CheckFunctionTemplateSpecialization` (so we check during the instantiation of dependent specializations, once the primary template is known).
https://github.com/llvm/llvm-project/pull/66636
More information about the cfe-commits
mailing list