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:
Jason Merrill 2007-09-14 02:07:25 -04:00 committed by Jason Merrill
parent d9933b9d64
commit 4f4141ffe2
5 changed files with 146 additions and 1 deletions

View File

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

View File

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

View File

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

View File

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

View File

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