]> granicus.if.org Git - clang/commitdiff
Diagnose virtual member functions marked override but not overriding any virtual...
authorAnders Carlsson <andersca@mac.com>
Thu, 20 Jan 2011 05:57:14 +0000 (05:57 +0000)
committerAnders Carlsson <andersca@mac.com>
Thu, 20 Jan 2011 05:57:14 +0000 (05:57 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123888 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Basic/DiagnosticSemaKinds.td
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
test/CXX/class.derived/class.virtual/p3-0x.cpp [new file with mode: 0644]

index b61fcc1ab3531d49ab3ac6907f40814e0d65cbd0..39127947372f6b2e0da05fadb94a0bbe5d7b4bb7 100644 (file)
@@ -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'">;
 
index d28548dc2f5366c69204a4520576ef8710adf2a0..2905076ff3ec291c6c17347c90c10c2406f7f02a 100644 (file)
@@ -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;
   }
index c58fbce5de8f5edffe9135584876895f66a8a1f4..8fe4852890d7bd0219697a9bce97a151074e2cb9 100644 (file)
@@ -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 (file)
index 0000000..83f1eb0
--- /dev/null
@@ -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;
+};