Merge origin/master into fix/2544 Resolve formatter_test.cc conflict by keeping MacroBeforeCloseParenFormatEquivalent alongside EndElseIfWithEOLCommentConverges from merged #2541.
diff --git a/verible/verilog/analysis/verilog-equivalence.cc b/verible/verilog/analysis/verilog-equivalence.cc index f8a47d0..026c197 100644 --- a/verible/verilog/analysis/verilog-equivalence.cc +++ b/verible/verilog/analysis/verilog-equivalence.cc
@@ -167,11 +167,21 @@ DiffStatus diff_status = DiffStatus::kEquivalent; auto recursive_comparator = [&](const TokenSequence::const_iterator l, const TokenSequence::const_iterator r) { + // Some token enums differ only by surrounding whitespace (e.g. whether a + // macro or ')' ends a line). Treat those pairs as matching enums when the + // spelling is unchanged so FormatEquivalent tolerates re-wrapping. + const bool whitespace_dependent_enum_match = + ((l->token_enum() == verilog_tokentype::MacroCallCloseToEndLine && + r->text() == ")") || + (r->token_enum() == verilog_tokentype::MacroCallCloseToEndLine && + l->text() == ")") || + ((l->token_enum() == verilog_tokentype::MacroIdentifier || + l->token_enum() == verilog_tokentype::MacroIdItem) && + (r->token_enum() == verilog_tokentype::MacroIdentifier || + r->token_enum() == verilog_tokentype::MacroIdItem) && + l->text() == r->text())); if (l->token_enum() != r->token_enum() && - !((l->token_enum() == verilog_tokentype::MacroCallCloseToEndLine && - r->text() == ")") || - (r->token_enum() == verilog_tokentype::MacroCallCloseToEndLine && - l->text() == ")"))) { + !whitespace_dependent_enum_match) { if (errstream != nullptr) { *errstream << "Mismatched token enums. got: "; token_printer(*l, *errstream); @@ -258,6 +268,16 @@ (r.text() == ")"))) { return true; } + // MacroIdentifier vs MacroIdItem depends only on whether the macro + // ends the line (see POST_MACRO_ID in verilog.lex). Spelling-equal + // macros are format-equivalent across that reclassification. + if ((l.token_enum() == verilog_tokentype::MacroIdentifier || + l.token_enum() == verilog_tokentype::MacroIdItem) && + (r.token_enum() == verilog_tokentype::MacroIdentifier || + r.token_enum() == verilog_tokentype::MacroIdItem) && + l.text() == r.text()) { + return true; + } return l.EquivalentWithoutLocation(r); }, errstream);
diff --git a/verible/verilog/analysis/verilog-equivalence_test.cc b/verible/verilog/analysis/verilog-equivalence_test.cc index 90b0ee1..1cb9436 100644 --- a/verible/verilog/analysis/verilog-equivalence_test.cc +++ b/verible/verilog/analysis/verilog-equivalence_test.cc
@@ -255,6 +255,21 @@ } } +// MacroIdentifier vs MacroIdItem depends on whether the macro ends the line. +TEST(FormatEquivalentTest, EquivalenceOfMacroIdentifierAndMacroIdItem) { + const char *kSameSpelling[] = { + "assign x = f(`TOKEN);\n", + "assign x = f(\n`TOKEN\n);\n", + }; + ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kEquivalent, + kSameSpelling[0], kSameSpelling[1]); + + // Different macro names remain different. + ExpectCompareWithErrstream(FormatEquivalent, DiffStatus::kDifferent, + "assign x = f(`TOKEN);\n", + "assign x = f(`OTHER);\n"); +} + TEST(FormatEquivalentTest, DiagnosticMismatch) { const char *kTestCases[] = { "module foo;\n",
diff --git a/verible/verilog/formatting/formatter_test.cc b/verible/verilog/formatting/formatter_test.cc index dce9f05..5501c58 100644 --- a/verible/verilog/formatting/formatter_test.cc +++ b/verible/verilog/formatting/formatter_test.cc
@@ -19380,6 +19380,24 @@ } } +// Regression for https://github.com/chipsalliance/verible/issues/2544: +// Wrapping a $bits(...)'(...) cast may leave `MACRO at EOL, reclassifying +// MacroIdentifier as MacroIdItem. FormatEquivalent must accept that, and +// formatting must still pass verification. +TEST(FormatterEndToEndTest, MacroBeforeCloseParenFormatEquivalent) { + static constexpr std::string_view kInput = + "module m;\n" + " assign result_value = $bits(result_value)'( " + "compare_bytes(input_data[DATA_WIDTH_INT-1:0], " + "input_datak[STROBE_WIDTH_INT-1:0], `TOKEN_BYTE) );\n" + "endmodule\n"; + FormatStyle style; + std::ostringstream stream; + const auto status = FormatVerilog(kInput, "<filename>", style, stream); + EXPECT_OK(status) << status.message(); + EXPECT_THAT(stream.str(), testing::HasSubstr("`TOKEN_BYTE")); +} + // Regression for https://github.com/chipsalliance/verible/issues/2540: // Trailing EOL comment after `end` before `else if` must not change whether // the else-if assignment stays on one line across re-format (convergence).