summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--clang/include/clang/Sema/Sema.h12
-rw-r--r--clang/lib/Sema/SemaDecl.cpp2
-rw-r--r--clang/lib/Sema/SemaDeclCXX.cpp29
-rw-r--r--clang/test/CXX/class.derived/class.virtual/p3-0x.cpp11
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}}
+};
+
+}
OpenPOWER on IntegriCloud