aboutsummaryrefslogtreecommitdiff
path: root/lib/Sema/SemaDeclCXX.cpp
diff options
context:
space:
mode:
authorAnders Carlsson <andersca@mac.com>2011-01-20 05:57:14 +0000
committerAnders Carlsson <andersca@mac.com>2011-01-20 05:57:14 +0000
commit9e682d9f567a51f26c3b0673837e23bafdb09c11 (patch)
tree00307ce64f4d2641e7cfd8cd18a9f3a2cad98d52 /lib/Sema/SemaDeclCXX.cpp
parentc7119a871df4d2d79db3e48fc9d0ab421be54a3d (diff)
Diagnose virtual member functions marked override but not overriding any virtual member functions.
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123888 91177308-0d34-0410-b5e6-96231b3b80d8
Diffstat (limited to 'lib/Sema/SemaDeclCXX.cpp')
-rw-r--r--lib/Sema/SemaDeclCXX.cpp30
1 files changed, 28 insertions, 2 deletions
diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp
index c58fbce5de..8fe4852890 100644
--- a/lib/Sema/SemaDeclCXX.cpp
+++ b/lib/Sema/SemaDeclCXX.cpp
@@ -852,6 +852,27 @@ Decl *Sema::ActOnAccessSpecifier(AccessSpecifier Access,
return ASDecl;
}
+/// CheckOverrideControl - Check C++0x override control semantics.
+static void
+CheckOverrideControl(Sema& SemaRef, const Decl *D) {
+ const CXXMethodDecl *MD = llvm::dyn_cast<CXXMethodDecl>(D);
+ if (!MD || !MD->isVirtual())
+ 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 =
+ MD->begin_overridden_methods() != MD->end_overridden_methods();
+ if (MD->isMarkedOverride() && !HasOverriddenMethods) {
+ SemaRef.Diag(MD->getLocation(),
+ diag::err_function_marked_override_not_overriding)
+ << MD->getDeclName();
+ return;
+ }
+}
+
/// 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
@@ -995,7 +1016,8 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Diag(Member->getLocStart(),
diag::override_keyword_only_allowed_on_virtual_member_functions)
<< "override" << FixItHint::CreateRemoval(VS.getOverrideLoc());
- }
+ } else
+ MD->setIsMarkedOverride(true);
}
if (VS.isFinalSpecified()) {
CXXMethodDecl *MD = dyn_cast<CXXMethodDecl>(Member);
@@ -1003,8 +1025,12 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D,
Diag(Member->getLocStart(),
diag::override_keyword_only_allowed_on_virtual_member_functions)
<< "final" << FixItHint::CreateRemoval(VS.getFinalLoc());
- }
+ } else
+ MD->setIsMarkedFinal(true);
}
+
+ CheckOverrideControl(*this, Member);
+
assert((Name || isInstField) && "No identifier for non-field ?");
if (Init)