From f6f7f9d6d77d16f569dac02c03eabf168ba40a7e Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sat, 1 Aug 2026 23:11:23 -0700 Subject: [PATCH] Consider lexical ordering for enum named constants Enum named constants use the parameter lookup path, including its lexical declaration-order check. Their declaration position is currently reported as zero, however, so a later enum named constant can incorrectly hide a matching constant from an outer scope. Attach the parsed enum item's source location to the elaborated enum constant and use its lexical position during lookup. Have the position lookup also identify enum named constants so relaxed-mode warnings do not call them parameters. Update the position after a warning to retain the existing warning suppression behavior. Signed-off-by: Lars-Peter Clausen --- elab_scope.cc | 2 +- net_scope.cc | 38 +++++++++++++++++++++++++++----------- netlist.h | 10 +++++++--- symbol_search.cc | 20 ++++++++++++++------ 4 files changed, 49 insertions(+), 21 deletions(-) diff --git a/elab_scope.cc b/elab_scope.cc index 9f640de5a..f9bb9bde7 100644 --- a/elab_scope.cc +++ b/elab_scope.cc @@ -355,7 +355,7 @@ static void elaborate_scope_enumeration(Design*des, NetScope*scope, } rc_flag = use_enum->insert_name(name_idx, cur->name, cur_value); - rc_flag &= scope->add_enumeration_name(use_enum, cur->name); + rc_flag &= scope->add_enumeration_name(use_enum, cur->name, *cur); if (! rc_flag) { cerr << use_enum->get_fileline() diff --git a/net_scope.cc b/net_scope.cc index ef8ee794a..607c51a8d 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -52,15 +52,17 @@ void Definitions::add_enumeration_set(const enum_type_t*key, netenum_t*enum_set) tmp = enum_set; } -bool Definitions::add_enumeration_name(const netenum_t*enum_set, perm_string name) +bool Definitions::add_enumeration_name(const netenum_t *enum_set, + perm_string name, + const LineInfo &location) { - netenum_t::iterator enum_val = enum_set->find_name(name); + auto enum_val = enum_set->find_name(name); assert(enum_val != enum_set->end_name()); - NetEConstEnum*val = new NetEConstEnum(name, enum_set, enum_val->second); + auto val = new NetEConstEnum(name, enum_set, enum_val->second); + val->set_line(location); - pair::iterator, bool> cur; - cur = enum_names_.insert(make_pair(name,val)); + auto cur = enum_names_.insert(make_pair(name, val)); // Return TRUE if the name is added (i.e. is NOT a duplicate.) return cur.second; @@ -466,23 +468,37 @@ LineInfo NetScope::get_parameter_line_info(perm_string key) const return LineInfo(); } -unsigned NetScope::get_parameter_lexical_pos(perm_string key) const +unsigned int NetScope::get_constant_lexical_pos(perm_string key, + bool &is_enum_name) const { map::const_iterator idx; idx = parameters.find(key); - if (idx != parameters.end()) return idx->second.lexical_pos; + if (idx != parameters.end()) { + is_enum_name = false; + return idx->second.lexical_pos; + } - // If we get here, assume an enumeration value. - return 0; + auto enum_idx = enum_names_.find(key); + assert(enum_idx != enum_names_.end()); + is_enum_name = true; + return enum_idx->second->lexical_pos(); } -void NetScope::set_parameter_lexical_pos(perm_string key, unsigned lexical_pos) +void NetScope::set_constant_lexical_pos(perm_string key, + unsigned int lexical_pos) { map::iterator idx; idx = parameters.find(key); - if (idx != parameters.end()) idx->second.lexical_pos = lexical_pos; + if (idx != parameters.end()) { + idx->second.lexical_pos = lexical_pos; + return; + } + + auto enum_idx = enum_names_.find(key); + assert(enum_idx != enum_names_.end()); + enum_idx->second->lexical_pos(lexical_pos); } void NetScope::print_type(ostream&stream) const diff --git a/netlist.h b/netlist.h index ba1d3936a..f64a97246 100644 --- a/netlist.h +++ b/netlist.h @@ -945,7 +945,9 @@ class Definitions { // up this enumeration based on the pform type. void add_enumeration_set(const enum_type_t*key, netenum_t*enum_set); - bool add_enumeration_name(const netenum_t*enum_set, perm_string enum_name); + bool add_enumeration_name(const netenum_t *enum_set, + perm_string enum_name, + const LineInfo &location); // Look up the enumeration set that was added with the given // key. This is used by enum_type_t::elaborate_type to locate @@ -1335,8 +1337,10 @@ class NetScope : public Definitions, public Attrib { LineInfo get_parameter_line_info(perm_string name) const; - unsigned get_parameter_lexical_pos(perm_string name) const; - void set_parameter_lexical_pos(perm_string name, unsigned lexical_pos); + unsigned int get_constant_lexical_pos(perm_string name, + bool &is_enum_name) const; + void set_constant_lexical_pos(perm_string name, + unsigned int lexical_pos); /* Module instance arrays are collected here for access during the multiple elaboration passes. */ diff --git a/symbol_search.cc b/symbol_search.cc index fc82cea9b..3baf8d118 100644 --- a/symbol_search.cc +++ b/symbol_search.cc @@ -237,22 +237,30 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, } } - if (const NetExpr*par = scope->get_parameter(des, path_tail.name, res->type)) { + if (const NetExpr *par = scope->get_parameter(des, path_tail.name, res->type)) { + bool is_enum_name; + unsigned int declaration_pos = + scope->get_constant_lexical_pos(path_tail.name, + is_enum_name); bool decl_after_use = !scope_is_bound - && !(scope->get_parameter_lexical_pos(path_tail.name) <= lexical_pos); + && !(declaration_pos <= lexical_pos); if (!gn_strict_parameter_declaration || !decl_after_use) { path.push_back(path_tail); res->scope = scope; res->par_val = par; res->path_head = path; if (warn_decl_after_use && decl_after_use) { + const char *kind = is_enum_name + ? "enum named constant" : "parameter"; cerr << li->get_fileline() - << ": warning: parameter `" << path_tail.name + << ": warning: " << kind << " `" + << path_tail.name << "` used before declaration." << endl; cerr << par->get_fileline() - << ": : the parameter is declared here." << endl; - // suppress further warnings for this parameter - scope->set_parameter_lexical_pos(path_tail.name, lexical_pos); + << ": : the " << kind + << " is declared here." << endl; + // suppress further warnings for this constant + scope->set_constant_lexical_pos(path_tail.name, lexical_pos); } return true; } else if (!res->decl_after_use) {