From 34005c92bb2feacee642f54f7a8fa1e6df49403c Mon Sep 17 00:00:00 2001 From: Mark Seaborn Date: Sun, 8 Dec 2013 00:51:21 +0000 Subject: [PATCH] Fix inlining to not lose the "cleanup" clause from landingpads 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 | 2 ++ test/Transforms/Inline/invoke-cleanup.ll | 39 ++++++++++++++++++++++++ 2 files changed, 41 insertions(+) create mode 100644 test/Transforms/Inline/invoke-cleanup.ll diff --git a/lib/Transforms/Utils/InlineFunction.cpp b/lib/Transforms/Utils/InlineFunction.cpp index 405f77e793f..e35a1d0b006 100644 --- a/lib/Transforms/Utils/InlineFunction.cpp +++ b/lib/Transforms/Utils/InlineFunction.cpp @@ -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 index 00000000000..457ae2addeb --- /dev/null +++ b/test/Transforms/Inline/invoke-cleanup.ll @@ -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