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