Commit 4f4141ff by Jason Merrill Committed by Jason Merrill

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
parent d9933b9d
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> 2007-09-13 Tom Tromey <tromey@redhat.com>
* parser.c (cp_lexer_new_main): Don't use * parser.c (cp_lexer_new_main): Don't use
......
...@@ -4276,6 +4276,7 @@ extern tree grokfield (const cp_declarator *, cp_decl_specifier_seq *, ...@@ -4276,6 +4276,7 @@ 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);
......
...@@ -985,13 +985,87 @@ grokbitfield (const cp_declarator *declarator, ...@@ -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 void
cplus_decl_attributes (tree *decl, tree attributes, int flags) cplus_decl_attributes (tree *decl, tree attributes, int flags)
{ {
if (*decl == NULL_TREE || *decl == void_type_node if (*decl == NULL_TREE || *decl == void_type_node
|| *decl == error_mark_node) || *decl == error_mark_node
|| attributes == NULL_TREE)
return; return;
if (processing_template_decl)
{
save_template_attributes (&attributes, decl);
if (attributes == NULL_TREE)
return;
}
if (TREE_CODE (*decl) == TEMPLATE_DECL) if (TREE_CODE (*decl) == TEMPLATE_DECL)
decl = &DECL_TEMPLATE_RESULT (*decl); decl = &DECL_TEMPLATE_RESULT (*decl);
......
...@@ -6477,6 +6477,33 @@ can_complete_type_without_circularity (tree type) ...@@ -6477,6 +6477,33 @@ can_complete_type_without_circularity (tree type)
return 1; 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 tree
instantiate_class_template (tree type) instantiate_class_template (tree type)
{ {
...@@ -6647,6 +6674,9 @@ instantiate_class_template (tree type) ...@@ -6647,6 +6674,9 @@ instantiate_class_template (tree type)
information. */ information. */
xref_basetypes (type, base_list); 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 /* Now that our base classes are set up, enter the scope of the
class, so that name lookups into base classes, etc. will work 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) ...@@ -7872,6 +7902,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
= remove_attribute ("visibility", DECL_ATTRIBUTES (r)); = remove_attribute ("visibility", DECL_ATTRIBUTES (r));
} }
determine_visibility (r); determine_visibility (r);
apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
args, complain, in_decl);
} }
break; break;
...@@ -7965,6 +7998,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -7965,6 +7998,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
if (!DECL_TEMPLATE_PARM_P (r)) if (!DECL_TEMPLATE_PARM_P (r))
DECL_ARG_TYPE (r) = type_passed_as (type); 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 /* Keep track of the first new parameter we
generate. That's what will be returned to the generate. That's what will be returned to the
caller. */ caller. */
...@@ -8007,6 +8043,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8007,6 +8043,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
TREE_CHAIN (r) = NULL_TREE; TREE_CHAIN (r) = NULL_TREE;
if (VOID_TYPE_P (type)) if (VOID_TYPE_P (type))
error ("instantiation of %q+D as type %qT", r, 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; break;
...@@ -8201,6 +8240,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain) ...@@ -8201,6 +8240,9 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
register_local_specialization (r, t); register_local_specialization (r, t);
TREE_CHAIN (r) = NULL_TREE; TREE_CHAIN (r) = NULL_TREE;
apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
args, complain, in_decl);
layout_decl (r, 0); layout_decl (r, 0);
} }
break; break;
......
// 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;
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