]> granicus.if.org Git - clang/commitdiff
Implement the first half of [dcl.attr.override]p6.
authorAnders Carlsson <andersca@mac.com>
Mon, 18 Oct 2010 16:24:27 +0000 (16:24 +0000)
committerAnders Carlsson <andersca@mac.com>
Mon, 18 Oct 2010 16:24:27 +0000 (16:24 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@116709 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
test/CXX/dcl.dcl/dcl.attr/dcl.attr.override/p6.cpp [new file with mode: 0644]

index 4d394a8c6d587e8f20fabd0d9500701c1862d725..9008b346c92a094bfe363f1ef256f6b21fc73d74 100644 (file)
@@ -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">;
index a65c69ddd5d29f98348be6a30c82133f685292b0..315bc4d804c709647ed1108004c17e43104a0e2f 100644 (file)
@@ -3228,6 +3228,29 @@ CheckClassMemberNameAttributes(Sema& SemaRef, const FunctionDecl *FD) {
       << MD->getDeclName();
     return;
   }
+
+  if (!MD->getParent()->hasAttr<BaseCheckAttr>())
+    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<CXXDestructorDecl>(MD)) {
+    llvm::SmallVector<const CXXMethodDecl*, 4> 
+      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 (file)
index 0000000..e3e78c2
--- /dev/null
@@ -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'}}
+};
+  
+}
+
+}