diff --git a/parse.y b/parse.y index 166b08b78..f065172ca 100644 --- a/parse.y +++ b/parse.y @@ -535,7 +535,7 @@ static void current_function_set_statement(const YYLTYPE&loc, vector /* Support some meta-comments as pragmas. */ %token K_MC_TRANSLATE_ON K_MC_TRANSLATE_OFF -%type from_exclude +%type from_exclude block_item_decls_opt %type number pos_neg_number %type signing unsigned_signed_opt signed_unsigned_opt %type K_automatic_opt K_packed_opt K_reg_opt K_static_opt K_virtual_opt @@ -2170,8 +2170,8 @@ block_item_decls ; block_item_decls_opt - : block_item_decls - | + : block_item_decls { $$ = true; } + | { $$ = false; } ; /* Type declarations are parsed here. The rule actions call pform @@ -5629,11 +5629,40 @@ statement_item /* This is roughly statement_item in the LRM */ FILE_NAME(tmp, @1); $$ = tmp; } - | K_begin statement_or_null_list K_end - { PBlock*tmp = new PBlock(PBlock::BL_SEQ); + /* In SystemVerilog an unnamed block can contain variable declarations. */ + | K_begin + { PBlock*tmp = pform_push_block_scope(0, PBlock::BL_SEQ); FILE_NAME(tmp, @1); - tmp->set_statement(*$2); - delete $2; + current_block_stack.push(tmp); + } + block_item_decls_opt + { if ($3) { + if (! gn_system_verilog()) { + yyerror("error: Variable declaration in unnamed block " + "requires SystemVerilog."); + } + } else { + /* If there are no declarations in the scope then just delete it. */ + pform_pop_scope(); + assert(! current_block_stack.empty()); + PBlock*tmp = current_block_stack.top(); + current_block_stack.pop(); + delete tmp; + } + } + statement_or_null_list K_end + { PBlock*tmp; + if ($3) { + pform_pop_scope(); + assert(! current_block_stack.empty()); + tmp = current_block_stack.top(); + current_block_stack.pop(); + } else { + tmp = new PBlock(PBlock::BL_SEQ); + FILE_NAME(tmp, @1); + } + if ($5) tmp->set_statement(*$5); + delete $5; $$ = tmp; } | K_begin ':' IDENTIFIER @@ -5674,6 +5703,9 @@ statement_item /* This is roughly statement_item in the LRM */ $$ = tmp; } | K_fork statement_or_null_list join_keyword +// HERE +// Create an anonymous scope and if no definitions are found then delete +// the scope and use a simple block. { PBlock*tmp = new PBlock($3); FILE_NAME(tmp, @1); tmp->set_statement(*$2); diff --git a/pform.cc b/pform.cc index 9d19cb68a..403612ff1 100644 --- a/pform.cc +++ b/pform.cc @@ -242,6 +242,11 @@ static listpform_cur_module; bool pform_library_flag = false; +/* + * Give each unnamed block that has a variable declaration a unique name. + */ +static unsigned scope_unnamed_block_with_decl = 1; + /* increment this for generate schemes within a module, and set it to zero when a new module starts. */ static unsigned scope_generate_counter = 1; @@ -439,7 +444,16 @@ PFunction* pform_push_function_scope(const struct vlltype&loc, const char*name, PBlock* pform_push_block_scope(char*name, PBlock::BL_TYPE bt) { - perm_string block_name = lex_strings.make(name); + perm_string block_name; + if (name) block_name = lex_strings.make(name); + else { + // Create a unique name for this unnamed block. + char tmp[32]; + snprintf(tmp, sizeof tmp, "$unm_blk_%u", + scope_unnamed_block_with_decl); + block_name = lex_strings.make(tmp); + scope_unnamed_block_with_decl += 1; + } PBlock*block = new PBlock(block_name, lexical_scope, bt); lexical_scope = block;