diff --git a/frontends/verilog/verilog_parser.y b/frontends/verilog/verilog_parser.y index 91b7afddf..e4b3258c2 100644 --- a/frontends/verilog/verilog_parser.y +++ b/frontends/verilog/verilog_parser.y @@ -163,12 +163,18 @@ static bool isInLocalScope(const std::string *name) static AstNode *getTypeDefinitionNode(std::string type_name) { - // return the definition nodes from the typedef statement - auto user_types = user_type_stack.back(); - log_assert(user_types->count(type_name) > 0); - auto typedef_node = (*user_types)[type_name]; - log_assert(typedef_node->type == AST_TYPEDEF); - return typedef_node->children[0]; + // check current scope then outer scopes for a name + for (auto it = user_type_stack.rbegin(); it != user_type_stack.rend(); ++it) { + if ((*it)->count(type_name) > 0) { + // return the definition nodes from the typedef statement + auto typedef_node = (**it)[type_name]; + log_assert(typedef_node->type == AST_TYPEDEF); + return typedef_node->children[0]; + } + } + + // The lexer recognized the name as a TOK_USER_TYPE, but now we can't find it anymore? + log_error("typedef for user type `%s' not found", type_name.c_str()); } static AstNode *copyTypeDefinition(std::string type_name) diff --git a/tests/svtypes/typedef_scopes.sv b/tests/svtypes/typedef_scopes.sv index 5507d84f2..9a898fac8 100644 --- a/tests/svtypes/typedef_scopes.sv +++ b/tests/svtypes/typedef_scopes.sv @@ -4,6 +4,7 @@ typedef enum logic {s0, s1} outer_enum_t; module top; + // globals are inherited outer_uint4_t u4_i = 8'hA5; outer_enum_t enum4_i = s0; always @(*) assert(u4_i == 4'h5); @@ -17,13 +18,22 @@ module top; always @(*) assert(inner_enum1 == 3'h3); if (1) begin: genblock + // type declarations in child scopes shadow their parents typedef logic [7:0] inner_type; parameter inner_type inner_const = 8'hA5; typedef enum logic [2:0] {s5=5, s6, s7} inner_enum_t; + inner_type inner_gb_i = inner_const; //8'hA5; inner_enum_t inner_gb_enum1 = s7; always @(*) assert(inner_gb_i == 8'hA5); always @(*) assert(inner_gb_enum1 == 3'h7); + + // check that copying of struct member types works over multiple type scopes + typedef struct packed { + outer_uint4_t x; + } mystruct_t; + mystruct_t mystruct; + always @(*) assert($bits(mystruct) == 4); end inner_type inner_i2 = 8'h42;