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

Reply via email to