diff options
-rw-r--r-- | clang/include/clang/Sema/Sema.h | 12 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDecl.cpp | 2 | ||||
-rw-r--r-- | clang/lib/Sema/SemaDeclCXX.cpp | 29 | ||||
-rw-r--r-- | clang/test/CXX/class.derived/class.virtual/p3-0x.cpp | 11 |
4 files changed, 35 insertions, 19 deletions
diff --git a/clang/include/clang/Sema/Sema.h b/clang/include/clang/Sema/Sema.h index 0db20c97d83..0cb65ea0df1 100644 --- a/clang/include/clang/Sema/Sema.h +++ b/clang/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/clang/lib/Sema/SemaDecl.cpp b/clang/lib/Sema/SemaDecl.cpp index 2905076ff3e..a3c3242a4e4 100644 --- a/clang/lib/Sema/SemaDecl.cpp +++ b/clang/lib/Sema/SemaDecl.cpp @@ -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; } diff --git a/clang/lib/Sema/SemaDeclCXX.cpp b/clang/lib/Sema/SemaDeclCXX.cpp index b9d760b4124..2f7640cd612 100644 --- a/clang/lib/Sema/SemaDeclCXX.cpp +++ b/clang/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<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. diff --git a/clang/test/CXX/class.derived/class.virtual/p3-0x.cpp b/clang/test/CXX/class.derived/class.virtual/p3-0x.cpp index d49d06cbddb..4bd9efda1f6 100644 --- a/clang/test/CXX/class.derived/class.virtual/p3-0x.cpp +++ b/clang/test/CXX/class.derived/class.virtual/p3-0x.cpp @@ -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}} +}; + +} |