r364100 - Devirtualize destructor of final class.

Hiroshi Yamauchi via cfe-commits cfe-commits at lists.llvm.org
Fri Jun 21 13:04:29 PDT 2019


Author: yamauchi
Date: Fri Jun 21 13:04:29 2019
New Revision: 364100

URL: http://llvm.org/viewvc/llvm-project?rev=364100&view=rev
Log:
Devirtualize destructor of final class.

Summary:
Take advantage of the final keyword to devirtualize destructor calls.

Fix https://bugs.llvm.org/show_bug.cgi?id=21368

Reviewers: rsmith

Reviewed By: rsmith

Subscribers: davidxl, Prazek, cfe-commits

Tags: #clang

Differential Revision: https://reviews.llvm.org/D63161

Added:
    cfe/trunk/test/CodeGenCXX/devirtualize-dtor-final.cpp
Modified:
    cfe/trunk/lib/CodeGen/CGExprCXX.cpp

Modified: cfe/trunk/lib/CodeGen/CGExprCXX.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/CodeGen/CGExprCXX.cpp?rev=364100&r1=364099&r2=364100&view=diff
==============================================================================
--- cfe/trunk/lib/CodeGen/CGExprCXX.cpp (original)
+++ cfe/trunk/lib/CodeGen/CGExprCXX.cpp Fri Jun 21 13:04:29 2019
@@ -1865,9 +1865,33 @@ static void EmitObjectDelete(CodeGenFunc
       Dtor = RD->getDestructor();
 
       if (Dtor->isVirtual()) {
-        CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType,
-                                                    Dtor);
-        return;
+        bool UseVirtualCall = true;
+        const Expr *Base = DE->getArgument();
+        if (auto *DevirtualizedDtor =
+                dyn_cast_or_null<const CXXDestructorDecl>(
+                    Dtor->getDevirtualizedMethod(
+                        Base, CGF.CGM.getLangOpts().AppleKext))) {
+          UseVirtualCall = false;
+          const CXXRecordDecl *DevirtualizedClass =
+              DevirtualizedDtor->getParent();
+          if (declaresSameEntity(getCXXRecord(Base), DevirtualizedClass)) {
+            // Devirtualized to the class of the base type (the type of the
+            // whole expression).
+            Dtor = DevirtualizedDtor;
+          } else {
+            // Devirtualized to some other type. Would need to cast the this
+            // pointer to that type but we don't have support for that yet, so
+            // do a virtual call. FIXME: handle the case where it is
+            // devirtualized to the derived type (the type of the inner
+            // expression) as in EmitCXXMemberOrOperatorMemberCallExpr.
+            UseVirtualCall = true;
+          }
+        }
+        if (UseVirtualCall) {
+          CGF.CGM.getCXXABI().emitVirtualObjectDelete(CGF, DE, Ptr, ElementType,
+                                                      Dtor);
+          return;
+        }
       }
     }
   }

Added: cfe/trunk/test/CodeGenCXX/devirtualize-dtor-final.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/CodeGenCXX/devirtualize-dtor-final.cpp?rev=364100&view=auto
==============================================================================
--- cfe/trunk/test/CodeGenCXX/devirtualize-dtor-final.cpp (added)
+++ cfe/trunk/test/CodeGenCXX/devirtualize-dtor-final.cpp Fri Jun 21 13:04:29 2019
@@ -0,0 +1,23 @@
+// RUN: %clang_cc1 -triple i386-unknown-unknown -std=c++11 %s -emit-llvm -o - | FileCheck %s
+
+namespace Test1 {
+  struct A { virtual ~A() {} };
+  struct B final : A {};
+  struct C : A { virtual ~C() final {} };
+  struct D { virtual ~D() final = 0; };
+  // CHECK-LABEL: define void @_ZN5Test13fooEPNS_1BE
+  void foo(B *b) {
+    // CHECK: call void @_ZN5Test11BD1Ev
+    delete b;
+  }
+  // CHECK-LABEL: define void @_ZN5Test14foo2EPNS_1CE
+  void foo2(C *c) {
+    // CHECK: call void @_ZN5Test11CD1Ev
+    delete c;
+  }
+  // CHECK-LABEL: define void @_ZN5Test14evilEPNS_1DE
+  void evil(D *p) {
+    // CHECK-NOT: call void @_ZN5Test11DD1Ev
+    delete p;
+  }
+}




More information about the cfe-commits mailing list