aboutsummaryrefslogtreecommitdiff
path: root/gcc
diff options
context:
space:
mode:
authorNathaniel Shead <nathanieloshead@gmail.com>2024-09-06 23:46:47 +1000
committerNathaniel Shead <nathanieloshead@gmail.com>2024-12-20 12:57:24 +1100
commiteebd8dfdc4f4a7f54b42f74c2e7f54f957930ecd (patch)
treea61e05143058082ca6ee4a3a35f2f942e8b42ede /gcc
parent0c2ae384326108fad5ca2713ad3c9b768162fe73 (diff)
downloadgcc-eebd8dfdc4f4a7f54b42f74c2e7f54f957930ecd.zip
gcc-eebd8dfdc4f4a7f54b42f74c2e7f54f957930ecd.tar.gz
gcc-eebd8dfdc4f4a7f54b42f74c2e7f54f957930ecd.tar.bz2
c++/modules: Support unnamed namespaces in header units
A header unit may contain unnamed namespaces, and those declarations are exported (as with any declaration in a header unit). This patch ensures that such declarations are correctly handled. The change to 'make_namespace_finish' is required so that if an unnamed namespace is first seen by an import it is correctly handled within 'add_imported_namespace'. I don't see any particular reason why handling of unnamed namespaces here had to be handled separately outside that function since these are the only two callers. gcc/cp/ChangeLog: * module.cc (depset::hash::add_binding_entity): Also walk unnamed namespaces. (module_state::write_namespaces): Adjust assertion. * name-lookup.cc (push_namespace): Move anon using-directive handling to... (make_namespace_finish): ...here. gcc/testsuite/ChangeLog: * g++.dg/modules/internal-9_a.H: New test. * g++.dg/modules/internal-9_b.C: New test. Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com> Reviewed-by: Jason Merrill <jason@redhat.com>
Diffstat (limited to 'gcc')
-rw-r--r--gcc/cp/module.cc7
-rw-r--r--gcc/cp/name-lookup.cc10
-rw-r--r--gcc/testsuite/g++.dg/modules/internal-9_a.H28
-rw-r--r--gcc/testsuite/g++.dg/modules/internal-9_b.C29
4 files changed, 65 insertions, 9 deletions
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 6774d47..c1886e6 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -13903,15 +13903,15 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_)
return (flags & WMB_Using
? flags & WMB_Export : DECL_MODULE_EXPORT_P (decl));
}
- else if (DECL_NAME (decl) && !data->met_namespace)
+ else if (!data->met_namespace)
{
/* Namespace, walk exactly once. */
- gcc_checking_assert (TREE_PUBLIC (decl));
data->met_namespace = true;
if (data->hash->add_namespace_entities (decl, data->partitions))
{
/* It contains an exported thing, so it is exported. */
gcc_checking_assert (DECL_MODULE_PURVIEW_P (decl));
+ gcc_checking_assert (TREE_PUBLIC (decl) || header_module_p ());
DECL_MODULE_EXPORT_P (decl) = true;
}
@@ -16329,8 +16329,7 @@ module_state::write_namespaces (elf_out *to, vec<depset *> spaces,
tree ns = b->get_entity ();
gcc_checking_assert (TREE_CODE (ns) == NAMESPACE_DECL);
- /* P1815 may have something to say about this. */
- gcc_checking_assert (TREE_PUBLIC (ns));
+ gcc_checking_assert (TREE_PUBLIC (ns) || header_module_p ());
unsigned flags = 0;
if (TREE_PUBLIC (ns))
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index 35e7dc8..7737b0f 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -9121,6 +9121,11 @@ make_namespace_finish (tree ns, tree *slot, bool from_import = false)
if (DECL_NAMESPACE_INLINE_P (ns) || !DECL_NAME (ns))
emit_debug_info_using_namespace (ctx, ns, true);
+
+ /* An unnamed namespace implicitly has a using-directive inserted so
+ that its contents are usable in the surrounding context. */
+ if (!DECL_NAMESPACE_INLINE_P (ns) && !DECL_NAME (ns))
+ add_using_namespace (NAMESPACE_LEVEL (ctx)->using_directives, ns);
}
/* Push into the scope of the NAME namespace. If NAME is NULL_TREE,
@@ -9257,11 +9262,6 @@ push_namespace (tree name, bool make_inline)
gcc_checking_assert (slot);
}
make_namespace_finish (ns, slot);
-
- /* Add the anon using-directive here, we don't do it in
- make_namespace_finish. */
- if (!DECL_NAMESPACE_INLINE_P (ns) && !name)
- add_using_namespace (current_binding_level->using_directives, ns);
}
}
diff --git a/gcc/testsuite/g++.dg/modules/internal-9_a.H b/gcc/testsuite/g++.dg/modules/internal-9_a.H
new file mode 100644
index 0000000..57fe60b
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/internal-9_a.H
@@ -0,0 +1,28 @@
+// { dg-additional-options "-fmodule-header" }
+// { dg-module-cmi {} }
+
+static int x = 123;
+static void f() {}
+template <typename T> static void t() {}
+
+namespace {
+ int y = 456;
+ void g() {};
+ template <typename T> void u() {}
+
+ namespace ns { int in_ns = 456; }
+
+ struct A {};
+ template <typename T> struct B {};
+
+ enum E { X };
+ enum class F { Y };
+
+ template <typename T> using U = int;
+
+#if __cplusplus >= 202002L
+ template <typename T> concept C = true;
+#endif
+}
+
+namespace ns2 = ns;
diff --git a/gcc/testsuite/g++.dg/modules/internal-9_b.C b/gcc/testsuite/g++.dg/modules/internal-9_b.C
new file mode 100644
index 0000000..5f8eeac2
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/internal-9_b.C
@@ -0,0 +1,29 @@
+// { dg-additional-options "-fmodules-ts" }
+
+import "internal-9_a.H";
+
+int main() {
+ auto x2 = x;
+ f();
+ t<int>();
+
+ auto y2 = y;
+ g();
+ u<int>();
+
+ int val1 = ns::in_ns;
+
+ A a;
+ B<int> b;
+
+ E e = X;
+ F f = F::Y;
+
+ U<int> temp;
+
+#if __cplusplus >= 202002L
+ static_assert(C<int>);
+#endif
+
+ int val2 = ns2::in_ns;
+}