This is the mail archive of the
gcc-patches@gcc.gnu.org
mailing list for the GCC project.
C++ PATCH for c++/43031 (verify_gimple failure with stdcall pointer-to-member-functions)
- From: Jason Merrill <jason at redhat dot com>
- To: gcc-patches List <gcc-patches at gcc dot gnu dot org>
- Date: Tue, 16 Feb 2010 01:05:00 -0500
- Subject: C++ PATCH for c++/43031 (verify_gimple failure with stdcall pointer-to-member-functions)
The problem here is that adding the stdcall attribute makes the method
type use structural type comparison, and useless_type_conversion_p
requires explicit conversions between aggregates that need structural
comparison. So we add such an explicit conversion at gimplification time.
An additional fix for 4.6 might be to avoid requiring structural
comparison; we should still be able to use TYPE_CANONICAL for types with
magic target attributes.
Tested x86_64-pc-linux-gnu, applied to trunk.
commit ea59d715be66fd59584248b18d6437ae7cf55bc1
Author: Jason Merrill <jason@redhat.com>
Date: Mon Feb 15 17:52:40 2010 -0500
PR c++/43031
* cp-gimplify.c (cp_gimplify_expr) [MODIFY_EXPR]: Use
VIEW_CONVERT_EXPR for conversions between structural equality types
that the back end can't tell are the same.
diff --git a/gcc/cp/cp-gimplify.c b/gcc/cp/cp-gimplify.c
index e0047cf..7dc79b2 100644
--- a/gcc/cp/cp-gimplify.c
+++ b/gcc/cp/cp-gimplify.c
@@ -552,6 +552,20 @@ cp_gimplify_expr (tree *expr_p, gimple_seq *pre_p, gimple_seq *post_p)
25979. */
case INIT_EXPR:
cp_gimplify_init_expr (expr_p, pre_p, post_p);
+ /* Fall through. */
+ case MODIFY_EXPR:
+ {
+ /* If the back end isn't clever enough to know that the lhs and rhs
+ types are the same, add an explicit conversion. */
+ tree op0 = TREE_OPERAND (*expr_p, 0);
+ tree op1 = TREE_OPERAND (*expr_p, 1);
+
+ if ((TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op0))
+ || TYPE_STRUCTURAL_EQUALITY_P (TREE_TYPE (op1)))
+ && !useless_type_conversion_p (TREE_TYPE (op1), TREE_TYPE (op0)))
+ TREE_OPERAND (*expr_p, 1) = build1 (VIEW_CONVERT_EXPR,
+ TREE_TYPE (op0), op1);
+ }
ret = GS_OK;
break;
diff --git a/gcc/testsuite/g++.dg/ext/attrib36.C b/gcc/testsuite/g++.dg/ext/attrib36.C
new file mode 100644
index 0000000..a4ee209
--- /dev/null
+++ b/gcc/testsuite/g++.dg/ext/attrib36.C
@@ -0,0 +1,20 @@
+// PR c++/43031
+// { dg-do compile { target i?86-*-* x86_64-*-* } }
+
+class T;
+class L { };
+class P : public L
+{
+ typedef void (__attribute__((__stdcall__)) T::*F) (L*);
+ void f(bool aAdd);
+};
+class T
+{
+public:
+ virtual void __attribute__((__stdcall__)) A(L *listener) = 0;
+ virtual void __attribute__((__stdcall__)) R(L *listener) = 0;
+};
+void P::f(bool aAdd)
+{
+ F addRemoveEventListener = (aAdd ? &T::A : &T::R);
+}