From 65b943b009f29ecb7eecce7f7e082c73c3d42d72 Mon Sep 17 00:00:00 2001 From: Lars-Peter Clausen Date: Sun, 16 Aug 2026 20:12:08 -0700 Subject: [PATCH] Do not create implicit nets for type identifiers `PEIdent::declare_implicit_nets()` checks visible nets, parameters, genvars, events, and enum constants before creating an implicit net, but does not check typedefs. Type identifiers are currently filtered by the grammar before they can reach this code, but this is not true when type and hierarchy identifier parsing use the same path. Check local and imported typedefs while searching the lexical scopes. Stop the type search when another local declaration hides an outer typedef. Signed-off-by: Lars-Peter Clausen --- PExpr.cc | 27 +++++++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/PExpr.cc b/PExpr.cc index 49a3971a2..c2fc64ce3 100644 --- a/PExpr.cc +++ b/PExpr.cc @@ -25,6 +25,7 @@ # include "compiler.h" # include "PExpr.h" +# include "PPackage.h" # include "PWire.h" # include "Module.h" # include "ivl_assert.h" @@ -419,6 +420,29 @@ static bool find_enum_constant(LexicalScope*scope, perm_string name) }); } +static bool is_typedef_identifier(LexicalScope *scope, perm_string name) +{ + while (scope) { + auto import = scope->explicit_imports.find(name); + if (import != scope->explicit_imports.end()) { + // An explicit import shadows declarations in outer scopes. + const auto &typedefs = import->second.package->typedefs; + return typedefs.find(name) != typedefs.end(); + } + + if (scope->typedefs.find(name) != scope->typedefs.end()) + return true; + + // A local non-type declaration also hides outer typedefs. + if (scope->local_symbols.find(name) != scope->local_symbols.end()) + return false; + + scope = scope->parent_scope(); + } + + return false; +} + void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type) { /* We create an implicit wire if: @@ -432,6 +456,9 @@ void PEIdent::declare_implicit_nets(LexicalScope*scope, NetNet::Type type) return; if (path_.name.size() == 1 && path_.name.front().index.empty()) { perm_string name = path_.name.front().name; + if (is_typedef_identifier(scope, name)) + return; + LexicalScope*ss = scope; while (ss) { if (ss->wires.find(name) != ss->wires.end())