This is the mail archive of the gcc-patches@gcc.gnu.org mailing list for the GCC project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

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);
+}

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]