aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp/pt.cc
diff options
context:
space:
mode:
Diffstat (limited to 'gcc/cp/pt.cc')
-rw-r--r--gcc/cp/pt.cc87
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);