From: Anders Carlsson Date: Thu, 20 Jan 2011 04:34:22 +0000 (+0000) Subject: Only allow virtual member functions to be marked 'override' and 'final'. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=aae5af24f031ad5f17872bd8b27ed5c175c0f90c;p=clang Only allow virtual member functions to be marked 'override' and 'final'. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123882 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 9e7d0a5761..b61fcc1ab3 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -870,6 +870,10 @@ def err_trailing_return_without_auto : Error< // C++0x attributes def err_repeat_attribute : Error<"'%0' attribute cannot be repeated">; +// C++0x override control +def override_keyword_only_allowed_on_virtual_member_functions : Error< + "only virtual member functions can be marked '%0'">; + // C++0x [[final]] def err_final_function_overridden : Error< "declaration of %0 overrides a 'final' function">; diff --git a/include/clang/Sema/DeclSpec.h b/include/clang/Sema/DeclSpec.h index 9c1f98fa1a..0f8624f0a3 100644 --- a/include/clang/Sema/DeclSpec.h +++ b/include/clang/Sema/DeclSpec.h @@ -1483,6 +1483,15 @@ public: bool SetVirtSpecifier(VirtSpecifier VS, SourceLocation Loc, const char *&PrevSpec); + bool isOverrideSpecified() const { return Specifiers & VS_Override; } + SourceLocation getOverrideLoc() const { return VS_overrideLoc; } + + bool isFinalSpecified() const { return Specifiers & VS_Final; } + SourceLocation getFinalLoc() const { return VS_finalLoc; } + + bool isNewSpecified() const { return Specifiers & VS_New; } + SourceLocation getNewLoc() const { return VS_newLoc; } + private: unsigned Specifiers; diff --git a/lib/Sema/SemaDeclCXX.cpp b/lib/Sema/SemaDeclCXX.cpp index c1523cffc1..c58fbce5de 100644 --- a/lib/Sema/SemaDeclCXX.cpp +++ b/lib/Sema/SemaDeclCXX.cpp @@ -989,6 +989,22 @@ Sema::ActOnCXXMemberDeclarator(Scope *S, AccessSpecifier AS, Declarator &D, FunTmpl->getTemplatedDecl()->setAccess(AS); } + if (VS.isOverrideSpecified()) { + CXXMethodDecl *MD = dyn_cast(Member); + if (!MD || !MD->isVirtual()) { + Diag(Member->getLocStart(), + diag::override_keyword_only_allowed_on_virtual_member_functions) + << "override" << FixItHint::CreateRemoval(VS.getOverrideLoc()); + } + } + if (VS.isFinalSpecified()) { + CXXMethodDecl *MD = dyn_cast(Member); + if (!MD || !MD->isVirtual()) { + Diag(Member->getLocStart(), + diag::override_keyword_only_allowed_on_virtual_member_functions) + << "final" << FixItHint::CreateRemoval(VS.getFinalLoc()); + } + } assert((Name || isInstField) && "No identifier for non-field ?"); if (Init) diff --git a/test/CXX/class/class.mem/p8-0x.cpp b/test/CXX/class/class.mem/p8-0x.cpp index 157a4c54b9..123cf90d19 100644 --- a/test/CXX/class/class.mem/p8-0x.cpp +++ b/test/CXX/class/class.mem/p8-0x.cpp @@ -4,3 +4,15 @@ struct A { virtual void g() override override; // expected-error {{member function already marked 'override'}} virtual void h() final final; // expected-error {{member function already marked 'final'}} }; + +struct B { + virtual void f() override; + void g() override; // expected-error {{only virtual member functions can be marked 'override'}} + int h override; // expected-error {{only virtual member functions can be marked 'override'}} +}; + +struct C { + virtual void f() final; + void g() final; // expected-error {{only virtual member functions can be marked 'final'}} + int h final; // expected-error {{only virtual member functions can be marked 'final'}} +};