On 06/20/2011 10:23 AM, Jason Merrill wrote:
strip_typedefs needs to propagate DECL_USER_ALIGN as well as attributes in the attribute list.
...except that we don't want to retain attributes on template type arguments, since they aren't part of mangling, so you could get a class template instantiation that is the same type regardless of the alignment of the argument, but the effective argument varies depending on which alignment was first used to instantiate it.
The PR suggests a warning when we drop the attributes, which makes sense. This patch does not yet provide the warning in the case of function templates, but does for class templates. Warning for function templates will wait until after Nathan's patch to improve template overloading diagnostics.
Tested x86_64-pc-linux-gnu, applying to trunk.
commit d4813fc54ee69f5880e588e8b9edf97baa0ad6cc Author: Jason Merrill <ja...@redhat.com> Date: Mon Jun 20 14:37:05 2011 -0400 PR c++/48138 * pt.c (canonicalize_type_argument): New. (convert_template_argument, unify): Use it. diff --git a/gcc/cp/pt.c b/gcc/cp/pt.c index 6f15101..4d2caa8 100644 --- a/gcc/cp/pt.c +++ b/gcc/cp/pt.c @@ -5916,6 +5916,28 @@ template_template_parm_bindings_ok_p (tree tparms, tree targs) return ret; } +/* Since type attributes aren't mangled, we need to strip them from + template type arguments. */ + +static tree +canonicalize_type_argument (tree arg, tsubst_flags_t complain) +{ + tree mv; + if (!arg || arg == error_mark_node || arg == TYPE_CANONICAL (arg)) + return arg; + mv = TYPE_MAIN_VARIANT (arg); + arg = strip_typedefs (arg); + if (TYPE_ALIGN (arg) != TYPE_ALIGN (mv) + || TYPE_ATTRIBUTES (arg) != TYPE_ATTRIBUTES (mv)) + { + if (complain & tf_warning) + warning (0, "ignoring attributes on template argument %qT", arg); + arg = build_aligned_type (arg, TYPE_ALIGN (mv)); + arg = cp_build_type_attribute_variant (arg, TYPE_ATTRIBUTES (mv)); + } + return arg; +} + /* Convert the indicated template ARG as necessary to match the indicated template PARM. Returns the converted ARG, or error_mark_node if the conversion was unsuccessful. Error and @@ -6092,7 +6114,7 @@ convert_template_argument (tree parm, the typedef, which is confusing if those future uses do not themselves also use the typedef. */ if (TYPE_P (val)) - val = strip_typedefs (val); + val = canonicalize_type_argument (val, complain); } else { @@ -6136,8 +6158,9 @@ convert_template_argument (tree parm, if (TREE_CODE (val) == SCOPE_REF) { /* Strip typedefs from the SCOPE_REF. */ - tree type = strip_typedefs (TREE_TYPE (val)); - tree scope = strip_typedefs (TREE_OPERAND (val, 0)); + tree type = canonicalize_type_argument (TREE_TYPE (val), complain); + tree scope = canonicalize_type_argument (TREE_OPERAND (val, 0), + complain); val = build_qualified_name (type, scope, TREE_OPERAND (val, 1), QUALIFIED_NAME_IS_TEMPLATE (val)); } @@ -15479,7 +15502,7 @@ unify (tree tparms, tree targs, tree parm, tree arg, int strict) return 1; /* Strip typedefs as in convert_template_argument. */ - arg = strip_typedefs (arg); + arg = canonicalize_type_argument (arg, tf_none); } /* If ARG is a parameter pack or an expansion, we cannot unify diff --git a/gcc/testsuite/g++.dg/ext/attr-aligned01.C b/gcc/testsuite/g++.dg/ext/attr-aligned01.C index a051c6e..c8ec07d 100644 --- a/gcc/testsuite/g++.dg/ext/attr-aligned01.C +++ b/gcc/testsuite/g++.dg/ext/attr-aligned01.C @@ -1,20 +1,25 @@ // PR c++/48138 -// { dg-options -std=c++0x } #define ALIGNED(x) __attribute__((aligned(x))) -#define SA(X) static_assert ((X),#X) +#define SA(X) int ar[(X)?1:-1]; template<typename T> void type_alignment(const T&) { struct { char c; T t; } s; - SA((char*)&s.t - (char*)&s.c == 8); + SA((char*)&s.t - (char*)&s.c == 1); } +template <class T> struct A { char c; T t; }; + int main() { typedef char unaligned[15]; typedef char aligned[15] ALIGNED(8); + A<aligned> a; // { dg-warning "ignoring attributes" } + + SA((char*)&a.t - (char*)&a.c == 1); + aligned z; - type_alignment(z); - type_alignment<unaligned ALIGNED(8)>(z); + type_alignment(z); // { dg-warning "ignoring attributes" "" { xfail *-*-* } } + type_alignment<unaligned ALIGNED(8)>(z); // { dg-warning "ignoring attributes" "" { xfail *-*-* } } }