diff options
author | Jason Merrill <jason@redhat.com> | 2007-09-14 02:07:25 -0400 |
---|---|---|
committer | Jason Merrill <jason@gcc.gnu.org> | 2007-09-14 02:07:25 -0400 |
commit | 4f4141ffe2458032fe7183e7579834145587dc3f (patch) | |
tree | 388e176a69dd27b65d6eeb4f7edbffb5f452e428 /gcc/cp | |
parent | d9933b9d648e6992468c894fec7e5e821125e4b7 (diff) | |
download | gcc-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/ChangeLog | 10 | ||||
-rw-r--r-- | gcc/cp/cp-tree.h | 1 | ||||
-rw-r--r-- | gcc/cp/decl2.c | 76 | ||||
-rw-r--r-- | gcc/cp/pt.c | 42 |
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; |