Tested x86_64-pc-linux-gnu. Does this approach make sense to you? Any other ideas?
-- 8< -- We weren't representing 'using namespace' at all in modules, which broke some of the <chrono> literals tests. I experimented with various approaches to representing them, and ended up with emitting them as a pseudo-binding for "using", which as a keyword can't have any real bindings. Then reading this pseudo-binding adds it to using_directives instead of the usual handling. gcc/cp/ChangeLog: * module.cc (depset::hash::add_binding_entity): Handle using-directive as a binding of "using". (depset::hash::add_namespace_entities): Record using-directives. (module_state::read_cluster): Read using-directive. * name-lookup.cc (name_lookup::search_namespace_only): Look up "using" first. (add_using_namespace): New overload. * name-lookup.h (add_using_namespace): Declare. gcc/testsuite/ChangeLog: * g++.dg/modules/namespace-8_a.C: New test. * g++.dg/modules/namespace-8_b.C: New test. --- gcc/cp/name-lookup.h | 1 + gcc/cp/module.cc | 37 +++++++++++++++++--- gcc/cp/name-lookup.cc | 12 +++++++ gcc/testsuite/g++.dg/modules/namespace-8_a.C | 12 +++++++ gcc/testsuite/g++.dg/modules/namespace-8_b.C | 8 +++++ 5 files changed, 65 insertions(+), 5 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/namespace-8_a.C create mode 100644 gcc/testsuite/g++.dg/modules/namespace-8_b.C diff --git a/gcc/cp/name-lookup.h b/gcc/cp/name-lookup.h index 54edadeed7f..50f5fe8d8c7 100644 --- a/gcc/cp/name-lookup.h +++ b/gcc/cp/name-lookup.h @@ -462,6 +462,7 @@ extern cxx_binding *outer_binding (tree, cxx_binding *, bool); extern void cp_emit_debug_info_for_using (tree, tree); extern void finish_nonmember_using_decl (tree scope, tree name); +extern void add_using_namespace (tree, tree); extern void finish_using_directive (tree target, tree attribs); void push_local_extern_decl_alias (tree decl); extern tree pushdecl (tree, bool hiding = false); diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index ddede0fdd43..72ded1062d0 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -13310,7 +13310,11 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_) auto data = static_cast <add_binding_data *> (data_); decl = strip_using_decl (decl); - if (!(TREE_CODE (decl) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (decl))) + bool using_directive = (TREE_CODE (decl) == NAMESPACE_DECL + && (flags & WMB_Using)); + + if (!(TREE_CODE (decl) == NAMESPACE_DECL && !DECL_NAMESPACE_ALIAS (decl)) + || using_directive) { tree inner = decl; @@ -13408,11 +13412,13 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_) /* We're adding something. */ if (!data->binding) { - data->binding = make_binding (data->ns, DECL_NAME (decl)); + tree name = DECL_NAME (decl); + if (using_directive) + name = get_identifier ("using"); + data->binding = make_binding (data->ns, name); data->hash->add_namespace_context (data->binding, data->ns); - depset **slot = data->hash->binding_slot (data->ns, - DECL_NAME (decl), true); + depset **slot = data->hash->binding_slot (data->ns, name, true); gcc_checking_assert (!*slot); *slot = data->binding; } @@ -13492,6 +13498,21 @@ depset::hash::add_namespace_entities (tree ns, bitmap partitions) count++; } + /* Record using-directives. */ + for (auto used: NAMESPACE_LEVEL (ns)->using_directives) + { + data.binding = nullptr; + if (!TREE_PUBLIC (used)) + /* Anonymous namespaces are TU-local. */; + else if (DECL_NAMESPACE_INLINE_P (used) + && is_nested_namespace (ns, used, /*inline only*/true)) + /* Avoid redundant using of inline namespace. */; + else + /* ??? should we try to distinguish whether the using-directive + is purview/exported? */ + add_binding_entity (used, WMB_Flags(WMB_Using|WMB_Purview), &data); + } + if (count) dump () && dump ("Found %u entries", count); dump.outdent (); @@ -15584,7 +15605,13 @@ module_state::read_cluster (unsigned snum) else { if ((flags & cbf_using) && - !DECL_DECLARES_FUNCTION_P (decl)) + TREE_CODE (decl) == NAMESPACE_DECL) + { + add_using_namespace (ns, decl); + decls = void_node; + } + else if ((flags & cbf_using) && + !DECL_DECLARES_FUNCTION_P (decl)) { /* We should only see a single non-function using-decl for a binding; more than that would clash. */ diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc index 30dfbfe2e48..45ae933bdc1 100644 --- a/gcc/cp/name-lookup.cc +++ b/gcc/cp/name-lookup.cc @@ -847,6 +847,11 @@ bool name_lookup::search_namespace_only (tree scope) { bool found = false; + if (modules_p () && name && !id_equal (name, "using")) + { + name_lookup u (get_identifier ("using")); + u.search_namespace_only (scope); + } if (tree *binding = find_namespace_slot (scope, name)) { tree val = *binding; @@ -8912,6 +8917,13 @@ add_using_namespace (vec<tree, va_gc> *&usings, tree target) vec_safe_push (usings, target); } +void +add_using_namespace (tree ns, tree target) +{ + add_using_namespace (NAMESPACE_LEVEL (ns)->using_directives, + ORIGINAL_NAMESPACE (target)); +} + /* Tell the debug system of a using directive. */ static void diff --git a/gcc/testsuite/g++.dg/modules/namespace-8_a.C b/gcc/testsuite/g++.dg/modules/namespace-8_a.C new file mode 100644 index 00000000000..67ffc6a8bfa --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/namespace-8_a.C @@ -0,0 +1,12 @@ +// { dg-additional-options "-fmodules" } + +export module M; + +export namespace B +{ + int i; +} +export namespace C +{ + using namespace B; +} diff --git a/gcc/testsuite/g++.dg/modules/namespace-8_b.C b/gcc/testsuite/g++.dg/modules/namespace-8_b.C new file mode 100644 index 00000000000..7db35bf955e --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/namespace-8_b.C @@ -0,0 +1,8 @@ +// { dg-additional-options "-fmodules" } + +import M; + +int main() +{ + C::i = 42; +} base-commit: 2fd9aef1db1a4260ee823bc3a3d4cfc22e95c543 -- 2.47.0