re PR c++/17743 (dependent expressions in attributes)

PR c++/17743
        * pt.c (apply_late_template_attributes): Set processing_template_decl.
        (tsubst_decl) [TYPE_DECL]: Preserve naming typedef, pass
        ATTR_FLAG_TYPE_IN_PLACE.
        (tsubst): Do unqualified lookup to find typedefs from current class.
        [ARRAY_TYPE]: Propagate alignment info.
        * decl2.c (is_late_template_attribute): Only defer handling of
        attribute aligned if the expression is dependent.
        (save_template_attributes): If we're deferring any attributes,
        make this a naming typedef.

From-SVN: r128590
This commit is contained in:
Jason Merrill 2007-09-18 18:50:03 -04:00 committed by Jason Merrill
parent 80a6ca747a
commit 5044ab0e64
4 changed files with 113 additions and 7 deletions

View File

@ -1,3 +1,16 @@
2007-09-18 Jason Merrill <jason@redhat.com>
PR c++/17743
* pt.c (apply_late_template_attributes): Set processing_template_decl.
(tsubst_decl) [TYPE_DECL]: Preserve naming typedef, pass
ATTR_FLAG_TYPE_IN_PLACE.
(tsubst): Do unqualified lookup to find typedefs from current class.
[ARRAY_TYPE]: Propagate alignment info.
* decl2.c (is_late_template_attribute): Only defer handling of
attribute aligned if the expression is dependent.
(save_template_attributes): If we're deferring any attributes,
make this a naming typedef.
2007-09-18 Paolo Carlini <pcarlini@suse.de>
PR c++/33462 (again)
@ -38,17 +51,12 @@
2007-09-16 Nathan Sidwell <nathan@codesourcery.com>
cp/
PR c++/32756
* call.c (maybe_handle_implicit_object): Set this_p, clear
rvaluedness_matches_p.
(compare_ics): Do not compare rvaluedness matching when one of the
operands is an implicit object.
testsuite/
PR c++/32756
* g++.dg/overload/operator3.C: New.
2007-09-14 Jason Merrill <jason@redhat.com>
PR c++/17743, c++/19163

View File

@ -992,7 +992,10 @@ bool
is_late_template_attribute (tree attr)
{
tree name = TREE_PURPOSE (attr);
if (is_attribute_p ("aligned", name))
tree args = TREE_VALUE (attr);
if (is_attribute_p ("aligned", name)
&& args
&& value_dependent_expression_p (TREE_VALUE (args)))
return true;
else
return false;
@ -1039,6 +1042,19 @@ save_template_attributes (tree *attr_p, tree *decl_p)
if (!late_attrs)
return;
/* Give this type a name so we know to look it up again at instantiation
time. */
if (TREE_CODE (*decl_p) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (*decl_p) == NULL_TREE)
{
tree oldt = TREE_TYPE (*decl_p);
tree newt = build_variant_type_copy (oldt);
DECL_ORIGINAL_TYPE (*decl_p) = oldt;
TREE_TYPE (*decl_p) = newt;
TYPE_NAME (newt) = *decl_p;
TREE_USED (newt) = TREE_USED (*decl_p);
}
if (DECL_P (*decl_p))
q = &DECL_ATTRIBUTES (*decl_p);
else

View File

@ -6493,6 +6493,10 @@ 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))
late_attrs = tree_cons
@ -6501,6 +6505,8 @@ apply_late_template_attributes (tree *decl_p, tree attributes, int attr_flags,
/*integral_constant_expression_p=*/false),
late_attrs);
--processing_template_decl;
cplus_decl_attributes (decl_p, late_attrs, attr_flags);
}
@ -8223,6 +8229,16 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
}
determine_visibility (r);
}
/* Preserve a typedef that names a type. */
else if (TREE_CODE (r) == TYPE_DECL
&& DECL_ORIGINAL_TYPE (t)
&& type != error_mark_node)
{
DECL_ORIGINAL_TYPE (r) = tsubst (DECL_ORIGINAL_TYPE (t),
args, complain, in_decl);
TREE_TYPE (r) = type = build_variant_type_copy (type);
TYPE_NAME (type) = r;
}
if (!local_p)
{
@ -8241,7 +8257,8 @@ tsubst_decl (tree t, tree args, tsubst_flags_t complain)
TREE_CHAIN (r) = NULL_TREE;
apply_late_template_attributes (&r, DECL_ATTRIBUTES (r), 0,
apply_late_template_attributes (&r, DECL_ATTRIBUTES (r),
(int) ATTR_FLAG_TYPE_IN_PLACE,
args, complain, in_decl);
layout_decl (r, 0);
}
@ -8534,6 +8551,43 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
gcc_assert (type != unknown_type_node);
/* Reuse typedefs. This is a rather complicated way to check whether the
type is a typedef from the same class template as the current scope,
but I can't think of a better one.
We need to do this to handle dependent attributes, specifically
attribute aligned. */
if (TYPE_P (t)
&& TYPE_NAME (t)
&& !IS_AGGR_TYPE (t)
&& current_class_type
&& CLASSTYPE_TEMPLATE_INFO (current_class_type))
{
tree decl = TYPE_NAME (t);
tree context = DECL_CONTEXT (decl);
if (context
&& CLASS_TYPE_P (context)
&& CLASSTYPE_TEMPLATE_INFO (context)
&& (CLASSTYPE_TI_TEMPLATE (context)
== CLASSTYPE_TI_TEMPLATE (current_class_type))
&& (tsubst_aggr_type (context, args, complain, in_decl,
/*entering_scope=*/0)
== current_class_type))
{
r = lookup_name (DECL_NAME (decl));
if (r && TREE_CODE (r) == TYPE_DECL
&& DECL_CONTEXT (r) == current_class_type)
{
r = TREE_TYPE (r);
r = cp_build_qualified_type_real
(r, cp_type_quals (t) | cp_type_quals (r),
complain | tf_ignore_bad_quals);
return r;
/* Else we're instantiating the typedef, so fall through. */
}
}
}
if (type
&& TREE_CODE (t) != TYPENAME_TYPE
&& TREE_CODE (t) != IDENTIFIER_NODE
@ -9013,6 +9067,13 @@ tsubst (tree t, tree args, tsubst_flags_t complain, tree in_decl)
}
r = build_cplus_array_type (type, domain);
if (TYPE_USER_ALIGN (t))
{
TYPE_ALIGN (r) = TYPE_ALIGN (t);
TYPE_USER_ALIGN (r) = 1;
}
return r;
}

View File

@ -0,0 +1,21 @@
// PR c++/17743
template<typename T>
struct X {
typedef char layout_type[sizeof(T)]
__attribute ((aligned(__alignof(double))));
layout_type data;
};
template<typename T>
struct Y {
typedef char layout_type[sizeof(T)]
__attribute ((aligned(__alignof(T))));
layout_type data;
};
template<bool> struct StaticAssert;
template<> struct StaticAssert<true> {};
StaticAssert<__alignof(X<double>) == __alignof(double)> d1;
StaticAssert<__alignof(Y<double>) == __alignof(double)> d2;