diff options
Diffstat (limited to 'gcc/cp/pt.cc')
-rw-r--r-- | gcc/cp/pt.cc | 87 |
1 files changed, 72 insertions, 15 deletions
diff --git a/gcc/cp/pt.cc b/gcc/cp/pt.cc index 538ff22..95b89f12 100644 --- a/gcc/cp/pt.cc +++ b/gcc/cp/pt.cc @@ -12134,13 +12134,18 @@ tsubst_attribute (tree t, tree *decl_p, tree args, location_t match_loc = cp_expr_loc_or_input_loc (TREE_PURPOSE (chain)); tree ctx = copy_list (TREE_VALUE (val)); tree append_args_list = TREE_CHAIN (TREE_CHAIN (chain)); - if (append_args_list && TREE_VALUE (append_args_list)) + if (append_args_list + && TREE_VALUE (append_args_list) + && TREE_CHAIN (TREE_VALUE (append_args_list))) { - append_args_list = TREE_VALUE (TREE_VALUE (append_args_list)); + append_args_list = TREE_VALUE (append_args_list); + append_args_list = TREE_VALUE (TREE_CHAIN (append_args_list)); for (; append_args_list; append_args_list = TREE_CHAIN (append_args_list)) { tree pref_list = TREE_VALUE (append_args_list); + if (pref_list == NULL_TREE || TREE_CODE (pref_list) != TREE_LIST) + continue; tree fr_list = TREE_VALUE (pref_list); int len = TREE_VEC_LENGTH (fr_list); for (int i = 0; i < len; i++) @@ -15920,6 +15925,11 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain, if (TYPE_USER_ALIGN (TREE_TYPE (t))) TREE_TYPE (r) = build_aligned_type (TREE_TYPE (r), TYPE_ALIGN (TREE_TYPE (t))); + + /* Preserve structural-ness of a partially instantiated typedef. */ + if (TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (t)) + && dependent_type_p (TREE_TYPE (r))) + SET_TYPE_STRUCTURAL_EQUALITY (TREE_TYPE (r)); } layout_decl (r, 0); @@ -17731,13 +17741,37 @@ maybe_dependent_member_ref (tree t, tree args, tsubst_flags_t complain, if (TYPE_P (t)) { + bool stripped = false; if (typedef_variant_p (t)) - t = strip_typedefs (t); - tree decl = TYPE_NAME (t); + { + /* Since this transformation may undesirably turn a deduced context + into a non-deduced one, we'd rather strip typedefs than perform + the transformation. */ + tree u = strip_typedefs (t); + if (u != t) + { + stripped = true; + t = u; + } + } + decl = TYPE_NAME (t); if (decl) decl = maybe_dependent_member_ref (decl, args, complain, in_decl); if (!decl) - return NULL_TREE; + { + if (stripped) + /* The original type was an alias from the current instantiation + which we stripped to something outside it. At this point we + need to commit to using the stripped type rather than deferring + to the caller (which would use the original type), to ensure + eligible bits of the stripped type get transformed. */ + return tsubst (t, args, complain, in_decl); + else + /* The original type wasn't a typedef, and we decided it doesn't + need rewriting, so just let the caller (tsubst) substitute it + normally. */ + return NULL_TREE; + } return cp_build_qualified_type (TREE_TYPE (decl), cp_type_quals (t), complain); } @@ -17755,7 +17789,8 @@ maybe_dependent_member_ref (tree t, tree args, tsubst_flags_t complain, if (TREE_CODE (t) == TYPE_DECL) { - if (TREE_CODE (TREE_TYPE (t)) == TYPENAME_TYPE + if (!is_typedef_decl (t) + && TREE_CODE (TREE_TYPE (t)) == TYPENAME_TYPE && TYPE_NAME (TREE_TYPE (t)) == t) /* The TYPE_DECL for a typename has DECL_CONTEXT of the typename scope, but it doesn't need to be rewritten again. */ @@ -25958,6 +25993,23 @@ mark_definable (tree decl) DECL_NOT_REALLY_EXTERN (clone) = 1; } +/* DECL is an explicit instantiation definition, ensure that it will + be written out here and that it won't clash with other instantiations + in other translation units. */ + +void +setup_explicit_instantiation_definition_linkage (tree decl) +{ + mark_definable (decl); + mark_needed (decl); + /* Always make artificials weak. */ + if (DECL_ARTIFICIAL (decl) && flag_weak) + comdat_linkage (decl); + /* We also want to put explicit instantiations in linkonce sections. */ + else if (TREE_PUBLIC (decl)) + maybe_make_one_only (decl); +} + /* Called if RESULT is explicitly instantiated, or is a member of an explicitly instantiated class. */ @@ -25995,16 +26047,8 @@ mark_decl_instantiated (tree result, int extern_p) } else { - mark_definable (result); - mark_needed (result); set_instantiating_module (result); - /* Always make artificials weak. */ - if (DECL_ARTIFICIAL (result) && flag_weak) - comdat_linkage (result); - /* For WIN32 we also want to put explicit instantiations in - linkonce sections. */ - else if (TREE_PUBLIC (result)) - maybe_make_one_only (result); + setup_explicit_instantiation_definition_linkage (result); if (TREE_CODE (result) == FUNCTION_DECL && DECL_TEMPLATE_INSTANTIATED (result)) /* If the function has already been instantiated, clear DECL_EXTERNAL, @@ -27219,6 +27263,19 @@ regenerate_decl_from_template (tree decl, tree tmpl, tree args) if (DECL_UNIQUE_FRIEND_P (decl)) goto done; + /* A template with a lambda in the signature also changes type if + regenerated (PR119401). */ + walk_tree_fn find_lambda + = [](tree *tp, int *, void *) + { + if (TREE_CODE (*tp) == LAMBDA_EXPR) + return *tp; + return NULL_TREE; + }; + if (cp_walk_tree_without_duplicates + (&TREE_TYPE (tmpl), find_lambda, nullptr)) + goto done; + /* Use the source location of the definition. */ DECL_SOURCE_LOCATION (decl) = DECL_SOURCE_LOCATION (tmpl); |