Diagnose when a virtual member function marked final is overridden.
llvm-svn: 123916
This commit is contained in:
parent
11b293b304
commit
3f610c75de
|
@ -2717,16 +2717,18 @@ public:
|
|||
bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
|
||||
const CXXMethodDecl *Old);
|
||||
|
||||
/// CheckOverridingFunctionAttributes - Checks whether attributes are
|
||||
/// incompatible or prevent overriding.
|
||||
bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
|
||||
const CXXMethodDecl *Old);
|
||||
|
||||
bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
|
||||
|
||||
/// CheckOverrideControl - Check C++0x override control semantics.
|
||||
void CheckOverrideControl(const Decl *D);
|
||||
|
||||
/// CheckForFunctionMarkedFinal - Checks whether a virtual member function
|
||||
/// overrides a virtual member function marked 'final', according to
|
||||
/// C++0x [class.virtual]p3.
|
||||
bool CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
|
||||
const CXXMethodDecl *Old);
|
||||
|
||||
|
||||
//===--------------------------------------------------------------------===//
|
||||
// C++ Access Control
|
||||
//
|
||||
|
|
|
@ -3347,7 +3347,7 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
|
|||
if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
|
||||
if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
|
||||
!CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
|
||||
!CheckOverridingFunctionAttributes(MD, OldMD)) {
|
||||
!CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
|
||||
MD->addOverriddenMethod(OldMD->getCanonicalDecl());
|
||||
AddedAny = true;
|
||||
}
|
||||
|
|
|
@ -875,6 +875,22 @@ void Sema::CheckOverrideControl(const Decl *D) {
|
|||
}
|
||||
}
|
||||
|
||||
/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member
|
||||
/// function overrides a virtual member function marked 'final', according to
|
||||
/// C++0x [class.virtual]p3.
|
||||
bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
|
||||
const CXXMethodDecl *Old) {
|
||||
// FIXME: Get rid of FinalAttr here.
|
||||
if (Old->hasAttr<FinalAttr>() || Old->isMarkedFinal()) {
|
||||
Diag(New->getLocation(), diag::err_final_function_overridden)
|
||||
<< New->getDeclName();
|
||||
Diag(Old->getLocation(), diag::note_overridden_virtual_function);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// ActOnCXXMemberDeclarator - This is invoked when a C++ class member
|
||||
/// declarator is parsed. 'AS' is the access specifier, 'BW' specifies the
|
||||
/// bitfield width if there is one and 'InitExpr' specifies the initializer if
|
||||
|
@ -6918,19 +6934,6 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
|
|||
return false;
|
||||
}
|
||||
|
||||
bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
|
||||
const CXXMethodDecl *Old)
|
||||
{
|
||||
if (Old->hasAttr<FinalAttr>()) {
|
||||
Diag(New->getLocation(), diag::err_final_function_overridden)
|
||||
<< New->getDeclName();
|
||||
Diag(Old->getLocation(), diag::note_overridden_virtual_function);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/// \brief Mark the given method pure.
|
||||
///
|
||||
/// \param Method the method to be marked pure.
|
||||
|
|
|
@ -40,3 +40,14 @@ template struct B<int, char, int>;
|
|||
template struct B<int>; // expected-note {{in instantiation of template class 'Test3::B<int>' requested here}}
|
||||
|
||||
}
|
||||
|
||||
namespace Test4 {
|
||||
struct B {
|
||||
virtual void f() const final; // expected-note {{overridden virtual function is here}}
|
||||
};
|
||||
|
||||
struct D : B {
|
||||
void f() const; // expected-error {{declaration of 'f' overrides a 'final' function}}
|
||||
};
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue