+/* Returns true iff ATTR is an attribute which needs to be applied at
+ instantiation time rather than template definition time. */
+
+static bool
+is_late_template_attribute (tree attr, tree decl)
+{
+ tree name = TREE_PURPOSE (attr);
+ tree args = TREE_VALUE (attr);
+ const struct attribute_spec *spec = lookup_attribute_spec (name);
+
+ if (!spec)
+ /* Unknown attribute. */
+ return false;
+
+ if (is_attribute_p ("aligned", name)
+ && args
+ && value_dependent_expression_p (TREE_VALUE (args)))
+ /* Can't apply this until we know the desired alignment. */
+ return true;
+ else if (TREE_CODE (decl) == TYPE_DECL || spec->type_required)
+ {
+ tree type = TYPE_P (decl) ? decl : TREE_TYPE (decl);
+
+ /* We can't apply any attributes to a completely unknown type until
+ instantiation time. */
+ enum tree_code code = TREE_CODE (type);
+ if (code == TEMPLATE_TYPE_PARM
+ || code == BOUND_TEMPLATE_TEMPLATE_PARM
+ || code == TYPENAME_TYPE)
+ return true;
+ else
+ return false;
+ }
+ else
+ return false;
+}
+
+/* ATTR_P is a list of attributes. Remove any attributes which need to be
+ applied at instantiation time and return them. If IS_DEPENDENT is true,
+ the declaration itself is dependent, so all attributes should be applied
+ at instantiation time. */
+
+static tree
+splice_template_attributes (tree *attr_p, tree decl)
+{
+ tree *p = attr_p;
+ tree late_attrs = NULL_TREE;
+ tree *q = &late_attrs;
+
+ if (!p)
+ return NULL_TREE;
+
+ for (; *p; )
+ {
+ if (is_late_template_attribute (*p, decl))
+ {
+ ATTR_IS_DEPENDENT (*p) = 1;
+ *q = *p;
+ *p = TREE_CHAIN (*p);
+ q = &TREE_CHAIN (*q);
+ *q = NULL_TREE;
+ }
+ else
+ p = &TREE_CHAIN (*p);
+ }
+
+ return late_attrs;
+}
+
+/* Remove any late attributes from the list in ATTR_P and attach them to
+ DECL_P. */
+
+static void
+save_template_attributes (tree *attr_p, tree *decl_p)
+{
+ tree late_attrs = splice_template_attributes (attr_p, *decl_p);
+ tree *q;
+
+ if (!late_attrs)
+ return;
+
+ /* Give this type a name so we know to look it up again at instantiation
+ time. */
+ if (TREE_CODE (*decl_p) == TYPE_DECL
+ && DECL_ORIGINAL_TYPE (*decl_p) == NULL_TREE)
+ {
+ tree oldt = TREE_TYPE (*decl_p);
+ tree newt = build_variant_type_copy (oldt);
+ DECL_ORIGINAL_TYPE (*decl_p) = oldt;
+ TREE_TYPE (*decl_p) = newt;
+ TYPE_NAME (newt) = *decl_p;
+ TREE_USED (newt) = TREE_USED (*decl_p);
+ }
+
+ if (DECL_P (*decl_p))
+ q = &DECL_ATTRIBUTES (*decl_p);
+ else
+ q = &TYPE_ATTRIBUTES (*decl_p);
+
+ if (*q)
+ q = &TREE_CHAIN (tree_last (*q));
+ *q = late_attrs;
+}
+
+/* Like decl_attributes, but handle C++ complexity. */
+