diff --git a/clang/lib/CodeGen/CGObjCRuntime.cpp b/clang/lib/CodeGen/CGObjCRuntime.cpp --- a/clang/lib/CodeGen/CGObjCRuntime.cpp +++ b/clang/lib/CodeGen/CGObjCRuntime.cpp @@ -22,6 +22,7 @@ #include "clang/AST/StmtObjC.h" #include "clang/CodeGen/CGFunctionInfo.h" #include "clang/CodeGen/CodeGenABITypes.h" +#include "llvm/IR/Instruction.h" #include "llvm/Support/SaveAndRestore.h" using namespace clang; @@ -227,13 +228,18 @@ CatchHandler &Handler = Handlers[I]; CGF.EmitBlock(Handler.Block); - llvm::CatchPadInst *CPI = nullptr; - SaveAndRestore RestoreCurrentFuncletPad(CGF.CurrentFuncletPad); - if (useFunclets) - if ((CPI = dyn_cast_or_null(Handler.Block->getFirstNonPHI()))) { + + CodeGenFunction::LexicalScope Cleanups(CGF, Handler.Body->getSourceRange()); + SaveAndRestore RevertAfterScope(CGF.CurrentFuncletPad); + if (useFunclets) { + llvm::Instruction *CPICandidate = Handler.Block->getFirstNonPHI(); + if (auto *CPI = dyn_cast_or_null(CPICandidate)) { CGF.CurrentFuncletPad = CPI; CPI->setOperand(2, CGF.getExceptionSlot().getPointer()); + CGF.EHStack.pushCleanup(NormalCleanup, CPI); } + } + llvm::Value *RawExn = CGF.getExceptionFromSlot(); // Enter the catch. @@ -241,8 +247,6 @@ if (beginCatchFn) Exn = CGF.EmitNounwindRuntimeCall(beginCatchFn, RawExn, "exn.adjusted"); - CodeGenFunction::LexicalScope cleanups(CGF, Handler.Body->getSourceRange()); - if (endCatchFn) { // Add a cleanup to leave the catch. bool EndCatchMightThrow = (Handler.Variable == nullptr); @@ -260,15 +264,13 @@ CGF.EmitAutoVarDecl(*CatchParam); EmitInitOfCatchParam(CGF, CastExn, CatchParam); } - if (CPI) - CGF.EHStack.pushCleanup(NormalCleanup, CPI); CGF.ObjCEHValueStack.push_back(Exn); CGF.EmitStmt(Handler.Body); CGF.ObjCEHValueStack.pop_back(); // Leave any cleanups associated with the catch. - cleanups.ForceCleanup(); + Cleanups.ForceCleanup(); CGF.EmitBranchThroughCleanup(Cont); } diff --git a/clang/test/CodeGenObjCXX/arc-exceptions-seh.mm b/clang/test/CodeGenObjCXX/arc-exceptions-seh.mm --- a/clang/test/CodeGenObjCXX/arc-exceptions-seh.mm +++ b/clang/test/CodeGenObjCXX/arc-exceptions-seh.mm @@ -7,23 +7,42 @@ // funclet tokens for llvm.objc.retain and llvm.objc.storeStrong and that they // refer to their catchpad's SSA value. -@class Ety; -void opaque(void); -void test_catch_with_objc_intrinsic(void) { +void do_something(); +void may_throw(id); + +void try_catch_with_objc_intrinsic() { + id ex; @try { - opaque(); - } @catch (Ety *ex) { - // Destroy ex when leaving catchpad. This emits calls to intrinsic functions - // llvm.objc.retain and llvm.objc.storeStrong + may_throw(ex); + } @catch (id ex_caught) { + do_something(); + may_throw(ex_caught); } } -// CHECK-LABEL: define{{.*}} void {{.*}}test_catch_with_objc_intrinsic -// ... -// CHECK: catch.dispatch: -// CHECK-NEXT: [[CATCHSWITCH:%[0-9]+]] = catchswitch within none -// ... -// CHECK: catch: -// CHECK-NEXT: [[CATCHPAD:%[0-9]+]] = catchpad within [[CATCHSWITCH]] -// CHECK: {{%[0-9]+}} = call {{.*}} @llvm.objc.retain{{.*}} [ "funclet"(token [[CATCHPAD]]) ] -// CHECK: call {{.*}} @llvm.objc.storeStrong{{.*}} [ "funclet"(token [[CATCHPAD]]) ] +// CHECK-LABEL: try_catch_with_objc_intrinsic +// +// CHECK: catch.dispatch: +// CHECK-NEXT: [[CATCHSWITCH:%[0-9]+]] = catchswitch within none [label %catch] +// +// All calls within a catchpad must have funclet tokens that refer to the +// enclosing catchpad: +// CHECK: catch: +// CHECK-NEXT: [[CATCHPAD:%[0-9]+]] = catchpad within [[CATCHSWITCH]] +// CHECK: call +// CHECK: @llvm.objc.retain +// CHECK: [ "funclet"(token [[CATCHPAD]]) ] +// CHECK: call +// CHECK: do_something +// CHECK: [ "funclet"(token [[CATCHPAD]]) ] +// CHECK: call +// CHECK: may_throw +// CHECK: [ "funclet"(token [[CATCHPAD]]) ] +// CHECK: call +// CHECK: @llvm.objc.storeStrong +// CHECK: [ "funclet"(token [[CATCHPAD]]) ] +// CHECK: catchret from [[CATCHPAD]] to label %catchret.dest +// +// This block exists and it's empty: +// CHECK: catchret.dest: +// CHECK-NEXT: br label %eh.cont