c++: imported templates and alias-template changes [PR 99283]

During development of modules, I had difficulty deciding whether the
module flags of a template should live on the decl_template_result,
the template_decl, or both.  I chose the latter, and require them to
be consistent.  This and a few other defects show how hard that
consistency is.  Hence this patch move to holding the flags on the
template-decl-result decl.  That's the entity various bits of the
parser have at the appropriate time.   Once needs STRIP_TEMPLATE in a
bunch of places, which this patch adds.  Also a check that we never
give a TEMPLATE_DECL to the module flag accessors.

This left a problem with how I was handling template aliases.  These
were in two parts -- separating the TEMPLATE_DECL from the TYPE_DECL.
That seemed somewhat funky, but development showed it necessary.  Of
course, that causes problems if the TEMPLATE_DECL cannot contain 'am
imported' information.  Investigating now shows that we do not need to
treat them separately.  By reverting a bit of template instantiation
machinery that caused the problem, we're back on course.  I think what
has happened is that between then and now, other typedef fixes have
corrected the underlying problem this separation was working around.
It allows a bunch of cleanup in the decl streamer, as we no longer
have to handle a null TEMPLATE_DECL_RESULT.

	PR c++/99283
	gcc/cp/
	* cp-tree.h (DECL_MODULE_CHECK): Ban TEMPLATE_DECL.
	(SET_TYPE_TEMPLATE_INFO): Restore Alias template setting.
	* decl.c (duplicate_decls): Remove template_decl module flag
	propagation.
	* module.cc (merge_kind_name): Add alias tmpl spec as a thing.
	(dumper::impl::nested_name): Adjust for template-decl module flag
	change.
	(trees_in::assert_definition): Likewise.
	(trees_in::install_entity): Likewise.
	(trees_out::decl_value): Likewise.  Remove alias template
	separation of template and type_decl.
	(trees_in::decl_value): Likewise.
	(trees_out::key_mergeable): Likewise,
	(trees_in::key_mergeable): Likewise.
	(trees_out::decl_node): Adjust for template-decl module flag
	change.
	(depset:#️⃣:make_dependency): Likewise.
	(get_originating_module, module_may_redeclare): Likewise.
	(set_instantiating_module, set_defining_module): Likewise.
	* name-lookup.c (name_lookup::search_adl): Likewise.
	(do_pushdecl): Likewise.
	* pt.c (build_template_decl): Likewise.
	(lookup_template_class_1): Remove special alias_template handling
	of DECL_TI_TEMPLATE.
	(tsubst_template_decl): Likewise.
	gcc/testsuite/
	* g++.dg/modules/pr99283-2_a.H: New.
	* g++.dg/modules/pr99283-2_b.H: New.
	* g++.dg/modules/pr99283-2_c.H: New.
	* g++.dg/modules/pr99283-3_a.H: New.
	* g++.dg/modules/pr99283-3_b.H: New.
	* g++.dg/modules/pr99283-4.H: New.
	* g++.dg/modules/tpl-alias-1_a.H: Adjust scans.
	* g++.dg/modules/tpl-alias-1_b.C: Adjust scans.
This commit is contained in:
Nathan Sidwell 2021-03-26 10:46:31 -07:00
parent c314741a53
commit d82797420c
13 changed files with 260 additions and 246 deletions

View File

@ -1661,9 +1661,11 @@ check_constraint_info (tree t)
#define CONSTRAINED_PARM_PROTOTYPE(NODE) \
DECL_INITIAL (TYPE_DECL_CHECK (NODE))
/* Module defines. */
// Too many _DECLS: FUNCTION,VAR,TYPE,TEMPLATE,CONCEPT or NAMESPACE
#define DECL_MODULE_CHECK(NODE) (NODE)
/* Module flags on FUNCTION,VAR,TYPE,CONCEPT or NAMESPACE
A TEMPLATE_DECL holds them on the DECL_TEMPLATE_RESULT object --
it's just not practical to keep them consistent. */
#define DECL_MODULE_CHECK(NODE) \
TREE_NOT_CHECK (NODE, TEMPLATE_DECL)
/* In the purview of a module (including header unit). */
#define DECL_MODULE_PURVIEW_P(N) \
@ -3626,9 +3628,10 @@ struct GTY(()) lang_decl {
/* Set the template information for a non-alias n ENUMERAL_, RECORD_,
or UNION_TYPE to VAL. ALIAS's are dealt with separately. */
#define SET_TYPE_TEMPLATE_INFO(NODE, VAL) \
(gcc_checking_assert (TREE_CODE (NODE) == ENUMERAL_TYPE \
|| (CLASS_TYPE_P (NODE) && !TYPE_ALIAS_P (NODE))), \
(TYPE_LANG_SLOT_1 (NODE) = (VAL))) \
(TREE_CODE (NODE) == ENUMERAL_TYPE \
|| (CLASS_TYPE_P (NODE) && !TYPE_ALIAS_P (NODE)) \
? (TYPE_LANG_SLOT_1 (NODE) = (VAL)) \
: (DECL_TEMPLATE_INFO (TYPE_NAME (NODE)) = (VAL))) \
#define TI_TEMPLATE(NODE) \
((struct tree_template_info*)TEMPLATE_INFO_CHECK (NODE))->tmpl

View File

@ -2275,10 +2275,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
}
}
DECL_MODULE_IMPORT_P (olddecl)
= DECL_MODULE_IMPORT_P (old_result)
= DECL_MODULE_IMPORT_P (newdecl);
return olddecl;
}
@ -2931,19 +2927,6 @@ duplicate_decls (tree newdecl, tree olddecl, bool hiding, bool was_hidden)
}
}
if (DECL_LANG_SPECIFIC (olddecl) && DECL_TEMPLATE_INFO (olddecl))
{
/* Repropagate the module information to the template. */
tree tmpl = DECL_TI_TEMPLATE (olddecl);
if (DECL_TEMPLATE_RESULT (tmpl) == olddecl)
{
DECL_MODULE_PURVIEW_P (tmpl) = DECL_MODULE_PURVIEW_P (olddecl);
gcc_checking_assert (!DECL_MODULE_IMPORT_P (olddecl));
DECL_MODULE_IMPORT_P (tmpl) = false;
}
}
if (VAR_OR_FUNCTION_DECL_P (newdecl))
{
if (DECL_EXTERNAL (olddecl)

View File

@ -2797,7 +2797,7 @@ static char const *const merge_kind_name[MK_hwm] =
NULL, NULL,
"decl spec", "decl tmpl spec", /* 20,21 decl (template). */
"alias spec", NULL, /* 22,23 alias. */
"alias spec", "alias tmpl spec", /* 22,23 alias (template). */
NULL, NULL, NULL, NULL,
NULL, NULL, NULL, NULL,
};
@ -4144,10 +4144,17 @@ dumper::impl::nested_name (tree t)
if (ti && TREE_CODE (TI_TEMPLATE (ti)) == TEMPLATE_DECL
&& (DECL_TEMPLATE_RESULT (TI_TEMPLATE (ti)) == t))
t = TI_TEMPLATE (ti);
tree not_tmpl = t;
if (TREE_CODE (t) == TEMPLATE_DECL)
fputs ("template ", stream);
{
fputs ("template ", stream);
not_tmpl = DECL_TEMPLATE_RESULT (t);
}
if (DECL_LANG_SPECIFIC (t) && DECL_MODULE_IMPORT_P (t))
if (not_tmpl
&& DECL_P (not_tmpl)
&& DECL_LANG_SPECIFIC (not_tmpl)
&& DECL_MODULE_IMPORT_P (not_tmpl))
{
/* We need to be careful here, so as to not explode on
inconsistent data -- we're probably debugging, because
@ -4484,9 +4491,9 @@ trees_in::assert_definition (tree decl ATTRIBUTE_UNUSED,
gcc_assert (!is_duplicate (decl)
? !slot
: (slot
|| !DECL_LANG_SPECIFIC (decl)
|| !DECL_MODULE_PURVIEW_P (decl)
|| (!DECL_MODULE_IMPORT_P (decl)
|| !DECL_LANG_SPECIFIC (STRIP_TEMPLATE (decl))
|| !DECL_MODULE_PURVIEW_P (STRIP_TEMPLATE (decl))
|| (!DECL_MODULE_IMPORT_P (STRIP_TEMPLATE (decl))
&& header_module_p ())));
if (TREE_CODE (decl) == TEMPLATE_DECL)
@ -7445,11 +7452,12 @@ trees_in::install_entity (tree decl)
(*entity_ary)[ident] = decl;
/* And into the entity map, if it's not already there. */
if (!DECL_LANG_SPECIFIC (decl)
|| !DECL_MODULE_ENTITY_P (decl))
tree not_tmpl = STRIP_TEMPLATE (decl);
if (!DECL_LANG_SPECIFIC (not_tmpl)
|| !DECL_MODULE_ENTITY_P (not_tmpl))
{
retrofit_lang_decl (decl);
DECL_MODULE_ENTITY_P (decl) = true;
retrofit_lang_decl (not_tmpl);
DECL_MODULE_ENTITY_P (not_tmpl) = true;
/* Insert into the entity hash (it cannot already be there). */
bool existed;
@ -7510,12 +7518,11 @@ trees_out::decl_value (tree decl, depset *dep)
tree o = get_originating_module_decl (decl);
bool is_mod = false;
if (dep && dep->is_alias_tmpl_inst ())
/* Alias template instantiations are templatey, but
found by name. */
is_mod = false;
else if (DECL_LANG_SPECIFIC (o) && DECL_MODULE_PURVIEW_P (o))
tree not_tmpl = STRIP_TEMPLATE (o);
if (DECL_LANG_SPECIFIC (not_tmpl)
&& DECL_MODULE_PURVIEW_P (not_tmpl))
is_mod = true;
b (is_mod);
}
b (dep && dep->has_defn ());
@ -7533,26 +7540,18 @@ trees_out::decl_value (tree decl, depset *dep)
int inner_tag = 0;
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
if (dep && dep->is_alias_tmpl_inst ())
inner = NULL_TREE;
else
{
inner = DECL_TEMPLATE_RESULT (decl);
inner_tag = insert (inner, WK_value);
}
inner = DECL_TEMPLATE_RESULT (decl);
inner_tag = insert (inner, WK_value);
if (streaming_p ())
{
int code = inner ? TREE_CODE (inner) : 0;
int code = TREE_CODE (inner);
u (code);
if (inner)
{
start (inner, true);
tree_node_bools (inner);
dump (dumper::TREE)
&& dump ("Writing %s:%d %C:%N%S", merge_kind_name[mk], inner_tag,
TREE_CODE (inner), inner, inner);
}
start (inner, true);
tree_node_bools (inner);
dump (dumper::TREE)
&& dump ("Writing %s:%d %C:%N%S", merge_kind_name[mk], inner_tag,
TREE_CODE (inner), inner, inner);
}
}
@ -7560,7 +7559,7 @@ trees_out::decl_value (tree decl, depset *dep)
int type_tag = 0;
tree stub_decl = NULL_TREE;
int stub_tag = 0;
if (inner && TREE_CODE (inner) == TYPE_DECL)
if (TREE_CODE (inner) == TYPE_DECL)
{
type = TREE_TYPE (inner);
bool has_type = (type == TYPE_MAIN_VARIANT (type)
@ -7612,7 +7611,7 @@ trees_out::decl_value (tree decl, depset *dep)
unsigned tpl_levels = 0;
if (decl != inner)
tpl_header (decl, &tpl_levels);
if (inner && TREE_CODE (inner) == FUNCTION_DECL)
if (TREE_CODE (inner) == FUNCTION_DECL)
fn_parms_init (inner);
/* Now write out the merging information, and then really
@ -7624,7 +7623,7 @@ trees_out::decl_value (tree decl, depset *dep)
&& dump ("Wrote:%d's %s merge key %C:%N", tag,
merge_kind_name[mk], TREE_CODE (decl), decl);
if (inner && TREE_CODE (inner) == FUNCTION_DECL)
if (TREE_CODE (inner) == FUNCTION_DECL)
fn_parms_fini (inner);
if (!is_key_order ())
@ -7636,18 +7635,6 @@ trees_out::decl_value (tree decl, depset *dep)
tree_node_vals (inner);
tpl_parms_fini (decl, tpl_levels);
}
else if (!inner)
{
/* A template alias instantiation. */
inner = DECL_TEMPLATE_RESULT (decl);
if (!is_key_order ())
tree_node (inner);
if (streaming_p ())
dump (dumper::TREE)
&& dump ("Wrote(%d) alias template %C:%N",
get_tag (inner), TREE_CODE (inner), inner);
inner = NULL_TREE;
}
if (type && !is_key_order ())
{
@ -7693,8 +7680,7 @@ trees_out::decl_value (tree decl, depset *dep)
install_entity (decl, dep);
}
if (inner
&& VAR_OR_FUNCTION_DECL_P (inner)
if (VAR_OR_FUNCTION_DECL_P (inner)
&& DECL_LANG_SPECIFIC (inner)
&& DECL_MODULE_ATTACHMENTS_P (inner)
&& !is_key_order ())
@ -7715,7 +7701,7 @@ trees_out::decl_value (tree decl, depset *dep)
}
bool is_typedef = false;
if (!type && inner && TREE_CODE (inner) == TYPE_DECL)
if (!type && TREE_CODE (inner) == TYPE_DECL)
{
tree t = TREE_TYPE (inner);
unsigned tdef_flags = 0;
@ -7766,10 +7752,9 @@ trees_out::decl_value (tree decl, depset *dep)
dump (dumper::TREE) && dump ("Written decl:%d %C:%N", tag,
TREE_CODE (decl), decl);
if (!inner || NAMESPACE_SCOPE_P (inner))
gcc_checking_assert (!inner
|| !dep == (VAR_OR_FUNCTION_DECL_P (inner)
&& DECL_LOCAL_DECL_P (inner)));
if (NAMESPACE_SCOPE_P (inner))
gcc_checking_assert (!dep == (VAR_OR_FUNCTION_DECL_P (inner)
&& DECL_LOCAL_DECL_P (inner)));
else if ((TREE_CODE (inner) == TYPE_DECL
&& !is_typedef
&& TYPE_NAME (TREE_TYPE (inner)) == inner)
@ -7828,31 +7813,23 @@ trees_in::decl_value ()
if (decl && TREE_CODE (decl) == TEMPLATE_DECL)
{
int code = u ();
if (!code)
{
inner = NULL_TREE;
DECL_TEMPLATE_RESULT (decl) = error_mark_node;
}
inner = start (code);
if (inner && tree_node_bools (inner))
DECL_TEMPLATE_RESULT (decl) = inner;
else
{
inner = start (code);
if (inner && tree_node_bools (inner))
DECL_TEMPLATE_RESULT (decl) = inner;
else
decl = NULL_TREE;
decl = NULL_TREE;
inner_tag = insert (inner);
if (decl)
dump (dumper::TREE)
&& dump ("Reading:%d %C", inner_tag, TREE_CODE (inner));
}
inner_tag = insert (inner);
if (decl)
dump (dumper::TREE)
&& dump ("Reading:%d %C", inner_tag, TREE_CODE (inner));
}
tree type = NULL_TREE;
int type_tag = 0;
tree stub_decl = NULL_TREE;
int stub_tag = 0;
if (decl && inner && TREE_CODE (inner) == TYPE_DECL)
if (decl && TREE_CODE (inner) == TYPE_DECL)
{
if (unsigned type_code = u ())
{
@ -7917,7 +7894,7 @@ trees_in::decl_value ()
if (decl != inner)
if (!tpl_header (decl, &tpl_levels))
goto bail;
if (inner && TREE_CODE (inner) == FUNCTION_DECL)
if (TREE_CODE (inner) == FUNCTION_DECL)
parm_tag = fn_parms_init (inner);
tree existing = key_mergeable (tag, mk, decl, inner, type, container, is_mod);
@ -7972,15 +7949,6 @@ trees_in::decl_value ()
if (!tpl_parms_fini (decl, tpl_levels))
goto bail;
}
else if (!inner)
{
inner = tree_node ();
DECL_TEMPLATE_RESULT (decl) = inner;
TREE_TYPE (decl) = TREE_TYPE (inner);
dump (dumper::TREE)
&& dump ("Read alias template %C:%N", TREE_CODE (inner), inner);
inner = NULL_TREE;
}
if (type && (!tree_node_vals (type)
|| (stub_decl && !tree_node_vals (stub_decl))))
@ -8009,8 +7977,7 @@ trees_in::decl_value ()
bool installed = install_entity (existing);
bool is_new = existing == decl;
if (inner
&& VAR_OR_FUNCTION_DECL_P (inner)
if (VAR_OR_FUNCTION_DECL_P (inner)
&& DECL_LANG_SPECIFIC (inner)
&& DECL_MODULE_ATTACHMENTS_P (inner))
{
@ -8039,7 +8006,7 @@ trees_in::decl_value ()
/* Regular typedefs will have a NULL TREE_TYPE at this point. */
unsigned tdef_flags = 0;
bool is_typedef = false;
if (!type && inner && TREE_CODE (inner) == TYPE_DECL)
if (!type && TREE_CODE (inner) == TYPE_DECL)
{
tdef_flags = u ();
if (tdef_flags & 1)
@ -8056,15 +8023,9 @@ trees_in::decl_value ()
if (installed)
{
/* Mark the entity as imported and add it to the entity
array and map. */
retrofit_lang_decl (decl);
DECL_MODULE_IMPORT_P (decl) = true;
if (inner_tag)
{
retrofit_lang_decl (inner);
DECL_MODULE_IMPORT_P (inner) = true;
}
/* Mark the entity as imported. */
retrofit_lang_decl (inner);
DECL_MODULE_IMPORT_P (inner) = true;
}
if (spec.spec)
@ -8158,7 +8119,7 @@ trees_in::decl_value ()
if (!is_matching_decl (existing, decl, is_typedef))
unmatched_duplicate (existing);
if (inner && TREE_CODE (inner) == FUNCTION_DECL)
if (TREE_CODE (inner) == FUNCTION_DECL)
{
tree e_inner = STRIP_TEMPLATE (existing);
for (auto parm = DECL_ARGUMENTS (inner);
@ -8211,8 +8172,7 @@ trees_in::decl_value ()
}
}
if (inner
&& !NAMESPACE_SCOPE_P (inner)
if (!NAMESPACE_SCOPE_P (inner)
&& ((TREE_CODE (inner) == TYPE_DECL
&& !is_typedef
&& TYPE_NAME (TREE_TYPE (inner)) == inner)
@ -8550,7 +8510,8 @@ trees_out::decl_node (tree decl, walk_kind ref)
else if (TREE_CODE (ctx) != FUNCTION_DECL
|| TREE_CODE (decl) == TEMPLATE_DECL
|| (dep_hash->sneakoscope && DECL_IMPLICIT_TYPEDEF_P (decl))
|| (DECL_LANG_SPECIFIC (decl) && DECL_MODULE_IMPORT_P (decl)))
|| (DECL_LANG_SPECIFIC (decl)
&& DECL_MODULE_IMPORT_P (decl)))
{
auto kind = (TREE_CODE (decl) == NAMESPACE_DECL
&& !DECL_NAMESPACE_ALIAS (decl)
@ -8607,6 +8568,7 @@ trees_out::decl_node (tree decl, walk_kind ref)
else
{
tree o = get_originating_module_decl (decl);
o = STRIP_TEMPLATE (o);
kind = (DECL_LANG_SPECIFIC (o) && DECL_MODULE_PURVIEW_P (o)
? "purview" : "GMF");
}
@ -10371,7 +10333,7 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
gcc_checking_assert
(match_mergeable_specialization (false, entry)
== TREE_TYPE (existing));
else if (mk & MK_tmpl_tmpl_mask)
if (mk & MK_tmpl_tmpl_mask)
existing = DECL_TI_TEMPLATE (existing);
}
else
@ -10401,7 +10363,7 @@ trees_out::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
if (IDENTIFIER_CONV_OP_P (name))
name = conv_op_identifier;
if (inner && TREE_CODE (inner) == FUNCTION_DECL)
if (TREE_CODE (inner) == FUNCTION_DECL)
{
/* Functions are distinguished by parameter types. */
tree fn_type = TREE_TYPE (inner);
@ -10737,7 +10699,7 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
key.ret = tree_node ();
else if (mk == MK_partial
|| ((mk == MK_named || mk == MK_friend_spec)
&& inner && TREE_CODE (inner) == FUNCTION_DECL))
&& TREE_CODE (inner) == FUNCTION_DECL))
{
key.ret = tree_node ();
tree arg, *arg_ptr = &key.args;
@ -10760,11 +10722,8 @@ trees_in::key_mergeable (int tag, merge_kind mk, tree decl, tree inner,
DECL_NAME (decl) = name;
DECL_CONTEXT (decl) = FROB_CONTEXT (container);
}
if (inner)
{
DECL_NAME (inner) = DECL_NAME (decl);
DECL_CONTEXT (inner) = DECL_CONTEXT (decl);
}
DECL_NAME (inner) = DECL_NAME (decl);
DECL_CONTEXT (inner) = DECL_CONTEXT (decl);
if (mk == MK_partial)
{
@ -12383,20 +12342,9 @@ depset::hash::make_dependency (tree decl, entity_kind ek)
gcc_checking_assert (TREE_CODE (decl) == OVERLOAD);
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
/* The template should have copied these from its result decl. */
tree res = DECL_TEMPLATE_RESULT (decl);
gcc_checking_assert (DECL_MODULE_EXPORT_P (decl)
== DECL_MODULE_EXPORT_P (res));
if (DECL_LANG_SPECIFIC (res))
{
gcc_checking_assert (DECL_MODULE_PURVIEW_P (decl)
== DECL_MODULE_PURVIEW_P (res));
gcc_checking_assert ((DECL_MODULE_IMPORT_P (decl)
== DECL_MODULE_IMPORT_P (res)));
}
}
/* The template should have copied these from its result decl. */
gcc_checking_assert (DECL_MODULE_EXPORT_P (decl)
== DECL_MODULE_EXPORT_P (DECL_TEMPLATE_RESULT (decl)));
depset **slot = entity_slot (decl, true);
depset *dep = *slot;
@ -12444,11 +12392,6 @@ depset::hash::make_dependency (tree decl, entity_kind ek)
*slot = redirect;
if (DECL_LANG_SPECIFIC (decl))
{
DECL_MODULE_IMPORT_P (partial) = DECL_MODULE_IMPORT_P (decl);
DECL_MODULE_PURVIEW_P (partial) = DECL_MODULE_PURVIEW_P (decl);
}
depset *tmpl_dep = make_dependency (partial, EK_PARTIAL);
gcc_checking_assert (tmpl_dep->get_entity_kind () == EK_PARTIAL);
@ -12478,46 +12421,48 @@ depset::hash::make_dependency (tree decl, entity_kind ek)
&& !(*eslot)->deps.length ());
}
if (ek != EK_USING
&& DECL_LANG_SPECIFIC (decl)
&& DECL_MODULE_IMPORT_P (decl))
if (ek != EK_USING)
{
/* Store the module number and index in cluster/section, so
we don't have to look them up again. */
unsigned index = import_entity_index (decl);
module_state *from = import_entity_module (index);
/* Remap will be zero for imports from partitions, which we
want to treat as-if declared in this TU. */
if (from->remap)
{
dep->cluster = index - from->entity_lwm;
dep->section = from->remap;
dep->set_flag_bit<DB_IMPORTED_BIT> ();
}
}
if (ek == EK_DECL
&& !dep->is_import ()
&& TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL
&& !(TREE_CODE (decl) == TEMPLATE_DECL
&& DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl)))
{
tree ctx = CP_DECL_CONTEXT (decl);
tree not_tmpl = STRIP_TEMPLATE (decl);
if (!TREE_PUBLIC (ctx))
/* Member of internal namespace. */
dep->set_flag_bit<DB_IS_INTERNAL_BIT> ();
else if (VAR_OR_FUNCTION_DECL_P (not_tmpl)
&& DECL_THIS_STATIC (not_tmpl))
if (DECL_LANG_SPECIFIC (not_tmpl)
&& DECL_MODULE_IMPORT_P (not_tmpl))
{
/* An internal decl. This is ok in a GM entity. */
if (!(header_module_p ()
|| !DECL_LANG_SPECIFIC (not_tmpl)
|| !DECL_MODULE_PURVIEW_P (not_tmpl)))
dep->set_flag_bit<DB_IS_INTERNAL_BIT> ();
/* Store the module number and index in cluster/section,
so we don't have to look them up again. */
unsigned index = import_entity_index (decl);
module_state *from = import_entity_module (index);
/* Remap will be zero for imports from partitions, which
we want to treat as-if declared in this TU. */
if (from->remap)
{
dep->cluster = index - from->entity_lwm;
dep->section = from->remap;
dep->set_flag_bit<DB_IMPORTED_BIT> ();
}
}
if (ek == EK_DECL
&& !dep->is_import ()
&& TREE_CODE (CP_DECL_CONTEXT (decl)) == NAMESPACE_DECL
&& !(TREE_CODE (decl) == TEMPLATE_DECL
&& DECL_UNINSTANTIATED_TEMPLATE_FRIEND_P (decl)))
{
tree ctx = CP_DECL_CONTEXT (decl);
if (!TREE_PUBLIC (ctx))
/* Member of internal namespace. */
dep->set_flag_bit<DB_IS_INTERNAL_BIT> ();
else if (VAR_OR_FUNCTION_DECL_P (not_tmpl)
&& DECL_THIS_STATIC (not_tmpl))
{
/* An internal decl. This is ok in a GM entity. */
if (!(header_module_p ()
|| !DECL_LANG_SPECIFIC (not_tmpl)
|| !DECL_MODULE_PURVIEW_P (not_tmpl)))
dep->set_flag_bit<DB_IS_INTERNAL_BIT> ();
}
}
}
if (!dep->is_import ())
@ -18394,15 +18339,16 @@ int
get_originating_module (tree decl, bool for_mangle)
{
tree owner = get_originating_module_decl (decl);
tree not_tmpl = STRIP_TEMPLATE (owner);
if (!DECL_LANG_SPECIFIC (owner))
if (!DECL_LANG_SPECIFIC (not_tmpl))
return for_mangle ? -1 : 0;
if (for_mangle
&& (DECL_MODULE_EXPORT_P (owner) || !DECL_MODULE_PURVIEW_P (owner)))
&& (DECL_MODULE_EXPORT_P (owner) || !DECL_MODULE_PURVIEW_P (not_tmpl)))
return -1;
if (!DECL_MODULE_IMPORT_P (owner))
if (!DECL_MODULE_IMPORT_P (not_tmpl))
return 0;
return get_importing_module (owner);
@ -18426,7 +18372,8 @@ module_may_redeclare (tree decl)
{
module_state *me = (*modules)[0];
module_state *them = me;
if (DECL_LANG_SPECIFIC (decl) && DECL_MODULE_IMPORT_P (decl))
tree not_tmpl = STRIP_TEMPLATE (decl);
if (DECL_LANG_SPECIFIC (not_tmpl) && DECL_MODULE_IMPORT_P (not_tmpl))
{
/* We can be given the TEMPLATE_RESULT. We want the
TEMPLATE_DECL. */
@ -18468,15 +18415,15 @@ module_may_redeclare (tree decl)
}
if (me == them)
return ((DECL_LANG_SPECIFIC (decl) && DECL_MODULE_PURVIEW_P (decl))
return ((DECL_LANG_SPECIFIC (not_tmpl) && DECL_MODULE_PURVIEW_P (not_tmpl))
== module_purview_p ());
if (!me->name)
me = me->parent;
/* We can't have found a GMF entity from a named module. */
gcc_checking_assert (DECL_LANG_SPECIFIC (decl)
&& DECL_MODULE_PURVIEW_P (decl));
gcc_checking_assert (DECL_LANG_SPECIFIC (not_tmpl)
&& DECL_MODULE_PURVIEW_P (not_tmpl));
return me && get_primary (them) == get_primary (me);
}
@ -18500,20 +18447,16 @@ set_instantiating_module (tree decl)
if (!modules_p ())
return;
decl = STRIP_TEMPLATE (decl);
if (!DECL_LANG_SPECIFIC (decl) && module_purview_p ())
retrofit_lang_decl (decl);
if (DECL_LANG_SPECIFIC (decl))
{
DECL_MODULE_PURVIEW_P (decl) = module_purview_p ();
/* If this was imported, we'll still be in the entity_hash. */
DECL_MODULE_IMPORT_P (decl) = false;
if (TREE_CODE (decl) == TEMPLATE_DECL)
{
tree res = DECL_TEMPLATE_RESULT (decl);
retrofit_lang_decl (res);
DECL_MODULE_PURVIEW_P (res) = DECL_MODULE_PURVIEW_P (decl);
DECL_MODULE_IMPORT_P (res) = false;
}
}
}
@ -18547,7 +18490,6 @@ set_defining_module (tree decl)
gcc_checking_assert (!use_tpl);
/* Get to the TEMPLATE_DECL. */
decl = TI_TEMPLATE (ti);
gcc_checking_assert (!DECL_MODULE_IMPORT_P (decl));
}
/* Record it on the class_members list. */

View File

@ -1666,8 +1666,9 @@ name_lookup::search_adl (tree fns, vec<tree, va_gc> *args)
continue;
tree origin = get_originating_module_decl (TYPE_NAME (scope));
if (!DECL_LANG_SPECIFIC (origin)
|| !DECL_MODULE_IMPORT_P (origin))
tree not_tmpl = STRIP_TEMPLATE (origin);
if (!DECL_LANG_SPECIFIC (not_tmpl)
|| !DECL_MODULE_IMPORT_P (not_tmpl))
/* Not imported. */
continue;
@ -3680,6 +3681,7 @@ do_pushdecl (tree decl, bool hiding)
if (iter.using_p ())
; /* Ignore using decls here. */
else if (iter.hidden_p ()
&& TREE_CODE (*iter) == FUNCTION_DECL
&& DECL_LANG_SPECIFIC (*iter)
&& DECL_MODULE_IMPORT_P (*iter))
; /* An undeclared builtin imported from elsewhere. */

View File

@ -4930,16 +4930,8 @@ build_template_decl (tree decl, tree parms, bool member_template_p)
DECL_SOURCE_LOCATION (tmpl) = DECL_SOURCE_LOCATION (decl);
DECL_MEMBER_TEMPLATE_P (tmpl) = member_template_p;
if (modules_p ())
{
/* Propagate module information from the decl. */
DECL_MODULE_EXPORT_P (tmpl) = DECL_MODULE_EXPORT_P (decl);
if (DECL_LANG_SPECIFIC (decl))
{
DECL_MODULE_PURVIEW_P (tmpl) = DECL_MODULE_PURVIEW_P (decl);
gcc_checking_assert (!DECL_MODULE_IMPORT_P (decl));
}
}
/* Propagate module information from the decl. */
DECL_MODULE_EXPORT_P (tmpl) = DECL_MODULE_EXPORT_P (decl);
return tmpl;
}
@ -10167,25 +10159,7 @@ lookup_template_class_1 (tree d1, tree arglist, tree in_decl, tree context,
}
/* Build template info for the new specialization. */
if (TYPE_ALIAS_P (t))
{
/* This is constructed during instantiation of the alias
decl. But for member templates of template classes, that
is not correct as we need to refer to the partially
instantiated template, not the most general template.
The incorrect knowledge will not have escaped this
instantiation process, so we're good just updating the
template_info we made then. */
tree ti = DECL_TEMPLATE_INFO (TYPE_NAME (t));
gcc_checking_assert (template_args_equal (TI_ARGS (ti), arglist));
if (TI_TEMPLATE (ti) != found)
{
gcc_checking_assert (DECL_TI_TEMPLATE (found) == TI_TEMPLATE (ti));
TI_TEMPLATE (ti) = found;
}
}
else
SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist));
SET_TYPE_TEMPLATE_INFO (t, build_template_info (found, arglist));
elt.spec = t;
slot = type_specializations->find_slot_with_hash (&elt, hash, INSERT);
@ -14297,8 +14271,7 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,
}
else
{
if (TREE_CODE (decl) != TYPE_DECL || !TYPE_DECL_ALIAS_P (decl))
DECL_TI_TEMPLATE (inner) = r;
DECL_TI_TEMPLATE (inner) = r;
DECL_TI_ARGS (r) = DECL_TI_ARGS (inner);
}
@ -14311,17 +14284,13 @@ tsubst_template_decl (tree t, tree args, tsubst_flags_t complain,
/* Propagate module information from the decl. */
DECL_MODULE_EXPORT_P (r) = DECL_MODULE_EXPORT_P (inner);
if (DECL_LANG_SPECIFIC (inner))
{
DECL_MODULE_PURVIEW_P (r) = DECL_MODULE_PURVIEW_P (inner);
/* If this is a constrained template, the above tsubst of
inner can find the unconstrained template, which may have
come from an import. This is ok, because we don't
register this instantiation (see below). */
gcc_checking_assert (!DECL_MODULE_IMPORT_P (inner)
|| (TEMPLATE_PARMS_CONSTRAINTS
(DECL_TEMPLATE_PARMS (t))));
DECL_MODULE_IMPORT_P (r) = false;
}
/* If this is a constrained template, the above tsubst of
inner can find the unconstrained template, which may have
come from an import. This is ok, because we don't
register this instantiation (see below). */
gcc_checking_assert (!DECL_MODULE_IMPORT_P (inner)
|| (TEMPLATE_PARMS_CONSTRAINTS
(DECL_TEMPLATE_PARMS (t))));
}
DECL_TEMPLATE_INSTANTIATIONS (r) = NULL_TREE;

View File

@ -0,0 +1,12 @@
// PR 99283 part 2 ICE on definition with qualified-name
// { dg-additional-options -fmodule-header }
// { dg-module-cmi {} }
inline namespace __cxx11 {
template<typename _CharT>
class collate;
}

View File

@ -0,0 +1,22 @@
// { dg-additional-options -fmodule-header }
// { dg-module-cmi {} }
import "pr99283-2_a.H";
inline namespace __cxx11 {
template<typename _CharT>
class collate
{
};
}
template<typename _CharT>
void Check ()
{
typedef collate<char> __collate_type;
}

View File

@ -0,0 +1,20 @@
// { dg-additional-options -fmodule-header }
// { dg-module-cmi {} }
import "pr99283-2_a.H";
template<typename _CharT>
class __cxx11::collate
{
};
template<typename _CharT>
void Check ()
{
typedef collate<char> __collate_type;
}

View File

@ -0,0 +1,31 @@
// PR 99283 part 2 ICE on definition with qualified-name
// { dg-additional-options -fmodule-header }
// { dg-module-cmi {} }
template<bool, typename _Tp>
struct enable_if;
template<typename _Tp>
struct enable_if<true, _Tp>
{ typedef _Tp type; };
template<typename _CharT>
class basic_string;
typedef basic_string<char> string;
template<typename _CharT>
class basic_string
{
private:
template<typename _Tp>
using _If_sv = typename enable_if<true, int>::type;
public:
const _CharT *c_str() const noexcept;
};
inline void stoi(const string& __str)
{
__str.c_str ();
}

View File

@ -0,0 +1,9 @@
// { dg-additional-options {-fmodule-header -fno-module-lazy} }
// { dg-module-cmi {} }
template<typename _CharT>
class basic_string;
typedef basic_string<char> string;
import "pr99283-3_a.H";

View File

@ -0,0 +1,20 @@
// PR 99283 part 3, ICE with template alias as default template parm
// of member template
// { dg-additional-options -fmodule-header }
// { dg-module-cmi {} }
template<typename _Traits>
struct _Insert
{
using size_type = int;
template<typename _Pair>
using _IFconsp = bool;
template<typename _Pair, typename = _IFconsp<_Pair>>
int insert (_Pair&& __v);
};
void Foo (typename _Insert<int>::size_type);

View File

@ -3,7 +3,7 @@
#include "tpl-alias-1.h"
// { dg-final { scan-lang-dump {Writing named:-[0-9]* template_decl:'::allocator_traits<::allocator<long int>>::template rebind_alloc<_Up>'} module } }
// { dg-final { scan-lang-dump {Writing decl spec:-[0-9]* type_decl:'::allocator_traits<::allocator<long int>>::rebind_alloc<_Up>'} module } }
// { dg-final { scan-lang-dump {Writing:-[0-9]*'s decl spec merge key \(specialization\) type_decl:'::allocator_traits<::allocator<long int>>::rebind_alloc<_Up>'} module } }
// { dg-final { scan-lang-dump {Wrote\(-[0-9]*\) alias template type_decl:'::allocator_traits<::allocator<long int>>::rebind_alloc<_Up>'} module } }
// { dg-final { scan-lang-dump {Writing decl tmpl spec:-[0-9]* template_decl:'::allocator_traits<::allocator<long int>>::template rebind_alloc<_Up>'} module } }
// { dg-final { scan-lang-dump {Writing decl tmpl spec:-[0-9]* type_decl:'::allocator_traits<::allocator<long int>>::template rebind_alloc<_Up>'} module } }
// { dg-final { scan-lang-dump {Writing:-[0-9]*'s alias spec merge key \(specialization\) type_decl:'::allocator_traits<::allocator<long int>>::rebind_alloc<long int>'} module } }

View File

@ -3,7 +3,8 @@
#include "tpl-alias-1.h"
import "tpl-alias-1_a.H";
// { dg-final { scan-lang-dump {Read:-[0-9]*'s named merge key \(matched\) template_decl:'::allocator_traits<::allocator<long int>>::template rebind_alloc'} module } }
// { dg-final { scan-lang-dump {Read:-[0-9]*'s decl spec merge key \(matched\) type_decl:'::allocator_traits<::allocator<_Tp>>::rebind_alloc'} module } }
// { dg-final { scan-lang-dump {Read alias template type_decl:'::allocator_traits<::allocator<long int>>::rebind_alloc<_Up>'} module } }
// { dg-final { scan-lang-dump {Deduping '::allocator_traits<::allocator<_Tp>>::template rebind_alloc'} module } }
// { dg-final { scan-lang-dump {Deduping '::allocator_traits<::allocator<long int>>::template rebind_alloc<_Up>'} module } }
// { dg-final { scan-lang-dump {Deduping '::allocator_traits<::allocator<long int>>::rebind_alloc<long int>'} module } }
// { dg-final { scan-lang-dump-not {merge key \(new\)} module } }