From: Anders Carlsson Date: Thu, 20 Jan 2011 05:57:14 +0000 (+0000) Subject: Diagnose virtual member functions marked override but not overriding any virtual... X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=9e682d9f567a51f26c3b0673837e23bafdb09c11;p=clang 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 --- 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(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(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; +};