llvmbot wrote:
<!--LLVM PR SUMMARY COMMENT--> @llvm/pr-subscribers-clangir Author: Andy Kaylor (andykaylor) <details> <summary>Changes</summary> This adds a verifier to enforce the requirement that every catch handler in a cir.try operation must begin with a cir.catch_param operation. --- Full diff: https://github.com/llvm/llvm-project/pull/181419.diff 4 Files Affected: - (modified) clang/include/clang/CIR/Dialect/IR/CIROps.td (+1) - (modified) clang/lib/CIR/Dialect/IR/CIRDialect.cpp (+32) - (modified) clang/test/CIR/IR/invalid-try-catch.cir (+45) - (modified) clang/test/CIR/IR/try-catch.cir (+8) ``````````diff diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 7085580d99718..496033d34d137 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -6279,6 +6279,7 @@ def CIR_TryOp : CIR_Op<"try",[ }]> ]; + let hasVerifier = 1; let hasLLVMLowering = false; } diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp index 4a25407d0f3cf..a8ef838111c29 100644 --- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp +++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp @@ -3774,6 +3774,38 @@ mlir::ValueRange cir::TryOp::getSuccessorInputs(RegionSuccessor successor) { : ValueRange(); } +LogicalResult cir::TryOp::verify() { + mlir::ArrayAttr handlerTypes = getHandlerTypes(); + if (!handlerTypes) { + if (!getHandlerRegions().empty()) + return emitOpError( + "handler regions must be empty when no handler types are present"); + return success(); + } + + mlir::MutableArrayRef<mlir::Region> handlerRegions = getHandlerRegions(); + + // The parser and builder won't allow this to happen, but the loop below + // relies on the sizes being the same, so we check it here. + if (handlerRegions.size() != handlerTypes.size()) + return emitOpError( + "number of handler regions and handler types must match"); + + for (const auto &[typeAttr, handlerRegion] : + llvm::zip(handlerTypes, handlerRegions)) { + // The unwind region does not require a cir.catch_param. + if (mlir::isa<cir::UnwindAttr>(typeAttr)) + continue; + + mlir::Block &entryBlock = handlerRegion.front(); + if (entryBlock.empty() || !mlir::isa<cir::CatchParamOp>(entryBlock.front())) + return emitOpError( + "catch handler region must start with 'cir.catch_param'"); + } + + return success(); +} + static void printTryHandlerRegions(mlir::OpAsmPrinter &printer, cir::TryOp op, mlir::MutableArrayRef<mlir::Region> handlerRegions, diff --git a/clang/test/CIR/IR/invalid-try-catch.cir b/clang/test/CIR/IR/invalid-try-catch.cir index c11abb9dd449b..18002e6db4467 100644 --- a/clang/test/CIR/IR/invalid-try-catch.cir +++ b/clang/test/CIR/IR/invalid-try-catch.cir @@ -136,6 +136,51 @@ cir.func dso_local @invalid_catch_all_with_type_info() { // ----- +!u8i = !cir.int<u, 8> +!void = !cir.void + +module { + +cir.global "private" constant external @_ZTIi : !cir.ptr<!u8i> + +cir.func dso_local @catch_handler_missing_catch_param() { + cir.scope { + // expected-error @below {{catch handler region must start with 'cir.catch_param'}} + cir.try { + cir.yield + } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] { + cir.yield + } unwind { + cir.resume + } + } + cir.return +} + +} + +// ----- + +!void = !cir.void + +module { + +cir.func dso_local @catch_all_handler_missing_catch_param() { + cir.scope { + // expected-error @below {{catch handler region must start with 'cir.catch_param'}} + cir.try { + cir.yield + } catch all { + cir.yield + } + } + cir.return +} + +} + +// ----- + module { cir.func dso_local @invalid_unwind_with_catch_all() { diff --git a/clang/test/CIR/IR/try-catch.cir b/clang/test/CIR/IR/try-catch.cir index 8ffce067ba043..3a5fe1a1573cc 100644 --- a/clang/test/CIR/IR/try-catch.cir +++ b/clang/test/CIR/IR/try-catch.cir @@ -1,6 +1,8 @@ // RUN: cir-opt %s --verify-roundtrip | FileCheck %s !u8i = !cir.int<u, 8> +!s32i = !cir.int<s, 32> +!void = !cir.void module { @@ -12,6 +14,7 @@ cir.func dso_local @empty_try_block_with_catch_all() { cir.try { cir.yield } catch all { + %0 = cir.catch_param : !cir.ptr<!void> cir.yield } } @@ -23,6 +26,7 @@ cir.func dso_local @empty_try_block_with_catch_all() { // CHECK: cir.try { // CHECK: cir.yield // CHECK: } catch all { +// CHECK: %[[CP:.*]] = cir.catch_param : !cir.ptr<!void> // CHECK: cir.yield // CHECK: } // CHECK: } @@ -56,8 +60,10 @@ cir.func dso_local @empty_try_block_with_catch_ist() { cir.try { cir.yield } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] { + %0 = cir.catch_param : !cir.ptr<!s32i> cir.yield } catch [type #cir.global_view<@_ZTIPKc> : !cir.ptr<!u8i>] { + %0 = cir.catch_param : !cir.ptr<!cir.ptr<!u8i>> cir.yield } unwind { cir.yield @@ -71,8 +77,10 @@ cir.func dso_local @empty_try_block_with_catch_ist() { // CHECK: cir.try { // CHECK: cir.yield // CHECK: } catch [type #cir.global_view<@_ZTIi> : !cir.ptr<!u8i>] { +// CHECK: %[[CP1:.*]] = cir.catch_param : !cir.ptr<!s32i> // CHECK: cir.yield // CHECK: } catch [type #cir.global_view<@_ZTIPKc> : !cir.ptr<!u8i>] { +// CHECK: %[[CP2:.*]] = cir.catch_param : !cir.ptr<!cir.ptr<!u8i>> // CHECK: cir.yield // CHECK: } unwind { // CHECK: cir.yield `````````` </details> https://github.com/llvm/llvm-project/pull/181419 _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
