aboutsummaryrefslogtreecommitdiff
path: root/gcc/cp
diff options
context:
space:
mode:
authorJason Merrill <jason@redhat.com>2007-09-14 02:07:25 -0400
committerJason Merrill <jason@gcc.gnu.org>2007-09-14 02:07:25 -0400
commit4f4141ffe2458032fe7183e7579834145587dc3f (patch)
tree388e176a69dd27b65d6eeb4f7edbffb5f452e428 /gcc/cp
parentd9933b9d648e6992468c894fec7e5e821125e4b7 (diff)
downloadgcc-4f4141ffe2458032fe7183e7579834145587dc3f.zip
gcc-4f4141ffe2458032fe7183e7579834145587dc3f.tar.gz
gcc-4f4141ffe2458032fe7183e7579834145587dc3f.tar.bz2
PR c++/17743, c++/19163
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. From-SVN: r128488
Diffstat (limited to 'gcc/cp')
-rw-r--r--gcc/cp/ChangeLog10
-rw-r--r--gcc/cp/cp-tree.h1
-rw-r--r--gcc/cp/decl2.c76
-rw-r--r--gcc/cp/pt.c42
4 files changed, 128 insertions, 1 deletions
diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog
index dfcbb02..26028a5 100644
--- a/gcc/cp/ChangeLog
+++ b/gcc/cp/ChangeLog
@@ -1,3 +1,13 @@
+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
diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h
index 5efbdb7..4f1e88c 100644
--- a/gcc/cp/cp-tree.h
+++ b/gcc/cp/cp-tree.h
@@ -4276,6 +4276,7 @@ extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *,
tree, bool, tree, tree);
extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *,
tree);
+extern bool is_late_template_attribute (tree);
extern void cplus_decl_attributes (tree *, tree, int);
extern void finish_anon_union (tree);
extern void cp_write_global_declarations (void);
diff --git a/gcc/cp/decl2.c b/gcc/cp/decl2.c
index db578d8..0c0961d 100644
--- a/gcc/cp/decl2.c
+++ b/gcc/cp/decl2.c
@@ -985,13 +985,87 @@ grokbitfield (const cp_declarator *declarator,
}
+/* 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);
diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c
index e26958c..d918d86 100644
--- a/gcc/cp/pt.c
+++ b/gcc/cp/pt.c
@@ -6477,6 +6477,33 @@ can_complete_type_without_circularity (tree type)
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)
{
@@ -6647,6 +6674,9 @@ 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
@@ -7872,6 +7902,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
= remove_attribute ("visibility", DECL_ATTRIBUTES (r));
}
determine_visibility (r);
+
+ apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
+ args, complain, in_decl);
}
break;
@@ -7965,6 +7998,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t 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);
+
/* Keep track of the first new parameter we
generate. That's what will be returned to the
caller. */
@@ -8007,6 +8043,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
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;
@@ -8201,6 +8240,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
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;