sv: fix up end label checking
authorZachary Snow <zach@zachjs.com>
Mon, 14 Jun 2021 19:32:01 +0000 (15:32 -0400)
committerZachary Snow <zachary.j.snow@gmail.com>
Thu, 17 Jun 2021 01:48:05 +0000 (21:48 -0400)
- 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
tests/simple/matching_end_labels.sv [new file with mode: 0644]
tests/verilog/block_end_label_only.ys [new file with mode: 0644]
tests/verilog/block_end_label_wrong.ys [new file with mode: 0644]
tests/verilog/gen_block_end_label_only.ys [new file with mode: 0644]
tests/verilog/gen_block_end_label_wrong.ys [new file with mode: 0644]
tests/verilog/module_end_label.ys [new file with mode: 0644]

index 1a76d0dea0b5b44b689a1ba5e1116c20cf0d6e4e..120a8bca3ccaa495e651c033ae89d5486051fb4c 100644 (file)
@@ -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 (file)
index 0000000..09182eb
--- /dev/null
@@ -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 (file)
index 0000000..5db1c78
--- /dev/null
@@ -0,0 +1,9 @@
+logger -expect error "Begin label missing where end label \(incorrect_name\) was given\." 1
+read_verilog -sv <<EOF
+module top;
+initial
+    begin
+        $display("HI");
+    end : incorrect_name
+endmodule
+EOF
diff --git a/tests/verilog/block_end_label_wrong.ys b/tests/verilog/block_end_label_wrong.ys
new file mode 100644 (file)
index 0000000..47dbbe3
--- /dev/null
@@ -0,0 +1,9 @@
+logger -expect error "Begin label \(correct_name\) and end label \(incorrect_name\) don't match\." 1
+read_verilog -sv <<EOF
+module top;
+initial
+    begin : correct_name
+        $display("HI");
+    end : incorrect_name
+endmodule
+EOF
diff --git a/tests/verilog/gen_block_end_label_only.ys b/tests/verilog/gen_block_end_label_only.ys
new file mode 100644 (file)
index 0000000..60dc047
--- /dev/null
@@ -0,0 +1,9 @@
+logger -expect error "Begin label missing where end label \(incorrect_name\) was given\." 1
+read_verilog -sv <<EOF
+module top;
+if (1)
+    begin
+        initial $display("HI");
+    end : incorrect_name
+endmodule
+EOF
diff --git a/tests/verilog/gen_block_end_label_wrong.ys b/tests/verilog/gen_block_end_label_wrong.ys
new file mode 100644 (file)
index 0000000..43cfc87
--- /dev/null
@@ -0,0 +1,9 @@
+logger -expect error "Begin label \(correct_name\) and end label \(incorrect_name\) don't match\." 1
+read_verilog -sv <<EOF
+module top;
+if (1)
+    begin : correct_name
+        initial $display("HI");
+    end : incorrect_name
+endmodule
+EOF
diff --git a/tests/verilog/module_end_label.ys b/tests/verilog/module_end_label.ys
new file mode 100644 (file)
index 0000000..c9e5a13
--- /dev/null
@@ -0,0 +1,15 @@
+logger -expect-no-warnings
+read_verilog -sv <<EOF
+module correct_name;
+localparam X = 1;
+endmodule : correct_name
+EOF
+
+design -reset
+
+logger -expect error "Module name \(correct_name\) and end label \(incorrect_name\) don't match\." 1
+read_verilog -sv <<EOF
+module correct_name;
+localparam X = 1;
+endmodule : incorrect_name
+EOF