From: Anders Carlsson Date: Thu, 20 Jan 2011 16:25:36 +0000 (+0000) Subject: Diagnose when a virtual member function marked final is overridden. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=2e1c730167d2b978c66558c029d163ffe64b9656;p=clang Diagnose when a virtual member function marked final is overridden. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123916 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Sema/Sema.h b/include/clang/Sema/Sema.h index 0db20c97d8..0cb65ea0df 100644 --- a/include/clang/Sema/Sema.h +++ b/include/clang/Sema/Sema.h @@ -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 // diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index 2905076ff3..a3c3242a4e 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3347,7 +3347,7 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) { if (CXXMethodDecl *OldMD = dyn_cast(*I)) { if (!CheckOverridingFunctionReturnType(MD, OldMD) && !CheckOverridingFunctionExceptionSpec(MD, OldMD) && - !CheckOverridingFunctionAttributes(MD, OldMD)) { + !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) { MD->addOverriddenMethod(OldMD->getCanonicalDecl()); AddedAny = true; } diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index b9d760b412..2f7640cd61 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -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() || 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()) { - 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. diff --git a/test/CXX/class.derived/class.virtual/p3-0x.cpp b/test/CXX/class.derived/class.virtual/p3-0x.cpp index d49d06cbdd..4bd9efda1f 100644 --- a/test/CXX/class.derived/class.virtual/p3-0x.cpp +++ b/test/CXX/class.derived/class.virtual/p3-0x.cpp @@ -40,3 +40,14 @@ template struct B; template struct B; // expected-note {{in instantiation of template class 'Test3::B' 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}} +}; + +}