From f2c2d73f36d7aaef90ded549143d1ee0c4d4a9f5 Mon Sep 17 00:00:00 2001 From: Zachary Snow Date: Mon, 14 Jun 2021 15:32:01 -0400 Subject: [PATCH] sv: fix up end label checking - disallow [gen]blocks with an end label but not begin label - check validity of module end label - fix memory leak of package name and end label - fix memory leak of module end label --- frontends/verilog/verilog_parser.y | 25 +++++++++++++------ tests/simple/matching_end_labels.sv | 29 ++++++++++++++++++++++ tests/verilog/block_end_label_only.ys | 9 +++++++ tests/verilog/block_end_label_wrong.ys | 9 +++++++ tests/verilog/gen_block_end_label_only.ys | 9 +++++++ tests/verilog/gen_block_end_label_wrong.ys | 9 +++++++ tests/verilog/module_end_label.ys | 15 +++++++++++ 7 files changed, 98 insertions(+), 7 deletions(-) create mode 100644 tests/simple/matching_end_labels.sv create mode 100644 tests/verilog/block_end_label_only.ys create mode 100644 tests/verilog/block_end_label_wrong.ys create mode 100644 tests/verilog/gen_block_end_label_only.ys create mode 100644 tests/verilog/gen_block_end_label_wrong.ys create mode 100644 tests/verilog/module_end_label.ys diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 1a76d0dea..120a8bca3 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -235,6 +235,16 @@ static void rewriteAsMemoryNode(AstNode *node, AstNode *rangeNode) node->children.push_back(rangeNode); } +static void checkLabelsMatch(const char *element, const std::string *before, const std::string *after) +{ + if (!before && after) + frontend_verilog_yyerror("%s missing where end label (%s) was given.", + element, after->c_str() + 1); + if (before && after && *before != *after) + frontend_verilog_yyerror("%s (%s) and end label (%s) don't match.", + element, before->c_str() + 1, after->c_str() + 1); +} + %} %define api.prefix {frontend_verilog_yy} @@ -457,7 +467,6 @@ module: port_counter = 0; mod->str = *$4; append_attr(mod, $1); - delete $4; } module_para_opt module_args_opt ';' module_body TOK_ENDMODULE opt_label { if (port_stubs.size() != 0) frontend_verilog_yyerror("Missing details for module port `%s'.", @@ -465,7 +474,10 @@ module: SET_AST_NODE_LOC(ast_stack.back(), @2, @$); ast_stack.pop_back(); log_assert(ast_stack.size() == 1); + checkLabelsMatch("Module name", $4, $11); current_ast_mod = NULL; + delete $4; + delete $11; exitTypeScope(); }; @@ -583,9 +595,10 @@ package: append_attr(mod, $1); } ';' package_body TOK_ENDPACKAGE opt_label { ast_stack.pop_back(); - if ($4 != NULL && $9 != NULL && *$4 != *$9) - frontend_verilog_yyerror("Package name (%s) and end label (%s) don't match.", $4->c_str()+1, $9->c_str()+1); + checkLabelsMatch("Package name", $4, $9); current_ast_mod = NULL; + delete $4; + delete $9; exitTypeScope(); }; @@ -2526,8 +2539,7 @@ behavioral_stmt: node->str = *$4; } behavioral_stmt_list TOK_END opt_label { exitTypeScope(); - if ($4 != NULL && $8 != NULL && *$4 != *$8) - frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $4->c_str()+1, $8->c_str()+1); + checkLabelsMatch("Begin label", $4, $8); AstNode *node = ast_stack.back(); // In SystemVerilog, unnamed blocks with block item declarations // create an implicit hierarchy scope @@ -2863,8 +2875,7 @@ gen_block: ast_stack.push_back(node); } module_gen_body TOK_END opt_label { exitTypeScope(); - if ($3 != NULL && $7 != NULL && *$3 != *$7) - frontend_verilog_yyerror("Begin label (%s) and end label (%s) don't match.", $3->c_str()+1, $7->c_str()+1); + checkLabelsMatch("Begin label", $3, $7); delete $3; delete $7; SET_AST_NODE_LOC(ast_stack.back(), @1, @7); diff --git a/tests/simple/matching_end_labels.sv b/tests/simple/matching_end_labels.sv new file mode 100644 index 000000000..09182ebcf --- /dev/null +++ b/tests/simple/matching_end_labels.sv @@ -0,0 +1,29 @@ +module top( + output reg [7:0] + out1, out2, out3, out4 +); + initial begin + begin : blk1 + reg x; + x = 1; + end + out1 = blk1.x; + begin : blk2 + reg x; + x = 2; + end : blk2 + out2 = blk2.x; + end + if (1) begin + if (1) begin : blk3 + reg x; + assign x = 3; + end + assign out3 = blk3.x; + if (1) begin : blk4 + reg x; + assign x = 4; + end : blk4 + assign out4 = blk4.x; + end +endmodule diff --git a/tests/verilog/block_end_label_only.ys b/tests/verilog/block_end_label_only.ys new file mode 100644 index 000000000..5db1c7879 --- /dev/null +++ b/tests/verilog/block_end_label_only.ys @@ -0,0 +1,9 @@ +logger -expect error "Begin label missing where end label \(incorrect_name\) was given\." 1 +read_verilog -sv <