Fix inlining to not lose the "cleanup" clause from landingpads
authorMark Seaborn <mseaborn@chromium.org>
Sun, 8 Dec 2013 00:51:21 +0000 (00:51 +0000)
committerMark Seaborn <mseaborn@chromium.org>
Sun, 8 Dec 2013 00:51:21 +0000 (00:51 +0000)
This fixes PR17872.  This bug can lead to C++ destructors not being
called when they should be, when an exception is thrown.

git-svn-id: https://llvm.org/svn/llvm-project/llvm/trunk@196711 91177308-0d34-0410-b5e6-96231b3b80d8

lib/Transforms/Utils/InlineFunction.cpp
test/Transforms/Inline/invoke-cleanup.ll [new file with mode: 0644]

index 405f77e793fdbccbd78269d5bd4e6930e53806d8..e35a1d0b006dcd640b1763547f14483b78cc710c 100644 (file)
@@ -238,6 +238,8 @@ static void HandleInlinedInvoke(InvokeInst *II, BasicBlock *FirstNewBlock,
     InlinedLPad->reserveClauses(OuterNum);
     for (unsigned OuterIdx = 0; OuterIdx != OuterNum; ++OuterIdx)
       InlinedLPad->addClause(OuterLPad->getClause(OuterIdx));
+    if (OuterLPad->isCleanup())
+      InlinedLPad->setCleanup(true);
   }
 
   for (Function::iterator BB = FirstNewBlock, E = Caller->end(); BB != E; ++BB){
diff --git a/test/Transforms/Inline/invoke-cleanup.ll b/test/Transforms/Inline/invoke-cleanup.ll
new file mode 100644 (file)
index 0000000..457ae2a
--- /dev/null
@@ -0,0 +1,39 @@
+; RUN: opt %s -inline -S | FileCheck %s
+
+declare void @external_func()
+
+@exception_type1 = external global i8
+@exception_type2 = external global i8
+
+
+define internal void @inner() {
+  invoke void @external_func()
+      to label %cont unwind label %lpad
+cont:
+  ret void
+lpad:
+  %lp = landingpad i32 personality i8* null
+      catch i8* @exception_type1
+  resume i32 %lp
+}
+
+; Test that the "cleanup" clause is kept when inlining @inner() into
+; this call site (PR17872), otherwise C++ destructors will not be
+; called when they should be.
+
+define void @outer() {
+  invoke void @inner()
+      to label %cont unwind label %lpad
+cont:
+  ret void
+lpad:
+  %lp = landingpad i32 personality i8* null
+      cleanup
+      catch i8* @exception_type2
+  resume i32 %lp
+}
+; CHECK: define void @outer
+; CHECK: landingpad
+; CHECK-NEXT: cleanup
+; CHECK-NEXT: catch i8* @exception_type1
+; CHECK-NEXT: catch i8* @exception_type2