From 61cfd24c970cac77d3aab4a4febb041a3d4bd4a9 Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Sat, 28 Feb 2026 02:41:34 -0500 Subject: [PATCH 1/3] [FIRRTL] Allow keywords as identifiers in expressions This change allows FIRRTL keywords like UInt, SInt, String, Integer, Bool, Double, and List to be used as identifiers in expression contexts when they are not followed by '(' or '<'. The lexer now creates special tokens (lp_UInt, langle_UInt, etc.) when these keywords are immediately followed by '(' or '<', allowing the parser to distinguish between: - 'UInt' as an identifier (e.g., wire UInt : UInt<8>) - 'UInt<8>(42)' as an integer literal expression - 'List()' as a list creation expression Both the type parser and expression parser have been updated to handle these new tokens, ensuring that types like 'UInt<8>' and 'List' work correctly in both type and expression contexts. Fixes #7838 AI-assisted-by: Augment (Claude Sonnet 4.5) Signed-off-by: Schuyler Eldridge --- lib/Dialect/FIRRTL/Import/FIRLexer.cpp | 13 ++ lib/Dialect/FIRRTL/Import/FIRLexer.h | 1 + lib/Dialect/FIRRTL/Import/FIRParser.cpp | 188 ++++++++++++++++---- lib/Dialect/FIRRTL/Import/FIRTokenKinds.def | 21 ++- test/Dialect/FIRRTL/parse-basic.fir | 26 ++- 5 files changed, 208 insertions(+), 41 deletions(-) diff --git a/lib/Dialect/FIRRTL/Import/FIRLexer.cpp b/lib/Dialect/FIRRTL/Import/FIRLexer.cpp index 5a60d682fad1..6da18d2d5bd0 100644 --- a/lib/Dialect/FIRRTL/Import/FIRLexer.cpp +++ b/lib/Dialect/FIRRTL/Import/FIRLexer.cpp @@ -419,6 +419,19 @@ FIRToken FIRLexer::lexIdentifierOrKeyword(const char *tokStart) { } } + // Check to see if this is a keyword followed by '<' character. + if (*curPtr == '<') { + FIRToken::Kind kind = llvm::StringSwitch(spelling) +#define TOK_LESSKEYWORD(SPELLING) .Case(#SPELLING, FIRToken::langle_##SPELLING) +#include "FIRTokenKinds.def" + .Default(FIRToken::identifier); +#undef TOK_LESSKEYWORD + if (kind != FIRToken::identifier) { + ++curPtr; + return formToken(kind, tokStart); + } + } + // See if the identifier is a keyword. By default, it is an identifier. FIRToken::Kind kind = llvm::StringSwitch(spelling) #define TOK_KEYWORD(SPELLING) .Case(#SPELLING, FIRToken::kw_##SPELLING) diff --git a/lib/Dialect/FIRRTL/Import/FIRLexer.h b/lib/Dialect/FIRRTL/Import/FIRLexer.h index 08fe16c85d69..d3f254992432 100644 --- a/lib/Dialect/FIRRTL/Import/FIRLexer.h +++ b/lib/Dialect/FIRRTL/Import/FIRLexer.h @@ -35,6 +35,7 @@ class FIRToken { #define TOK_PUNCTUATION(NAME, SPELLING) NAME, #define TOK_KEYWORD(SPELLING) kw_##SPELLING, #define TOK_LPKEYWORD(SPELLING) lp_##SPELLING, +#define TOK_LESSKEYWORD(SPELLING) langle_##SPELLING, #include "FIRTokenKinds.def" }; diff --git a/lib/Dialect/FIRRTL/Import/FIRParser.cpp b/lib/Dialect/FIRRTL/Import/FIRParser.cpp index 6f604e61afd3..2a4af15d6456 100644 --- a/lib/Dialect/FIRRTL/Import/FIRParser.cpp +++ b/lib/Dialect/FIRRTL/Import/FIRParser.cpp @@ -275,6 +275,9 @@ struct FIRParser { template ParseResult parseOptionalWidth(T &result); + // Parse 'intLit' '>' assuming '<' was already consumed. + ParseResult parseWidth(int32_t &result); + // Parse the 'id' grammar, which is an identifier or an allowed keyword. ParseResult parseId(StringRef &result, const Twine &message); ParseResult parseId(StringAttr &result, const Twine &message); @@ -702,6 +705,18 @@ ParseResult FIRParser::parseOptionalWidth(T &result) { return success(); } +/// Parse a width specifier: intLit '>' +/// This is used when the '<' has already been consumed. +ParseResult FIRParser::parseWidth(int32_t &result) { + auto widthLoc = getToken().getLoc(); + if (parseIntLit(result, "expected width") || + parseToken(FIRToken::greater, "expected '>'")) + return failure(); + if (result < 0) + return emitError(widthLoc, "invalid width specifier"), failure(); + return success(); +} + /// id ::= Id | keywordAsId /// /// Parse the 'id' grammar, which is an identifier or an allowed keyword. On @@ -1016,22 +1031,41 @@ ParseResult FIRParser::parseType(FIRRTLType &result, const Twine &message) { break; case FIRToken::kw_UInt: + consumeToken(FIRToken::kw_UInt); + // Width is not present since langle_UInt would have been lexed instead. + result = UIntType::get(getContext(), -1); + break; + case FIRToken::kw_SInt: - case FIRToken::kw_Analog: { + consumeToken(FIRToken::kw_SInt); + // Width is not present since langle_SInt would have been lexed instead. + result = SIntType::get(getContext(), -1); + break; + + case FIRToken::kw_Analog: + consumeToken(FIRToken::kw_Analog); + // Width is not present since langle_Analog would have been lexed instead. + result = AnalogType::get(getContext(), -1); + break; + + case FIRToken::langle_UInt: + case FIRToken::langle_SInt: + case FIRToken::langle_Analog: { + // The '<' has already been consumed by the lexer, so we need to parse + // the mandatory width and the trailing '>'. auto kind = getToken().getKind(); consumeToken(); - // Parse a width specifier if present. int32_t width; - if (parseOptionalWidth(width)) + if (parseWidth(width)) return failure(); - if (kind == FIRToken::kw_SInt) + if (kind == FIRToken::langle_SInt) result = SIntType::get(getContext(), width); - else if (kind == FIRToken::kw_UInt) + else if (kind == FIRToken::langle_UInt) result = UIntType::get(getContext(), width); else { - assert(kind == FIRToken::kw_Analog); + assert(kind == FIRToken::langle_Analog); result = AnalogType::get(getContext(), width); } break; @@ -1219,6 +1253,22 @@ ParseResult FIRParser::parseType(FIRRTLType &result, const Twine &message) { if (requireFeature({4, 0, 0}, "Lists") || parseListType(result)) return failure(); break; + + case FIRToken::langle_List: { + // The '<' has already been consumed by the lexer, so we need to parse + // the element type and the trailing '>'. + if (requireFeature({4, 0, 0}, "Lists")) + return failure(); + consumeToken(); + + PropertyType elementType; + if (parsePropertyType(elementType, "expected List element type") || + parseToken(FIRToken::greater, "expected '>' in List type")) + return failure(); + + result = ListType::get(getContext(), elementType); + break; + } } // Handle postfix vector sizes. @@ -1959,7 +2009,9 @@ struct FIRStmtParser : public FIRParser { ParseResult parsePostFixFieldId(Value &result); ParseResult parsePostFixIntSubscript(Value &result); ParseResult parsePostFixDynamicSubscript(Value &result); - ParseResult parseIntegerLiteralExp(Value &result); + ParseResult + parseIntegerLiteralExp(Value &result, std::optional isSigned = {}, + std::optional allocatedWidth = {}); ParseResult parseListExp(Value &result); ParseResult parseListConcatExp(Value &result); ParseResult parseCatExp(Value &result); @@ -2227,19 +2279,34 @@ ParseResult FIRStmtParser::parseExpImpl(Value &result, const Twine &message, return failure(); break; - case FIRToken::kw_UInt: - case FIRToken::kw_SInt: + case FIRToken::langle_UInt: + case FIRToken::langle_SInt: { + // The '<' has already been consumed by the lexer, so we need to parse + // the mandatory width and '>'. + bool isSigned = getToken().is(FIRToken::langle_SInt); + consumeToken(); + int32_t width; + if (parseWidth(width)) + return failure(); + + // Now parse the '(' intLit ')' part. + if (parseIntegerLiteralExp(result, isSigned, width)) + return failure(); + break; + } + + case FIRToken::lp_UInt: + case FIRToken::lp_SInt: if (parseIntegerLiteralExp(result)) return failure(); break; - case FIRToken::kw_String: { + case FIRToken::lp_String: { if (requireFeature({3, 1, 0}, "Strings")) return failure(); locationProcessor.setLoc(getToken().getLoc()); - consumeToken(FIRToken::kw_String); + consumeToken(FIRToken::lp_String); StringRef spelling; - if (parseToken(FIRToken::l_paren, "expected '(' in String expression") || - parseGetSpelling(spelling) || + if (parseGetSpelling(spelling) || parseToken(FIRToken::string, "expected string literal in String expression") || parseToken(FIRToken::r_paren, "expected ')' in String expression")) @@ -2249,14 +2316,13 @@ ParseResult FIRStmtParser::parseExpImpl(Value &result, const Twine &message, builder, attr, builder.getType(), attr); break; } - case FIRToken::kw_Integer: { + case FIRToken::lp_Integer: { if (requireFeature({3, 1, 0}, "Integers")) return failure(); locationProcessor.setLoc(getToken().getLoc()); - consumeToken(FIRToken::kw_Integer); + consumeToken(FIRToken::lp_Integer); APInt value; - if (parseToken(FIRToken::l_paren, "expected '(' in Integer expression") || - parseIntLit(value, "expected integer literal in Integer expression") || + if (parseIntLit(value, "expected integer literal in Integer expression") || parseToken(FIRToken::r_paren, "expected ')' in Integer expression")) return failure(); APSInt apint(value, /*isUnsigned=*/false); @@ -2265,13 +2331,11 @@ ParseResult FIRStmtParser::parseExpImpl(Value &result, const Twine &message, builder.getType(), apint); break; } - case FIRToken::kw_Bool: { + case FIRToken::lp_Bool: { if (requireFeature(missingSpecFIRVersion, "Bools")) return failure(); locationProcessor.setLoc(getToken().getLoc()); - consumeToken(FIRToken::kw_Bool); - if (parseToken(FIRToken::l_paren, "expected '(' in Bool expression")) - return failure(); + consumeToken(FIRToken::lp_Bool); bool value; if (consumeIf(FIRToken::kw_true)) value = true; @@ -2286,13 +2350,11 @@ ParseResult FIRStmtParser::parseExpImpl(Value &result, const Twine &message, builder, attr, builder.getType(), value); break; } - case FIRToken::kw_Double: { + case FIRToken::lp_Double: { if (requireFeature(missingSpecFIRVersion, "Doubles")) return failure(); locationProcessor.setLoc(getToken().getLoc()); - consumeToken(FIRToken::kw_Double); - if (parseToken(FIRToken::l_paren, "expected '(' in Double expression")) - return failure(); + consumeToken(FIRToken::lp_Double); auto spelling = getTokenSpelling(); if (parseToken(FIRToken::floatingpoint, "expected floating point in Double expression") || @@ -2308,7 +2370,8 @@ ParseResult FIRStmtParser::parseExpImpl(Value &result, const Twine &message, builder, attr, builder.getType(), attr); break; } - case FIRToken::kw_List: { + case FIRToken::lp_List: + case FIRToken::langle_List: { if (requireFeature({4, 0, 0}, "Lists")) return failure(); if (isLeadingStmt) @@ -2359,6 +2422,13 @@ ParseResult FIRStmtParser::parseExpImpl(Value &result, const Twine &message, // try them. case FIRToken::identifier: // exp ::= id case FIRToken::literal_identifier: + case FIRToken::kw_UInt: + case FIRToken::kw_SInt: + case FIRToken::kw_String: + case FIRToken::kw_Integer: + case FIRToken::kw_Bool: + case FIRToken::kw_Double: + case FIRToken::kw_List: default: { StringRef name; auto loc = getToken().getLoc(); @@ -2596,17 +2666,48 @@ ParseResult FIRStmtParser::parsePostFixDynamicSubscript(Value &result) { /// integer-literal-exp ::= 'UInt' optional-width '(' intLit ')' /// ::= 'SInt' optional-width '(' intLit ')' -ParseResult FIRStmtParser::parseIntegerLiteralExp(Value &result) { - bool isSigned = getToken().is(FIRToken::kw_SInt); +/// +/// If isSigned and allocatedWidth are provided, it means the type and width +/// were already parsed (e.g., from a langle_UInt token) and should be used +/// instead of parsing them from the token stream. +ParseResult +FIRStmtParser::parseIntegerLiteralExp(Value &result, + std::optional isSignedOpt, + std::optional allocatedWidth) { auto loc = getToken().getLoc(); - consumeToken(); - // Parse a width specifier if present. + // Determine signedness and whether '(' was already consumed. + bool isSigned; + bool hasLParen; + if (isSignedOpt) { + // Signedness was provided by caller (from langle_ token). + isSigned = *isSignedOpt; + hasLParen = false; + } else { + // Determine from current token (lp_ token). + isSigned = getToken().is(FIRToken::lp_SInt); + hasLParen = getToken().isAny(FIRToken::lp_UInt, FIRToken::lp_SInt); + consumeToken(); + } + + // Parse a width specifier if not already provided. int32_t width; APInt value; - if (parseOptionalWidth(width) || - parseToken(FIRToken::l_paren, "expected '(' in integer expression") || - parseIntLit(value, "expected integer value") || + + if (allocatedWidth) { + width = *allocatedWidth; + } else { + if (parseOptionalWidth(width)) + return failure(); + } + + // If we consumed an lp_ token, the '(' was already consumed by the lexer. + // Otherwise, we need to parse it. + if (!hasLParen && + parseToken(FIRToken::l_paren, "expected '(' in integer expression")) + return failure(); + + if (parseIntLit(value, "expected integer value") || parseToken(FIRToken::r_paren, "expected ')' in integer expression")) return failure(); @@ -2640,13 +2741,24 @@ ParseResult FIRStmtParser::parseIntegerLiteralExp(Value &result) { /// list-exp ::= list-type '(' exp* ')' ParseResult FIRStmtParser::parseListExp(Value &result) { auto loc = getToken().getLoc(); - FIRRTLType type; - if (parseListType(type)) + bool hasLAngle = getToken().is(FIRToken::langle_List); + bool hasLParen = getToken().is(FIRToken::lp_List); + consumeToken(); + + PropertyType elementType; + // If we consumed a langle_ token, the '<' was already consumed by the lexer. + if (!hasLAngle && parseToken(FIRToken::less, "expected '<' in List type")) return failure(); - auto listType = type_cast(type); - auto elementType = listType.getElementType(); - if (parseToken(FIRToken::l_paren, "expected '(' in List expression")) + if (parsePropertyType(elementType, "expected List element type") || + parseToken(FIRToken::greater, "expected '>' in List type")) + return failure(); + + auto listType = ListType::get(getContext(), elementType); + + // If we consumed an lp_ token, the '(' was already consumed by the lexer. + if (!hasLParen && + parseToken(FIRToken::l_paren, "expected '(' in List expression")) return failure(); SmallVector operands; diff --git a/lib/Dialect/FIRRTL/Import/FIRTokenKinds.def b/lib/Dialect/FIRRTL/Import/FIRTokenKinds.def index 28485ce50ae5..9d4fc3943143 100644 --- a/lib/Dialect/FIRRTL/Import/FIRTokenKinds.def +++ b/lib/Dialect/FIRRTL/Import/FIRTokenKinds.def @@ -14,7 +14,7 @@ #if !defined(TOK_MARKER) && !defined(TOK_IDENTIFIER) && \ !defined(TOK_LITERAL) && !defined(TOK_PUNCTUATION) && \ !defined(TOK_KEYWORD) && !defined(TOK_LPKEYWORD) && \ - !defined(TOK_LPKEYWORD_PRIM) + !defined(TOK_LESSKEYWORD) && !defined(TOK_LPKEYWORD_PRIM) #error Must define one of the TOK_ macros. #endif @@ -41,6 +41,9 @@ VERSION, FEATURE) \ TOK_LPKEYWORD(SPELLING) #endif +#ifndef TOK_LESSKEYWORD +#define TOK_LESSKEYWORD(SPELLING) +#endif // Markers TOK_MARKER(eof) @@ -199,6 +202,21 @@ TOK_LPKEYWORD(intrinsic) TOK_LPKEYWORD(cat) TOK_LPKEYWORD(unsafe_domain_cast) +TOK_LPKEYWORD(UInt) +TOK_LPKEYWORD(SInt) +TOK_LPKEYWORD(String) +TOK_LPKEYWORD(Integer) +TOK_LPKEYWORD(Bool) +TOK_LPKEYWORD(Double) +TOK_LPKEYWORD(List) + +// Keywords when followed by a '<'. These turn "foo" into +// FIRToken::langle_foo enums. +TOK_LESSKEYWORD(UInt) +TOK_LESSKEYWORD(SInt) +TOK_LESSKEYWORD(Analog) +TOK_LESSKEYWORD(List) + // These are for LPKEYWORD cases that correspond to a primitive operation. TOK_LPKEYWORD_PRIM(add, AddPrimOp, 2, 0, FIRVersion(0, 0, 0), "Base") TOK_LPKEYWORD_PRIM(and, AndPrimOp, 2, 0, FIRVersion(0, 0, 0), "Base") @@ -253,4 +271,5 @@ TOK_LPKEYWORD_PRIM(integer_shl, IntegerShlOp, 2, 0, FIRVersion(3, 1, 0), #undef TOK_PUNCTUATION #undef TOK_KEYWORD #undef TOK_LPKEYWORD +#undef TOK_LESSKEYWORD #undef TOK_LPKEYWORD_PRIM diff --git a/test/Dialect/FIRRTL/parse-basic.fir b/test/Dialect/FIRRTL/parse-basic.fir index 473f4fbfbef3..de688244095c 100644 --- a/test/Dialect/FIRRTL/parse-basic.fir +++ b/test/Dialect/FIRRTL/parse-basic.fir @@ -383,8 +383,8 @@ circuit MyModule : ; CHECK: firrtl.circuit "MyModule" ; CHECK: firrtl.attach %a8, %a8, %a8 : attach (a8, a8, a8) - wire pred: UInt <1> - wire en: UInt <1> + wire pred: UInt<1> + wire en: UInt<1> connect pred, eq(i8, i8) connect en, not(reset) ; CHECK: firrtl.assert %clock, %pred, %en, "X equals Y when Z is valid" : !firrtl.clock, !firrtl.uint<1>, !firrtl.uint<1> {eventControl = 0 : i32, isConcurrent = false} @@ -2298,3 +2298,25 @@ circuit UnknownProperties: ; CHECK: %[[#INSTANCE:]] = firrtl.unknown : !firrtl.class<@Foo()> ; CHECK-NEXT: firrtl.propassign %c, %[[#INSTANCE]] : !firrtl.class<@Foo()> propassign c, Unknown: Inst + +; // ----- + +; Test that keywords can be used as identifiers when not followed by '(' or '<' +; and as expressions when followed by '(' or '<' + +FIRRTL version 4.0.0 +circuit KeywordIdentifiers : + public module KeywordIdentifiers : + ; CHECK-LABEL: firrtl.module @KeywordIdentifiers + + ; Test UInt and SInt as identifiers + ; CHECK: %UInt = firrtl.wire + ; CHECK: %SInt = firrtl.wire + wire UInt : UInt<8> + wire SInt : SInt<8> + + ; Test UInt<>() and SInt<>() as expressions + ; CHECK: firrtl.constant 42 + ; CHECK: firrtl.constant -10 + connect UInt, UInt<8>(42) + connect SInt, SInt<8>(-10) From a772db54585d0565022a826814eed3f96aa90e55 Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Mon, 2 Mar 2026 13:01:03 -0500 Subject: [PATCH 2/3] fixup! [FIRRTL] Allow keywords as identifiers in expressions --- lib/Dialect/FIRRTL/Import/FIRParser.cpp | 31 ++++++++++--------------- 1 file changed, 12 insertions(+), 19 deletions(-) diff --git a/lib/Dialect/FIRRTL/Import/FIRParser.cpp b/lib/Dialect/FIRRTL/Import/FIRParser.cpp index 2a4af15d6456..4006b8aa85d0 100644 --- a/lib/Dialect/FIRRTL/Import/FIRParser.cpp +++ b/lib/Dialect/FIRRTL/Import/FIRParser.cpp @@ -2010,7 +2010,7 @@ struct FIRStmtParser : public FIRParser { ParseResult parsePostFixIntSubscript(Value &result); ParseResult parsePostFixDynamicSubscript(Value &result); ParseResult - parseIntegerLiteralExp(Value &result, std::optional isSigned = {}, + parseIntegerLiteralExp(Value &result, bool isSigned, std::optional allocatedWidth = {}); ParseResult parseListExp(Value &result); ParseResult parseListConcatExp(Value &result); @@ -2296,8 +2296,11 @@ ParseResult FIRStmtParser::parseExpImpl(Value &result, const Twine &message, } case FIRToken::lp_UInt: + if (parseIntegerLiteralExp(result, /*isSigned=*/false)) + return failure(); + break; case FIRToken::lp_SInt: - if (parseIntegerLiteralExp(result)) + if (parseIntegerLiteralExp(result, /*isSigned=*/true)) return failure(); break; case FIRToken::lp_String: { @@ -2667,28 +2670,18 @@ ParseResult FIRStmtParser::parsePostFixDynamicSubscript(Value &result) { /// integer-literal-exp ::= 'UInt' optional-width '(' intLit ')' /// ::= 'SInt' optional-width '(' intLit ')' /// -/// If isSigned and allocatedWidth are provided, it means the type and width -/// were already parsed (e.g., from a langle_UInt token) and should be used -/// instead of parsing them from the token stream. +/// If allocatedWidth is provided, it means the width was already parsed +/// (e.g., from a langle_UInt token) and should be used instead of parsing +/// it from the token stream. ParseResult -FIRStmtParser::parseIntegerLiteralExp(Value &result, - std::optional isSignedOpt, +FIRStmtParser::parseIntegerLiteralExp(Value &result, bool isSigned, std::optional allocatedWidth) { auto loc = getToken().getLoc(); - // Determine signedness and whether '(' was already consumed. - bool isSigned; - bool hasLParen; - if (isSignedOpt) { - // Signedness was provided by caller (from langle_ token). - isSigned = *isSignedOpt; - hasLParen = false; - } else { - // Determine from current token (lp_ token). - isSigned = getToken().is(FIRToken::lp_SInt); - hasLParen = getToken().isAny(FIRToken::lp_UInt, FIRToken::lp_SInt); + // Determine if '(' was already consumed by the lexer. + bool hasLParen = getToken().isAny(FIRToken::lp_UInt, FIRToken::lp_SInt); + if (hasLParen) consumeToken(); - } // Parse a width specifier if not already provided. int32_t width; From e32a91e88653c71d4bebad89cc8c73e40e1d1271 Mon Sep 17 00:00:00 2001 From: Schuyler Eldridge Date: Mon, 2 Mar 2026 13:28:09 -0500 Subject: [PATCH 3/3] fixup! [FIRRTL] Allow keywords as identifiers in expressions --- lib/Dialect/FIRRTL/Import/FIRParser.cpp | 33 +------------------------ 1 file changed, 1 insertion(+), 32 deletions(-) diff --git a/lib/Dialect/FIRRTL/Import/FIRParser.cpp b/lib/Dialect/FIRRTL/Import/FIRParser.cpp index 4006b8aa85d0..50b17c0fbba9 100644 --- a/lib/Dialect/FIRRTL/Import/FIRParser.cpp +++ b/lib/Dialect/FIRRTL/Import/FIRParser.cpp @@ -271,10 +271,6 @@ struct FIRParser { // Parse 'verLit' into specified value ParseResult parseVersionLit(const Twine &message); - // Parse ('<' intLit '>')? setting result to -1 if not present. - template - ParseResult parseOptionalWidth(T &result); - // Parse 'intLit' '>' assuming '<' was already consumed. ParseResult parseWidth(int32_t &result); @@ -685,26 +681,6 @@ ParseResult FIRParser::parseVersionLit(const Twine &message) { return success(); } -// optional-width ::= ('<' intLit '>')? -// -// This returns with result equal to -1 if not present. -template -ParseResult FIRParser::parseOptionalWidth(T &result) { - if (!consumeIf(FIRToken::less)) - return result = -1, success(); - - // Parse a width specifier if present. - auto widthLoc = getToken().getLoc(); - if (parseIntLit(result, "expected width") || - parseToken(FIRToken::greater, "expected >")) - return failure(); - - if (result < 0) - return emitError(widthLoc, "invalid width specifier"), failure(); - - return success(); -} - /// Parse a width specifier: intLit '>' /// This is used when the '<' has already been consumed. ParseResult FIRParser::parseWidth(int32_t &result) { @@ -2684,16 +2660,9 @@ FIRStmtParser::parseIntegerLiteralExp(Value &result, bool isSigned, consumeToken(); // Parse a width specifier if not already provided. - int32_t width; + int32_t width = allocatedWidth.value_or(-1); APInt value; - if (allocatedWidth) { - width = *allocatedWidth; - } else { - if (parseOptionalWidth(width)) - return failure(); - } - // If we consumed an lp_ token, the '(' was already consumed by the lexer. // Otherwise, we need to parse it. if (!hasLParen &&