Bootstrapped and regtested on x86_64-pc-linux-gnu, OK for trunk? -- >8 --
When we started streaming the bit to handle merging of imported temploid friends in r15-2807, I unthinkingly only streamed it in the '!state->is_header ()' case. This patch reworks the streaming logic to ensure that this data is always streamed, including for unique entities (in case that ever comes up somehow). This does make the streaming slightly less efficient, as functions and types will need an extra byte, but this doesn't appear to make a huge difference to the size of the resulting module; the 'std' module on my machine grows by 0.2% from 30671136 to 30730144 bytes. PR c++/118582 gcc/cp/ChangeLog: * module.cc (trees_out::decl_value): Always stream imported_temploid_friends information. (trees_in::decl_value): Likewise. gcc/testsuite/ChangeLog: * g++.dg/modules/pr118582_a.H: New test. * g++.dg/modules/pr118582_b.H: New test. * g++.dg/modules/pr118582_c.H: New test. Signed-off-by: Nathaniel Shead <nathanielosh...@gmail.com> --- gcc/cp/module.cc | 47 +++++++++++------------ gcc/testsuite/g++.dg/modules/pr118582_a.H | 16 ++++++++ gcc/testsuite/g++.dg/modules/pr118582_b.H | 6 +++ gcc/testsuite/g++.dg/modules/pr118582_c.H | 5 +++ 4 files changed, 49 insertions(+), 25 deletions(-) create mode 100644 gcc/testsuite/g++.dg/modules/pr118582_a.H create mode 100644 gcc/testsuite/g++.dg/modules/pr118582_b.H create mode 100644 gcc/testsuite/g++.dg/modules/pr118582_c.H diff --git a/gcc/cp/module.cc b/gcc/cp/module.cc index 813c1436141..17215594fd3 100644 --- a/gcc/cp/module.cc +++ b/gcc/cp/module.cc @@ -2791,7 +2791,7 @@ static keyed_map_t *keyed_table; /* Instantiations of temploid friends imported from another module need to be attached to the same module as the temploid. This maps - these decls to the temploid they are instantiated them, as there is + these decls to the temploid they are instantiated from, as there is no other easy way to get this information. */ static GTY((cache)) decl_tree_cache_map *imported_temploid_friends; @@ -7961,7 +7961,6 @@ trees_out::decl_value (tree decl, depset *dep) } merge_kind mk = get_merge_kind (decl, dep); - bool is_imported_temploid_friend = imported_temploid_friends->get (decl); if (CHECKING_P) { @@ -7998,10 +7997,6 @@ trees_out::decl_value (tree decl, depset *dep) is_attached = true; bits.b (is_attached); - - /* Also tell the importer whether this is an imported temploid - friend, which has implications for merging. */ - bits.b (is_imported_temploid_friend); } bits.b (dep && dep->has_defn ()); } @@ -8087,6 +8082,16 @@ trees_out::decl_value (tree decl, depset *dep) tree container = decl_container (decl); unsigned tpl_levels = 0; + /* Also tell the importer whether this is a temploid friend attached + to a different module (which has implications for merging), so that + importers can reconstruct this information on stream-in. */ + if (TREE_CODE (inner) == FUNCTION_DECL || TREE_CODE (inner) == TYPE_DECL) + { + tree* temploid_friend_slot = imported_temploid_friends->get (decl); + gcc_checking_assert (!temploid_friend_slot || *temploid_friend_slot); + tree_node (temploid_friend_slot ? *temploid_friend_slot : NULL_TREE); + } + { auto wmk = make_temp_override (dep_hash->writing_merge_key, true); if (decl != inner) @@ -8182,14 +8187,6 @@ trees_out::decl_value (tree decl, depset *dep) } } - if (is_imported_temploid_friend) - { - /* Write imported temploid friends so that importers can reconstruct - this information on stream-in. */ - tree* slot = imported_temploid_friends->get (decl); - tree_node (*slot); - } - bool is_typedef = false; if (!type && TREE_CODE (inner) == TYPE_DECL) { @@ -8266,7 +8263,6 @@ trees_in::decl_value () { int tag = 0; bool is_attached = false; - bool is_imported_temploid_friend = false; bool has_defn = false; unsigned mk_u = u (); if (mk_u >= MK_hwm || !merge_kind_name[mk_u]) @@ -8287,10 +8283,7 @@ trees_in::decl_value () { bits_in bits = stream_bits (); if (!(mk & MK_template_mask) && !state->is_header ()) - { - is_attached = bits.b (); - is_imported_temploid_friend = bits.b (); - } + is_attached = bits.b (); has_defn = bits.b (); } @@ -8385,6 +8378,12 @@ trees_in::decl_value () tree container = decl_container (); unsigned tpl_levels = 0; + /* If this is an imported temploid friend, get the owning decl its + attachment is determined by (or NULL_TREE otherwise). */ + tree temploid_friend = NULL_TREE; + if (TREE_CODE (inner) == FUNCTION_DECL || TREE_CODE (inner) == TYPE_DECL) + temploid_friend = tree_node (); + /* Figure out if this decl is already known about. */ int parm_tag = 0; @@ -8395,7 +8394,7 @@ trees_in::decl_value () parm_tag = fn_parms_init (inner); tree existing = key_mergeable (tag, mk, decl, inner, type, container, - is_attached, is_imported_temploid_friend); + is_attached, temploid_friend); tree existing_inner = existing; if (existing) { @@ -8500,11 +8499,6 @@ trees_in::decl_value () } } - if (is_imported_temploid_friend) - if (tree owner = tree_node ()) - if (is_new) - imported_temploid_friends->put (decl, owner); - /* Regular typedefs will have a NULL TREE_TYPE at this point. */ unsigned tdef_flags = 0; bool is_typedef = false; @@ -8530,6 +8524,9 @@ trees_in::decl_value () DECL_MODULE_IMPORT_P (inner) = true; } + if (temploid_friend) + imported_temploid_friends->put (decl, temploid_friend); + if (spec.spec) set_constraints (decl, spec.spec); diff --git a/gcc/testsuite/g++.dg/modules/pr118582_a.H b/gcc/testsuite/g++.dg/modules/pr118582_a.H new file mode 100644 index 00000000000..1c9ad1313ef --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr118582_a.H @@ -0,0 +1,16 @@ +// PR c++/118582 +// { dg-additional-options "-fmodule-header -fno-module-lazy -std=c++20" } +// { dg-module-cmi {} } + +template <typename> struct I; + +template <typename T> + requires (!requires { T::x; }) +struct I<T> { + using type = int; +}; + +template <typename> +struct R { + friend void f(); +}; diff --git a/gcc/testsuite/g++.dg/modules/pr118582_b.H b/gcc/testsuite/g++.dg/modules/pr118582_b.H new file mode 100644 index 00000000000..8a85a06a740 --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr118582_b.H @@ -0,0 +1,6 @@ +// PR c++/118582 +// { dg-additional-options "-fmodule-header -fno-module-lazy -std=c++20" } +// { dg-module-cmi {} } + +import "pr118582_a.H"; +using T = I<R<int>>::type; diff --git a/gcc/testsuite/g++.dg/modules/pr118582_c.H b/gcc/testsuite/g++.dg/modules/pr118582_c.H new file mode 100644 index 00000000000..555bebb270b --- /dev/null +++ b/gcc/testsuite/g++.dg/modules/pr118582_c.H @@ -0,0 +1,5 @@ +// PR c++/118582 +// { dg-additional-options "-fmodule-header -fno-module-lazy -std=c++20" } +// { dg-module-cmi {} } + +import "pr118582_b.H"; -- 2.47.0