llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir @llvm/pr-subscribers-clang Author: Andy Kaylor (andykaylor) <details> <summary>Changes</summary> We had a problem where scope terminators were not being created correctly when a cleanup scope appeared inside the body of a try operation. This was caused by cleanup scope operation not being properly flushed before the try body scope was completed. This change fixes the problem by creating a RunCleanupsScope in the lambda that pupulates the try body and forcing cleanups before adding the yield terminator to the try body. The test case also exposed a secondary bug where we were not properly updating the innermostEHScope variable when popping a cleanup from the eh stack. That is also fixed here. --- Full diff: https://github.com/llvm/llvm-project/pull/183869.diff 3 Files Affected: - (modified) clang/lib/CIR/CodeGen/CIRGenCleanup.cpp (+1) - (modified) clang/lib/CIR/CodeGen/CIRGenException.cpp (+5) - (modified) clang/test/CIR/CodeGen/try-catch-tmp.cpp (+60) ``````````diff diff --git a/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp b/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp index c9806de61acc6..44b8ff7d4ad63 100644 --- a/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenCleanup.cpp @@ -160,6 +160,7 @@ void EHScopeStack::popCleanup() { assert(isa<EHCleanupScope>(*begin())); EHCleanupScope &cleanup = cast<EHCleanupScope>(*begin()); innermostNormalCleanup = cleanup.getEnclosingNormalCleanup(); + innermostEHScope = cleanup.getEnclosingEHScope(); deallocate(cleanup.getAllocatedSize()); cir::CleanupScopeOp cleanupScope = cleanup.getCleanupScopeOp(); diff --git a/clang/lib/CIR/CodeGen/CIRGenException.cpp b/clang/lib/CIR/CodeGen/CIRGenException.cpp index 94b0e251a1420..be90e19d03c76 100644 --- a/clang/lib/CIR/CodeGen/CIRGenException.cpp +++ b/clang/lib/CIR/CodeGen/CIRGenException.cpp @@ -322,8 +322,13 @@ mlir::LogicalResult CIRGenFunction::emitCXXTryStmt(const CXXTryStmt &s) { builder, tryLoc, /*tryBuilder=*/ [&](mlir::OpBuilder &b, mlir::Location loc) { + // Create a RunCleanupsScope that allows us to apply any cleanups that + // are created for statements within the try body before exiting the + // try body. + RunCleanupsScope tryBodyCleanups(*this); if (emitStmt(s.getTryBlock(), /*useCurrentScope=*/true).failed()) tryRes = mlir::failure(); + tryBodyCleanups.forceCleanup(); cir::YieldOp::create(builder, loc); }, /*handlersBuilder=*/ diff --git a/clang/test/CIR/CodeGen/try-catch-tmp.cpp b/clang/test/CIR/CodeGen/try-catch-tmp.cpp index 02f0df6d8753d..5cb60aaf6b2cc 100644 --- a/clang/test/CIR/CodeGen/try-catch-tmp.cpp +++ b/clang/test/CIR/CodeGen/try-catch-tmp.cpp @@ -327,3 +327,63 @@ void call_function_inside_try_catch_with_exception_type_and_catch_all() { // OGCG: %[[BEGIN_CATCH:.*]] = call ptr @__cxa_begin_catch(ptr %[[TMP_EXCEPTION]]) // OGCG: call void @__cxa_end_catch() // OGCG: br label %[[TRY_CONT]] + +struct S { + ~S(); +}; + +void cleanup_inside_try_body() { + try { + S s; + division(); + } catch (...) { + } +} + +// CIR: cir.func {{.*}} @_Z23cleanup_inside_try_bodyv(){{.*}} personality(@__gxx_personality_v0) { +// CIR: cir.scope { +// CIR: %[[S:.*]] = cir.alloca !rec_S, !cir.ptr<!rec_S>, ["s"] +// CIR: cir.try { +// CIR: cir.cleanup.scope { +// CIR: cir.call @_Z8divisionv() +// CIR: cir.yield +// CIR: } cleanup all { +// CIR: cir.call @_ZN1SD1Ev(%[[S]]) +// CIR: cir.yield +// CIR: } +// CIR: cir.yield +// CIR: } catch all (%[[TOKEN:.*]]: !cir.eh_token {{.*}}) { +// CIR: %[[CATCH_TOKEN:.*]], %[[EXN_PTR:.*]] = cir.begin_catch %[[TOKEN]] : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>) +// CIR: cir.cleanup.scope { +// CIR: cir.yield +// CIR: } cleanup all { +// CIR: cir.end_catch %[[CATCH_TOKEN]] : !cir.catch_token +// CIR: cir.yield +// CIR: } +// CIR: cir.yield +// CIR: } +// CIR: } + +// OGCG: define {{.*}} void @_Z23cleanup_inside_try_bodyv() {{.*}} personality ptr @__gxx_personality_v0 { +// OGCG: %[[S:.*]] = alloca %struct.S +// OGCG: %[[EXN_SLOT:.*]] = alloca ptr +// OGCG: %[[EHSELECTOR_SLOT:.*]] = alloca i32 +// OGCG: %[[CALL:.*]] = invoke {{.*}} i32 @_Z8divisionv() +// OGCG: to label %[[INVOKE_CONT:.*]] unwind label %[[LANDING_PAD:.*]] +// OGCG: [[INVOKE_CONT]]: +// OGCG: call void @_ZN1SD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %[[S]]) +// OGCG: br label %[[TRY_CONT:.*]] +// OGCG: [[LANDING_PAD]]: +// OGCG: %[[LANDING_PAD:.*]] = landingpad { ptr, i32 } +// OGCG: catch ptr null +// OGCG: %[[EXCEPTION:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 0 +// OGCG: store ptr %[[EXCEPTION]], ptr %[[EXN_SLOT]] +// OGCG: %[[EH_TYPE_ID:.*]] = extractvalue { ptr, i32 } %[[LANDING_PAD]], 1 +// OGCG: store i32 %[[EH_TYPE_ID]], ptr %[[EHSELECTOR_SLOT]] +// OGCG: call void @_ZN1SD1Ev(ptr noundef nonnull align 1 dereferenceable(1) %[[S]]) +// OGCG: br label %[[CATCH:.*]] +// OGCG: [[CATCH]]: +// OGCG: %[[EXCEPTION:.*]] = load ptr, ptr %[[EXN_SLOT]] +// OGCG: %[[BEGIN_CATCH:.*]] = call ptr @__cxa_begin_catch(ptr %[[EXCEPTION]]) +// OGCG: call void @__cxa_end_catch() +// OGCG: br label %[[TRY_CONT]] `````````` </details> https://github.com/llvm/llvm-project/pull/183869 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
