static tree tsubst_template_parm (tree, tree, tsubst_flags_t);
static tree instantiate_alias_template (tree, tree, tsubst_flags_t);
static bool complex_alias_template_p (const_tree tmpl);
+static tree tsubst_attributes (tree, tree, tsubst_flags_t, tree);
/* Make the current scope suitable for access checking when we are
processing T. T can be FUNCTION_DECL for instantiated function
t = start_enum (TYPE_IDENTIFIER (template_type), NULL_TREE,
tsubst (ENUM_UNDERLYING_TYPE (template_type),
arglist, complain, in_decl),
+ tsubst_attributes (TYPE_ATTRIBUTES (template_type),
+ arglist, complain, in_decl),
SCOPED_ENUM_P (template_type), NULL);
if (t == error_mark_node)
static tree tsubst_omp_clauses (tree, bool, bool, tree, tsubst_flags_t, tree);
+/* Instantiate a single dependent attribute T (a TREE_LIST), and return either
+ T or a new TREE_LIST, possibly a chain in the case of a pack expansion. */
+
+static tree
+tsubst_attribute (tree t, tree *decl_p, tree args,
+ tsubst_flags_t complain, tree in_decl)
+{
+ gcc_assert (ATTR_IS_DEPENDENT (t));
+
+ tree val = TREE_VALUE (t);
+ if (val == NULL_TREE)
+ /* Nothing to do. */;
+ else if ((flag_openmp || flag_openmp_simd || flag_cilkplus)
+ && is_attribute_p ("omp declare simd",
+ get_attribute_name (t)))
+ {
+ tree clauses = TREE_VALUE (val);
+ clauses = tsubst_omp_clauses (clauses, true, false, args,
+ complain, in_decl);
+ c_omp_declare_simd_clauses_to_decls (*decl_p, clauses);
+ clauses = finish_omp_clauses (clauses, false, true);
+ tree parms = DECL_ARGUMENTS (*decl_p);
+ clauses
+ = c_omp_declare_simd_clauses_to_numbers (parms, clauses);
+ if (clauses)
+ val = build_tree_list (NULL_TREE, clauses);
+ else
+ val = NULL_TREE;
+ }
+ /* If the first attribute argument is an identifier, don't
+ pass it through tsubst. Attributes like mode, format,
+ cleanup and several target specific attributes expect it
+ unmodified. */
+ else if (attribute_takes_identifier_p (get_attribute_name (t)))
+ {
+ tree chain
+ = tsubst_expr (TREE_CHAIN (val), args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+ if (chain != TREE_CHAIN (val))
+ val = tree_cons (NULL_TREE, TREE_VALUE (val), chain);
+ }
+ else if (PACK_EXPANSION_P (val))
+ {
+ /* An attribute pack expansion. */
+ tree purp = TREE_PURPOSE (t);
+ tree pack = tsubst_pack_expansion (val, args, complain, in_decl);
+ int len = TREE_VEC_LENGTH (pack);
+ tree list = NULL_TREE;
+ tree *q = &list;
+ for (int i = 0; i < len; ++i)
+ {
+ tree elt = TREE_VEC_ELT (pack, i);
+ *q = build_tree_list (purp, elt);
+ q = &TREE_CHAIN (*q);
+ }
+ return list;
+ }
+ else
+ val = tsubst_expr (val, args, complain, in_decl,
+ /*integral_constant_expression_p=*/false);
+
+ if (val != TREE_VALUE (t))
+ return build_tree_list (TREE_PURPOSE (t), val);
+ return t;
+}
+
+/* Instantiate any dependent attributes in ATTRIBUTES, returning either it
+ unchanged or a new TREE_LIST chain. */
+
+static tree
+tsubst_attributes (tree attributes, tree args,
+ tsubst_flags_t complain, tree in_decl)
+{
+ tree last_dep = NULL_TREE;
+
+ for (tree t = attributes; t; t = TREE_CHAIN (t))
+ if (ATTR_IS_DEPENDENT (t))
+ {
+ last_dep = t;
+ attributes = copy_list (attributes);
+ break;
+ }
+
+ if (last_dep)
+ for (tree *p = &attributes; *p; p = &TREE_CHAIN (*p))
+ {
+ tree t = *p;
+ if (ATTR_IS_DEPENDENT (t))
+ {
+ tree subst = tsubst_attribute (t, NULL, args, complain, in_decl);
+ if (subst == t)
+ continue;
+ *p = subst;
+ do
+ p = &TREE_CHAIN (*p);
+ while (*p);
+ *p = TREE_CHAIN (t);
+ }
+ }
+
+ return attributes;
+}
+
/* 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. */
{
*p = TREE_CHAIN (t);
TREE_CHAIN (t) = NULL_TREE;
- if ((flag_openmp || flag_openmp_simd || flag_cilkplus)
- && is_attribute_p ("omp declare simd",
- get_attribute_name (t))
- && TREE_VALUE (t))
- {
- tree clauses = TREE_VALUE (TREE_VALUE (t));
- clauses = tsubst_omp_clauses (clauses, true, false, args,
- complain, in_decl);
- c_omp_declare_simd_clauses_to_decls (*decl_p, clauses);
- clauses = finish_omp_clauses (clauses, false, true);
- tree parms = DECL_ARGUMENTS (*decl_p);
- clauses
- = c_omp_declare_simd_clauses_to_numbers (parms, clauses);
- if (clauses)
- TREE_VALUE (TREE_VALUE (t)) = clauses;
- else
- TREE_VALUE (t) = NULL_TREE;
- }
- /* If the first attribute argument is an identifier, don't
- pass it through tsubst. Attributes like mode, format,
- cleanup and several target specific attributes expect it
- unmodified. */
- else if (attribute_takes_identifier_p (get_attribute_name (t))
- && TREE_VALUE (t))
- {
- tree chain
- = tsubst_expr (TREE_CHAIN (TREE_VALUE (t)), args, complain,
- in_decl,
- /*integral_constant_expression_p=*/false);
- if (chain != TREE_CHAIN (TREE_VALUE (t)))
- TREE_VALUE (t)
- = tree_cons (NULL_TREE, TREE_VALUE (TREE_VALUE (t)),
- chain);
- }
- else if (TREE_VALUE (t) && PACK_EXPANSION_P (TREE_VALUE (t)))
- {
- /* An attribute pack expansion. */
- tree purp = TREE_PURPOSE (t);
- tree pack = (tsubst_pack_expansion
- (TREE_VALUE (t), args, complain, in_decl));
- int len = TREE_VEC_LENGTH (pack);
- for (int i = 0; i < len; ++i)
- {
- tree elt = TREE_VEC_ELT (pack, i);
- *q = build_tree_list (purp, elt);
- q = &TREE_CHAIN (*q);
- }
- continue;
- }
- else
- TREE_VALUE (t)
- = tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
- /*integral_constant_expression_p=*/false);
- *q = t;
- q = &TREE_CHAIN (t);
+ *q = tsubst_attribute (t, decl_p, args, complain, in_decl);
+ do
+ q = &TREE_CHAIN (*q);
+ while (*q);
}
else
p = &TREE_CHAIN (t);