Skip to content

Commit 21cccfa

Browse files
committed
c++/modules: Fix exporting temploid friends in header units [PR118582]
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 <[email protected]>
1 parent 9ddf4a6 commit 21cccfa

File tree

4 files changed

+49
-25
lines changed

4 files changed

+49
-25
lines changed

gcc/cp/module.cc

Lines changed: 22 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -2791,7 +2791,7 @@ static keyed_map_t *keyed_table;
27912791

27922792
/* Instantiations of temploid friends imported from another module
27932793
need to be attached to the same module as the temploid. This maps
2794-
these decls to the temploid they are instantiated them, as there is
2794+
these decls to the temploid they are instantiated from, as there is
27952795
no other easy way to get this information. */
27962796
static GTY((cache)) decl_tree_cache_map *imported_temploid_friends;
27972797

@@ -7961,7 +7961,6 @@ trees_out::decl_value (tree decl, depset *dep)
79617961
}
79627962

79637963
merge_kind mk = get_merge_kind (decl, dep);
7964-
bool is_imported_temploid_friend = imported_temploid_friends->get (decl);
79657964

79667965
if (CHECKING_P)
79677966
{
@@ -7998,10 +7997,6 @@ trees_out::decl_value (tree decl, depset *dep)
79987997
is_attached = true;
79997998

80007999
bits.b (is_attached);
8001-
8002-
/* Also tell the importer whether this is an imported temploid
8003-
friend, which has implications for merging. */
8004-
bits.b (is_imported_temploid_friend);
80058000
}
80068001
bits.b (dep && dep->has_defn ());
80078002
}
@@ -8087,6 +8082,16 @@ trees_out::decl_value (tree decl, depset *dep)
80878082
tree container = decl_container (decl);
80888083
unsigned tpl_levels = 0;
80898084

8085+
/* Also tell the importer whether this is a temploid friend attached
8086+
to a different module (which has implications for merging), so that
8087+
importers can reconstruct this information on stream-in. */
8088+
if (TREE_CODE (inner) == FUNCTION_DECL || TREE_CODE (inner) == TYPE_DECL)
8089+
{
8090+
tree* temploid_friend_slot = imported_temploid_friends->get (decl);
8091+
gcc_checking_assert (!temploid_friend_slot || *temploid_friend_slot);
8092+
tree_node (temploid_friend_slot ? *temploid_friend_slot : NULL_TREE);
8093+
}
8094+
80908095
{
80918096
auto wmk = make_temp_override (dep_hash->writing_merge_key, true);
80928097
if (decl != inner)
@@ -8182,14 +8187,6 @@ trees_out::decl_value (tree decl, depset *dep)
81828187
}
81838188
}
81848189

8185-
if (is_imported_temploid_friend)
8186-
{
8187-
/* Write imported temploid friends so that importers can reconstruct
8188-
this information on stream-in. */
8189-
tree* slot = imported_temploid_friends->get (decl);
8190-
tree_node (*slot);
8191-
}
8192-
81938190
bool is_typedef = false;
81948191
if (!type && TREE_CODE (inner) == TYPE_DECL)
81958192
{
@@ -8266,7 +8263,6 @@ trees_in::decl_value ()
82668263
{
82678264
int tag = 0;
82688265
bool is_attached = false;
8269-
bool is_imported_temploid_friend = false;
82708266
bool has_defn = false;
82718267
unsigned mk_u = u ();
82728268
if (mk_u >= MK_hwm || !merge_kind_name[mk_u])
@@ -8287,10 +8283,7 @@ trees_in::decl_value ()
82878283
{
82888284
bits_in bits = stream_bits ();
82898285
if (!(mk & MK_template_mask) && !state->is_header ())
8290-
{
8291-
is_attached = bits.b ();
8292-
is_imported_temploid_friend = bits.b ();
8293-
}
8286+
is_attached = bits.b ();
82948287

82958288
has_defn = bits.b ();
82968289
}
@@ -8385,6 +8378,12 @@ trees_in::decl_value ()
83858378
tree container = decl_container ();
83868379
unsigned tpl_levels = 0;
83878380

8381+
/* If this is an imported temploid friend, get the owning decl its
8382+
attachment is determined by (or NULL_TREE otherwise). */
8383+
tree temploid_friend = NULL_TREE;
8384+
if (TREE_CODE (inner) == FUNCTION_DECL || TREE_CODE (inner) == TYPE_DECL)
8385+
temploid_friend = tree_node ();
8386+
83888387
/* Figure out if this decl is already known about. */
83898388
int parm_tag = 0;
83908389

@@ -8395,7 +8394,7 @@ trees_in::decl_value ()
83958394
parm_tag = fn_parms_init (inner);
83968395

83978396
tree existing = key_mergeable (tag, mk, decl, inner, type, container,
8398-
is_attached, is_imported_temploid_friend);
8397+
is_attached, temploid_friend);
83998398
tree existing_inner = existing;
84008399
if (existing)
84018400
{
@@ -8500,11 +8499,6 @@ trees_in::decl_value ()
85008499
}
85018500
}
85028501

8503-
if (is_imported_temploid_friend)
8504-
if (tree owner = tree_node ())
8505-
if (is_new)
8506-
imported_temploid_friends->put (decl, owner);
8507-
85088502
/* Regular typedefs will have a NULL TREE_TYPE at this point. */
85098503
unsigned tdef_flags = 0;
85108504
bool is_typedef = false;
@@ -8530,6 +8524,9 @@ trees_in::decl_value ()
85308524
DECL_MODULE_IMPORT_P (inner) = true;
85318525
}
85328526

8527+
if (temploid_friend)
8528+
imported_temploid_friends->put (decl, temploid_friend);
8529+
85338530
if (spec.spec)
85348531
set_constraints (decl, spec.spec);
85358532

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
// PR c++/118582
2+
// { dg-additional-options "-fmodule-header -fno-module-lazy -std=c++20" }
3+
// { dg-module-cmi {} }
4+
5+
template <typename> struct I;
6+
7+
template <typename T>
8+
requires (!requires { T::x; })
9+
struct I<T> {
10+
using type = int;
11+
};
12+
13+
template <typename>
14+
struct R {
15+
friend void f();
16+
};
Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,6 @@
1+
// PR c++/118582
2+
// { dg-additional-options "-fmodule-header -fno-module-lazy -std=c++20" }
3+
// { dg-module-cmi {} }
4+
5+
import "pr118582_a.H";
6+
using T = I<R<int>>::type;
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
// PR c++/118582
2+
// { dg-additional-options "-fmodule-header -fno-module-lazy -std=c++20" }
3+
// { dg-module-cmi {} }
4+
5+
import "pr118582_b.H";

0 commit comments

Comments
 (0)