diff options
author | Nathaniel Shead <nathanieloshead@gmail.com> | 2024-09-06 23:46:47 +1000 |
---|---|---|
committer | Nathaniel Shead <nathanieloshead@gmail.com> | 2024-12-20 12:57:24 +1100 |
commit | eebd8dfdc4f4a7f54b42f74c2e7f54f957930ecd (patch) | |
tree | a61e05143058082ca6ee4a3a35f2f942e8b42ede | |
parent | 0c2ae384326108fad5ca2713ad3c9b768162fe73 (diff) | |
download | gcc-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>
-rw-r--r-- | gcc/cp/module.cc | 7 | ||||
-rw-r--r-- | gcc/cp/name-lookup.cc | 10 | ||||
-rw-r--r-- | gcc/testsuite/g++.dg/modules/internal-9_a.H | 28 | ||||
-rw-r--r-- | 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 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; +} |