aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/module.cc
diff options
context:
space:
mode:
authorNathaniel Shead <nathanieloshead@gmail.com>2024-06-15 22:50:14 +1000
committerNathaniel Shead <nathanieloshead@gmail.com>2024-08-07 11:49:47 +1000
commitca287145f23ec3ea987fc2eacde3994096cc528e (patch)
treea0b762064f6cb6e3d7e131c200535cb7b6c0630d /gcc/cp/module.cc
parentb7f719612515a86d1d2a36e24b02ade3f0904e10 (diff)
downloadgcc-ca287145f23ec3ea987fc2eacde3994096cc528e.zip
gcc-ca287145f23ec3ea987fc2eacde3994096cc528e.tar.gz
gcc-ca287145f23ec3ea987fc2eacde3994096cc528e.tar.bz2
c++/modules: Ensure deduction guides are always reachable [PR115231]
Deduction guides are represented as 'normal' functions currently, and have no special handling in modules. However, this causes some issues; by [temp.deduct.guide] a deduction guide is not found by normal name lookup and instead all reachable deduction guides for a class template should be considered, but this does not happen currently. To solve this, this patch ensures that all deduction guides are considered exported to ensure that they are always visible to importers if they are reachable. Another alternative here would be to add a new kind of "all reachable" flag to name lookup, but that is complicated by some difficulties in handling GM entities; this may be a better way to go if more kinds of entities end up needing this handling, however. Another issue here is that because deduction guides are "unrelated" functions, they will usually get discarded from the GMF, so this patch ensures that when finding dependencies, GMF deduction guides will also have bindings created. We do this in find_dependencies so that we don't unnecessarily create bindings for GMF deduction guides that are never reached; for consistency we do this for *all* deduction guides, not just GM ones. We also make sure that the opposite (a deduction guide being the only purview reference to a GMF template) correctly marks it as reachable. Finally, when merging deduction guides from multiple modules, the name lookup code may now return two-dimensional overload sets, so update callers to match. As a small drive-by improvement this patch also updates the error pretty printing code to add a space before the '->' when printing a deduction guide, so we get 'S(int) -> S<int>' instead of 'S(int)-> S<int>'. PR c++/115231 gcc/cp/ChangeLog: * error.cc (dump_function_decl): Add a space before '->' when printing deduction guides. * module.cc (depset::hash::add_binding_entity): Don't create bindings for guides here, only mark dependencies. (depset::hash::add_deduction_guides): New. (depset::hash::find_dependencies): Add deduction guide dependencies for a class template. (module_state::write_cluster): Always consider deduction guides as exported. * pt.cc (deduction_guides_for): Use 'lkp_iterator' instead of 'ovl_iterator'. gcc/testsuite/ChangeLog: * g++.dg/modules/dguide-1_a.C: New test. * g++.dg/modules/dguide-1_b.C: New test. * g++.dg/modules/dguide-2_a.C: New test. * g++.dg/modules/dguide-2_b.C: New test. * g++.dg/modules/dguide-3_a.C: New test. * g++.dg/modules/dguide-3_b.C: New test. * g++.dg/modules/dguide-3_c.C: New test. * g++.dg/modules/dguide-3_d.C: New test. Signed-off-by: Nathaniel Shead <nathanieloshead@gmail.com>
Diffstat (limited to 'gcc/cp/module.cc')
-rw-r--r--gcc/cp/module.cc65
1 files changed, 65 insertions, 0 deletions
diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc
index 7130faf..723f089 100644
--- a/gcc/cp/module.cc
+++ b/gcc/cp/module.cc
@@ -2589,6 +2589,9 @@ public:
void add_partial_entities (vec<tree, va_gc> *);
void add_class_entities (vec<tree, va_gc> *);
+ private:
+ void add_deduction_guides (tree decl);
+
public:
void find_dependencies (module_state *);
bool finalize_dependencies ();
@@ -13172,6 +13175,15 @@ depset::hash::add_binding_entity (tree decl, WMB_Flags flags, void *data_)
/* Ignore NTTP objects. */
return false;
+ if (deduction_guide_p (decl))
+ {
+ /* Ignore deduction guides, bindings for them will be created within
+ find_dependencies for their class template. But still build a dep
+ for them so that we don't discard them. */
+ data->hash->make_dependency (decl, EK_FOR_BINDING);
+ return false;
+ }
+
if (!(flags & WMB_Using) && CP_DECL_CONTEXT (decl) != data->ns)
{
/* An unscoped enum constant implicitly brought into the containing
@@ -13600,6 +13612,50 @@ find_pending_key (tree decl, tree *decl_p = nullptr)
return ns;
}
+/* Creates bindings and dependencies for all deduction guides of
+ the given class template DECL as needed. */
+
+void
+depset::hash::add_deduction_guides (tree decl)
+{
+ /* Alias templates never have deduction guides. */
+ if (DECL_ALIAS_TEMPLATE_P (decl))
+ return;
+
+ /* We don't need to do anything for class-scope deduction guides,
+ as they will be added as members anyway. */
+ if (!DECL_NAMESPACE_SCOPE_P (decl))
+ return;
+
+ tree ns = CP_DECL_CONTEXT (decl);
+ tree name = dguide_name (decl);
+
+ /* We always add all deduction guides with a given name at once,
+ so if there's already a binding there's nothing to do. */
+ if (find_binding (ns, name))
+ return;
+
+ tree guides = lookup_qualified_name (ns, name, LOOK_want::NORMAL,
+ /*complain=*/false);
+ if (guides == error_mark_node)
+ return;
+
+ /* We have bindings to add. */
+ depset *binding = make_binding (ns, name);
+ add_namespace_context (binding, ns);
+
+ depset **slot = binding_slot (ns, name, /*insert=*/true);
+ *slot = binding;
+
+ for (lkp_iterator it (guides); it; ++it)
+ {
+ gcc_checking_assert (!TREE_VISITED (*it));
+ depset *dep = make_dependency (*it, EK_FOR_BINDING);
+ binding->deps.safe_push (dep);
+ dep->deps.safe_push (binding);
+ }
+}
+
/* Iteratively find dependencies. During the walk we may find more
entries on the same binding that need walking. */
@@ -13660,6 +13716,10 @@ depset::hash::find_dependencies (module_state *module)
walker.end ();
if (!walker.is_key_order ()
+ && DECL_CLASS_TEMPLATE_P (decl))
+ add_deduction_guides (decl);
+
+ if (!walker.is_key_order ()
&& TREE_CODE (decl) == TEMPLATE_DECL
&& !DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl))
{
@@ -15158,6 +15218,11 @@ module_state::write_cluster (elf_out *to, depset *scc[], unsigned size,
flags |= cbf_hidden;
else if (DECL_MODULE_EXPORT_P (STRIP_TEMPLATE (bound)))
flags |= cbf_export;
+ else if (deduction_guide_p (bound))
+ /* Deduction guides are always exported so that they are
+ visible to name lookup whenever their class template
+ is reachable. */
+ flags |= cbf_export;
}
gcc_checking_assert (DECL_P (bound));