1 // RUN: mlir-tblgen -gen-op-decls -I %S/../../include %s | FileCheck %s --check-prefix=DECL
2 // RUN: mlir-tblgen -gen-op-defs -I %S/../../include %s | FileCheck %s --check-prefix=DEF
3 // RUN: mlir-tblgen -print-records -I %S/../../include %s | FileCheck %s --check-prefix=RECORD
5 include "mlir/IR/OpBase.td"
7 def Test_Dialect : Dialect {
9 let cppNamespace = "foobar";
11 class NS_Op<string mnemonic, list<OpTrait> traits> :
12 Op<Test_Dialect, mnemonic, traits>;
14 def SomeAttr : Attr<CPred<"some-condition">, "some attribute kind"> {
15 let storageType = "some-attr-kind";
16 let returnType = "some-return-type";
17 let convertFromStorage = "$_self.some-convert-from-storage()";
18 let constBuilderCall = "some-const-builder-call($_builder, $0)";
21 def SomeAttrDef : AttrDef<Test_Dialect, "SomeAttr"> {
25 // Test required, optional, default-valued attributes
28 def AOp : NS_Op<"a_op", []> {
31 DefaultValuedAttr<SomeAttr, "4.2">:$bAttr,
32 OptionalAttr<SomeAttr>:$cAttr
36 // DECL-LABEL: AOp declarations
38 // Test attribute name methods
41 // DECL: static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames()
42 // DECL-NEXT: static ::llvm::StringRef attrNames[] =
43 // DECL-SAME: {::llvm::StringRef("aAttr"), ::llvm::StringRef("bAttr"), ::llvm::StringRef("cAttr")};
44 // DECL-NEXT: return ::llvm::makeArrayRef(attrNames);
46 // DECL: ::mlir::StringAttr aAttrAttrName()
47 // DECL-NEXT: return getAttributeNameForIndex(0);
48 // DECL: ::mlir::StringAttr aAttrAttrName(::mlir::OperationName name)
49 // DECL-NEXT: return getAttributeNameForIndex(name, 0);
51 // DECL: ::mlir::StringAttr bAttrAttrName()
52 // DECL-NEXT: return getAttributeNameForIndex(1);
53 // DECL: ::mlir::StringAttr bAttrAttrName(::mlir::OperationName name)
54 // DECL-NEXT: return getAttributeNameForIndex(name, 1);
56 // DECL: ::mlir::StringAttr cAttrAttrName()
57 // DECL-NEXT: return getAttributeNameForIndex(2);
58 // DECL: ::mlir::StringAttr cAttrAttrName(::mlir::OperationName name)
59 // DECL-NEXT: return getAttributeNameForIndex(name, 2);
61 // DEF-LABEL: AOp definitions
66 // DEF: ::mlir::LogicalResult AOpAdaptor::verify
67 // DEF: auto tblgen_aAttr = odsAttrs.get("aAttr");
68 // DEF-NEXT: if (!tblgen_aAttr)
69 // DEF-NEXT: return emitError(loc, "'test.a_op' op ""requires attribute 'aAttr'");
70 // DEF: if (tblgen_aAttr && !((some-condition)))
71 // DEF-NEXT: return emitError(loc, "'test.a_op' op ""attribute 'aAttr' failed to satisfy constraint: some attribute kind");
72 // DEF: auto tblgen_bAttr = odsAttrs.get("bAttr");
73 // DEF-NEXT: if (tblgen_bAttr && !((some-condition)))
74 // DEF-NEXT: return emitError(loc, "'test.a_op' op ""attribute 'bAttr' failed to satisfy constraint: some attribute kind");
75 // DEF: auto tblgen_cAttr = odsAttrs.get("cAttr");
76 // DEF-NEXT: if (tblgen_cAttr && !((some-condition)))
77 // DEF-NEXT: return emitError(loc, "'test.a_op' op ""attribute 'cAttr' failed to satisfy constraint: some attribute kind");
79 // Test getter methods
82 // DEF: some-attr-kind AOp::aAttrAttr()
83 // DEF-NEXT: (*this)->getAttr(aAttrAttrName()).cast<some-attr-kind>()
84 // DEF: some-return-type AOp::aAttr() {
85 // DEF-NEXT: auto attr = aAttrAttr()
86 // DEF-NEXT: return attr.some-convert-from-storage();
88 // DEF: some-attr-kind AOp::bAttrAttr()
89 // DEF-NEXT: return (*this)->getAttr(bAttrAttrName()).dyn_cast_or_null<some-attr-kind>()
90 // DEF: some-return-type AOp::bAttr() {
91 // DEF-NEXT: auto attr = bAttrAttr();
92 // DEF-NEXT: if (!attr)
93 // DEF-NEXT: return some-const-builder-call(::mlir::Builder((*this)->getContext()), 4.2).some-convert-from-storage();
94 // DEF-NEXT: return attr.some-convert-from-storage();
96 // DEF: some-attr-kind AOp::cAttrAttr()
97 // DEF-NEXT: return (*this)->getAttr(cAttrAttrName()).dyn_cast_or_null<some-attr-kind>()
98 // DEF: ::llvm::Optional<some-return-type> AOp::cAttr() {
99 // DEF-NEXT: auto attr = cAttrAttr()
100 // DEF-NEXT: return attr ? ::llvm::Optional<some-return-type>(attr.some-convert-from-storage()) : (::llvm::None);
102 // Test setter methods
105 // DEF: void AOp::aAttrAttr(some-attr-kind attr) {
106 // DEF-NEXT: (*this)->setAttr(aAttrAttrName(), attr);
107 // DEF: void AOp::bAttrAttr(some-attr-kind attr) {
108 // DEF-NEXT: (*this)->setAttr(bAttrAttrName(), attr);
109 // DEF: void AOp::cAttrAttr(some-attr-kind attr) {
110 // DEF-NEXT: (*this)->setAttr(cAttrAttrName(), attr);
112 // Test remove methods
115 // DEF: ::mlir::Attribute AOp::removeCAttrAttr() {
116 // DEF-NEXT: return (*this)->removeAttr(cAttrAttrName());
118 // Test build methods
121 // DEF: void AOp::build(
122 // DEF: odsState.addAttribute(aAttrAttrName(odsState.name), aAttr);
123 // DEF: odsState.addAttribute(bAttrAttrName(odsState.name), bAttr);
125 // DEF-NEXT: odsState.addAttribute(cAttrAttrName(odsState.name), cAttr);
127 // DEF: void AOp::build(
128 // DEF: some-return-type aAttr, some-return-type bAttr, /*optional*/some-attr-kind cAttr
129 // DEF: odsState.addAttribute(aAttrAttrName(odsState.name), some-const-builder-call(odsBuilder, aAttr));
131 // DEF: void AOp::build(
132 // DEF: ::llvm::ArrayRef<::mlir::NamedAttribute> attributes
133 // DEF: odsState.addAttributes(attributes);
135 // Test the above but with prefix.
137 def Test2_Dialect : Dialect {
139 let cppNamespace = "foobar2";
140 let emitAccessorPrefix = kEmitAccessorPrefix_Prefixed;
142 def AgetOp : Op<Test2_Dialect, "a_get_op", []> {
145 DefaultValuedAttr<SomeAttr, "4.2">:$bAttr,
146 OptionalAttr<SomeAttr>:$cAttr
150 // DECL-LABEL: AgetOp declarations
152 // Test attribute name methods
155 // DECL: static ::llvm::ArrayRef<::llvm::StringRef> getAttributeNames()
156 // DECL-NEXT: static ::llvm::StringRef attrNames[] =
157 // DECL-SAME: {::llvm::StringRef("aAttr"), ::llvm::StringRef("bAttr"), ::llvm::StringRef("cAttr")};
158 // DECL-NEXT: return ::llvm::makeArrayRef(attrNames);
160 // DECL: ::mlir::StringAttr getAAttrAttrName()
161 // DECL-NEXT: return getAttributeNameForIndex(0);
162 // DECL: ::mlir::StringAttr getAAttrAttrName(::mlir::OperationName name)
163 // DECL-NEXT: return getAttributeNameForIndex(name, 0);
165 // DECL: ::mlir::StringAttr getBAttrAttrName()
166 // DECL-NEXT: return getAttributeNameForIndex(1);
167 // DECL: ::mlir::StringAttr getBAttrAttrName(::mlir::OperationName name)
168 // DECL-NEXT: return getAttributeNameForIndex(name, 1);
170 // DECL: ::mlir::StringAttr getCAttrAttrName()
171 // DECL-NEXT: return getAttributeNameForIndex(2);
172 // DECL: ::mlir::StringAttr getCAttrAttrName(::mlir::OperationName name)
173 // DECL-NEXT: return getAttributeNameForIndex(name, 2);
175 // DEF-LABEL: AgetOp definitions
177 // Test verify method
180 // DEF: ::mlir::LogicalResult AgetOpAdaptor::verify
181 // DEF: auto tblgen_aAttr = odsAttrs.get("aAttr");
182 // DEF-NEXT: if (!tblgen_aAttr)
183 // DEF-NEXT. return emitError(loc, "'test2.a_get_op' op ""requires attribute 'aAttr'");
184 // DEF: if (tblgen_aAttr && !((some-condition)))
185 // DEF-NEXT: return emitError(loc, "'test2.a_get_op' op ""attribute 'aAttr' failed to satisfy constraint: some attribute kind");
186 // DEF: auto tblgen_bAttr = odsAttrs.get("bAttr");
187 // DEF-NEXT: if (tblgen_bAttr && !((some-condition)))
188 // DEF-NEXT: return emitError(loc, "'test2.a_get_op' op ""attribute 'bAttr' failed to satisfy constraint: some attribute kind");
189 // DEF: auto tblgen_cAttr = odsAttrs.get("cAttr");
190 // DEF-NEXT: if (tblgen_cAttr && !((some-condition)))
191 // DEF-NEXT: return emitError(loc, "'test2.a_get_op' op ""attribute 'cAttr' failed to satisfy constraint: some attribute kind");
193 // Test getter methods
196 // DEF: some-attr-kind AgetOp::getAAttrAttr()
197 // DEF-NEXT: (*this)->getAttr(getAAttrAttrName()).cast<some-attr-kind>()
198 // DEF: some-return-type AgetOp::getAAttr() {
199 // DEF-NEXT: auto attr = getAAttrAttr()
200 // DEF-NEXT: return attr.some-convert-from-storage();
202 // DEF: some-attr-kind AgetOp::getBAttrAttr()
203 // DEF-NEXT: return (*this)->getAttr(getBAttrAttrName()).dyn_cast_or_null<some-attr-kind>()
204 // DEF: some-return-type AgetOp::getBAttr() {
205 // DEF-NEXT: auto attr = getBAttrAttr();
206 // DEF-NEXT: if (!attr)
207 // DEF-NEXT: return some-const-builder-call(::mlir::Builder((*this)->getContext()), 4.2).some-convert-from-storage();
208 // DEF-NEXT: return attr.some-convert-from-storage();
210 // DEF: some-attr-kind AgetOp::getCAttrAttr()
211 // DEF-NEXT: return (*this)->getAttr(getCAttrAttrName()).dyn_cast_or_null<some-attr-kind>()
212 // DEF: ::llvm::Optional<some-return-type> AgetOp::getCAttr() {
213 // DEF-NEXT: auto attr = getCAttrAttr()
214 // DEF-NEXT: return attr ? ::llvm::Optional<some-return-type>(attr.some-convert-from-storage()) : (::llvm::None);
216 // Test setter methods
219 // DEF: void AgetOp::setAAttrAttr(some-attr-kind attr) {
220 // DEF-NEXT: (*this)->setAttr(getAAttrAttrName(), attr);
221 // DEF: void AgetOp::setBAttrAttr(some-attr-kind attr) {
222 // DEF-NEXT: (*this)->setAttr(getBAttrAttrName(), attr);
223 // DEF: void AgetOp::setCAttrAttr(some-attr-kind attr) {
224 // DEF-NEXT: (*this)->setAttr(getCAttrAttrName(), attr);
226 // Test remove methods
229 // DEF: ::mlir::Attribute AgetOp::removeCAttrAttr() {
230 // DEF-NEXT: return (*this)->removeAttr(getCAttrAttrName());
232 // Test build methods
235 // DEF: void AgetOp::build(
236 // DEF: odsState.addAttribute(getAAttrAttrName(odsState.name), aAttr);
237 // DEF: odsState.addAttribute(getBAttrAttrName(odsState.name), bAttr);
239 // DEF-NEXT: odsState.addAttribute(getCAttrAttrName(odsState.name), cAttr);
241 // DEF: void AgetOp::build(
242 // DEF: some-return-type aAttr, some-return-type bAttr, /*optional*/some-attr-kind cAttr
243 // DEF: odsState.addAttribute(getAAttrAttrName(odsState.name), some-const-builder-call(odsBuilder, aAttr));
245 // DEF: void AgetOp::build(
246 // DEF: ::llvm::ArrayRef<::mlir::NamedAttribute> attributes
247 // DEF: odsState.addAttributes(attributes);
249 def SomeTypeAttr : TypeAttrBase<"SomeType", "some type attribute">;
251 def BOp : NS_Op<"b_op", []> {
260 ElementsAttr:$elements_attr,
261 FlatSymbolRefAttr:$function_attr,
262 SomeTypeAttr:$some_type_attr,
263 ArrayAttr:$array_attr,
264 TypedArrayAttrBase<SomeAttr, "SomeAttr array">:$some_attr_array,
270 // Test common attribute kinds' constraints
273 // DEF-LABEL: BOpAdaptor::verify
274 // DEF: if (tblgen_any_attr && !((true)))
275 // DEF: if (tblgen_bool_attr && !((tblgen_bool_attr.isa<::mlir::BoolAttr>())))
276 // DEF: if (tblgen_i32_attr && !(((tblgen_i32_attr.isa<::mlir::IntegerAttr>())) && ((tblgen_i32_attr.cast<::mlir::IntegerAttr>().getType().isSignlessInteger(32)))))
277 // DEF: if (tblgen_i64_attr && !(((tblgen_i64_attr.isa<::mlir::IntegerAttr>())) && ((tblgen_i64_attr.cast<::mlir::IntegerAttr>().getType().isSignlessInteger(64)))))
278 // DEF: if (tblgen_f32_attr && !(((tblgen_f32_attr.isa<::mlir::FloatAttr>())) && ((tblgen_f32_attr.cast<::mlir::FloatAttr>().getType().isF32()))))
279 // DEF: if (tblgen_f64_attr && !(((tblgen_f64_attr.isa<::mlir::FloatAttr>())) && ((tblgen_f64_attr.cast<::mlir::FloatAttr>().getType().isF64()))))
280 // DEF: if (tblgen_str_attr && !((tblgen_str_attr.isa<::mlir::StringAttr>())))
281 // DEF: if (tblgen_elements_attr && !((tblgen_elements_attr.isa<::mlir::ElementsAttr>())))
282 // DEF: if (tblgen_function_attr && !((tblgen_function_attr.isa<::mlir::FlatSymbolRefAttr>())))
283 // DEF: if (tblgen_some_type_attr && !(((tblgen_some_type_attr.isa<::mlir::TypeAttr>())) && ((tblgen_some_type_attr.cast<::mlir::TypeAttr>().getValue().isa<SomeType>()))))
284 // DEF: if (tblgen_array_attr && !((tblgen_array_attr.isa<::mlir::ArrayAttr>())))
285 // DEF: if (tblgen_some_attr_array && !(((tblgen_some_attr_array.isa<::mlir::ArrayAttr>())) && (::llvm::all_of(tblgen_some_attr_array.cast<::mlir::ArrayAttr>(), [&](::mlir::Attribute attr) { return (some-condition); }))))
286 // DEF: if (tblgen_type_attr && !(((tblgen_type_attr.isa<::mlir::TypeAttr>())) && ((tblgen_type_attr.cast<::mlir::TypeAttr>().getValue().isa<::mlir::Type>()))))
288 // Test common attribute kind getters' return types
291 // DEF: ::mlir::Attribute BOp::any_attr()
292 // DEF: bool BOp::bool_attr()
293 // DEF: uint32_t BOp::i32_attr()
294 // DEF: uint64_t BOp::i64_attr()
295 // DEF: ::llvm::APFloat BOp::f32_attr()
296 // DEF: ::llvm::APFloat BOp::f64_attr()
297 // DEF: ::llvm::StringRef BOp::str_attr()
298 // DEF: ::mlir::ElementsAttr BOp::elements_attr()
299 // DEF: ::llvm::StringRef BOp::function_attr()
300 // DEF: SomeType BOp::some_type_attr()
301 // DEF: ::mlir::ArrayAttr BOp::array_attr()
302 // DEF: ::mlir::ArrayAttr BOp::some_attr_array()
303 // DEF: ::mlir::Type BOp::type_attr()
305 // Test building constant values for array attribute kinds
308 def COp : NS_Op<"c_op", []> {
310 DefaultValuedAttr<I32ArrayAttr, "{1, 2}">:$i32_array_attr,
311 DefaultValuedAttr<I64ArrayAttr, "{3, 4}">:$i64_array_attr,
312 DefaultValuedAttr<F32ArrayAttr, "{5.f, 6.f}">:$f32_array_attr,
313 DefaultValuedAttr<F64ArrayAttr, "{7., 8.}">:$f64_array_attr,
314 DefaultValuedAttr<StrArrayAttr, "{\"a\", \"b\"}">:$str_array_attr
318 // DEF-LABEL: COp definitions
319 // DEF: ::mlir::Builder((*this)->getContext()).getI32ArrayAttr({1, 2})
320 // DEF: ::mlir::Builder((*this)->getContext()).getI64ArrayAttr({3, 4})
321 // DEF: ::mlir::Builder((*this)->getContext()).getF32ArrayAttr({5.f, 6.f})
322 // DEF: ::mlir::Builder((*this)->getContext()).getF64ArrayAttr({7., 8.})
323 // DEF: ::mlir::Builder((*this)->getContext()).getStrArrayAttr({"a", "b"})
326 // Test builder method which takes unwrapped values for attributes
329 def I32Case5: I32EnumAttrCase<"case5", 5>;
330 def I32Case10: I32EnumAttrCase<"case10", 10>;
332 def SomeI32Enum: I32EnumAttr<
333 "SomeI32Enum", "", [I32Case5, I32Case10]>;
335 def DOp : NS_Op<"d_op", []> {
341 SomeI32Enum:$enum_attr,
342 DefaultValuedAttr<I32Attr, "42">:$dv_i32_attr,
343 DefaultValuedAttr<F64Attr, "8.">:$dv_f64_attr,
344 DefaultValuedStrAttr<StrAttr, "abc">:$dv_str_attr,
345 DefaultValuedAttr<BoolAttr, "true">:$dv_bool_attr,
346 DefaultValuedAttr<SomeI32Enum, "::SomeI32Enum::case5">:$dv_enum_attr
350 // DECL-LABEL: DOp declarations
351 // DECL: static void build({{.*}}, uint32_t i32_attr, ::llvm::APFloat f64_attr, ::llvm::StringRef str_attr, bool bool_attr, ::SomeI32Enum enum_attr, uint32_t dv_i32_attr, ::llvm::APFloat dv_f64_attr, ::llvm::StringRef dv_str_attr = "abc", bool dv_bool_attr = true, ::SomeI32Enum dv_enum_attr = ::SomeI32Enum::case5)
353 // DEF-LABEL: DOp definitions
354 // DEF: odsState.addAttribute(str_attrAttrName(odsState.name), odsBuilder.getStringAttr(str_attr));
355 // DEF: odsState.addAttribute(dv_str_attrAttrName(odsState.name), odsBuilder.getStringAttr(dv_str_attr));
357 // Test derived type attr.
359 def DerivedTypeAttrOp : NS_Op<"derived_type_attr_op", []> {
360 let results = (outs AnyTensor:$output);
361 DerivedTypeAttr element_dtype = DerivedTypeAttr<"return output().getType();">;
364 // DECL: class DerivedTypeAttrOp : public ::mlir::Op
365 // DECL-SAME: DerivedAttributeOpInterface::Trait
366 // DECL: static bool isDerivedAttribute
367 // DEF: bool DerivedTypeAttrOp::isDerivedAttribute(::llvm::StringRef name) {
368 // DEF: if (name == "element_dtype") return true;
369 // DEF: return false;
371 // DEF: DerivedTypeAttrOp::materializeDerivedAttributes
373 // Test that only default valued attributes at the end of the arguments
374 // list get default values in the builder signature
377 def EOp : NS_Op<"e_op", []> {
380 DefaultValuedAttr<I32Attr, "42">:$dv_i32_attr,
382 DefaultValuedAttr<F64Attr, "8.">:$dv_f64_attr,
384 DefaultValuedStrAttr<StrAttr, "abc">:$dv_str_attr,
386 DefaultValuedAttr<BoolAttr, "true">:$dv_bool_attr,
387 SomeI32Enum:$enum_attr,
388 DefaultValuedAttr<SomeI32Enum, "::SomeI32Enum::case5">:$dv_enum_attr
392 // DECL-LABEL: EOp declarations
393 // DECL: static void build({{.*}}, uint32_t i32_attr, uint32_t dv_i32_attr, ::llvm::APFloat f64_attr, ::llvm::APFloat dv_f64_attr, ::llvm::StringRef str_attr, ::llvm::StringRef dv_str_attr, bool bool_attr, bool dv_bool_attr, ::SomeI32Enum enum_attr, ::SomeI32Enum dv_enum_attr = ::SomeI32Enum::case5)
396 // Test proper namespacing for AttrDef
399 def NamespaceOp : NS_Op<"namespace_op", []> {
405 // DECL: foobar::SomeAttrAttr AttrDef()
408 // Test mixing operands and attributes in arbitrary order
411 def MixOperandsAndAttrs : NS_Op<"mix_operands_and_attrs", []> {
412 let arguments = (ins F32Attr:$attr, F32:$operand, F32Attr:$otherAttr, F32:$otherArg);
415 def OpWithDefaultAndRegion : NS_Op<"default_with_region", []> {
417 DefaultValuedAttr<BoolAttr, "true">:$dv_bool_attr
419 let regions = (region VariadicRegion<AnyRegion>:$region);
422 // We should not have a default attribute in this case.
424 // DECL-LABEL: OpWithDefaultAndRegion declarations
425 // DECL: static void build({{.*}}, bool dv_bool_attr, unsigned regionCount)
427 def OpWithDefaultAndSuccessor : NS_Op<"default_with_succ", []> {
429 DefaultValuedAttr<BoolAttr, "true">:$dv_bool_attr
431 let successors = (successor VariadicSuccessor<AnySuccessor>:$succ);
434 // We should not have a default attribute in this case.
436 // DECL-LABEL: OpWithDefaultAndSuccessor declarations
437 // DECL: static void build({{.*}}, bool dv_bool_attr, ::mlir::BlockRange succ)
439 // DEF-LABEL: MixOperandsAndAttrs definitions
440 // DEF-DAG: ::mlir::Value MixOperandsAndAttrs::operand()
441 // DEF-DAG: ::mlir::Value MixOperandsAndAttrs::otherArg()
442 // DEF-DAG: void MixOperandsAndAttrs::build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, ::mlir::FloatAttr attr, ::mlir::Value operand, ::mlir::FloatAttr otherAttr, ::mlir::Value otherArg)
443 // DEF-DAG: ::llvm::APFloat MixOperandsAndAttrs::attr()
444 // DEF-DAG: ::llvm::APFloat MixOperandsAndAttrs::otherAttr()
446 // Test unit attributes.
449 def UnitAttrOp : NS_Op<"unit_attr_op", []> {
450 let arguments = (ins UnitAttr:$attr);
453 // DEF-LABEL: UnitAttrOp definitions
454 // DEF: bool UnitAttrOp::attr() {
455 // DEF: return {{.*}} != nullptr
457 // DEF: ::mlir::Attribute UnitAttrOp::removeAttrAttr() {
458 // DEF-NEXT: (*this)->removeAttr(attrAttrName());
460 // DEF: build(::mlir::OpBuilder &odsBuilder, ::mlir::OperationState &odsState, /*optional*/::mlir::UnitAttr attr)
463 // Test elementAttr field of TypedArrayAttr.
466 def SomeTypedArrayAttr : TypedArrayAttrBase<SomeAttr, "SomeAttr array">;
468 // RECORD-LABEL: def SomeTypedArrayAttr
469 // RECORD: Attr elementAttr = SomeAttr;
471 def Test_Dialect_2 : Dialect {
472 let name = "dialect_2";
474 def MyStruct : StructAttr<"MyStruct", Test_Dialect_2,
475 [StructFieldAttr<"potatoes", I64ElementsAttr>]> {
476 let summary = "A structure describing a number of potatoes.";
479 def StructAttrOp : NS_Op<"struct_attr_op", []> {
485 // DECL: dialect_2::MyStruct potatoes();