[clang] [CIR] Introduce cir.construct_catch_param (PR #195283)
Andy Kaylor via cfe-commits
cfe-commits at lists.llvm.org
Mon May 4 11:48:28 PDT 2026
https://github.com/andykaylor updated https://github.com/llvm/llvm-project/pull/195283
>From 269fc8648a11db1a07640218c1c7d9e6a188ef56 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akaylor at nvidia.com>
Date: Thu, 30 Apr 2026 17:30:02 -0700
Subject: [PATCH 1/2] [CIR] Introduce cir.construct_catch_param
Add a new CIR operation, `cir.construct_catch_param`, which abstractly
represents the target-specific operations that must performed before
`cir.begin_catch` to bind an in-flight exception object to the local
alloca for a catch parameter.
Generation and lowering of this operation is deferred to follow-up changes.
Assisted-by: Cursor / claude-opus-4.7-thinking-xhigh
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 51 +++++
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 39 +++-
clang/test/CIR/IR/construct-catch-param.cir | 63 ++++++
.../CIR/IR/invalid-construct-catch-param.cir | 212 ++++++++++++++++++
4 files changed, 364 insertions(+), 1 deletion(-)
create mode 100644 clang/test/CIR/IR/construct-catch-param.cir
create mode 100644 clang/test/CIR/IR/invalid-construct-catch-param.cir
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index 97d623ba5e6d9..bf0b895a55d4c 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -7704,6 +7704,57 @@ def CIR_InitCatchParamOp : CIR_Op<"init_catch_param"> {
let hasLLVMLowering = false;
}
+//===----------------------------------------------------------------------===//
+// EH Operations: ConstructCatchParamOp
+//===----------------------------------------------------------------------===//
+
+def CIR_ConstructCatchParamOp : CIR_Op<"construct_catch_param", [
+ DeclareOpInterfaceMethods<SymbolUserOpInterface>
+ ]> {
+ let summary = "Construct a catch parameter from the in-flight exception";
+ let description = [{
+ `cir.construct_catch_param` abstractly represents the target-specific work
+ that must be performed before `cir.begin_catch` to bind the in-flight
+ exception object to the local alloca used for the catch parameter.
+
+ For example, for non-pointer, non-reference catch parameters whose type has
+ a non-trivial copy constructor, the Itanium C++ ABI requires
+ calling `__cxa_get_exception_ptr` to obtain the adjusted exception pointer
+ and then invoking the catch parameter's copy constructor to create a local
+ copy of the object before `__cxa_begin_catch` is invoked.
+
+ This operation takes a `!cir.eh_token` that represents the in-flight
+ exception and the alloca value that is used for the local copy of the
+ exception object. The `copy_fn` attribute is a flat symbol reference to a
+ `cir.func` thunk that copies the exception object to a local alloca value.
+
+ This operation is replaced with a target-specific representation during
+ the EHABI lowering pass. For some targets, such as the Microsoft ABI,
+ this operation is a no-op and is simply erased during lowering.
+
+ Example:
+
+ ```
+ cir.construct_catch_param non_trivial_copy %eh_token to %param_addr
+ copy_fn = @__clang_cir_catch_init_T : !cir.eh_token, !cir.ptr<!rec_T>
+ ```
+ }];
+
+ let arguments = (ins
+ CIR_EhTokenType:$eh_token,
+ CIR_PointerType:$param_addr,
+ CIR_InitCatchKind:$kind,
+ FlatSymbolRefAttr:$copy_fn
+ );
+
+ let assemblyFormat = [{
+ $kind $eh_token `to` $param_addr `:` qualified(type($eh_token)) `,`
+ qualified(type($param_addr)) `,` `copy_fn` `=` $copy_fn attr-dict
+ }];
+
+ let hasLLVMLowering = false;
+}
+
//===----------------------------------------------------------------------===//
// Atomic operations
//===----------------------------------------------------------------------===//
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 7386819d8fce9..9bf750eb9a125 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -4138,7 +4138,15 @@ LogicalResult cir::TryOp::verify() {
if (mlir::isa<cir::UnwindAttr>(typeAttr))
continue;
- if (entryBlock.empty() || !mlir::isa<cir::BeginCatchOp>(entryBlock.front()))
+ // A catch handler region must start with cir.begin_catch, optionally
+ // preceded by a single cir.construct_catch_param that performs any
+ // pre-begin_catch initialization for the catch parameter.
+ if (entryBlock.empty())
+ return emitOpError("catch handler region must not be empty");
+ mlir::Operation *firstOp = &entryBlock.front();
+ if (mlir::isa<cir::ConstructCatchParamOp>(firstOp))
+ firstOp = firstOp->getNextNode();
+ if (!firstOp || !mlir::isa<cir::BeginCatchOp>(firstOp))
return emitOpError(
"catch handler region must start with 'cir.begin_catch'");
}
@@ -4285,6 +4293,35 @@ cir::EhTypeIdOp::verifySymbolUses(SymbolTableCollection &symbolTable) {
return success();
}
+//===----------------------------------------------------------------------===//
+// ConstructCatchParamOp
+//===----------------------------------------------------------------------===//
+
+LogicalResult cir::ConstructCatchParamOp::verifySymbolUses(
+ SymbolTableCollection &symbolTable) {
+ auto fn =
+ symbolTable.lookupNearestSymbolFrom<cir::FuncOp>(*this, getCopyFnAttr());
+ if (!fn)
+ return emitOpError("'")
+ << getCopyFn() << "' does not reference a valid cir.func";
+
+ cir::FuncType fnType = fn.getFunctionType();
+ if (fnType.getNumInputs() != 2 || !fnType.hasVoidReturn())
+ return emitOpError("catch-init copy_fn must take two pointer arguments and "
+ "return void");
+
+ if (fnType.getInput(0) != getParamAddr().getType())
+ return emitOpError("first argument of catch-init copy_fn must match the "
+ "type of 'param_addr'");
+
+ if (fnType.getInput(1) != getParamAddr().getType())
+ return emitOpError(
+ "second argument of catch-init copy_fn must be a pointer "
+ "to the catch type");
+
+ return success();
+}
+
//===----------------------------------------------------------------------===//
// EhDispatchOp
//===----------------------------------------------------------------------===//
diff --git a/clang/test/CIR/IR/construct-catch-param.cir b/clang/test/CIR/IR/construct-catch-param.cir
new file mode 100644
index 0000000000000..609de91461c10
--- /dev/null
+++ b/clang/test/CIR/IR/construct-catch-param.cir
@@ -0,0 +1,63 @@
+// RUN: cir-opt %s --verify-roundtrip | FileCheck %s
+
+!s8i = !cir.int<s, 8>
+!u8i = !cir.int<u, 8>
+!void = !cir.void
+!rec_E = !cir.record<struct "E" padded {!u8i}>
+
+module {
+
+cir.global "private" constant external @_ZTI1E : !cir.ptr<!u8i>
+
+// A CIRGen-style catch-init helper thunk: takes (dest, src) and returns void.
+// `cir.construct_catch_param` references this function via its `copy_fn`
+// attribute; the verifier checks the symbol resolves and matches the
+// (T*, T*) -> void signature.
+cir.func linkonce_odr hidden @__clang_cir_catch_copy__ZTS1E(
+ %arg0: !cir.ptr<!rec_E>, %arg1: !cir.ptr<!rec_E>) {
+ cir.return
+}
+
+// CHECK: cir.func linkonce_odr hidden @__clang_cir_catch_copy__ZTS1E(
+// CHECK: cir.return
+// CHECK: }
+
+// Positive shape: a `cir.try` whose typed catch handler region begins with
+// `cir.construct_catch_param` (referring to an alloca defined in the
+// enclosing scope) followed by `cir.begin_catch`.
+cir.func @construct_catch_param_basic() {
+ cir.scope {
+ %param = cir.alloca !rec_E, !cir.ptr<!rec_E>, ["e"] {alignment = 1 : i64}
+ cir.try {
+ cir.yield
+ } catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
+ (%eh_token: !cir.eh_token) {
+ cir.construct_catch_param non_trivial_copy %eh_token to %param
+ : !cir.eh_token, !cir.ptr<!rec_E>,
+ copy_fn = @__clang_cir_catch_copy__ZTS1E
+ %catch_token, %exn_ptr = cir.begin_catch %eh_token
+ : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
+ cir.cleanup.scope {
+ cir.yield
+ } cleanup eh {
+ cir.end_catch %catch_token : !cir.catch_token
+ cir.yield
+ }
+ cir.yield
+ }
+ }
+ cir.return
+}
+
+// CHECK-LABEL: cir.func @construct_catch_param_basic()
+// CHECK: %[[E:.*]] = cir.alloca !rec_E, !cir.ptr<!rec_E>, ["e"]
+// CHECK: cir.try {
+// CHECK: cir.yield
+// CHECK: } catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
+// CHECK-SAME: (%[[EH:.*]]: !cir.eh_token) {
+// CHECK: cir.construct_catch_param non_trivial_copy %[[EH]] to %[[E]]
+// CHECK-SAME: : !cir.eh_token, !cir.ptr<!rec_E>,
+// CHECK-SAME: copy_fn = @__clang_cir_catch_copy__ZTS1E
+// CHECK: cir.begin_catch %[[EH]]
+
+}
diff --git a/clang/test/CIR/IR/invalid-construct-catch-param.cir b/clang/test/CIR/IR/invalid-construct-catch-param.cir
new file mode 100644
index 0000000000000..8a22d590589f6
--- /dev/null
+++ b/clang/test/CIR/IR/invalid-construct-catch-param.cir
@@ -0,0 +1,212 @@
+// RUN: cir-opt %s -verify-diagnostics -split-input-file
+
+!u8i = !cir.int<u, 8>
+!s32i = !cir.int<s, 32>
+!void = !cir.void
+!rec_E = !cir.record<struct "E" padded {!u8i}>
+
+module {
+
+cir.global "private" constant external @_ZTI1E : !cir.ptr<!u8i>
+
+cir.func @copy_fn_missing() {
+ cir.scope {
+ %p = cir.alloca !rec_E, !cir.ptr<!rec_E>, ["e"] {alignment = 1 : i64}
+ cir.try {
+ cir.yield
+ } catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
+ (%eh_token: !cir.eh_token) {
+ // expected-error @below {{'__not_a_func' does not reference a valid cir.func}}
+ cir.construct_catch_param non_trivial_copy %eh_token to %p
+ : !cir.eh_token, !cir.ptr<!rec_E>, copy_fn = @__not_a_func
+ %catch_token, %exn_ptr = cir.begin_catch %eh_token
+ : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
+ cir.end_catch %catch_token : !cir.catch_token
+ cir.yield
+ }
+ }
+ cir.return
+}
+
+}
+
+// -----
+
+!u8i = !cir.int<u, 8>
+!void = !cir.void
+!rec_E = !cir.record<struct "E" padded {!u8i}>
+
+module {
+
+cir.global "private" constant external @_ZTI1E : !cir.ptr<!u8i>
+
+// copy_fn takes only one argument (should be two).
+cir.func private @bad_copy_fn_arity(!cir.ptr<!rec_E>)
+
+cir.func @copy_fn_wrong_arity() {
+ cir.scope {
+ %p = cir.alloca !rec_E, !cir.ptr<!rec_E>, ["e"] {alignment = 1 : i64}
+ cir.try {
+ cir.yield
+ } catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
+ (%eh_token: !cir.eh_token) {
+ // expected-error @below {{catch-init copy_fn must take two pointer arguments and return void}}
+ cir.construct_catch_param non_trivial_copy %eh_token to %p
+ : !cir.eh_token, !cir.ptr<!rec_E>, copy_fn = @bad_copy_fn_arity
+ %catch_token, %exn_ptr = cir.begin_catch %eh_token
+ : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
+ cir.end_catch %catch_token : !cir.catch_token
+ cir.yield
+ }
+ }
+ cir.return
+}
+
+}
+
+// -----
+
+!u8i = !cir.int<u, 8>
+!s32i = !cir.int<s, 32>
+!void = !cir.void
+!rec_E = !cir.record<struct "E" padded {!u8i}>
+
+module {
+
+cir.global "private" constant external @_ZTI1E : !cir.ptr<!u8i>
+
+// copy_fn returns a non-void type.
+cir.func private @bad_copy_fn_ret(
+ !cir.ptr<!rec_E>, !cir.ptr<!rec_E>) -> !s32i
+
+cir.func @copy_fn_non_void_return() {
+ cir.scope {
+ %p = cir.alloca !rec_E, !cir.ptr<!rec_E>, ["e"] {alignment = 1 : i64}
+ cir.try {
+ cir.yield
+ } catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
+ (%eh_token: !cir.eh_token) {
+ // expected-error @below {{catch-init copy_fn must take two pointer arguments and return void}}
+ cir.construct_catch_param non_trivial_copy %eh_token to %p
+ : !cir.eh_token, !cir.ptr<!rec_E>, copy_fn = @bad_copy_fn_ret
+ %catch_token, %exn_ptr = cir.begin_catch %eh_token
+ : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
+ cir.end_catch %catch_token : !cir.catch_token
+ cir.yield
+ }
+ }
+ cir.return
+}
+
+}
+
+// -----
+
+!u8i = !cir.int<u, 8>
+!s32i = !cir.int<s, 32>
+!void = !cir.void
+!rec_E = !cir.record<struct "E" padded {!u8i}>
+
+module {
+
+cir.global "private" constant external @_ZTI1E : !cir.ptr<!u8i>
+
+// copy_fn's first parameter does not match the catch parameter pointer
+// type (!cir.ptr<!s32i> vs !cir.ptr<!rec_E>).
+cir.func private @bad_copy_fn_first_arg(
+ !cir.ptr<!s32i>, !cir.ptr<!rec_E>)
+
+cir.func @copy_fn_first_arg_mismatch() {
+ cir.scope {
+ %p = cir.alloca !rec_E, !cir.ptr<!rec_E>, ["e"] {alignment = 1 : i64}
+ cir.try {
+ cir.yield
+ } catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
+ (%eh_token: !cir.eh_token) {
+ // expected-error @below {{first argument of catch-init copy_fn must match the type of 'param_addr'}}
+ cir.construct_catch_param non_trivial_copy %eh_token to %p
+ : !cir.eh_token, !cir.ptr<!rec_E>, copy_fn = @bad_copy_fn_first_arg
+ %catch_token, %exn_ptr = cir.begin_catch %eh_token
+ : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
+ cir.end_catch %catch_token : !cir.catch_token
+ cir.yield
+ }
+ }
+ cir.return
+}
+
+}
+
+// -----
+
+!u8i = !cir.int<u, 8>
+!s32i = !cir.int<s, 32>
+!void = !cir.void
+!rec_E = !cir.record<struct "E" padded {!u8i}>
+
+module {
+
+cir.global "private" constant external @_ZTI1E : !cir.ptr<!u8i>
+
+// copy_fn's second parameter does not match the catch parameter pointer
+// type (the source argument must also be !cir.ptr<!rec_E>).
+cir.func private @bad_copy_fn_second_arg(
+ !cir.ptr<!rec_E>, !cir.ptr<!s32i>)
+
+cir.func @copy_fn_second_arg_mismatch() {
+ cir.scope {
+ %p = cir.alloca !rec_E, !cir.ptr<!rec_E>, ["e"] {alignment = 1 : i64}
+ cir.try {
+ cir.yield
+ } catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
+ (%eh_token: !cir.eh_token) {
+ // expected-error @below {{second argument of catch-init copy_fn must be a pointer to the catch type}}
+ cir.construct_catch_param non_trivial_copy %eh_token to %p
+ : !cir.eh_token, !cir.ptr<!rec_E>, copy_fn = @bad_copy_fn_second_arg
+ %catch_token, %exn_ptr = cir.begin_catch %eh_token
+ : !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
+ cir.end_catch %catch_token : !cir.catch_token
+ cir.yield
+ }
+ }
+ cir.return
+}
+
+}
+
+// -----
+
+!u8i = !cir.int<u, 8>
+!void = !cir.void
+!rec_E = !cir.record<struct "E" padded {!u8i}>
+
+module {
+
+cir.global "private" constant external @_ZTI1E : !cir.ptr<!u8i>
+
+cir.func linkonce_odr hidden @__clang_cir_catch_copy__ZTS1E(
+ %arg0: !cir.ptr<!rec_E>, %arg1: !cir.ptr<!rec_E>) {
+ cir.return
+}
+
+// `cir.construct_catch_param` itself verifies, but `cir.try` rejects the
+// catch handler because the op after `cir.construct_catch_param` is not
+// `cir.begin_catch`.
+cir.func @construct_not_followed_by_begin_catch() {
+ cir.scope {
+ %p = cir.alloca !rec_E, !cir.ptr<!rec_E>, ["e"] {alignment = 1 : i64}
+ // expected-error @below {{catch handler region must start with 'cir.begin_catch'}}
+ cir.try {
+ cir.yield
+ } catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
+ (%eh_token: !cir.eh_token) {
+ cir.construct_catch_param non_trivial_copy %eh_token to %p
+ : !cir.eh_token, !cir.ptr<!rec_E>,
+ copy_fn = @__clang_cir_catch_copy__ZTS1E
+ cir.yield
+ }
+ }
+ cir.return
+}
+
+}
>From 5ef4b86313634922e161f88be1a144bf64096022 Mon Sep 17 00:00:00 2001
From: Andy Kaylor <akaylor at nvidia.com>
Date: Mon, 4 May 2026 11:48:00 -0700
Subject: [PATCH 2/2] Address review feedback
---
clang/include/clang/CIR/Dialect/IR/CIROps.td | 8 +++---
clang/lib/CIR/Dialect/IR/CIRDialect.cpp | 2 +-
clang/test/CIR/IR/construct-catch-param.cir | 6 ++---
.../CIR/IR/invalid-construct-catch-param.cir | 25 +++++++++----------
4 files changed, 19 insertions(+), 22 deletions(-)
diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td
index bf0b895a55d4c..8ead23c83cb50 100644
--- a/clang/include/clang/CIR/Dialect/IR/CIROps.td
+++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td
@@ -7717,7 +7717,7 @@ def CIR_ConstructCatchParamOp : CIR_Op<"construct_catch_param", [
that must be performed before `cir.begin_catch` to bind the in-flight
exception object to the local alloca used for the catch parameter.
- For example, for non-pointer, non-reference catch parameters whose type has
+ For example: for non-pointer, non-reference catch parameters whose type has
a non-trivial copy constructor, the Itanium C++ ABI requires
calling `__cxa_get_exception_ptr` to obtain the adjusted exception pointer
and then invoking the catch parameter's copy constructor to create a local
@@ -7736,7 +7736,7 @@ def CIR_ConstructCatchParamOp : CIR_Op<"construct_catch_param", [
```
cir.construct_catch_param non_trivial_copy %eh_token to %param_addr
- copy_fn = @__clang_cir_catch_init_T : !cir.eh_token, !cir.ptr<!rec_T>
+ using @__clang_cir_catch_init_T : !cir.ptr<!rec_T>
```
}];
@@ -7748,8 +7748,8 @@ def CIR_ConstructCatchParamOp : CIR_Op<"construct_catch_param", [
);
let assemblyFormat = [{
- $kind $eh_token `to` $param_addr `:` qualified(type($eh_token)) `,`
- qualified(type($param_addr)) `,` `copy_fn` `=` $copy_fn attr-dict
+ $kind $eh_token `to` $param_addr `using` $copy_fn `:`
+ qualified(type($param_addr)) attr-dict
}];
let hasLLVMLowering = false;
diff --git a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
index 9bf750eb9a125..47ccb291ea745 100644
--- a/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
+++ b/clang/lib/CIR/Dialect/IR/CIRDialect.cpp
@@ -4144,7 +4144,7 @@ LogicalResult cir::TryOp::verify() {
if (entryBlock.empty())
return emitOpError("catch handler region must not be empty");
mlir::Operation *firstOp = &entryBlock.front();
- if (mlir::isa<cir::ConstructCatchParamOp>(firstOp))
+ if (mlir::isa_and_present<cir::ConstructCatchParamOp>(firstOp))
firstOp = firstOp->getNextNode();
if (!firstOp || !mlir::isa<cir::BeginCatchOp>(firstOp))
return emitOpError(
diff --git a/clang/test/CIR/IR/construct-catch-param.cir b/clang/test/CIR/IR/construct-catch-param.cir
index 609de91461c10..805d917aef30b 100644
--- a/clang/test/CIR/IR/construct-catch-param.cir
+++ b/clang/test/CIR/IR/construct-catch-param.cir
@@ -33,8 +33,7 @@ cir.func @construct_catch_param_basic() {
} catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
(%eh_token: !cir.eh_token) {
cir.construct_catch_param non_trivial_copy %eh_token to %param
- : !cir.eh_token, !cir.ptr<!rec_E>,
- copy_fn = @__clang_cir_catch_copy__ZTS1E
+ using @__clang_cir_catch_copy__ZTS1E : !cir.ptr<!rec_E>
%catch_token, %exn_ptr = cir.begin_catch %eh_token
: !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
cir.cleanup.scope {
@@ -56,8 +55,7 @@ cir.func @construct_catch_param_basic() {
// CHECK: } catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
// CHECK-SAME: (%[[EH:.*]]: !cir.eh_token) {
// CHECK: cir.construct_catch_param non_trivial_copy %[[EH]] to %[[E]]
-// CHECK-SAME: : !cir.eh_token, !cir.ptr<!rec_E>,
-// CHECK-SAME: copy_fn = @__clang_cir_catch_copy__ZTS1E
+// CHECK-SAME: using @__clang_cir_catch_copy__ZTS1E : !cir.ptr<!rec_E>
// CHECK: cir.begin_catch %[[EH]]
}
diff --git a/clang/test/CIR/IR/invalid-construct-catch-param.cir b/clang/test/CIR/IR/invalid-construct-catch-param.cir
index 8a22d590589f6..6704b549e1ecd 100644
--- a/clang/test/CIR/IR/invalid-construct-catch-param.cir
+++ b/clang/test/CIR/IR/invalid-construct-catch-param.cir
@@ -17,8 +17,8 @@ cir.func @copy_fn_missing() {
} catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
(%eh_token: !cir.eh_token) {
// expected-error @below {{'__not_a_func' does not reference a valid cir.func}}
- cir.construct_catch_param non_trivial_copy %eh_token to %p
- : !cir.eh_token, !cir.ptr<!rec_E>, copy_fn = @__not_a_func
+ cir.construct_catch_param non_trivial_copy %eh_token to %p using @__not_a_func
+ : !cir.ptr<!rec_E>
%catch_token, %exn_ptr = cir.begin_catch %eh_token
: !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
cir.end_catch %catch_token : !cir.catch_token
@@ -51,8 +51,8 @@ cir.func @copy_fn_wrong_arity() {
} catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
(%eh_token: !cir.eh_token) {
// expected-error @below {{catch-init copy_fn must take two pointer arguments and return void}}
- cir.construct_catch_param non_trivial_copy %eh_token to %p
- : !cir.eh_token, !cir.ptr<!rec_E>, copy_fn = @bad_copy_fn_arity
+ cir.construct_catch_param non_trivial_copy %eh_token to %p using @bad_copy_fn_arity
+ : !cir.ptr<!rec_E>
%catch_token, %exn_ptr = cir.begin_catch %eh_token
: !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
cir.end_catch %catch_token : !cir.catch_token
@@ -87,8 +87,8 @@ cir.func @copy_fn_non_void_return() {
} catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
(%eh_token: !cir.eh_token) {
// expected-error @below {{catch-init copy_fn must take two pointer arguments and return void}}
- cir.construct_catch_param non_trivial_copy %eh_token to %p
- : !cir.eh_token, !cir.ptr<!rec_E>, copy_fn = @bad_copy_fn_ret
+ cir.construct_catch_param non_trivial_copy %eh_token to %p using @bad_copy_fn_ret
+ : !cir.ptr<!rec_E>
%catch_token, %exn_ptr = cir.begin_catch %eh_token
: !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
cir.end_catch %catch_token : !cir.catch_token
@@ -124,8 +124,8 @@ cir.func @copy_fn_first_arg_mismatch() {
} catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
(%eh_token: !cir.eh_token) {
// expected-error @below {{first argument of catch-init copy_fn must match the type of 'param_addr'}}
- cir.construct_catch_param non_trivial_copy %eh_token to %p
- : !cir.eh_token, !cir.ptr<!rec_E>, copy_fn = @bad_copy_fn_first_arg
+ cir.construct_catch_param non_trivial_copy %eh_token to %p using @bad_copy_fn_first_arg
+ : !cir.ptr<!rec_E>
%catch_token, %exn_ptr = cir.begin_catch %eh_token
: !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
cir.end_catch %catch_token : !cir.catch_token
@@ -161,8 +161,8 @@ cir.func @copy_fn_second_arg_mismatch() {
} catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
(%eh_token: !cir.eh_token) {
// expected-error @below {{second argument of catch-init copy_fn must be a pointer to the catch type}}
- cir.construct_catch_param non_trivial_copy %eh_token to %p
- : !cir.eh_token, !cir.ptr<!rec_E>, copy_fn = @bad_copy_fn_second_arg
+ cir.construct_catch_param non_trivial_copy %eh_token to %p using @bad_copy_fn_second_arg
+ : !cir.ptr<!rec_E>
%catch_token, %exn_ptr = cir.begin_catch %eh_token
: !cir.eh_token -> (!cir.catch_token, !cir.ptr<!void>)
cir.end_catch %catch_token : !cir.catch_token
@@ -200,9 +200,8 @@ cir.func @construct_not_followed_by_begin_catch() {
cir.yield
} catch [type #cir.global_view<@_ZTI1E> : !cir.ptr<!u8i>]
(%eh_token: !cir.eh_token) {
- cir.construct_catch_param non_trivial_copy %eh_token to %p
- : !cir.eh_token, !cir.ptr<!rec_E>,
- copy_fn = @__clang_cir_catch_copy__ZTS1E
+ cir.construct_catch_param non_trivial_copy %eh_token to %p using @__clang_cir_catch_copy__ZTS1E
+ : !cir.ptr<!rec_E>
cir.yield
}
}
More information about the cfe-commits
mailing list