logan-5 created this revision.
logan-5 added a reviewer: rsmith.
logan-5 added a project: clang.
Herald added subscribers: cfe-commits, Prazek.

A class with a destructor marked `final` cannot be derived from, so it should 
afford the same devirtualization opportunities as marking the entire class 
`final`.


Repository:
  rC Clang

https://reviews.llvm.org/D66621

Files:
  clang/lib/AST/DeclCXX.cpp
  clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp


Index: clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
===================================================================
--- clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
+++ clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
@@ -24,6 +24,20 @@
   }
 }
 
+namespace Test2a {
+  struct A {
+    virtual ~A() final {}
+    virtual int f();
+  };
+
+  // CHECK-LABEL: define i32 @_ZN6Test2a1fEPNS_1AE
+  int f(A *a) {
+    // CHECK: call i32 @_ZN6Test2a1A1fEv
+    return a->f();
+  }
+}
+
+
 namespace Test3 {
   struct A {
     virtual int f();
Index: clang/lib/AST/DeclCXX.cpp
===================================================================
--- clang/lib/AST/DeclCXX.cpp
+++ clang/lib/AST/DeclCXX.cpp
@@ -2067,9 +2067,11 @@
   if (DevirtualizedMethod->hasAttr<FinalAttr>())
     return DevirtualizedMethod;
 
-  // Similarly, if the class itself is marked 'final' it can't be overridden
-  // and we can therefore devirtualize the member function call.
-  if (BestDynamicDecl->hasAttr<FinalAttr>())
+  // Similarly, if the class itself or its destructor is marked 'final',
+  // the class can't be overridden and we can therefore devirtualize the 
+  // member function call.
+  if (BestDynamicDecl->hasAttr<FinalAttr>() ||
+      BestDynamicDecl->getDestructor()->hasAttr<FinalAttr>())
     return DevirtualizedMethod;
 
   if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {


Index: clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
===================================================================
--- clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
+++ clang/test/CodeGenCXX/devirtualize-virtual-function-calls-final.cpp
@@ -24,6 +24,20 @@
   }
 }
 
+namespace Test2a {
+  struct A {
+    virtual ~A() final {}
+    virtual int f();
+  };
+
+  // CHECK-LABEL: define i32 @_ZN6Test2a1fEPNS_1AE
+  int f(A *a) {
+    // CHECK: call i32 @_ZN6Test2a1A1fEv
+    return a->f();
+  }
+}
+
+
 namespace Test3 {
   struct A {
     virtual int f();
Index: clang/lib/AST/DeclCXX.cpp
===================================================================
--- clang/lib/AST/DeclCXX.cpp
+++ clang/lib/AST/DeclCXX.cpp
@@ -2067,9 +2067,11 @@
   if (DevirtualizedMethod->hasAttr<FinalAttr>())
     return DevirtualizedMethod;
 
-  // Similarly, if the class itself is marked 'final' it can't be overridden
-  // and we can therefore devirtualize the member function call.
-  if (BestDynamicDecl->hasAttr<FinalAttr>())
+  // Similarly, if the class itself or its destructor is marked 'final',
+  // the class can't be overridden and we can therefore devirtualize the 
+  // member function call.
+  if (BestDynamicDecl->hasAttr<FinalAttr>() ||
+      BestDynamicDecl->getDestructor()->hasAttr<FinalAttr>())
     return DevirtualizedMethod;
 
   if (const auto *DRE = dyn_cast<DeclRefExpr>(Base)) {
_______________________________________________
cfe-commits mailing list
cfe-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits

Reply via email to