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:#️⃣: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>
This commit is contained in:
parent
0c2ae38432
commit
eebd8dfdc4
4 changed files with 65 additions and 9 deletions
|
@ -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))
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
|
28
gcc/testsuite/g++.dg/modules/internal-9_a.H
Normal file
28
gcc/testsuite/g++.dg/modules/internal-9_a.H
Normal file
|
@ -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;
|
29
gcc/testsuite/g++.dg/modules/internal-9_b.C
Normal file
29
gcc/testsuite/g++.dg/modules/internal-9_b.C
Normal file
|
@ -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;
|
||||
}
|
Loading…
Add table
Reference in a new issue