https://gcc.gnu.org/g:eebd8dfdc4f4a7f54b42f74c2e7f54f957930ecd
commit r15-6380-geebd8dfdc4f4a7f54b42f74c2e7f54f957930ecd Author: Nathaniel Shead <nathanielosh...@gmail.com> Date: Fri Sep 6 23:46:47 2024 +1000 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 <nathanielosh...@gmail.com> Reviewed-by: Jason Merrill <ja...@redhat.com> Diff: --- gcc/cp/module.cc | 7 +++---- gcc/cp/name-lookup.cc | 10 +++++----- gcc/testsuite/g++.dg/modules/internal-9_a.H | 28 ++++++++++++++++++++++++++++ gcc/testsuite/g++.dg/modules/internal-9_b.C | 29 +++++++++++++++++++++++++++++ 4 files changed, 65 insertions(+), 9 deletions(-) diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 6774d472f191..c1886e6c3b6e 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 35e7dc81377a..7737b0fbf732 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 000000000000..57fe60bb3c05 --- /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 000000000000..5f8eeac2340e --- /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; +}