diff options
author | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-08-06 03:25:17 +0000 |
---|---|---|
committer | Richard Smith <richard-llvm@metafoo.co.uk> | 2012-08-06 03:25:17 +0000 |
commit | a4b39658673954fb9f75673594b50028685fc665 (patch) | |
tree | 13821d87c6cc9ca70b5f0802f12007038fee80fd /lib/Sema/SemaDeclCXX.cpp | |
parent | eef00293897a73cc47f4d42e2653ff47c59d6030 (diff) |
PR13499: Don't try to check whether 'override' has been validly applied until
we know whether the function is virtual. But check it as soon as we do know;
in some cases we don't need to wait for an instantiation.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@161316 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 74 |
1 files changed, 39 insertions, 35 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index 9933bd10e1..71c72da93d 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -1405,32 +1405,50 @@ bool Sema::ActOnAccessSpecifier(AccessSpecifier Access, return ProcessAccessDeclAttributeList(ASDecl, Attrs); } -/// CheckOverrideControl - Check C++0x override control semantics. -void Sema::CheckOverrideControl(const Decl *D) { +/// CheckOverrideControl - Check C++11 override control semantics. +void Sema::CheckOverrideControl(Decl *D) { const CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(D); - if (!MD || !MD->isVirtual()) + + // Do we know which functions this declaration might be overriding? + bool OverridesAreKnown = !MD || + (!MD->getParent()->hasAnyDependentBases() && + !MD->getType()->isDependentType()); + + if (!MD || !MD->isVirtual()) { + if (OverridesAreKnown) { + if (OverrideAttr *OA = D->getAttr<OverrideAttr>()) { + Diag(OA->getLocation(), + diag::override_keyword_only_allowed_on_virtual_member_functions) + << "override" << FixItHint::CreateRemoval(OA->getLocation()); + D->dropAttr<OverrideAttr>(); + } + if (FinalAttr *FA = D->getAttr<FinalAttr>()) { + Diag(FA->getLocation(), + diag::override_keyword_only_allowed_on_virtual_member_functions) + << "final" << FixItHint::CreateRemoval(FA->getLocation()); + D->dropAttr<FinalAttr>(); + } + } return; + } - if (MD->isDependentContext()) + if (!OverridesAreKnown) return; - // C++0x [class.virtual]p3: - // If a virtual function is marked with the virt-specifier override and does - // not override a member function of a base class, - // the program is ill-formed. - bool HasOverriddenMethods = + // C++11 [class.virtual]p5: + // If a virtual function is marked with the virt-specifier override and + // does not override a member function of a base class, the program is + // ill-formed. + bool HasOverriddenMethods = MD->begin_overridden_methods() != MD->end_overridden_methods(); - if (MD->hasAttr<OverrideAttr>() && !HasOverriddenMethods) { - Diag(MD->getLocation(), - diag::err_function_marked_override_not_overriding) + if (MD->hasAttr<OverrideAttr>() && !HasOverriddenMethods) + Diag(MD->getLocation(), diag::err_function_marked_override_not_overriding) << MD->getDeclName(); - return; - } } -/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member +/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member /// function overrides a virtual member function marked 'final', according to -/// C++0x [class.virtual]p3. +/// C++11 [class.virtual]p4. bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New, const CXXMethodDecl *Old) { if (!Old->hasAttr<FinalAttr>()) @@ -1609,31 +1627,17 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, FunTmpl->getTemplatedDecl()->setAccess(AS); } - if (VS.isOverrideSpecified()) { - CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member); - if (!MD || !MD->isVirtual()) { - Diag(Member->getLocStart(), - diag::override_keyword_only_allowed_on_virtual_member_functions) - << "override" << FixItHint::CreateRemoval(VS.getOverrideLoc()); - } else - MD->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context)); - } - if (VS.isFinalSpecified()) { - CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member); - if (!MD || !MD->isVirtual()) { - Diag(Member->getLocStart(), - diag::override_keyword_only_allowed_on_virtual_member_functions) - << "final" << FixItHint::CreateRemoval(VS.getFinalLoc()); - } else - MD->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context)); - } + if (VS.isOverrideSpecified()) + Member->addAttr(new (Context) OverrideAttr(VS.getOverrideLoc(), Context)); + if (VS.isFinalSpecified()) + Member->addAttr(new (Context) FinalAttr(VS.getFinalLoc(), Context)); if (VS.getLastLocation().isValid()) { // Update the end location of a method that has a virt-specifiers. if (CXXMethodDecl *MD = dyn_cast_or_null<CXXMethodDecl>(Member)) MD->setRangeEnd(VS.getLastLocation()); } - + CheckOverrideControl(Member); assert((Name || isInstField) && "No identifier for non-field ?"); |