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
This commit is contained in:
parent
d9933b9d64
commit
4f4141ffe2
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
42
gcc/cp/pt.c
42
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;
|
||||
|
|
|
@ -0,0 +1,18 @@
|
|||
// PR c++/17743
|
||||
|
||||
template <unsigned Len, unsigned Align>
|
||||
struct aligned_storage
|
||||
{
|
||||
typedef char type[Len] __attribute__((aligned((Align))));
|
||||
};
|
||||
|
||||
template<typename T>
|
||||
struct X
|
||||
{
|
||||
typename aligned_storage<sizeof(T),__alignof(T)>::type data;
|
||||
};
|
||||
|
||||
template<bool> struct StaticAssert;
|
||||
template<> struct StaticAssert<true> {};
|
||||
|
||||
StaticAssert<__alignof (X<double>) == __alignof (double)> dummy;
|
Loading…
Reference in New Issue