aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/name-lookup.c
diff options
context:
space:
mode:
authorNathan Sidwell <nathan@acm.org>2021-03-03 10:09:41 -0800
committerNathan Sidwell <nathan@acm.org>2021-03-04 04:46:57 -0800
commitc778a237c1c605c2c5606c212c1ace756739442b (patch)
tree4c90f1be0fe5d3e256efb289c060e23ce1438fbf /gcc/cp/name-lookup.c
parent4c955b4ad37cf31c1d7cfa146c2b3ead2042869b (diff)
downloadgcc-c778a237c1c605c2c5606c212c1ace756739442b.zip
gcc-c778a237c1c605c2c5606c212c1ace756739442b.tar.gz
gcc-c778a237c1c605c2c5606c212c1ace756739442b.tar.bz2
c++: Redesign pending entity handling [PR 99170]
This patch addresses 99170. with modules (and in particular header units), one module can provide a (maybe nested) class or template and another module can provide a definition or (maybe partial) specialization of said entity, or member thereof. when both are imported into a 3rd TU, and that TU instantiates or uses the class, it needs to stream in those entities (in general). But how does it key those entities to the original? It can't /just/ use the entity index, because, when header-units and/or partitions are in play, the entity index /is not unique/. I had two complicated schemes that tried to unify that, but it failed. Here's a simpler scheme. Such pending entities are keyed to the namespace and identifier of the namespace-scope entity that contains them. Thus the final TU needs to find that entity and look in a hash table for lists of sections that need loading just before instantiating a template or looking inside a class. I would like to make this more efficient, but given the complex scheme failed, I'm shooting for correctness right now. There will be a follow up patch to complete the cleanup this enables. PR c++/99170 gcc/cp/ * cp-tree.h * lex.c (cxx_dup_lang_specific_decl): Adjust for module_attached_p rename. * module.cc (class pending_key): New. (default_hash_traits<pending_key>): New specialization. (pending_map_t): New typedef. (pending_table): Replace old table. (trees_out::lang_decl_bools): Adjust. (trees_in::lang_decl_bools): Adjust. (trees_in::install_entity): Drop pending member and specialization handling. (find_pending_key): New. (depset::hash::fiund_dependencies): Use it. (pendset_lazy_load): Delete. (module_state::write_cluster): Don't count pendings here. Bye Duff's device-like thing. (module_state::write_pendings): Reimplement. (module_state::read_pendings): Reimplement. (lazy_specializations_p): Delete. (module_state::write): Adjust write_pendings call. (lazy_load_pendings): New. (lazy_load_specializations): Delete. (lazy_load_members): Delete. (init_modules): Adjust. * name-lookup.c (maybe_lazily_declare): Call lazy_load_pendings not lazy_load_members. (note_pending_specializations): Delete. (load_pending_specializations): Delete. * name-lookup.h (BINDING_VECTR_PENDING_SPECIALIZATIONS_P): Delete. (BINDING_VECTOR_PENDING_MEMBERS_P): Delete. (BINDING_VECTR_PENDING_MEMBERS_P): Delete. (note_pending_specializations): Delete. (load_pending_specializations): Delete. * pt.c (lookup_template_class_1): Call lazy_load_pendings not lazy_load_specializations. (instantiate_template_class_1): Likewise. (instantiate_decl): Call lazy_load_pendings. * typeck.c (complete_type): Likewise. gcc/testsuite/ * g++.dg/modules/pr99170-1_a.H: New. * g++.dg/modules/pr99170-1_b.C: New. * g++.dg/modules/pr99170-2.h: New. * g++.dg/modules/pr99170-2_a.C: New. * g++.dg/modules/pr99170-2_b.C: New. * g++.dg/modules/pr99170-3_a.H: New. * g++.dg/modules/pr99170-3_b.C: New. * g++.dg/modules/inst-2_b.C: Adjust scan. * g++.dg/modules/inst-4_a.C: Adjust scan. * g++.dg/modules/inst-4_b.C: Adjust scan. * g++.dg/modules/member-def-1_b.C: Adjust scan. * g++.dg/modules/member-def-1_c.C: Adjust scan. * g++.dg/modules/tpl-spec-1_a.C: Adjust scan. * g++.dg/modules/tpl-spec-1_b.C: Adjust scan. * g++.dg/modules/tpl-spec-2_b.C: Adjust scan. * g++.dg/modules/tpl-spec-2_c.C: Adjust scan. * g++.dg/modules/tpl-spec-2_d.C: Adjust scan. * g++.dg/modules/tpl-spec-3_a.C: Adjust scan. * g++.dg/modules/tpl-spec-3_b.C: Adjust scan. * g++.dg/modules/tpl-spec-4_a.C: Adjust scan. * g++.dg/modules/tpl-spec-4_b.C: Adjust scan. * g++.dg/modules/tpl-spec-5_a.C: Adjust scan. * g++.dg/modules/tpl-spec-5_b.C: Adjust scan.
Diffstat (limited to 'gcc/cp/name-lookup.c')
-rw-r--r--gcc/cp/name-lookup.c59
1 files changed, 4 insertions, 55 deletions
diff --git a/gcc/cp/name-lookup.c b/gcc/cp/name-lookup.c
index 66c35a1..f577087 100644
--- a/gcc/cp/name-lookup.c
+++ b/gcc/cp/name-lookup.c
@@ -1916,10 +1916,10 @@ get_class_binding_direct (tree klass, tree name, bool want_type)
static void
maybe_lazily_declare (tree klass, tree name)
{
- tree main_decl = TYPE_NAME (TYPE_MAIN_VARIANT (klass));
- if (DECL_LANG_SPECIFIC (main_decl)
- && DECL_MODULE_PENDING_MEMBERS_P (main_decl))
- lazy_load_members (main_decl);
+ /* See big comment anout module_state::write_pendings regarding adding a check
+ bit. */
+ if (modules_p ())
+ lazy_load_pendings (TYPE_NAME (klass));
/* Lazily declare functions, if we're going to search these. */
if (IDENTIFIER_CTOR_P (name))
@@ -4101,57 +4101,6 @@ set_module_binding (tree ns, tree name, unsigned mod, int mod_glob,
}
void
-note_pending_specializations (tree ns, tree name, bool is_header)
-{
- if (tree *slot = find_namespace_slot (ns, name, false))
- if (TREE_CODE (*slot) == BINDING_VECTOR)
- {
- tree vec = *slot;
- BINDING_VECTOR_PENDING_SPECIALIZATIONS_P (vec) = true;
- if (is_header)
- BINDING_VECTOR_PENDING_IS_HEADER_P (vec) = true;
- else
- BINDING_VECTOR_PENDING_IS_PARTITION_P (vec) = true;
- }
-}
-
-void
-load_pending_specializations (tree ns, tree name)
-{
- tree *slot = find_namespace_slot (ns, name, false);
-
- if (!slot || TREE_CODE (*slot) != BINDING_VECTOR
- || !BINDING_VECTOR_PENDING_SPECIALIZATIONS_P (*slot))
- return;
-
- tree vec = *slot;
- BINDING_VECTOR_PENDING_SPECIALIZATIONS_P (vec) = false;
-
- bool do_header = BINDING_VECTOR_PENDING_IS_HEADER_P (vec);
- bool do_partition = BINDING_VECTOR_PENDING_IS_PARTITION_P (vec);
- BINDING_VECTOR_PENDING_IS_HEADER_P (vec) = false;
- BINDING_VECTOR_PENDING_IS_PARTITION_P (vec) = false;
-
- gcc_checking_assert (do_header | do_partition);
- binding_cluster *cluster = BINDING_VECTOR_CLUSTER_BASE (vec);
- unsigned ix = BINDING_VECTOR_NUM_CLUSTERS (vec);
- if (BINDING_VECTOR_SLOTS_PER_CLUSTER == BINDING_SLOTS_FIXED)
- {
- ix--;
- cluster++;
- }
-
- for (; ix--; cluster++)
- for (unsigned jx = 0; jx != BINDING_VECTOR_SLOTS_PER_CLUSTER; jx++)
- if (cluster->indices[jx].span
- && cluster->slots[jx].is_lazy ()
- && lazy_specializations_p (cluster->indices[jx].base,
- do_header, do_partition))
- lazy_load_binding (cluster->indices[jx].base, ns, name,
- &cluster->slots[jx]);
-}
-
-void
add_module_namespace_decl (tree ns, tree decl)
{
gcc_assert (!DECL_CHAIN (decl));