From dc66f2fe7e1fc0ac799c84bd3e911f52a3c3212b Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 27 Jun 2026 10:01:43 -0700 Subject: [PATCH] Support class properties shadowing type names SystemVerilog allows a class property to have the same name as a visible type. The lexer reports the visible type name as `TYPE_IDENTIFIER` before the property has been installed, which made constructs such as `typedef int T; class C; int T; endclass` fail in the class item grammar. A class property with the same name as the class itself hits the same problem. Member references such as `obj.T` or `obj.C` can also hit the same tokenization problem in hierarchical names. Parse class properties through the same declaration helper used for variables so the first type/name pair can be disambiguated. Also let hierarchical member names use `identifier_name`. Stop type lookup when a class scope already has a property with the same name. This makes method body references resolve as properties instead of visible types, including type names found through wildcard imports. Signed-off-by: Lars-Peter Clausen --- parse.y | 15 +++++---------- pform.cc | 10 ++++++++++ 2 files changed, 15 insertions(+), 10 deletions(-) diff --git a/parse.y b/parse.y index 1c9caf208..35e6c89fb 100644 --- a/parse.y +++ b/parse.y @@ -1172,11 +1172,11 @@ class_item /* IEEE1800-2005: A.1.8 */ /* IEEE1800-2017: A.1.9 Class items: Class properties... */ - | property_qualifier_opt data_type list_of_variable_decl_assignments ';' - { pform_class_property(@2, $1, $2, $3); } + | property_qualifier_opt list_of_variable_decl_assignments_with_type ';' + { pform_class_property(@2, $1, $2.type, $2.decl_assignments); } - | K_const class_item_qualifier_opt data_type list_of_variable_decl_assignments ';' - { pform_class_property(@1, $2 | property_qualifier_t::make_const(), $3, $4); } + | K_const class_item_qualifier_opt list_of_variable_decl_assignments_with_type ';' + { pform_class_property(@1, $2 | property_qualifier_t::make_const(), $3.type, $3.decl_assignments); } /* IEEEE1800-2017: A.1.9 Class items: class_item ::= { property_qualifier} data_declaration */ @@ -1212,11 +1212,6 @@ class_item /* IEEE1800-2005: A.1.8 */ /* Here are some error matching rules to help recover from various syntax errors within a class declaration. */ - | property_qualifier_opt data_type error ';' - { yyerror(@3, "error: Errors in variable names after data type."); - yyerrok; - } - | property_qualifier_opt IDENTIFIER error ';' { yyerror(@3, "error: %s doesn't name a type.", $2); yyerrok; @@ -4749,7 +4744,7 @@ hierarchy_identifier $$->push_back(name_component_t(lex_strings.make($1))); delete[]$1; } - | hierarchy_identifier '.' IDENTIFIER + | hierarchy_identifier '.' identifier_name { pform_name_t * tmp = $1; tmp->push_back(name_component_t(lex_strings.make($3))); delete[]$3; diff --git a/pform.cc b/pform.cc index cf2f730ce..7aead1052 100644 --- a/pform.cc +++ b/pform.cc @@ -929,6 +929,16 @@ typedef_t* pform_test_type_identifier(const struct vlltype&loc, const char*txt) if (sym != cur_scope->local_symbols.end()) return nullptr; + // Class properties are tracked in the class type, not in + // local_symbols, but still shadow type names before lookup falls + // through to wildcard imports. + if (auto cur_class = dynamic_cast (cur_scope)) { + if (cur_class->type && + cur_class->type->properties.find(name) != + cur_class->type->properties.end()) + return nullptr; + } + PPackage*pkg = pform_find_potential_import(loc, cur_scope, name, false, false); if (pkg) { cur = pkg->typedefs.find(name);