From 41f4ff0fbce3be001de1a4e6ee0d9c44e0a71e46 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 26 Jul 2026 12:06:55 -0700 Subject: [PATCH] Use the bound typedef to find its declaration scope Type names are resolved to `typedef_t` objects during parsing. During elaboration `find_typedef_scope()` currently resolves the name again through the completed import table. An import appearing after the original reference can therefore redirect it to a different typedef with the same name. Search the enclosing and package scopes for the exact `typedef_t` object instead. This preserves the parsing-time binding and returns the scope that owns the selected typedef. Signed-off-by: Lars-Peter Clausen --- net_scope.cc | 29 ++++++++++++++++++++--------- netlist.h | 2 +- 2 files changed, 21 insertions(+), 10 deletions(-) diff --git a/net_scope.cc b/net_scope.cc index be9d1c4c6..13a31ed80 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -239,28 +239,39 @@ void NetScope::add_typedefs(const map*typedefs) typedefs_ = *typedefs; } +/* + * Type names are resolved to typedef_t objects during parsing. Locate the + * scope that owns that exact object instead of resolving its name again + * during elaboration. A name lookup here could follow an import that appears + * after the original type reference and select a different typedef. + */ NetScope*NetScope::find_typedef_scope(const Design*des, const typedef_t*type_i) { ivl_assert(*this, type_i); + // First check the enclosing lexical scopes and compilation unit. NetScope *cur_scope = this; while (cur_scope) { auto it = cur_scope->typedefs_.find(type_i->name); if (it != cur_scope->typedefs_.end() && it->second == type_i) return cur_scope; - NetScope*import_scope = cur_scope->find_import(des, type_i->name); - if (import_scope) - cur_scope = import_scope; - else if (cur_scope == unit_) - return 0; - else - cur_scope = cur_scope->parent(); - if (cur_scope == 0) + if (cur_scope == unit_) + break; + + cur_scope = cur_scope->parent(); + if (!cur_scope) cur_scope = unit_; } - return 0; + // Imported typedefs are owned by package scopes outside that chain. + for (auto package : des->find_package_scopes()) { + auto it = package->typedefs_.find(type_i->name); + if (it != package->typedefs_.end() && it->second == type_i) + return package; + } + + return nullptr; } /* diff --git a/netlist.h b/netlist.h index 0af9d7ad9..8643158c2 100644 --- a/netlist.h +++ b/netlist.h @@ -1002,7 +1002,7 @@ class NetScope : public Definitions, public Attrib { void add_typedefs(const std::map*typedefs); - /* Search the scope hierarchy for the scope where 'type' was defined. */ + /* Locate the scope that owns the resolved typedef object. */ NetScope*find_typedef_scope(const Design*des, const typedef_t*type_i); /* Parameters exist within a scope, and these methods allow