This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
Re: C++ PATCH for c++/48138 (losing __attribute ((aligned)) on template argument)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Cc: Nathan Froyd <froydnj at codesourcery dot com>
- Date: Mon, 20 Jun 2011 22:12:09 -0400
- Subject: Re: C++ PATCH for c++/48138 (losing __attribute ((aligned)) on template argument)
- References: <4DFF57E3.7080407@redhat.com>
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 <jason@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 *-*-* } }
}