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 <lars@metafoo.de>
This commit is contained in:
parent
8df804c273
commit
41f4ff0fbc
29
net_scope.cc
29
net_scope.cc
|
|
@ -239,28 +239,39 @@ void NetScope::add_typedefs(const map<perm_string,typedef_t*>*typedefs)
|
||||||
typedefs_ = *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)
|
NetScope*NetScope::find_typedef_scope(const Design*des, const typedef_t*type_i)
|
||||||
{
|
{
|
||||||
ivl_assert(*this, type_i);
|
ivl_assert(*this, type_i);
|
||||||
|
|
||||||
|
// First check the enclosing lexical scopes and compilation unit.
|
||||||
NetScope *cur_scope = this;
|
NetScope *cur_scope = this;
|
||||||
while (cur_scope) {
|
while (cur_scope) {
|
||||||
auto it = cur_scope->typedefs_.find(type_i->name);
|
auto it = cur_scope->typedefs_.find(type_i->name);
|
||||||
if (it != cur_scope->typedefs_.end() && it->second == type_i)
|
if (it != cur_scope->typedefs_.end() && it->second == type_i)
|
||||||
return cur_scope;
|
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_;
|
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;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
||||||
|
|
@ -1002,7 +1002,7 @@ class NetScope : public Definitions, public Attrib {
|
||||||
|
|
||||||
void add_typedefs(const std::map<perm_string,typedef_t*>*typedefs);
|
void add_typedefs(const std::map<perm_string,typedef_t*>*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);
|
NetScope*find_typedef_scope(const Design*des, const typedef_t*type_i);
|
||||||
|
|
||||||
/* Parameters exist within a scope, and these methods allow
|
/* Parameters exist within a scope, and these methods allow
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue