My reworking of pending-entity loading introduced a GC problem. The
post-load processing needs to inhibit GCs (that would otherwise occur in
clone_decl). That wasn't happening on one code path, leading to
dangling pointers in the active call frames.
PR c++/99423
gcc/cp/
* module.cc (post_load_processing): Assert not gcable.
(laxy_load_pendings): Extend no-gc region around
post_load_processing.
gcc/testsuite/
* g++.dg/modules/pr99423_a.H: New.
* g++.dg/modules/pr99423_b.H: New.
--
Nathan Sidwell
diff --git c/gcc/cp/module.cc w/gcc/cp/module.cc
index 2518d73c220..db5fa9076c3 100644
--- c/gcc/cp/module.cc
+++ w/gcc/cp/module.cc
@@ -17194,6 +17194,10 @@ module_state::write_inits (elf_out *to, depset::hash &table, unsigned *crc_ptr)
static void
post_load_processing ()
{
+ /* We mustn't cause a GC, our caller should have arranged for that
+ not to happen. */
+ gcc_checking_assert (function_depth);
+
if (!post_load_decls)
return;
@@ -18882,9 +18886,9 @@ lazy_load_pendings (tree decl)
pending_table->remove (key);
dump.pop (n);
- function_depth--;
lazy_snum = 0;
post_load_processing ();
+ function_depth--;
}
timevar_stop (TV_MODULE_IMPORT);
diff --git c/gcc/testsuite/g++.dg/modules/pr99423_a.H w/gcc/testsuite/g++.dg/modules/pr99423_a.H
new file mode 100644
index 00000000000..db3406c6dd3
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99423_a.H
@@ -0,0 +1,13 @@
+// PR 99423 ICE seeing GC freed entities
+// { dg-additional-options -fmodule-header }
+// { dg-module-cmi {} }
+template<typename _T1>
+struct pair
+{
+ pair() { }
+};
+
+inline pair<bool> blob ()
+{
+ return {};
+}
diff --git c/gcc/testsuite/g++.dg/modules/pr99423_b.H w/gcc/testsuite/g++.dg/modules/pr99423_b.H
new file mode 100644
index 00000000000..c02ab29a3ee
--- /dev/null
+++ w/gcc/testsuite/g++.dg/modules/pr99423_b.H
@@ -0,0 +1,6 @@
+// { dg-additional-options {-fmodule-header --param ggc-min-expand=0 --param ggc-min-heapsize=0} }
+// { dg-module-cmi {} }
+
+import "pr99423_a.H";
+
+pair<bool> boom();