Commit a7f6bc8c by Jason Merrill Committed by Jason Merrill

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
parent 1e74fb44
2007-09-22 Jason Merrill <jason@redhat.com>
PR c++/19407
* attribs.c (lookup_attribute_spec): Split out...
(decl_attributes): From here.
* tree.h: Declare it.
2007-09-22 Richard Sandiford <rsandifo@nildram.co.uk> 2007-09-22 Richard Sandiford <rsandifo@nildram.co.uk>
* doc/sourcebuild.texi: Document dg-add-options mips16_attribute. * doc/sourcebuild.texi: Document dg-add-options mips16_attribute.
...@@ -196,6 +196,20 @@ init_attributes (void) ...@@ -196,6 +196,20 @@ init_attributes (void)
attributes_initialized = true; 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, /* 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, which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL,
it should be modified in place; if a TYPE, a copy should be created it should be modified in place; if a TYPE, a copy should be created
...@@ -221,16 +235,9 @@ decl_attributes (tree *node, tree attributes, int flags) ...@@ -221,16 +235,9 @@ decl_attributes (tree *node, tree attributes, int flags)
tree name = TREE_PURPOSE (a); tree name = TREE_PURPOSE (a);
tree args = TREE_VALUE (a); tree args = TREE_VALUE (a);
tree *anode = node; tree *anode = node;
const struct attribute_spec *spec = NULL; const struct attribute_spec *spec = lookup_attribute_spec (name);
bool no_add_attrs = 0; bool no_add_attrs = 0;
tree fn_ptr_tmp = NULL_TREE; 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) if (spec == NULL)
{ {
......
2007-09-22 Jason Merrill <jason@redhat.com>
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 <jakub@redhat.com> 2007-09-20 Jakub Jelinek <jakub@redhat.com>
PR c++/33496 PR c++/33496
......
...@@ -58,6 +58,7 @@ struct diagnostic_context; ...@@ -58,6 +58,7 @@ struct diagnostic_context;
TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR) TARGET_EXPR_IMPLICIT_P (in TARGET_EXPR)
TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX) TEMPLATE_PARM_PARAMETER_PACK (in TEMPLATE_PARM_INDEX)
TYPE_REF_IS_RVALUE (in REFERENCE_TYPE) TYPE_REF_IS_RVALUE (in REFERENCE_TYPE)
ATTR_IS_DEPENDENT (in the TREE_LIST for an attribute)
1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE) 1: IDENTIFIER_VIRTUAL_P (in IDENTIFIER_NODE)
TI_PENDING_TEMPLATE_FLAG. TI_PENDING_TEMPLATE_FLAG.
TEMPLATE_PARMS_FOR_INLINE. TEMPLATE_PARMS_FOR_INLINE.
...@@ -988,10 +989,6 @@ enum languages { lang_c, lang_cplusplus, lang_java }; ...@@ -988,10 +989,6 @@ enum languages { lang_c, lang_cplusplus, lang_java };
((T) == RECORD_TYPE || (T) == UNION_TYPE) ((T) == RECORD_TYPE || (T) == UNION_TYPE)
#define TAGGED_TYPE_P(T) \ #define TAGGED_TYPE_P(T) \
(CLASS_TYPE_P (T) || TREE_CODE (T) == ENUMERAL_TYPE) (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) #define IS_OVERLOAD_TYPE(T) TAGGED_TYPE_P (T)
/* True if this a "Java" type, defined in 'extern "Java"'. */ /* True if this a "Java" type, defined in 'extern "Java"'. */
...@@ -2134,6 +2131,10 @@ struct lang_decl GTY(()) ...@@ -2134,6 +2131,10 @@ struct lang_decl GTY(())
directives */ directives */
#define TREE_INDIRECT_USING(NODE) (TREE_LIST_CHECK (NODE)->base.lang_flag_0) #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 tree decl_shadowed_for_var_lookup (tree);
extern void decl_shadowed_for_var_insert (tree, tree); extern void decl_shadowed_for_var_insert (tree, tree);
...@@ -4280,7 +4281,6 @@ extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *, ...@@ -4280,7 +4281,6 @@ extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *,
tree, bool, tree, tree); tree, bool, tree, tree);
extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *, extern tree grokbitfield (const cp_declarator *, cp_decl_specifier_seq *,
tree); tree);
extern bool is_late_template_attribute (tree);
extern void cplus_decl_attributes (tree *, tree, int); extern void cplus_decl_attributes (tree *, tree, int);
extern void finish_anon_union (tree); extern void finish_anon_union (tree);
extern void cp_write_global_declarations (void); extern void cp_write_global_declarations (void);
......
...@@ -800,16 +800,7 @@ grokfield (const cp_declarator *declarator, ...@@ -800,16 +800,7 @@ grokfield (const cp_declarator *declarator,
value = push_template_decl (value); value = push_template_decl (value);
if (attrlist) 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; return value;
} }
...@@ -988,24 +979,43 @@ grokbitfield (const cp_declarator *declarator, ...@@ -988,24 +979,43 @@ grokbitfield (const cp_declarator *declarator,
/* Returns true iff ATTR is an attribute which needs to be applied at /* Returns true iff ATTR is an attribute which needs to be applied at
instantiation time rather than template definition time. */ instantiation time rather than template definition time. */
bool static bool
is_late_template_attribute (tree attr) is_late_template_attribute (tree attr, tree decl)
{ {
tree name = TREE_PURPOSE (attr); tree name = TREE_PURPOSE (attr);
tree args = TREE_VALUE (attr); tree args = TREE_VALUE (attr);
const struct attribute_spec *spec = lookup_attribute_spec (name);
if (is_attribute_p ("aligned", name) if (is_attribute_p ("aligned", name)
&& args && args
&& value_dependent_expression_p (TREE_VALUE (args))) && value_dependent_expression_p (TREE_VALUE (args)))
/* Can't apply this until we know the desired alignment. */
return true; 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 else
return false; return false;
} }
/* ATTR_P is a list of attributes. Remove any attributes which need to be /* 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 static tree
splice_template_attributes (tree *attr_p) splice_template_attributes (tree *attr_p, tree decl)
{ {
tree *p = attr_p; tree *p = attr_p;
tree late_attrs = NULL_TREE; tree late_attrs = NULL_TREE;
...@@ -1016,8 +1026,9 @@ splice_template_attributes (tree *attr_p) ...@@ -1016,8 +1026,9 @@ splice_template_attributes (tree *attr_p)
for (; *p; ) for (; *p; )
{ {
if (is_late_template_attribute (*p)) if (is_late_template_attribute (*p, decl))
{ {
ATTR_IS_DEPENDENT (*p) = 1;
*q = *p; *q = *p;
*p = TREE_CHAIN (*p); *p = TREE_CHAIN (*p);
q = &TREE_CHAIN (*q); q = &TREE_CHAIN (*q);
...@@ -1036,7 +1047,7 @@ splice_template_attributes (tree *attr_p) ...@@ -1036,7 +1047,7 @@ splice_template_attributes (tree *attr_p)
static void static void
save_template_attributes (tree *attr_p, tree *decl_p) 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; tree *q;
if (!late_attrs) if (!late_attrs)
......
...@@ -6494,20 +6494,14 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags, ...@@ -6494,20 +6494,14 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
else else
TYPE_ATTRIBUTES (*decl_p) = attributes; 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)) for (t = attributes; t; t = TREE_CHAIN (t))
if (is_late_template_attribute (t)) if (ATTR_IS_DEPENDENT (t))
late_attrs = tree_cons late_attrs = tree_cons
(TREE_PURPOSE (t), (TREE_PURPOSE (t),
tsubst_expr (TREE_VALUE (t), args, complain, in_decl, tsubst_expr (TREE_VALUE (t), args, complain, in_decl,
/*integral_constant_expression_p=*/false), /*integral_constant_expression_p=*/false),
late_attrs); late_attrs);
--processing_template_decl;
cplus_decl_attributes (decl_p, late_attrs, attr_flags); cplus_decl_attributes (decl_p, late_attrs, attr_flags);
} }
...@@ -8085,21 +8079,17 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8085,21 +8079,17 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
bool local_p; bool local_p;
if (TREE_CODE (t) == TYPE_DECL if (TREE_CODE (t) == TYPE_DECL
&& MAYBE_TAGGED_TYPE_P (TREE_TYPE (t))) && t == TYPE_MAIN_DECL (TREE_TYPE (t)))
{
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 /* If this is the canonical decl, we don't have to
mess with instantiations, and often we can't (for mess with instantiations, and often we can't (for
typename, template type parms and such). Note that typename, template type parms and such). Note that
TYPE_NAME is not correct for the above test if TYPE_NAME is not correct for the above test if
we've copied the type for a typedef. */ we've copied the type for a typedef. */
type = tsubst (TREE_TYPE (t), args, complain, in_decl);
r = TYPE_NAME (type); r = TYPE_NAME (type);
break; break;
} }
}
/* Check to see if we already have the specialization we /* Check to see if we already have the specialization we
need. */ need. */
...@@ -8555,16 +8545,15 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl) ...@@ -8555,16 +8545,15 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_assert (type != unknown_type_node); gcc_assert (type != unknown_type_node);
/* Reuse typedefs. We need to do this to handle dependent attributes, /* Reuse typedefs. We need to do this to handle dependent attributes,
specifically attribute aligned. */ such as attribute aligned. */
if (TYPE_P (t) if (TYPE_P (t)
&& TYPE_NAME (t) && TYPE_NAME (t)
&& !MAYBE_TAGGED_TYPE_P (t) && TYPE_NAME (t) != TYPE_MAIN_DECL (t))
&& TREE_CODE (t) != TEMPLATE_TEMPLATE_PARM
&& TREE_CODE (t) != UNBOUND_CLASS_TEMPLATE)
{ {
tree decl = TYPE_NAME (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 tmpl = most_general_template (DECL_TI_TEMPLATE (decl));
tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl); tree gen_args = tsubst (DECL_TI_ARGS (decl), args, complain, in_decl);
......
...@@ -7,8 +7,8 @@ template <typename T> ...@@ -7,8 +7,8 @@ template <typename T>
struct BVector struct BVector
{ {
typedef T T2; typedef T T2;
typedef T value_type __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" { xfail *-*-* } } typedef T2 value_type2 __attribute__ ((aligned(8))); // { dg-bogus "attribute" "attribute" }
value_type v; value_type v;
}; };
BVector<int> m; BVector<int> m;
...@@ -16,7 +16,7 @@ BVector<int> m; ...@@ -16,7 +16,7 @@ BVector<int> m;
template <template <class> class T> template <template <class> class T>
struct BV2 struct BV2
{ {
typedef T<float> value_type __attribute__((aligned(8))); // { dg-bogus "attribute" "attribute" { xfail *-*-* } } typedef T<float> value_type __attribute__((aligned(8))); // { dg-bogus "attribute" "attribute" }
value_type v; value_type v;
}; };
BV2<BVector> m2; BV2<BVector> m2;
......
// PR c++/19407
// { dg-do run }
typedef float global_vector_type __attribute__((vector_size(16)));
template <class T> struct A
{
typedef T type;
};
template < typename Val > struct S
{
typedef typename A<Val>::type vector_type __attribute__((vector_size(16)));
typedef Val vector_type2 __attribute__((vector_size(16)));
int pr_size() { return sizeof(vector_type); }
int pr_size2() { return sizeof(vector_type2); }
};
int main()
{
if (sizeof (S<float>::vector_type) != sizeof (global_vector_type))
return 1;
if (sizeof (S<float>::vector_type2) != sizeof (global_vector_type))
return 2;
S<float> x;
if (x.pr_size() != sizeof (global_vector_type))
return 3;
if (x.pr_size2() != sizeof (global_vector_type))
return 4;
return 0;
}
// An intermediate version of the fix for c++/19407 broke this example.
struct A
{
typedef struct { int i; } S;
};
template <class T>
struct B: public A
{
template <class U>
static S f ();
};
template struct B<int>;
...@@ -5002,6 +5002,8 @@ extern bool must_pass_in_stack_var_size_or_pad (enum machine_mode, const_tree); ...@@ -5002,6 +5002,8 @@ extern bool must_pass_in_stack_var_size_or_pad (enum machine_mode, const_tree);
/* In attribs.c. */ /* In attribs.c. */
extern const struct attribute_spec *lookup_attribute_spec (tree);
/* Process the attributes listed in ATTRIBUTES and install them in *NODE, /* 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, which is either a DECL (including a TYPE_DECL) or a TYPE. If a DECL,
it should be modified in place; if a TYPE, a copy should be created it should be modified in place; if a TYPE, a copy should be created
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment