diff --git a/PScope.h b/PScope.h index b4f1b2029..c92fa620c 100644 --- a/PScope.h +++ b/PScope.h @@ -43,6 +43,16 @@ class PCallTask; class Design; class NetScope; +struct package_import_t : public LineInfo { + package_import_t() = default; + explicit package_import_t(PPackage *pkg) : package(pkg) { } + + PPackage *package = nullptr; + // LineInfo records where the imported name became locally visible. +}; + +using package_import_map_t = std::map; + /* * The PScope class is a base representation of an object that * represents lexical scope. For example, a module, a function/task, a @@ -71,7 +81,7 @@ class LexicalScope { // Symbols that are explicitly imported. This contains the package where // the symbol has been decelared. When using exports, this might not be // the same as the package where it has been imported from. - std::mapexplicit_imports; + package_import_map_t explicit_imports; // Symbols that are explicitly imported. This contains the set of // packages from which the symbol has been imported. When using exports // the same identifier can be imported via multiple packages. @@ -86,7 +96,7 @@ class LexicalScope { // later in the scope. So here we stash the potential imports for // task and function calls. They will be added to the explicit // imports if we don't find a local definition. - std::mappossible_imports; + package_import_map_t possible_imports; struct range_t { // True if this is an exclude diff --git a/net_scope.cc b/net_scope.cc index 13a31ed80..ef8ee794a 100644 --- a/net_scope.cc +++ b/net_scope.cc @@ -111,7 +111,6 @@ NetScope::NetScope(NetScope*up, const hname_t&n, NetScope::TYPE t, NetScope*in_u : type_(t), name_(n), nested_module_(nest), program_block_(program), is_interface_(interface), is_unit_(compilation_unit), unit_(in_unit), up_(up) { - imports_ = 0; events_ = 0; lcounter_ = 0; is_auto_ = false; @@ -215,22 +214,26 @@ void NetScope::set_line(perm_string file, perm_string def_file, def_lineno_ = def_lineno; } -void NetScope::add_imports(const map*imports) +void NetScope::add_imports(const package_import_map_t *imports) { if (!imports->empty()) imports_ = imports; } -NetScope*NetScope::find_import(const Design*des, perm_string name) +NetScope *NetScope::find_import(const Design *des, perm_string name, + unsigned int lexical_pos) { - if (imports_ == 0) - return 0; + if (!imports_) + return nullptr; - map::const_iterator cur = imports_->find(name); - if (cur != imports_->end()) { - return des->find_package(cur->second->pscope_name()); - } else - return 0; + auto cur = imports_->find(name); + if (cur == imports_->end()) + return nullptr; + + if (cur->second.lexical_pos() > lexical_pos) + return nullptr; + + return des->find_package(cur->second.package->pscope_name()); } void NetScope::add_typedefs(const map*typedefs) diff --git a/netlist.h b/netlist.h index 8643158c2..ba1d3936a 100644 --- a/netlist.h +++ b/netlist.h @@ -26,6 +26,7 @@ * can be passed around in this form to the various stages and design * processors. */ +# include # include # include # include @@ -997,8 +998,9 @@ class NetScope : public Definitions, public Attrib { if a unique name couldn't be generated. */ bool auto_name(const char* prefix, char pad, const char* suffix); - void add_imports(const std::map*imports); - NetScope*find_import(const Design*des, perm_string name); + void add_imports(const package_import_map_t *imports); + NetScope *find_import(const Design *des, perm_string name, + unsigned int lexical_pos = UINT_MAX); void add_typedefs(const std::map*typedefs); @@ -1377,7 +1379,7 @@ class NetScope : public Definitions, public Attrib { signed char time_unit_, time_prec_; bool time_from_timescale_; - const std::map*imports_; + const package_import_map_t *imports_ = nullptr; std::maptypedefs_; diff --git a/pform.cc b/pform.cc index a6927eaff..c33c49dae 100644 --- a/pform.cc +++ b/pform.cc @@ -412,10 +412,9 @@ LexicalScope* pform_peek_scope(void) static void pform_check_possible_imports(LexicalScope *scope) { - map::const_iterator cur; - for (cur = scope->possible_imports.begin(); cur != scope->possible_imports.end(); ++cur) { - if (scope->local_symbols.find(cur->first) == scope->local_symbols.end()) - scope->explicit_imports[cur->first] = cur->second; + for (const auto &cur : scope->possible_imports) { + if (!scope->local_symbols.count(cur.first)) + scope->explicit_imports[cur.first] = cur.second; } scope->possible_imports.clear(); } @@ -473,13 +472,12 @@ static void add_local_symbol(LexicalScope*scope, perm_string name, PNamedItem*it } // Check for conflict with an explicit import. - map::const_iterator cur_pkg - = scope->explicit_imports.find(name); + auto cur_pkg = scope->explicit_imports.find(name); if (cur_pkg != scope->explicit_imports.end()) { cerr << item->get_fileline() << ": error: " "'" << name << "' has already been " "imported into this scope from package '" - << cur_pkg->second->pscope_name() << "'." << endl; + << cur_pkg->second.package->pscope_name() << "'." << endl; error_count += 1; return; } @@ -931,10 +929,9 @@ typedef_t* pform_test_type_identifier(const struct vlltype&loc, const char*txt) // something other than a type, then give up now because // the name has at least shadowed any other possible // meaning for this name. - map::iterator cur_pkg; - cur_pkg = cur_scope->explicit_imports.find(name); + auto cur_pkg = cur_scope->explicit_imports.find(name); if (cur_pkg != cur_scope->explicit_imports.end()) { - PPackage*pkg = cur_pkg->second; + auto pkg = cur_pkg->second.package; cur = pkg->typedefs.find(name); if (cur != pkg->typedefs.end()) return cur->second; diff --git a/pform_package.cc b/pform_package.cc index a1ab9c060..c9b9660dc 100644 --- a/pform_package.cc +++ b/pform_package.cc @@ -41,6 +41,14 @@ static map packages_by_name; static PPackage*pform_cur_package = 0; +static package_import_t make_package_import(PPackage *pkg, + const struct vlltype &loc) +{ + package_import_t import(pkg); + FILE_NAME(&import, loc); + return import; +} + void pform_start_package_declaration(const struct vlltype&loc, const char*name, LexicalScope::lifetime_t lifetime) { @@ -97,10 +105,12 @@ PPackage *pform_find_potential_import(const struct vlltype&loc, LexicalScope*sco found_pkg = decl_pkg; if (make_explicit) { - if (tf_call) - scope->possible_imports[name] = found_pkg; - else { - scope->explicit_imports[name] = found_pkg; + if (tf_call) { + scope->possible_imports.emplace( + name, make_package_import(found_pkg, loc)); + } else { + scope->explicit_imports.emplace( + name, make_package_import(found_pkg, loc)); scope->explicit_imports_from[name].insert(search_pkg); } } @@ -122,9 +132,9 @@ PPackage *pform_package_importable(PPackage *pkg, perm_string name) // *::* will match all imports, P::* will match all imports // from a package and P::ID will match a specific identifier // from a package. - if ((!exp.pkg || exp.pkg == import_pkg->second) && + if ((!exp.pkg || exp.pkg == import_pkg->second.package) && (exp.name.nil() || exp.name == name)) - return import_pkg->second; + return import_pkg->second.package; } return nullptr; @@ -166,19 +176,20 @@ void pform_package_import(const struct vlltype&loc, PPackage*pkg, const char*ide } // Check for conflict with previous import. - map::const_iterator cur_pkg - = scope->explicit_imports.find(use_ident); + auto cur_pkg = scope->explicit_imports.find(use_ident); if (cur_pkg != scope->explicit_imports.end()) { - if (cur_pkg->second != pkg_decl) { + if (cur_pkg->second.package != pkg_decl) { cerr << loc.get_fileline() << ": error: " "'" << use_ident << "' has already been " "imported into this scope from package '" - << cur_pkg->second->pscope_name() << "'." << endl; + << cur_pkg->second.package->pscope_name() + << "'." << endl; error_count += 1; } } - scope->explicit_imports[use_ident] = pkg_decl; + scope->explicit_imports.emplace( + use_ident, make_package_import(pkg_decl, loc)); scope->explicit_imports_from[use_ident].insert(pkg); } else { diff --git a/symbol_search.cc b/symbol_search.cc index 863c9717e..c5a29aa47 100644 --- a/symbol_search.cc +++ b/symbol_search.cc @@ -372,7 +372,8 @@ bool symbol_search(const LineInfo*li, Design*des, NetScope*scope, break; // Imports are not visible through hierachical names - if (NetScope*import_scope = scope->find_import(des, path_tail.name)) { + if (auto import_scope = scope->find_import( + des, path_tail.name, lexical_pos)) { scope = import_scope; continue; }