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
This commit is contained in:
Jason Merrill 2007-09-22 22:36:34 -04:00 committed by Jason Merrill
parent 1e74fb44cd
commit a7f6bc8c74
10 changed files with 136 additions and 56 deletions

View File

@ -1,3 +1,10 @@
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>
* doc/sourcebuild.texi: Document dg-add-options mips16_attribute.

View File

@ -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)
{

View File

@ -1,3 +1,19 @@
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>
PR c++/33496

View File

@ -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);

View File

@ -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)

View File

@ -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);

View File

@ -7,8 +7,8 @@ template <typename T>
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<int> m;
@ -16,7 +16,7 @@ BVector<int> m;
template <template <class> class T>
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;
};
BV2<BVector> m2;

View File

@ -0,0 +1,33 @@
// 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;
}

View File

@ -0,0 +1,15 @@
// 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>;

View File

@ -5002,6 +5002,8 @@ extern bool must_pass_in_stack_var_size_or_pad (enum machine_mode, const_tree);
/* In attribs.c. */
extern const struct attribute_spec *lookup_attribute_spec (tree);
/* 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,
it should be modified in place; if a TYPE, a copy should be created