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:
parent
1e74fb44cd
commit
a7f6bc8c74
@ -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.
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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);
|
||||
|
@ -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)
|
||||
|
37
gcc/cp/pt.c
37
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);
|
||||
|
@ -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;
|
||||
|
33
gcc/testsuite/g++.dg/ext/tmplattr5.C
Normal file
33
gcc/testsuite/g++.dg/ext/tmplattr5.C
Normal 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;
|
||||
}
|
15
gcc/testsuite/g++.dg/template/typedef7.C
Normal file
15
gcc/testsuite/g++.dg/template/typedef7.C
Normal 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>;
|
@ -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
|
||||
|
Loading…
Reference in New Issue
Block a user