Merge pull request #2581 from kbrunham-intel/fix/2008
Fix formatter abort on non-ANSI wire signed ports
diff --git a/verible/verilog/formatting/formatter_test.cc b/verible/verilog/formatting/formatter_test.cc
index 61950a0..5205a01 100644
--- a/verible/verilog/formatting/formatter_test.cc
+++ b/verible/verilog/formatting/formatter_test.cc
@@ -21003,6 +21003,114 @@
}
}
+// Regression for https://github.com/chipsalliance/verible/issues/2008
+// (also https://github.com/chipsalliance/verible/issues/2474 and
+// https://github.com/chipsalliance/verible/issues/2063):
+// Non-ANSI "input wire signed" used to abort in the tree-unwrapper because
+// the CST visited "signed" before "wire", which is the reverse of source
+// order.
+TEST(FormatterEndToEndTest, NonAnsiWireSignedModulePortDoesNotAbort) {
+ static constexpr FormatterTestCase kTestCases[] = {
+ {// Original issue #2008 sample
+ "module uut( sig1 );\n"
+ "\n"
+ "input wire signed [15:0] sig1;\n"
+ "\n"
+ "endmodule\n",
+ "module uut (\n"
+ " sig1\n"
+ ");\n"
+ "\n"
+ " input wire signed [15:0] sig1;\n"
+ "\n"
+ "endmodule\n"},
+ {// Issue #2474 sample
+ "module myModule (\n"
+ " myinput\n"
+ ");\n"
+ "input wire signed [7:0] myInput;\n"
+ "endmodule\n",
+ "module myModule (\n"
+ " myinput\n"
+ ");\n"
+ " input wire signed [7:0] myInput;\n"
+ "endmodule\n"},
+ {// Issue #2063 sample: signed wire with no packed dimensions
+ "module top(a);\n"
+ " input wire signed a;\n"
+ "endmodule\n",
+ "module top (\n"
+ " a\n"
+ ");\n"
+ " input wire signed a;\n"
+ "endmodule\n"},
+ {// Same production with logic instead of wire
+ "module uut(sig1);\n"
+ "input logic signed [15:0] sig1;\n"
+ "endmodule\n",
+ "module uut (\n"
+ " sig1\n"
+ ");\n"
+ " input logic signed [15:0] sig1;\n"
+ "endmodule\n"},
+ {// output / inout net types
+ "module uut(sig1, sig2);\n"
+ "output wire signed [15:0] sig1;\n"
+ "inout wire signed [7:0] sig2;\n"
+ "endmodule\n",
+ "module uut (\n"
+ " sig1,\n"
+ " sig2\n"
+ ");\n"
+ " output wire signed [15:0] sig1;\n"
+ " inout wire signed [7:0] sig2;\n"
+ "endmodule\n"},
+ {// unsigned is the same production
+ "module uut(sig1);\n"
+ "input wire unsigned [15:0] sig1;\n"
+ "endmodule\n",
+ "module uut (\n"
+ " sig1\n"
+ ");\n"
+ " input wire unsigned [15:0] sig1;\n"
+ "endmodule\n"},
+ {// ANSI form already worked; keep as a regression
+ "module uut(input wire signed [15:0] sig1);\n"
+ "endmodule\n",
+ "module uut (\n"
+ " input wire signed [15:0] sig1\n"
+ ");\n"
+ "endmodule\n"},
+ {// Non-ANSI without signed still works
+ "module uut(sig1);\n"
+ "input wire [15:0] sig1;\n"
+ "endmodule\n",
+ "module uut (\n"
+ " sig1\n"
+ ");\n"
+ " input wire [15:0] sig1;\n"
+ "endmodule\n"},
+ {// Non-ANSI signed without net type still works
+ "module uut(sig1);\n"
+ "input signed [15:0] sig1;\n"
+ "endmodule\n",
+ "module uut (\n"
+ " sig1\n"
+ ");\n"
+ " input signed [15:0] sig1;\n"
+ "endmodule\n"},
+ };
+ FormatStyle style; // default column_limit (100)
+ for (const auto &test_case : kTestCases) {
+ VLOG(1) << "code-to-format:\n" << test_case.input << "<EOF>";
+ std::ostringstream stream;
+ const auto status =
+ FormatVerilog(test_case.input, "<filename>", style, stream);
+ EXPECT_OK(status) << status.message();
+ EXPECT_EQ(stream.str(), test_case.expected) << "code:\n" << test_case.input;
+ }
+}
+
} // namespace
} // namespace formatter
} // namespace verilog
diff --git a/verible/verilog/parser/verilog.y b/verible/verilog/parser/verilog.y
index f1c24a8..a6de1a8 100644
--- a/verible/verilog/parser/verilog.y
+++ b/verible/verilog/parser/verilog.y
@@ -5623,15 +5623,23 @@
| port_direction signed_unsigned_opt list_of_module_item_identifiers ';'
{ $$ = MakeTaggedNode(N::kModulePortDeclaration, $1, MakeDataType($2, nullptr, nullptr), $3, $4);}
/* implicit type */
+ /* Keep net/var type before signing so CST leaf order matches source
+ * ("wire signed", not "signed" then "wire"). The formatter walks CST
+ * order and CHECK-fails when a later leaf appears earlier in the file.
+ * Wrap as kDataTypePrimitive like the TK_bit rule so
+ * GetBaseTypeFromDataType still treats child 1 as the type.
+ */
| port_direction port_net_type signed_unsigned_opt decl_dimensions_opt
list_of_identifiers_unpacked_dimensions ';'
{ $$ = MakeTaggedNode(N::kModulePortDeclaration, $1,
- MakeDataType($3, ForwardChildren($2), MakePackedDimensionsNode($4)),
+ MakeDataType(MakeTaggedNode(N::kDataTypePrimitive, $2, $3),
+ MakePackedDimensionsNode($4)),
$5, $6); }
| dir var_type signed_unsigned_opt decl_dimensions_opt
list_of_port_identifiers ';'
{ $$ = MakeTaggedNode(N::kModulePortDeclaration, $1,
- MakeDataType($3, ForwardChildren($2), MakePackedDimensionsNode($4)),
+ MakeDataType(MakeTaggedNode(N::kDataTypePrimitive, $2, $3),
+ MakePackedDimensionsNode($4)),
$5, $6); }
| port_direction TK_bit signed_unsigned_opt decl_dimensions_opt
list_of_identifiers_unpacked_dimensions ';'