From a7f6bc8c748862257b9b6e22034fd4ae0ffd4c38 Mon Sep 17 00:00:00 2001 From: Jason Merrill Date: Sat, 22 Sep 2007 22:36:34 -0400 Subject: [PATCH] re PR c++/19407 (vector keyword in typedef inside template struct ignored) PR c++/19407 * cp/cp-tree.h (ATTR_IS_DEPENDENT): New macro. (MAYBE_TAGGED_TYPE_P): Remove. * cp/pt.c (apply_late_template_attributes): Check ATTR_IS_DEPENDENT instead of calling is_late_template_attribute again. (tsubst_decl) [TYPE_DECL]: Just check if the name is the tag. (tsubst): A typedef is a TYPE_NAME != TYPE_MAIN_DECL. Don't crash on typedefs from non-template classes. * cp/decl2.c (grokfield): Don't sorry about attrs on template parms. (is_late_template_attribute): All attributes applied to template parms or typename types are dependent. Static, take decl. (splice_template_attributes): Pass decl through. (save_template_attributes): Likewise. * attribs.c (lookup_attribute_spec): Split out... (decl_attributes): From here. * tree.h: Declare it. From-SVN: r128681 --- gcc/ChangeLog | 7 ++++ gcc/attribs.c | 23 ++++++++----- gcc/cp/ChangeLog | 16 +++++++++ gcc/cp/cp-tree.h | 10 +++--- gcc/cp/decl2.c | 43 +++++++++++++++--------- gcc/cp/pt.c | 37 +++++++------------- gcc/testsuite/g++.dg/ext/attrib20.C | 6 ++-- gcc/testsuite/g++.dg/ext/tmplattr5.C | 33 ++++++++++++++++++ gcc/testsuite/g++.dg/template/typedef7.C | 15 +++++++++ gcc/tree.h | 2 ++ 10 files changed, 136 insertions(+), 56 deletions(-) create mode 100644 gcc/testsuite/g++.dg/ext/tmplattr5.C create mode 100644 gcc/testsuite/g++.dg/template/typedef7.C diff --git a/gcc/ChangeLog b/gcc/ChangeLog index 85934036f35..2de9c65b9ad 100644 --- a/gcc/ChangeLog +++ b/gcc/ChangeLog @@ -1,3 +1,10 @@ +2007-09-22 Jason Merrill + + PR c++/19407 + * attribs.c (lookup_attribute_spec): Split out... + (decl_attributes): From here. + * tree.h: Declare it. + 2007-09-22 Richard Sandiford * doc/sourcebuild.texi: Document dg-add-options mips16_attribute. diff --git a/gcc/attribs.c b/gcc/attribs.c index feb1c301570..31b92cad508 100644 --- a/gcc/attribs.c +++ b/gcc/attribs.c @@ -195,6 +195,20 @@ init_attributes (void) } attributes_initialized = true; } + +/* Return the spec for the attribute named NAME. */ + +const struct attribute_spec * +lookup_attribute_spec (tree name) +{ + struct substring attr; + + attr.str = IDENTIFIER_POINTER (name); + attr.length = IDENTIFIER_LENGTH (name); + extract_attribute_substring (&attr); + return htab_find_with_hash (attribute_hash, &attr, + substring_hash (attr.str, attr.length)); +} /* Process the attributes listed in ATTRIBUTES and install them in *NODE, which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL, @@ -221,16 +235,9 @@ decl_attributes (tree *node, tree attributes, int flags) tree name = TREE_PURPOSE (a); tree args = TREE_VALUE (a); tree *anode = node; - const struct attribute_spec *spec = NULL; + const struct attribute_spec *spec = lookup_attribute_spec (name); bool no_add_attrs = 0; tree fn_ptr_tmp = NULL_TREE; - struct substring attr; - - attr.str = IDENTIFIER_POINTER (name); - attr.length = IDENTIFIER_LENGTH (name); - extract_attribute_substring (&attr); - spec = htab_find_with_hash (attribute_hash, &attr, - substring_hash (attr.str, attr.length)); if (spec == NULL) { diff --git a/gcc/cp/ChangeLog b/gcc/cp/ChangeLog index 5310aa9e4a9..4c4e5847d3a 100644 --- a/gcc/cp/ChangeLog +++ b/gcc/cp/ChangeLog @@ -1,3 +1,19 @@ +2007-09-22 Jason Merrill + + PR c++/19407 + * cp-tree.h (ATTR_IS_DEPENDENT): New macro. + (MAYBE_TAGGED_TYPE_P): Remove. + * pt.c (apply_late_template_attributes): Check ATTR_IS_DEPENDENT + instead of calling is_late_template_attribute again. + (tsubst_decl) [TYPE_DECL]: Just check if the name is the tag. + (tsubst): A typedef is a TYPE_NAME != TYPE_MAIN_DECL. + Don't crash on typedefs from non-template classes. + * decl2.c (grokfield): Don't sorry about attrs on template parms. + (is_late_template_attribute): All attributes applied to template + parms or typename types are dependent. Static. + (splice_template_attributes): Pass decl through. + (save_template_attributes): Likewise. + 2007-09-20 Jakub Jelinek PR c++/33496 diff --git a/gcc/cp/cp-tree.h b/gcc/cp/cp-tree.h index 1ddf88492c6..fbe1bcc0170 100644 --- a/gcc/cp/cp-tree.h +++ b/gcc/cp/cp-tree.h @@ -58,6 +58,7 @@ struct diagnostic_context; TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR) TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX) TYPE_REF_IS_RVALUE (in REFERENCE_TYPE) + ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute) 1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) TI_PENDING_TEMPLATE_FLAG. TEMPLATE_PARMS_FOR_INLINE. @@ -988,10 +989,6 @@ enum languages { lang_c, lang_cplusplus, lang_java }; ((T) == RECORD_TYPE || (T) == UNION_TYPE) #define TAGGED_TYPE_P(T) \ (CLASS_TYPE_P (T) || TREE_CODE (T) == ENUMERAL_TYPE) -/* A tagged type or a dependent type that might be a tagged type when - instantiated. Like IS_AGGR_TYPE, but include enums as well. */ -#define MAYBE_TAGGED_TYPE_P(T) \ - (IS_AGGR_TYPE(T) || TREE_CODE (T) == ENUMERAL_TYPE) #define IS_OVERLOAD_TYPE(T) TAGGED_TYPE_P (T) /* True if this a "Java" type, defined in 'extern "Java"'. */ @@ -2134,6 +2131,10 @@ struct lang_decl GTY(()) directives */ #define TREE_INDIRECT_USING(NODE) (TREE_LIST_CHECK (NODE)->base.lang_flag_0) +/* In a TREE_LIST in an attribute list, indicates that the attribute + must be applied at instantiation time. */ +#define ATTR_IS_DEPENDENT(NODE) (TREE_LIST_CHECK (NODE)->base.lang_flag_0) + extern tree decl_shadowed_for_var_lookup (tree); extern void decl_shadowed_for_var_insert (tree, tree); @@ -4280,7 +4281,6 @@ 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 a8c0f9262a0..d58194265db 100644 --- a/gcc/cp/decl2.c +++ b/gcc/cp/decl2.c @@ -800,16 +800,7 @@ grokfield (const cp_declarator *declarator, value = push_template_decl (value); if (attrlist) - { - /* Avoid storing attributes in template parameters: - tsubst is not ready to handle them. */ - tree type = TREE_TYPE (value); - if (TREE_CODE (type) == TEMPLATE_TYPE_PARM - || TREE_CODE (type) == BOUND_TEMPLATE_TEMPLATE_PARM) - sorry ("applying attributes to template parameters is not implemented"); - else - cplus_decl_attributes (&value, attrlist, 0); - } + cplus_decl_attributes (&value, attrlist, 0); return value; } @@ -988,24 +979,43 @@ 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) +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 (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. */ + 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) +splice_template_attributes (tree *attr_p, tree decl) { tree *p = attr_p; tree late_attrs = NULL_TREE; @@ -1016,8 +1026,9 @@ splice_template_attributes (tree *attr_p) for (; *p; ) { - if (is_late_template_attribute (*p)) + if (is_late_template_attribute (*p, decl)) { + ATTR_IS_DEPENDENT (*p) = 1; *q = *p; *p = TREE_CHAIN (*p); q = &TREE_CHAIN (*q); @@ -1036,7 +1047,7 @@ splice_template_attributes (tree *attr_p) static void save_template_attributes (tree *attr_p, tree *decl_p) { - tree late_attrs = splice_template_attributes (attr_p); + tree late_attrs = splice_template_attributes (attr_p, *decl_p); tree *q; if (!late_attrs) diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 8accea4afad..c9ec37034a5 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -6494,20 +6494,14 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, else TYPE_ATTRIBUTES (*decl_p) = attributes; - /* Set processing_template_decl so we can check for dependent - expressions. */ - ++processing_template_decl; - for (t = attributes; t; t = TREE_CHAIN (t)) - if (is_late_template_attribute (t)) + if (ATTR_IS_DEPENDENT (t)) late_attrs = tree_cons (TREE_PURPOSE (t), tsubst_expr (TREE_VALUE (t), args, complain, in_decl, /*integral_constant_expression_p=*/false), late_attrs); - --processing_template_decl; - cplus_decl_attributes (decl_p, late_attrs, attr_flags); } @@ -8085,20 +8079,16 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) bool local_p; if (TREE_CODE (t) == TYPE_DECL - && MAYBE_TAGGED_TYPE_P (TREE_TYPE (t))) + && t == TYPE_MAIN_DECL (TREE_TYPE (t))) { + /* If this is the canonical decl, we don't have to + mess with instantiations, and often we can't (for + typename, template type parms and such). Note that + TYPE_NAME is not correct for the above test if + we've copied the type for a typedef. */ type = tsubst (TREE_TYPE (t), args, complain, in_decl); - if (TREE_CODE (type) == TEMPLATE_TEMPLATE_PARM - || t == TYPE_MAIN_DECL (TREE_TYPE (t))) - { - /* If this is the canonical decl, we don't have to - mess with instantiations, and often we can't (for - typename, template type parms and such). Note that - TYPE_NAME is not correct for the above test if - we've copied the type for a typedef. */ - r = TYPE_NAME (type); - break; - } + r = TYPE_NAME (type); + break; } /* Check to see if we already have the specialization we @@ -8555,16 +8545,15 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) gcc_assert (type != unknown_type_node); /* Reuse typedefs. We need to do this to handle dependent attributes, - specifically attribute aligned. */ + such as attribute aligned. */ if (TYPE_P (t) && TYPE_NAME (t) - && !MAYBE_TAGGED_TYPE_P (t) - && TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM - && TREE_CODE (t) != UNBOUND_CLASS_TEMPLATE) + && TYPE_NAME (t) != TYPE_MAIN_DECL (t)) { tree decl = TYPE_NAME (t); - if (DECL_CLASS_SCOPE_P (decl)) + if (DECL_CLASS_SCOPE_P (decl) + && CLASSTYPE_TEMPLATE_INFO (DECL_CONTEXT (decl))) { tree tmpl = most_general_template (DECL_TI_TEMPLATE (decl)); tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl); diff --git a/gcc/testsuite/g++.dg/ext/attrib20.C b/gcc/testsuite/g++.dg/ext/attrib20.C index e46e8ae2077..25b27f307b5 100644 --- a/gcc/testsuite/g++.dg/ext/attrib20.C +++ b/gcc/testsuite/g++.dg/ext/attrib20.C @@ -7,8 +7,8 @@ template struct BVector { typedef T T2; - typedef T value_type __attribute__ ((aligned(8))); // { dg-bogus "attribute" "attribute" { xfail *-*-* } } - typedef T2 value_type2 __attribute__ ((aligned(8))); // { dg-bogus "attribute" "attribute" { xfail *-*-* } } + typedef T value_type __attribute__ ((aligned(8))); // { dg-bogus "attribute" "attribute" } + typedef T2 value_type2 __attribute__ ((aligned(8))); // { dg-bogus "attribute" "attribute" } value_type v; }; BVector m; @@ -16,7 +16,7 @@ BVector m; template