diff --git a/mlir/test/mlir-tblgen/attr-or-type-format.td b/mlir/test/mlir-tblgen/attr-or-type-format.td --- a/mlir/test/mlir-tblgen/attr-or-type-format.td +++ b/mlir/test/mlir-tblgen/attr-or-type-format.td @@ -177,6 +177,23 @@ let assemblyFormat = "$a"; } +// Check that the self-type parameter can be referenced without being bound. + +// ATTR-LABEL: Attribute TestHAttr::parse +// ATTR: _result_type = reqType +// ATTR: parseUseType(odsParser, +// ATTR-NEXT: *_result_type + +// ATTR-LABEL: void TestHAttr::print +// ATTR: printUseType(odsPrinter, +// ATTR-NEXT: getType() + +def AttrE : TestAttr<"TestH"> { + let parameters = (ins AttributeSelfTypeParameter<"">:$type); + let mnemonic = "attr_e"; + let assemblyFormat = "custom(ref($type))"; +} + /// Test type parser and printer that mix variables and struct are generated /// correctly. diff --git a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp --- a/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp +++ b/mlir/tools/mlir-tblgen/AttrOrTypeFormatGen.cpp @@ -290,6 +290,12 @@ os.indent(); os << "::mlir::Builder odsBuilder(odsParser.getContext());\n"; + // Store the initial location of the parser. + ctx.addSubst("_loc", "odsLoc"); + os << tgfmt("::llvm::SMLoc $_loc = $_parser.getCurrentLocation();\n" + "(void) $_loc;\n", + &ctx); + // Declare variables to store all of the parameters. Allocated parameters // such as `ArrayRef` and `StringRef` must provide a `storageType`. Store // FailureOr to defer type construction for parameters that are parsed in @@ -298,14 +304,10 @@ for (const AttrOrTypeParameter ¶m : params) { os << formatv("::mlir::FailureOr<{0}> _result_{1};\n", param.getCppStorageType(), param.getName()); + if (auto *selfTypeParam = dyn_cast(¶m)) + genAttrSelfTypeParser(os, ctx, *selfTypeParam); } - // Store the initial location of the parser. - ctx.addSubst("_loc", "odsLoc"); - os << tgfmt("::llvm::SMLoc $_loc = $_parser.getCurrentLocation();\n" - "(void) $_loc;\n", - &ctx); - // Generate call to each parameter parser. for (FormatElement *el : elements) genElementParser(el, ctx, os); @@ -313,8 +315,6 @@ // Emit an assert for each mandatory parameter. Triggering an assert means // the generated parser is incorrect (i.e. there is a bug in this code). for (const AttrOrTypeParameter ¶m : params) { - if (auto *selfTypeParam = dyn_cast(¶m)) - genAttrSelfTypeParser(os, ctx, *selfTypeParam); if (param.isOptional()) continue; os << formatv("assert(::mlir::succeeded(_result_{0}));\n", param.getName()); @@ -1033,7 +1033,7 @@ seenParams.set(idx); // Otherwise, to be referenced, a variable must have been bound. - } else if (!seenParams.test(idx)) { + } else if (!seenParams.test(idx) && !isa(*it)) { return emitError(loc, "parameter '" + name + "' must be bound before it is referenced"); }