]> granicus.if.org Git - clang/commitdiff
Diagnose when a virtual member function marked final is overridden.
authorAnders Carlsson <andersca@mac.com>
Thu, 20 Jan 2011 16:25:36 +0000 (16:25 +0000)
committerAnders Carlsson <andersca@mac.com>
Thu, 20 Jan 2011 16:25:36 +0000 (16:25 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@123916 91177308-0d34-0410-b5e6-96231b3b80d8

include/clang/Sema/Sema.h
lib/Sema/SemaDecl.cpp
lib/Sema/SemaDeclCXX.cpp
test/CXX/class.derived/class.virtual/p3-0x.cpp

index 0db20c97d830df9db63eb3dc5dc64fb5c96a790f..0cb65ea0df1f6347314a05db7c07a16374a6262a 100644 (file)
@@ -2717,16 +2717,18 @@ public:
   bool CheckOverridingFunctionExceptionSpec(const CXXMethodDecl *New,
                                             const CXXMethodDecl *Old);
 
-  /// CheckOverridingFunctionAttributes - Checks whether attributes are
-  /// incompatible or prevent overriding.
-  bool CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
-                                         const CXXMethodDecl *Old);
-
   bool CheckPureMethod(CXXMethodDecl *Method, SourceRange InitRange);
 
   /// CheckOverrideControl - Check C++0x override control semantics.
   void CheckOverrideControl(const Decl *D);
 
+  /// CheckForFunctionMarkedFinal - Checks whether a virtual member function
+  /// overrides a virtual member function marked 'final', according to
+  /// C++0x [class.virtual]p3.
+  bool CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
+                                              const CXXMethodDecl *Old);
+  
+
   //===--------------------------------------------------------------------===//
   // C++ Access Control
   //
index 2905076ff3ec291c6c17347c90c10c2406f7f02a..a3c3242a4e40fdd1124d85f44effa8a312e53085 100644 (file)
@@ -3347,7 +3347,7 @@ bool Sema::AddOverriddenMethods(CXXRecordDecl *DC, CXXMethodDecl *MD) {
       if (CXXMethodDecl *OldMD = dyn_cast<CXXMethodDecl>(*I)) {
         if (!CheckOverridingFunctionReturnType(MD, OldMD) &&
             !CheckOverridingFunctionExceptionSpec(MD, OldMD) &&
-            !CheckOverridingFunctionAttributes(MD, OldMD)) {
+            !CheckIfOverriddenFunctionIsMarkedFinal(MD, OldMD)) {
           MD->addOverriddenMethod(OldMD->getCanonicalDecl());
           AddedAny = true;
         }
index b9d760b41244e3e6b30928beeee86200488a892f..2f7640cd612068ee5c3bd232c55a133af80f4c55 100644 (file)
@@ -875,6 +875,22 @@ void Sema::CheckOverrideControl(const Decl *D) {
   }
 }
 
+/// CheckIfOverriddenFunctionIsMarkedFinal - Checks whether a virtual member 
+/// function overrides a virtual member function marked 'final', according to
+/// C++0x [class.virtual]p3.
+bool Sema::CheckIfOverriddenFunctionIsMarkedFinal(const CXXMethodDecl *New,
+                                                  const CXXMethodDecl *Old) {
+  // FIXME: Get rid of FinalAttr here.
+  if (Old->hasAttr<FinalAttr>() || Old->isMarkedFinal()) {
+    Diag(New->getLocation(), diag::err_final_function_overridden)
+      << New->getDeclName();
+    Diag(Old->getLocation(), diag::note_overridden_virtual_function);
+    return true;
+  }
+  
+  return false;
+}
+
 /// 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
@@ -6918,19 +6934,6 @@ bool Sema::CheckOverridingFunctionReturnType(const CXXMethodDecl *New,
   return false;
 }
 
-bool Sema::CheckOverridingFunctionAttributes(const CXXMethodDecl *New,
-                                             const CXXMethodDecl *Old)
-{
-  if (Old->hasAttr<FinalAttr>()) {
-    Diag(New->getLocation(), diag::err_final_function_overridden)
-      << New->getDeclName();
-    Diag(Old->getLocation(), diag::note_overridden_virtual_function);
-    return true;
-  }
-
-  return false;
-}
-
 /// \brief Mark the given method pure.
 ///
 /// \param Method the method to be marked pure.
index d49d06cbddbd783e3570403e46a1e8923f1d38fd..4bd9efda1f6c9b3791b45cbfc931a2328de8619b 100644 (file)
@@ -40,3 +40,14 @@ template struct B<int, char, int>;
 template struct B<int>; // expected-note {{in instantiation of template class 'Test3::B<int>' requested here}}
 
 }
+
+namespace Test4 {
+struct B {
+  virtual void f() const final; // expected-note {{overridden virtual function is here}}
+};
+
+struct D : B {
+  void f() const; // expected-error {{declaration of 'f' overrides a 'final' function}}
+};
+
+}