diff options
Diffstat (limited to 'clang/lib/Sema/SemaDecl.cpp')
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 44 |
1 files changed, 21 insertions, 23 deletions
diff --git a/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index db598b05b3f..612761177cd 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -5231,10 +5231,13 @@ bool Sema::DiagnoseClassNameShadow(DeclContext *DC, /// /// \param Loc The location of the name of the entity being declared. /// +/// \param IsTemplateId Whether the name is a (simple-)template-id, and thus +/// we're declaring an explicit / partial specialization / instantiation. +/// /// \returns true if we cannot safely recover from this error, false otherwise. bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, DeclarationName Name, - SourceLocation Loc) { + SourceLocation Loc, bool IsTemplateId) { DeclContext *Cur = CurContext; while (isa<LinkageSpecDecl>(Cur) || isa<CapturedDecl>(Cur)) Cur = Cur->getParent(); @@ -5261,8 +5264,9 @@ bool Sema::diagnoseQualifiedDeclaration(CXXScopeSpec &SS, DeclContext *DC, } // Check whether the qualifying scope encloses the scope of the original - // declaration. - if (!Cur->Encloses(DC)) { + // declaration. For a template-id, we perform the checks in + // CheckTemplateSpecializationScope. + if (!Cur->Encloses(DC) && !IsTemplateId) { if (Cur->isRecord()) Diag(Loc, diag::err_member_qualification) << Name << SS.getRange(); @@ -5374,8 +5378,9 @@ NamedDecl *Sema::HandleDeclarator(Scope *S, Declarator &D, return nullptr; } if (!D.getDeclSpec().isFriendSpecified()) { - if (diagnoseQualifiedDeclaration(D.getCXXScopeSpec(), DC, - Name, D.getIdentifierLoc())) { + if (diagnoseQualifiedDeclaration( + D.getCXXScopeSpec(), DC, Name, D.getIdentifierLoc(), + D.getName().getKind() == UnqualifiedIdKind::IK_TemplateId)) { if (DC->isRecord()) return nullptr; @@ -8828,10 +8833,6 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, if (CurContext->isDependentContext() && CurContext->isRecord() && !isFriend) { isDependentClassScopeExplicitSpecialization = true; - Diag(NewFD->getLocation(), getLangOpts().MicrosoftExt ? - diag::ext_function_specialization_in_class : - diag::err_function_specialization_in_class) - << NewFD->getDeclName(); } else if (!NewFD->isInvalidDecl() && CheckFunctionTemplateSpecialization( NewFD, (HasExplicitTemplateArgs ? &TemplateArgs : nullptr), @@ -9117,12 +9118,12 @@ Sema::ActOnFunctionDeclarator(Scope *S, Declarator &D, DeclContext *DC, } // Here we have an function template explicit specialization at class scope. - // The actually specialization will be postponed to template instatiation + // The actual specialization will be postponed to template instatiation // time via the ClassScopeFunctionSpecializationDecl node. if (isDependentClassScopeExplicitSpecialization) { ClassScopeFunctionSpecializationDecl *NewSpec = ClassScopeFunctionSpecializationDecl::Create( - Context, CurContext, SourceLocation(), + Context, CurContext, NewFD->getLocation(), cast<CXXMethodDecl>(NewFD), HasExplicitTemplateArgs, TemplateArgs); CurContext->addDecl(NewSpec); @@ -9633,16 +9634,16 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, Previous.clear(); Previous.addDecl(OldDecl); - if (FunctionTemplateDecl *OldTemplateDecl - = dyn_cast<FunctionTemplateDecl>(OldDecl)) { + if (FunctionTemplateDecl *OldTemplateDecl = + dyn_cast<FunctionTemplateDecl>(OldDecl)) { auto *OldFD = OldTemplateDecl->getTemplatedDecl(); NewFD->setPreviousDeclaration(OldFD); adjustDeclContextForDeclaratorDecl(NewFD, OldFD); FunctionTemplateDecl *NewTemplateDecl = NewFD->getDescribedFunctionTemplate(); assert(NewTemplateDecl && "Template/non-template mismatch"); - if (auto *Method = dyn_cast<CXXMethodDecl>(NewFD)) { - Method->setAccess(OldTemplateDecl->getAccess()); + if (NewFD->isCXXClassMember()) { + NewFD->setAccess(OldTemplateDecl->getAccess()); NewTemplateDecl->setAccess(OldTemplateDecl->getAccess()); } @@ -9668,7 +9669,7 @@ bool Sema::CheckFunctionDeclaration(Scope *S, FunctionDecl *NewFD, // This needs to happen first so that 'inline' propagates. NewFD->setPreviousDeclaration(OldFD); adjustDeclContextForDeclaratorDecl(NewFD, OldFD); - if (isa<CXXMethodDecl>(NewFD)) + if (NewFD->isCXXClassMember()) NewFD->setAccess(OldFD->getAccess()); } } @@ -14310,13 +14311,10 @@ CreateNewDecl: if (SS.isNotEmpty()) { if (SS.isSet()) { // If this is either a declaration or a definition, check the - // nested-name-specifier against the current context. We don't do this - // for explicit specializations, because they have similar checking - // (with more specific diagnostics) in the call to - // CheckMemberSpecialization, below. - if (!isMemberSpecialization && - (TUK == TUK_Definition || TUK == TUK_Declaration) && - diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc)) + // nested-name-specifier against the current context. + if ((TUK == TUK_Definition || TUK == TUK_Declaration) && + diagnoseQualifiedDeclaration(SS, DC, OrigName, Loc, + isMemberSpecialization)) Invalid = true; New->setQualifierInfo(SS.getWithLocInContext(Context)); |