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::hash::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. -- Nathan Sidwell
diff --git c/gcc/cp/cp-tree.h w/gcc/cp/cp-tree.h index e68e3905f80..a4d4d69075f 100644 --- c/gcc/cp/cp-tree.h +++ w/gcc/cp/cp-tree.h @@ -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 diff --git c/gcc/cp/decl.c w/gcc/cp/decl.c index 3483b0c0398..6789aa859cc 100644 --- c/gcc/cp/decl.c +++ w/gcc/cp/decl.c @@ -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) diff --git c/gcc/cp/module.cc w/gcc/cp/module.cc index e4da5557f9e..8a1cfbdfdcb 100644 --- c/gcc/cp/module.cc +++ w/gcc/cp/module.cc @@ -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) + tree not_tmpl = STRIP_TEMPLATE (decl); + + if (DECL_LANG_SPECIFIC (not_tmpl) + && DECL_MODULE_IMPORT_P (not_tmpl)) { - dep->cluster = index - from->entity_lwm; - dep->section = from->remap; - dep->set_flag_bit<DB_IMPORTED_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); - 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 (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))) { - /* 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))) + 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. */ diff --git c/gcc/cp/name-lookup.c w/gcc/cp/name-lookup.c index f4263f15f62..3bce3d597dc 100644 --- c/gcc/cp/name-lookup.c +++ w/gcc/cp/name-lookup.c @@ -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. */ diff --git c/gcc/cp/pt.c w/gcc/cp/pt.c index 2736bb43299..a056ecefd1d 100644 --- c/gcc/cp/pt.c +++ w/gcc/cp/pt.c @@ -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; diff --git c/gcc/testsuite/g++.dg/modules/pr99283-2_a.H w/gcc/testsuite/g++.dg/modules/pr99283-2_a.H new file mode 100644 index 00000000000..c5faf1d6205 --- /dev/null +++ w/gcc/testsuite/g++.dg/modules/pr99283-2_a.H @@ -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; + +} + + diff --git c/gcc/testsuite/g++.dg/modules/pr99283-2_b.H w/gcc/testsuite/g++.dg/modules/pr99283-2_b.H new file mode 100644 index 00000000000..a1b7d603ff7 --- /dev/null +++ w/gcc/testsuite/g++.dg/modules/pr99283-2_b.H @@ -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; +} + + + + + + diff --git c/gcc/testsuite/g++.dg/modules/pr99283-2_c.H w/gcc/testsuite/g++.dg/modules/pr99283-2_c.H new file mode 100644 index 00000000000..82639282f07 --- /dev/null +++ w/gcc/testsuite/g++.dg/modules/pr99283-2_c.H @@ -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; +} + + + + + + diff --git c/gcc/testsuite/g++.dg/modules/pr99283-3_a.H w/gcc/testsuite/g++.dg/modules/pr99283-3_a.H new file mode 100644 index 00000000000..5926b9d2672 --- /dev/null +++ w/gcc/testsuite/g++.dg/modules/pr99283-3_a.H @@ -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 (); +} diff --git c/gcc/testsuite/g++.dg/modules/pr99283-3_b.H w/gcc/testsuite/g++.dg/modules/pr99283-3_b.H new file mode 100644 index 00000000000..cb14de613e3 --- /dev/null +++ w/gcc/testsuite/g++.dg/modules/pr99283-3_b.H @@ -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"; diff --git c/gcc/testsuite/g++.dg/modules/pr99283-4.H w/gcc/testsuite/g++.dg/modules/pr99283-4.H new file mode 100644 index 00000000000..d15ccc440b7 --- /dev/null +++ w/gcc/testsuite/g++.dg/modules/pr99283-4.H @@ -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); + + diff --git c/gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H w/gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H index 502a649c74d..37002ee9ae1 100644 --- c/gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H +++ w/gcc/testsuite/g++.dg/modules/tpl-alias-1_a.H @@ -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 } } diff --git c/gcc/testsuite/g++.dg/modules/tpl-alias-1_b.C w/gcc/testsuite/g++.dg/modules/tpl-alias-1_b.C index 59fd09c0454..cc9499f54fc 100644 --- c/gcc/testsuite/g++.dg/modules/tpl-alias-1_b.C +++ w/gcc/testsuite/g++.dg/modules/tpl-alias-1_b.C @@ -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 } }