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]

Re: [PATCH]: PR29066 ptrmemfunc_vbit_in_delta is broken


Mark Mitchell wrote:
Ryan Mansfield wrote:
Hi,

In build_binary_op, the NE_EXPR/EQ_EXPR comparison of a ptrmemfunc type to a
null_ptr_cst only looks at the pfn. This breaks ptrmemfunc_vbit_in_delta targets as it is possible to have a pfn of 0.


since, here, the compiler just needs to update delta; it has no need to
check PFN.  Therefore, I would expect that your code should explicitly
check DELTA & 1, rather than just DELTA.

Right, the ABI clearly says "A pointer to member function is NULL when ptr = 0 and the least significant bit of adj is zero."


Is the attached patch OK?

Regards,

Ryan Mansfield
Index: gcc/cp/typeck.c
===================================================================
--- gcc/cp/typeck.c	(revision 118481)
+++ gcc/cp/typeck.c	(working copy)
@@ -3266,6 +3266,26 @@
 	}
       else if (TYPE_PTRMEMFUNC_P (type0) && null_ptr_cst_p (op1))
 	{
+	  if (TARGET_PTRMEMFUNC_VBIT_LOCATION
+	      == ptrmemfunc_vbit_in_delta)
+	    {
+	      tree e; 
+	      tree pfn0 = pfn_from_ptrmemfunc (op0);
+	      tree delta0 = build_ptrmemfunc_access_expr (op0,
+			 	 		delta_identifier);
+	      tree e1 = cp_build_binary_op (EQ_EXPR,
+	  			            pfn0,
+				      	    cp_convert (TREE_TYPE (pfn0),
+						        integer_zero_node));
+	      tree e2 = cp_build_binary_op (BIT_AND_EXPR, 
+					    delta0,
+				            integer_one_node);
+	      e2 = cp_build_binary_op (EQ_EXPR, e2, integer_zero_node);
+	      e = cp_build_binary_op (TRUTH_ANDIF_EXPR, e1, e2);
+	      if (code == EQ_EXPR)
+	        return e;
+	      return cp_build_binary_op (EQ_EXPR, e, integer_zero_node);
+	    }
 	  op0 = build_ptrmemfunc_access_expr (op0, pfn_identifier);
 	  op1 = cp_convert (TREE_TYPE (op0), integer_zero_node);
 	  result_type = TREE_TYPE (op0);
@@ -3305,11 +3325,15 @@
 	  delta1 = build_ptrmemfunc_access_expr (op1,
 						 delta_identifier);
 	  e1 = cp_build_binary_op (EQ_EXPR, delta0, delta1);
-	  e2 = cp_build_binary_op (EQ_EXPR,
-				   pfn0,
-				   cp_convert (TREE_TYPE (pfn0),
-					       integer_zero_node));
-	  e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2);
+	  if (TARGET_PTRMEMFUNC_VBIT_LOCATION
+	      != ptrmemfunc_vbit_in_delta)
+	    {
+	      e2 = cp_build_binary_op (EQ_EXPR,
+		      		       pfn0,
+			   	       cp_convert (TREE_TYPE (pfn0),
+						   integer_zero_node));
+	      e1 = cp_build_binary_op (TRUTH_ORIF_EXPR, e1, e2);
+	    }
 	  e2 = build2 (EQ_EXPR, boolean_type_node, pfn0, pfn1);
 	  e = cp_build_binary_op (TRUTH_ANDIF_EXPR, e2, e1);
 	  if (code == EQ_EXPR)
Index: gcc/testsuite/g++.dg/other/pr29066.C
===================================================================
--- gcc/testsuite/g++.dg/other/pr29066.C	(revision 0)
+++ gcc/testsuite/g++.dg/other/pr29066.C	(revision 0)
@@ -0,0 +1,43 @@
+// PR c++/29066
+// Test pointer to member function comparison
+// { dg-do run }
+// { dg-options "" }
+
+extern "C" void abort (void);
+
+struct X
+{
+  virtual void a(void)=0;
+};
+
+struct Z : public X
+{
+  void a(void) {};
+};
+
+
+void f(X *obj)
+{
+  void (X::*xp)(void) = 0;
+  void (X::*xp2)(void) = 0;
+
+  xp = &X::a;
+
+  if (xp == xp2)
+    {
+      abort(); 
+    } 
+
+  if (xp == 0)
+    {
+      abort();
+    }
+}
+
+int main(int argc, char* argv[])
+{
+  Z myobj;
+
+  f(&myobj);
+  return 0;
+}

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