Patchwork [C++] PR 54170

login
register
mail settings
Submitter Paolo Carlini
Date Dec. 1, 2012, 7:04 p.m.
Message ID <50BA54D4.5070508@oracle.com>
Download mbox | patch
Permalink /patch/203147/
State New
Headers show

Comments

Paolo Carlini - Dec. 1, 2012, 7:04 p.m.
Hi,

On 12/01/2012 07:13 AM, Jason Merrill wrote:
> On 11/30/2012 04:05 PM, Paolo Carlini wrote:
>> @@ -219,10 +219,15 @@ cp_convert_to_pointer (tree type, tree expr, tsubs
>> -    expr = build_int_cst (type, 0);
>> +    expr = (TREE_SIDE_EFFECTS (expr)
>> +        ? build_nop (type, expr)
>> +        : build_int_cst (type, 0));
>
> This seems to rely on a nop being sufficient to convert from any null 
> pointer constant to the appropriate pointer type, which I don't think 
> is safe if the integer is smaller than a pointer.
>
> I'm also not sure if we want to rely on nullptr_t expressions actually 
> having the value 0.
Thanks a lot. What about the below? I'm consistently building a 
COMPOUND_EXPR for the simpler plain pointers too; the hunk for pointers 
to member functions can be *very* simple: in fact I had already tried 
this solution but something else was wrong yesterday and seemed not to 
work, huumpf.

Tested x86_64-linux.

Thanks again,
Paolo.

////////////////////
Jason Merrill - Dec. 3, 2012, 2:13 p.m.
OK, thanks.

Jason

Patch

Index: cp/cvt.c
===================================================================
--- cp/cvt.c	(revision 194020)
+++ cp/cvt.c	(working copy)
@@ -215,16 +215,14 @@  cp_convert_to_pointer (tree type, tree expr, tsubs
 	return build_ptrmemfunc (TYPE_PTRMEMFUNC_FN_TYPE (type), expr, 0,
 				 /*c_cast_p=*/false, complain);
 
-      if (TYPE_PTRDATAMEM_P (type))
-	{
-	  /* A NULL pointer-to-member is represented by -1, not by
-	     zero.  */
-	  expr = build_int_cst_type (type, -1);
-	}
-      else
-	expr = build_int_cst (type, 0);
+      /* A NULL pointer-to-data-member is represented by -1, not by
+	 zero.  */
+      tree val = (TYPE_PTRDATAMEM_P (type)
+		  ? build_int_cst_type (type, -1)
+		  : build_int_cst (type, 0));
 
-      return expr;
+      return (TREE_SIDE_EFFECTS (expr)
+	      ? build2 (COMPOUND_EXPR, type, expr, val) : val);
     }
   else if (TYPE_PTRMEM_P (type) && INTEGRAL_CODE_P (form))
     {
Index: cp/typeck.c
===================================================================
--- cp/typeck.c	(revision 194020)
+++ cp/typeck.c	(working copy)
@@ -7567,7 +7567,7 @@  build_ptrmemfunc (tree type, tree pfn, int force,
   /* Handle null pointer to member function conversions.  */
   if (null_ptr_cst_p (pfn))
     {
-      pfn = build_c_cast (input_location, type, nullptr_node);
+      pfn = build_c_cast (input_location, type, pfn);
       return build_ptrmemfunc1 (to_type,
 				integer_zero_node,
 				pfn);
Index: testsuite/g++.dg/cpp0x/lambda/lambda-nullptr.C
===================================================================
--- testsuite/g++.dg/cpp0x/lambda/lambda-nullptr.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/lambda/lambda-nullptr.C	(working copy)
@@ -0,0 +1,47 @@ 
+// PR c++/54170
+// { dg-do run { target c++11 } }
+
+#include <cassert> 
+
+struct A;
+typedef A* ptr;
+typedef int (A::*pmf) (int);
+typedef int (A::*pdm);
+
+int total;
+
+void add(int n)
+{
+  total += n;
+}
+
+template <typename RType, typename Callable>
+RType Call(Callable native_func, int arg)
+{
+  return native_func(arg);
+}
+
+template <typename RType>
+RType do_test(int delta)
+{
+  return Call<RType>([=](int delta) { add(delta); return nullptr; }, delta);
+}
+
+template <typename RType>
+void test()
+{
+  total = 0;
+  assert (!do_test<RType>(5));
+  assert (total == 5);
+  assert (!do_test<RType>(20));
+  assert (total == 25);
+  assert (!do_test<RType>(-256));
+  assert (total == -231);
+}
+
+int main()
+{
+  test<ptr>();
+  test<pdm>();
+  test<pmf>();
+}