c++: Implement dependent ADL for use with modules
[module.global.frag] p3.3 says "A declaration D is decl-reachable from a
declaration S in the same translation unit if ... S contains a dependent
call E ([temp.dep]) and D is found by any name lookup performed for an
expression synthesized from E by replacing each type-dependent argument
or operand with a value of a placeholder type with no associated
namespaces or entities".
This requires doing partial ADL ondependent calls, in case there are
non-dependent arguments that would cause new functions to become
decl-reachable. This patch implements this with an additional lookup
during modules streaming to find any such entities.
This causes us to do ADL in more circumstances; this means also that we
might instantiate templates in cases we didn't use to. This could cause
issues given we have already started our modules walk at this point, or
break any otherwise valid existing code. To fix this patch adds a flag
to do a "tentative" ADL pass which doesn't attempt to complete any types
(and hence cause instantiations to occur); this means that we might miss
some associated entities however. During a tentative walk we can also
skip entities that we know won't contribute to the missing
decl-reachable set, as an optimisation.
One implementation limitation is that both modules tree walking and
name lookup marks tree nodes as TREE_VISITED for different purposes; to
avoid conflicts this patch caches calls that will require lookup in a
separate worklist to be processed after the walk is done.
PR c++/122712
gcc/cp/ChangeLog:
* module.cc (depset::hash::dep_adl_info): New type.
(depset::hash::dep_adl_entity_list): New work list.
(depset::hash::hash): Create it.
(depset::hash::~hash): Release it.
(trees_out::tree_value): Cache possibly dependent
calls during tree walk.
(depset::hash::add_dependent_adl_entities): New function.
(depset::hash::find_dependencies): Process cached entities.
* name-lookup.cc (name_lookup::tentative): New member.
(name_lookup::name_lookup): Initialize it.
(name_lookup::preserve_state): Propagate tentative from previous
lookup.
(name_lookup::adl_namespace_fns): Don't search imported bindings
during tentative lookup.
(name_lookup::adl_class): Don't attempt to complete class types
during tentative lookup.
(name_lookup::search_adl): Skip type-dependent args and avoid
unnecessary work during tentative lookup.
(lookup_arg_dependent): Add tentative parameter.
* name-lookup.h (lookup_arg_dependent): Likewise.
gcc/testsuite/ChangeLog:
* g++.dg/modules/adl-12_a.C: New test.
* g++.dg/modules/adl-12_b.C: New test.
Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
Reviewed-by: Jason Merrill <jason@redhat.com>
5 files changed