val = tsubst_expr (val, args, complain, in_decl,
/*integral_constant_expression_p=*/false);
+ if (val == error_mark_node)
+ return error_mark_node;
if (val != TREE_VALUE (t))
return build_tree_list (TREE_PURPOSE (t), val);
return t;
/* Apply any attributes which had to be deferred until instantiation
time. DECL_P, ATTRIBUTES and ATTR_FLAGS are as cplus_decl_attributes;
- ARGS, COMPLAIN, IN_DECL are as tsubst. */
+ ARGS, COMPLAIN, IN_DECL are as tsubst. Returns true normally,
+ false on error. */
-static void
+static bool
apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
tree args, tsubst_flags_t complain, tree in_decl)
{
tree *p;
if (attributes == NULL_TREE)
- return;
+ return true;
if (DECL_P (*decl_p))
{
if (TREE_TYPE (*decl_p) == error_mark_node)
- return;
+ return false;
p = &DECL_ATTRIBUTES (*decl_p);
/* DECL_ATTRIBUTES comes from copy_node in tsubst_decl, and is identical
to our attributes parameter. */
t = *p;
if (ATTR_IS_DEPENDENT (t))
{
+ *q = tsubst_attribute (t, decl_p, args, complain, in_decl);
+ if (*q == error_mark_node)
+ return false;
*p = TREE_CHAIN (t);
TREE_CHAIN (t) = NULL_TREE;
- *q = tsubst_attribute (t, decl_p, args, complain, in_decl);
while (*q)
q = &TREE_CHAIN (*q);
}
cplus_decl_attributes (decl_p, late_attrs, attr_flags);
}
+ return true;
}
/* The template TMPL is being instantiated with the template arguments TARGS.
tsubst (DECL_FRIEND_CONTEXT (t),
args, complain, in_decl));
+ if (!apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl))
+ return error_mark_node;
+
/* Set up the DECL_TEMPLATE_INFO for R. There's no need to do
this in the special friend case mentioned above where
GEN_TMPL is NULL. */
&& !processing_template_decl)
defaulted_late_check (r);
- apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
- args, complain, in_decl);
if (flag_openmp)
if (tree attr = lookup_attribute ("omp declare variant base",
DECL_ATTRIBUTES (r)))
/* The template parameters for this new template are all the
template parameters for the old template, except the
outermost level of parameters. */
+ auto tparm_guard = make_temp_override (current_template_parms);
DECL_TEMPLATE_PARMS (r)
+ = current_template_parms
= tsubst_template_parms (DECL_TEMPLATE_PARMS (t), args,
complain);
if (!DECL_TEMPLATE_PARM_P (r))
DECL_ARG_TYPE (r) = type_passed_as (type);
- apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
- args, complain, in_decl);
+ if (!apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl))
+ return error_mark_node;
/* Keep track of the first new parameter we
generate. That's what will be returned to the
finish_member_declaration. */
DECL_CHAIN (r) = NULL_TREE;
- apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
- args, complain, in_decl);
+ if (!apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl))
+ return error_mark_node;
if (vec)
TREE_VEC_ELT (vec, i) = r;
DECL_CHAIN (r) = NULL_TREE;
- apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
- /*flags=*/0,
- args, complain, in_decl);
+ if (!apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
+ /*flags=*/0,
+ args, complain, in_decl))
+ return error_mark_node;
/* Preserve a typedef that names a type. */
if (is_typedef_decl (r) && type != error_mark_node)