From 693d467ed44ecb754762aff129accce30c306422 Mon Sep 17 00:00:00 2001 From: Anders Carlsson Date: Mon, 18 Oct 2010 16:24:27 +0000 Subject: [PATCH] Implement the first half of [dcl.attr.override]p6. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116709 91177308-0d34-0410-b5e6-96231b3b80d8 --- include/clang/Basic/DiagnosticSemaKinds.td | 3 ++ lib/Sema/SemaDecl.cpp | 23 ++++++++++ .../dcl.dcl/dcl.attr/dcl.attr.override/p6.cpp | 45 +++++++++++++++++++ 3 files changed, 71 insertions(+) create mode 100644 test/CXX/dcl.dcl/dcl.attr/dcl.attr.override/p6.cpp diff --git a/include/clang/Basic/DiagnosticSemaKinds.td b/include/clang/Basic/DiagnosticSemaKinds.td index 4d394a8c6d..9008b346c9 100644 --- a/include/clang/Basic/DiagnosticSemaKinds.td +++ b/include/clang/Basic/DiagnosticSemaKinds.td @@ -834,6 +834,9 @@ def err_final_base : Error< 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'">; + // C++0x scoped enumerations def err_enum_invalid_underlying : Error< "non-integral type %0 is an invalid underlying type">; diff --git a/lib/Sema/SemaDecl.cpp b/lib/Sema/SemaDecl.cpp index a65c69ddd5..315bc4d804 100644 --- a/lib/Sema/SemaDecl.cpp +++ b/lib/Sema/SemaDecl.cpp @@ -3228,6 +3228,29 @@ CheckClassMemberNameAttributes(Sema& SemaRef, const FunctionDecl *FD) { << MD->getDeclName(); return; } + + if (!MD->getParent()->hasAttr()) + return; + + /// C++ [dcl.attr.override]p6: + /// In a class definition marked base_check, if a virtual member function + /// that is neither implicitly-declared nor a destructor overrides a + /// member function of a base class and it is not marked override, the + /// program is ill-formed. + if (HasOverriddenMethods && !HasOverrideAttr && !MD->isImplicit() && + !isa(MD)) { + llvm::SmallVector + OverriddenMethods(MD->begin_overridden_methods(), + MD->end_overridden_methods()); + + SemaRef.Diag(MD->getLocation(), + diag::err_function_overriding_without_override) + << MD->getDeclName() << (unsigned)OverriddenMethods.size(); + + for (unsigned I = 0; I != OverriddenMethods.size(); ++I) + SemaRef.Diag(OverriddenMethods[I]->getLocation(), + diag::note_overridden_virtual_function); + } } NamedDecl* diff --git a/test/CXX/dcl.dcl/dcl.attr/dcl.attr.override/p6.cpp b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.override/p6.cpp new file mode 100644 index 0000000000..e3e78c2a17 --- /dev/null +++ b/test/CXX/dcl.dcl/dcl.attr/dcl.attr.override/p6.cpp @@ -0,0 +1,45 @@ +// RUN: %clang_cc1 -std=c++0x -fsyntax-only -verify %s + +namespace Override { + +namespace Test1 { + +struct A { + virtual ~A(); +}; + +struct [[base_check]] B : A { + virtual ~B(); +}; + +} + +namespace Test2 { + +struct A { + virtual void f(); // expected-note {{overridden virtual function is here}} +}; + +struct [[base_check]] B : A { + virtual void f(); // expected-error {{'f' overrides function without being marked 'override'}} +}; + +} + +namespace Test3 { + +struct A { + virtual void f(); // expected-note {{overridden virtual function is here}} +}; + +struct B { + virtual void f(); // expected-note {{overridden virtual function is here}} +}; + +struct [[base_check]] C : A, B { + virtual void f(); // expected-error {{'f' overrides functions without being marked 'override'}} +}; + +} + +} -- 2.40.0