+2007-09-14 Jason Merrill <jason@redhat.com>
+
+ PR c++/17743, c++/19163
+ * decl2.c (is_late_template_attribute): New fn.
+ (splice_template_attributes, save_template_attributes): New fns.
+ (cplus_decl_attributes): Call save_template_attributes.
+ * pt.c (apply_late_template_attributes): New fn.
+ (instantiate_class_template, tsubst_decl): Use it.
+ * cp-tree.h: Declare is_late_template_attribute.
+
2007-09-13 Tom Tromey <tromey@redhat.com>
* parser.c (cp_lexer_new_main): Don't use
}
\f
+/* Returns true iff ATTR is an attribute which needs to be applied at
+ instantiation time rather than template definition time. */
+
+bool
+is_late_template_attribute (tree attr)
+{
+ tree name = TREE_PURPOSE (attr);
+ if (is_attribute_p ("aligned", name))
+ return true;
+ else
+ return false;
+}
+
+/* ATTR_P is a list of attributes. Remove any attributes which need to be
+ applied at instantiation time and return them. */
+
+static tree
+splice_template_attributes (tree *attr_p)
+{
+ 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))
+ {
+ *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);
+ tree *q;
+
+ if (!late_attrs)
+ return;
+
+ 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. */
+
void
cplus_decl_attributes (tree *decl, tree attributes, int flags)
{
if (*decl == NULL_TREE || *decl == void_type_node
- || *decl == error_mark_node)
+ || *decl == error_mark_node
+ || attributes == NULL_TREE)
return;
+ if (processing_template_decl)
+ {
+ save_template_attributes (&attributes, decl);
+ if (attributes == NULL_TREE)
+ return;
+ }
+
if (TREE_CODE (*decl) == TEMPLATE_DECL)
decl = &DECL_TEMPLATE_RESULT (*decl);
return 1;
}
+/* 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. */
+
+static void
+apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
+ tree args, tsubst_flags_t complain, tree in_decl)
+{
+ tree late_attrs = NULL_TREE;
+ tree t;
+
+ if (DECL_P (*decl_p))
+ DECL_ATTRIBUTES (*decl_p) = attributes;
+ else
+ TYPE_ATTRIBUTES (*decl_p) = attributes;
+
+ for (t = attributes; t; t = TREE_CHAIN (t))
+ if (is_late_template_attribute (t))
+ late_attrs = tree_cons
+ (TREE_PURPOSE (t),
+ tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
+ /*integral_constant_expression_p=*/false),
+ late_attrs);
+
+ cplus_decl_attributes (decl_p, late_attrs, attr_flags);
+}
+
tree
instantiate_class_template (tree type)
{
information. */
xref_basetypes (type, base_list);
+ apply_late_template_attributes (&type, TYPE_ATTRIBUTES (pattern),
+ (int) ATTR_FLAG_TYPE_IN_PLACE,
+ args, tf_error, NULL_TREE);
/* Now that our base classes are set up, enter the scope of the
class, so that name lookups into base classes, etc. will work
= remove_attribute ("visibility", DECL_ATTRIBUTES (r));
}
determine_visibility (r);
+
+ apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl);
}
break;
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);
+
/* Keep track of the first new parameter we
generate. That's what will be returned to the
caller. */
TREE_CHAIN (r) = NULL_TREE;
if (VOID_TYPE_P (type))
error ("instantiation of %q+D as type %qT", r, type);
+
+ apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl);
}
break;
register_local_specialization (r, t);
TREE_CHAIN (r) = NULL_TREE;
+
+ apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl);
layout_decl (r, 0);
}
break;