diff --git a/source/parsing/Lexer.cpp b/source/parsing/Lexer.cpp index 6d76df7c9..775f55808 100644 --- a/source/parsing/Lexer.cpp +++ b/source/parsing/Lexer.cpp @@ -1070,7 +1070,6 @@ Token Lexer::lexApostrophe() { return create(TokenKind::UnbasedUnsizedLiteral, logic_t::x); case 'Z': case 'z': - case '?': advance(); return create(TokenKind::UnbasedUnsizedLiteral, logic_t::z); case 's': diff --git a/source/parsing/Parser_expressions.cpp b/source/parsing/Parser_expressions.cpp index 6a7759cb0..123b7910b 100644 --- a/source/parsing/Parser_expressions.cpp +++ b/source/parsing/Parser_expressions.cpp @@ -91,7 +91,11 @@ ExpressionSyntax& Parser::parseSubExpression(bitmask options, if (isNewExpr(leftOperand)) return parseNewExpression(leftOperand->as(), options); - leftOperand = &parsePostfixExpression(*leftOperand, options); + // Don't try to parse postfix if we didn't find a valid primary to begin with. + if (leftOperand->kind != SyntaxKind::IdentifierName || + !leftOperand->as().identifier.isMissing()) { + leftOperand = &parsePostfixExpression(*leftOperand, options); + } } options &= ~ExpressionOptions::AllowSuperNewCall; diff --git a/tests/unittests/parsing/ExpressionParsingTests.cpp b/tests/unittests/parsing/ExpressionParsingTests.cpp index 51662a664..797da290a 100644 --- a/tests/unittests/parsing/ExpressionParsingTests.cpp +++ b/tests/unittests/parsing/ExpressionParsingTests.cpp @@ -978,3 +978,16 @@ endclass REQUIRE(diagnostics.size() == 1); CHECK(diagnostics[0].code == diag::WrongLanguageVersion); } + +TEST_CASE("Unbased unsized question mark parsing") { + auto& text = R"( +module bug(input logic [1:0] a, input logic s, output logic [1:0]y); + assign y = s? a: '?; +endmodule +)"; + + parseCompilationUnit(text); + + REQUIRE(diagnostics.size() == 1); + CHECK(diagnostics[0].code == diag::ExpectedExpression); +}