diff options
-rw-r--r-- | include/clang/Basic/DiagnosticSemaKinds.td | 7 | ||||
-rw-r--r-- | lib/Sema/SemaDecl.cpp | 3 | ||||
-rw-r--r-- | lib/Sema/SemaDeclCXX.cpp | 30 | ||||
-rw-r--r-- | test/CXX/class.derived/class.virtual/p3-0x.cpp | 10 |
4 files changed, 43 insertions, 7 deletions
diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index b61fcc1ab3..3912794737 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -874,16 +874,15 @@ def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">; def override_keyword_only_allowed_on_virtual_member_functions : Error< "only virtual member functions can be marked '%0'">; +def err_function_marked_override_not_overriding : Error< + "%0 marked 'override' but does not override any member functions">; + // C++0x [[final]] def err_final_function_overridden : Error< "declaration of %0 overrides a 'final' function">; def err_final_base : Error< "derivation from 'final' %0">; -// C++0x [[override]] -def err_override_function_not_overriding : Error< - "%0 marked 'override' but does not override any member functions">; - def err_function_overriding_without_override : Error< "%0 overrides function%s1 without being marked 'override'">; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index d28548dc2f..2905076ff3 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3388,7 +3388,8 @@ CheckClassMemberNameAttributes(Sema& SemaRef, const FunctionDecl *FD) { /// If a virtual member function f is marked override and does not override /// a member function of a base class the program is ill-formed. if (HasOverrideAttr && !HasOverriddenMethods) { - SemaRef.Diag(MD->getLocation(), diag::err_override_function_not_overriding) + SemaRef.Diag(MD->getLocation(), + diag::err_function_marked_override_not_overriding) << MD->getDeclName(); return; } 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) diff --git a/test/CXX/class.derived/class.virtual/p3-0x.cpp b/test/CXX/class.derived/class.virtual/p3-0x.cpp new file mode 100644 index 0000000000..83f1eb0439 --- /dev/null +++ b/test/CXX/class.derived/class.virtual/p3-0x.cpp @@ -0,0 +1,10 @@ +// RUN: %clang_cc1 -fsyntax-only -std=c++0x -verify %s + +struct B { + virtual void f(int); +}; + +struct D : B { + virtual void f(long) override; // expected-error {{'f' marked 'override' but does not override any member functions}} + void f(int) override; +}; |