https://github.com/xlauko updated https://github.com/llvm/llvm-project/pull/220878
>From cb3ca388a54f852e5cf3864c6d27d1e39ffbc6a5 Mon Sep 17 00:00:00 2001 From: Henrich Lauko <[email protected]> Date: Thu, 3 Sep 2026 12:44:31 +0000 Subject: [PATCH] [CIR] Give the cleanup kind a proper standalone attribute spelling CleanupKindAttr overrode its assembly format to a bare `$value` so `cir.cleanup.scope` would print `cleanup all`. The cost was that the attribute had no readable standalone form, falling back to `#cir<cleanup_kind all>`. The `enum($attr)` operation directive removes the tradeoff. The attribute keeps CIR_EnumAttr's bracketed default and now spells `#cir.cleanup<all>`, while the operations ask for the bare keyword. The mnemonic drops the `_kind` suffix the C++ class name carries. Operation syntax is unchanged. invalid-loop-cleanup.cir now gets one diagnostic from the enum parser instead of two. --- .../clang/CIR/Dialect/IR/CIREnumAttr.td | 11 ++++++++++ clang/include/clang/CIR/Dialect/IR/CIROps.td | 12 ++++------- clang/test/CIR/IR/cleanup-scope.cir | 21 +++++++++++++++++++ clang/test/CIR/IR/invalid-loop-cleanup.cir | 6 ++---- 4 files changed, 38 insertions(+), 12 deletions(-) diff --git a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td index f75598d6ca75c..8d436e5d9b62c 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td +++ b/clang/include/clang/CIR/Dialect/IR/CIREnumAttr.td @@ -32,6 +32,17 @@ class CIR_I32BitEnumAttr<string name, string summary, let cppNamespace = "::cir"; } +// Unlike the upstream `EnumAttr`, which defaults to a bare `$value`, CIR enum +// attributes keep the `<` `>` delimiters so that a standalone attribute spells +// as `#cir.<mnemonic><value>` rather than falling back to the generic +// `#cir<mnemonic value>` syntax. Operations that want the bare symbolic value +// must therefore wrap the argument in the `enum` assembly format directive, +// as in `enum($cleanupKind)`. Referring to the argument directly would print +// the stripped attribute body, i.e. `<all>` including the delimiters. +// +// The def name is not free: `CIRLoweringEmitter` derives an `isa<cir::...>` +// entry for `CXXABILowering.cpp` by dropping the prefix up to the first +// underscore, so a def must be named `CIR_<CppClassName>`. class CIR_EnumAttr<EnumAttrInfo info, string name = "", list<Trait> traits = []> : EnumAttr<CIR_Dialect, info, name, traits> { let assemblyFormat = "`<` $value `>`"; diff --git a/clang/include/clang/CIR/Dialect/IR/CIROps.td b/clang/include/clang/CIR/Dialect/IR/CIROps.td index 70d34884c70a4..2f334da9acf2c 100644 --- a/clang/include/clang/CIR/Dialect/IR/CIROps.td +++ b/clang/include/clang/CIR/Dialect/IR/CIROps.td @@ -1345,7 +1345,7 @@ def CIR_CleanupKind : CIR_I32EnumAttr<"CleanupKind", "cleanup kind", [ let genSpecializedAttr = 0; } -def CIR_CleanupKindAttr : CIR_EnumAttr<CIR_CleanupKind, "cleanup_kind"> { +def CIR_CleanupKindAttr : CIR_EnumAttr<CIR_CleanupKind, "cleanup"> { let summary = "Cleanup kind attribute"; let description = [{ Cleanup kind attributes. @@ -1361,10 +1361,6 @@ def CIR_CleanupKindAttr : CIR_EnumAttr<CIR_CleanupKind, "cleanup_kind"> { }]> ]; - let assemblyFormat = [{ - $value - }]; - let extraClassDeclaration = [{ bool isNormal() const { return getValue() == CleanupKind::Normal || @@ -1427,7 +1423,7 @@ def CIR_CleanupScopeOp : CIR_Op<"cleanup.scope", [ let skipDefaultBuilders = 1; let assemblyFormat = [{ - $bodyRegion `cleanup` $cleanupKind $cleanupRegion attr-dict + $bodyRegion `cleanup` enum($cleanupKind) $cleanupRegion attr-dict }]; let builders = [ @@ -2296,7 +2292,7 @@ def CIR_WhileOp : CIR_WhileOpBase<"while"> { let regions = (region MinSizedRegion<1>:$cond, MinSizedRegion<1>:$body, MaxSizedRegion<1>:$cleanup); let assemblyFormat = [{ - $cond `do` $body (`cleanup` $cleanupKind $cleanup^)? attr-dict + $cond `do` $body (`cleanup` enum($cleanupKind) $cleanup^)? attr-dict }]; let description = [{ @@ -2456,7 +2452,7 @@ def CIR_ForOp : CIR_LoopOpBase<"for"> { `:` `cond` $cond `body` $body `step` $step - (`cleanup` $cleanupKind $cleanup^)? + (`cleanup` enum($cleanupKind) $cleanup^)? attr-dict }]; diff --git a/clang/test/CIR/IR/cleanup-scope.cir b/clang/test/CIR/IR/cleanup-scope.cir index 614a753d5abd7..db08dc32112f5 100644 --- a/clang/test/CIR/IR/cleanup-scope.cir +++ b/clang/test/CIR/IR/cleanup-scope.cir @@ -133,4 +133,25 @@ cir.func @return_within_cleanup() { // CHECK: cir.return // CHECK: } +// Test that the cleanup kind attribute keeps its own delimiters when it is +// printed standalone, while the operation still prints a bare keyword. +cir.func @cleanup_attr_standalone() { + cir.cleanup.scope { + cir.yield + } cleanup all { + cir.yield + } {cir.test = [#cir.cleanup<normal>, #cir.cleanup<eh>, + #cir.cleanup<all>]} + cir.return +} + +// CHECK: cir.func @cleanup_attr_standalone() { +// CHECK: cir.cleanup.scope { +// CHECK: cir.yield +// CHECK: } cleanup all { +// CHECK: cir.yield +// CHECK: } {cir.test = [#cir.cleanup<normal>, #cir.cleanup<eh>, #cir.cleanup<all>]} +// CHECK: cir.return +// CHECK: } + } diff --git a/clang/test/CIR/IR/invalid-loop-cleanup.cir b/clang/test/CIR/IR/invalid-loop-cleanup.cir index ea07513bde788..2a4f6582d5581 100644 --- a/clang/test/CIR/IR/invalid-loop-cleanup.cir +++ b/clang/test/CIR/IR/invalid-loop-cleanup.cir @@ -16,8 +16,7 @@ cir.func @while_cleanup_missing_kind() { cir.condition(%cond) } do { cir.yield - // expected-error @below {{expected valid keyword or string}} - // expected-error @below {{failed to parse CIR_CleanupKindAttr}} + // expected-error @below {{expected string or keyword containing one of the following enum values for attribute 'cleanupKind' [normal, eh, all]}} } cleanup { cir.call @dtor(%s) nothrow : (!cir.ptr<!rec_S>) -> () cir.yield @@ -45,8 +44,7 @@ cir.func @for_cleanup_missing_kind() { cir.yield } step { cir.yield - // expected-error @below {{expected valid keyword or string}} - // expected-error @below {{failed to parse CIR_CleanupKindAttr}} + // expected-error @below {{expected string or keyword containing one of the following enum values for attribute 'cleanupKind' [normal, eh, all]}} } cleanup { cir.call @dtor(%s) nothrow : (!cir.ptr<!rec_S>) -> () cir.yield _______________________________________________ cfe-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/cfe-commits
