-- >8 --
The crash in the given testcase occurs because the fix for PR122053,
r16-4228-gfa6544ef5f50a824cabeda4906453d4545fbf66f, added a call to
lazy_load_pending when doing push_tag, to prevent ICEs at least when
types are textually redefined in lieu of full PR99000 support.
But this means that we might not have loaded the declarations of the ABI
types in lookup_elaborated_type to merge them there yet, but still have
them by the time we get to check_module_override, causing errors, and
then an ICE because tinfo_base_init is not prepared for xref_tag to
fail.
It turns out that doing the lazy load in pushtag is too late; we replace
the decl, but we don't replace the type, and then we end up returning
the type that we were building anyway rather than the type we were
hoping to match against.
The reason I'd done it there originally is because that's the earliest
we have a decl to do lazy_load_pendings with, but it seems that instead
we should have another interface to lazy_load_pendings that can be used
if you already know the name and namespace of the entity that you're
keying too.
PR c++/124485
gcc/cp/ChangeLog:
* cp-tree.h (lazy_load_pendings): Declare new overload.
* module.cc (lazy_load_pendings): Define it.
* name-lookup.cc (lookup_elaborated_type): Load pending entities
with given name before doing namespace-scope lookup.
(pushtag): Remove no-longer-needed pending load.
gcc/testsuite/ChangeLog:
* g++.dg/modules/class-8_b.C: Adjusted expected behaviour.
* g++.dg/modules/pr124485_a.C: New test.
* g++.dg/modules/pr124485_b.C: New test.
Signed-off-by: Nathaniel Shead <[email protected]>
---
gcc/cp/cp-tree.h | 1 +
gcc/cp/module.cc | 20 +++++++++++++++-----
gcc/cp/name-lookup.cc | 13 +++++++------
gcc/testsuite/g++.dg/modules/class-8_b.C | 2 +-
gcc/testsuite/g++.dg/modules/pr124485_a.C | 13 +++++++++++++
gcc/testsuite/g++.dg/modules/pr124485_b.C | 7 +++++++
6 files changed, 44 insertions(+), 12 deletions(-)
create mode 100644 gcc/testsuite/g++.dg/modules/pr124485_a.C
create mode 100644 gcc/testsuite/g++.dg/modules/pr124485_b.C
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 7444cc83770..ea3cb049785 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -7997,6 +7997,7 @@ extern void mangle_module (int m, bool include_partition);
extern void mangle_module_fini ();
extern void lazy_load_binding (unsigned mod, tree ns, tree id,
binding_slot *bslot);
+extern void lazy_load_pendings (tree ns, tree name);
extern void lazy_load_pendings (tree decl);
extern module_state *preprocess_module (module_state *, location_t,
bool in_purview,
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 2125cc00fbe..83d24a3267d 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -22577,19 +22577,19 @@ lazy_load_binding (unsigned mod, tree ns, tree id,
binding_slot *mslot)
module->get_flatname ());
}
-/* Load any pending entities keyed to the top-key of DECL. */
+/* Load any pending entities keyed to NS and NAME.
+ Used to find pending types if we don't yet have a decl built. */
void
-lazy_load_pendings (tree decl)
+lazy_load_pendings (tree ns, tree name)
{
/* Make sure lazy loading from a template context behaves as if
from a non-template context. */
processing_template_decl_sentinel ptds;
- tree key_decl;
pending_key key;
- key.ns = find_pending_key (decl, &key_decl);
- key.id = DECL_NAME (key_decl);
+ key.ns = ns;
+ key.id = name;
auto *pending_vec = pending_table ? pending_table->get (key) : nullptr;
if (!pending_vec)
@@ -22642,6 +22642,16 @@ lazy_load_pendings (tree decl)
key.ns, &"::"[key.ns == global_namespace ? 2 : 0], key.id);
}
+/* Load any pending entities keyed to the top-key of DECL. */
+
+void
+lazy_load_pendings (tree decl)
+{
+ tree key_decl;
+ tree ns = find_pending_key (decl, &key_decl);
+ return lazy_load_pendings (ns, DECL_NAME (key_decl));
+}
+
static void
direct_import (module_state *import, cpp_reader *reader)
{
diff --git a/gcc/cp/name-lookup.cc b/gcc/cp/name-lookup.cc
index cbf970f30df..13aafab4e68 100644
--- a/gcc/cp/name-lookup.cc
+++ b/gcc/cp/name-lookup.cc
@@ -8490,6 +8490,13 @@ lookup_elaborated_type (tree name, TAG_how how)
/* Look in the innermost namespace. */
tree ns = b->this_entity;
+
+ /* If an import is going to provide a definition for this tag,
+ load it now so that we don't get confused later when processing
+ this tag's definition. */
+ if (modules_p ())
+ lazy_load_pendings (ns, name);
+
if (tree *slot = find_namespace_slot (ns, name))
{
tree bind = *slot;
@@ -8796,12 +8803,6 @@ pushtag (tree name, tree type, TAG_how how)
}
else
{
- /* If an import is going to provide a definition for this tag,
- load it now so that we don't get confused later when processing
- this tag's definition. */
- if (modules_p ())
- lazy_load_pendings (decl);
-
decl = do_pushdecl_with_scope
(decl, b, /*hiding=*/(how == TAG_how::HIDDEN_FRIEND));
if (decl == error_mark_node)
diff --git a/gcc/testsuite/g++.dg/modules/class-8_b.C
b/gcc/testsuite/g++.dg/modules/class-8_b.C
index 0bb01ac6a33..dcaa25f72d6 100644
--- a/gcc/testsuite/g++.dg/modules/class-8_b.C
+++ b/gcc/testsuite/g++.dg/modules/class-8_b.C
@@ -20,4 +20,4 @@ void bob ()
}
// { dg-final { scan-lang-dump {Lazily binding '::A'@'foo' section:} module } }
-// { dg-final { scan-lang-dump {Lazily binding '::B'@'foo' section:} module } }
+// { dg-final { scan-lang-dump {Reading 1 pending entities keyed to '::B'}
module } }
diff --git a/gcc/testsuite/g++.dg/modules/pr124485_a.C
b/gcc/testsuite/g++.dg/modules/pr124485_a.C
new file mode 100644
index 00000000000..01f252f9978
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr124485_a.C
@@ -0,0 +1,13 @@
+// PR c++/124485
+// { dg-additional-options "-fmodules -Wno-global-module" }
+// { dg-module-cmi foo }
+
+module;
+namespace __cxxabiv1 {
+ struct __class_type_info {};
+}
+struct type_info {
+ void __do_upcast(__cxxabiv1::__class_type_info);
+};
+export module foo;
+type_info t;
diff --git a/gcc/testsuite/g++.dg/modules/pr124485_b.C
b/gcc/testsuite/g++.dg/modules/pr124485_b.C
new file mode 100644
index 00000000000..ef85b6a4661
--- /dev/null
+++ b/gcc/testsuite/g++.dg/modules/pr124485_b.C
@@ -0,0 +1,7 @@
+// PR c++/124485
+// { dg-additional-options "-fmodules -Wno-global-module" }
+
+import foo;
+struct Type {
+ virtual ~Type() {}
+};