diff mbox

[C++] PR 67216 ("false is still a null pointer constant")

Message ID 55D22A8F.8060701@oracle.com
State New
Headers show

Commit Message

Paolo Carlini Aug. 17, 2015, 6:40 p.m. UTC
Hi,

the bug is very clear: in C++11 we reject the testcase because 
null_ptr_cst_p returns 'true' for 'false', whereas [conv.ptr] is 
carefully worded in terms of integer literals not boolean literals. The 
obvious fix, using == INTEGER_TYPE instead of CP_INTEGRAL_TYPE_P, 
appears to work well.

Tested x86_64-linux.

Thanks,
Paolo.

///////////////////////
/cp
2015-08-17  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/67216
	* call.c (null_ptr_cst_p): In C++11 return 'false' for 'false'.

/testsuite
2015-08-17  Paolo Carlini  <paolo.carlini@oracle.com>

	PR c++/67216
	* g++.dg/cpp0x/nullptr34.C: New.
	* g++.dg/warn/Wconversion2.C: Adjust.
	* g++.dg/warn/Wnull-conversion-1.C: Likewise.

Comments

Jason Merrill Aug. 17, 2015, 6:50 p.m. UTC | #1
On 08/17/2015 02:40 PM, Paolo Carlini wrote:
> the bug is very clear: in C++11 we reject the testcase because
> null_ptr_cst_p returns 'true' for 'false', whereas [conv.ptr] is
> carefully worded in terms of integer literals not boolean literals. The
> obvious fix, using == INTEGER_TYPE instead of CP_INTEGRAL_TYPE_P,
> appears to work well.

OK. I wonder if we can also drop the STRIP_NOPs on the C++11 path.

Jason
Paolo Carlini Aug. 17, 2015, 6:52 p.m. UTC | #2
Hi,

On 08/17/2015 08:50 PM, Jason Merrill wrote:
> On 08/17/2015 02:40 PM, Paolo Carlini wrote:
>> the bug is very clear: in C++11 we reject the testcase because
>> null_ptr_cst_p returns 'true' for 'false', whereas [conv.ptr] is
>> carefully worded in terms of integer literals not boolean literals. The
>> obvious fix, using == INTEGER_TYPE instead of CP_INTEGRAL_TYPE_P,
>> appears to work well.
> OK. I wonder if we can also drop the STRIP_NOPs on the C++11 path.
You are not alone ;) No, not trivially, without we ICE on pr51313.C.

Thanks,
Paolo.
Jason Merrill Aug. 17, 2015, 6:59 p.m. UTC | #3
On 08/17/2015 02:52 PM, Paolo Carlini wrote:
> On 08/17/2015 08:50 PM, Jason Merrill wrote:
>> OK. I wonder if we can also drop the STRIP_NOPs on the C++11 path.
> You are not alone ;) No, not trivially, without we ICE on pr51313.C.

Hmm, that testcase is ill-formed.  We ought to reject it, though not ICE.

Jason
Paolo Carlini Aug. 17, 2015, 7:20 p.m. UTC | #4
Hi,

On 08/17/2015 08:59 PM, Jason Merrill wrote:
> On 08/17/2015 02:52 PM, Paolo Carlini wrote:
>> On 08/17/2015 08:50 PM, Jason Merrill wrote:
>>> OK. I wonder if we can also drop the STRIP_NOPs on the C++11 path.
>> You are not alone ;) No, not trivially, without we ICE on pr51313.C.
>
> Hmm, that testcase is ill-formed.  We ought to reject it, though not ICE.
Yes, now I see. At the moment however, I have no idea where that 
NOP_EXPR is coming from and whether it would be safe to assume in 
null_ptr_cst_p that one can occur only due to a bug elsewhere... Note 
that integer_zerop calls STRIP_NOPS right at the beginning anyway and 
the ICE comes from TREE_OVERFLOW.

Anyway, about the substance of pr51313.C, is it Ok with you if I add an 
xfailed dg-error to it and investigate it separately?

Thanks!
Paolo.
Jason Merrill Aug. 17, 2015, 7:26 p.m. UTC | #5
On 08/17/2015 03:20 PM, Paolo Carlini wrote:
> On 08/17/2015 08:59 PM, Jason Merrill wrote:
>> On 08/17/2015 02:52 PM, Paolo Carlini wrote:
>>> On 08/17/2015 08:50 PM, Jason Merrill wrote:
>>>> OK. I wonder if we can also drop the STRIP_NOPs on the C++11 path.
>>> You are not alone ;) No, not trivially, without we ICE on pr51313.C.
>>
>> Hmm, that testcase is ill-formed.  We ought to reject it, though not ICE.
> Yes, now I see. At the moment however, I have no idea where that
> NOP_EXPR is coming from and whether it would be safe to assume in
> null_ptr_cst_p that one can occur only due to a bug elsewhere...

I imagine it's coming from built-in folding of isdigit, which is not a bug.

> Note
> that integer_zerop calls STRIP_NOPS right at the beginning anyway and
> the ICE comes from TREE_OVERFLOW.

So I guess null_ptr_cst_p should check for INTEGER_CST before calling 
integer_zerop.

> Anyway, about the substance of pr51313.C, is it Ok with you if I add an
> xfailed dg-error to it and investigate it separately?

Please also reopen 51313 if you do that.

Jason
diff mbox

Patch

Index: cp/call.c
===================================================================
--- cp/call.c	(revision 226939)
+++ cp/call.c	(working copy)
@@ -524,22 +524,34 @@  struct z_candidate {
 bool
 null_ptr_cst_p (tree t)
 {
+  tree type = TREE_TYPE (t);
+
   /* [conv.ptr]
 
      A null pointer constant is an integral constant expression
      (_expr.const_) rvalue of integer type that evaluates to zero or
      an rvalue of type std::nullptr_t. */
-  if (NULLPTR_TYPE_P (TREE_TYPE (t)))
+  if (NULLPTR_TYPE_P (type))
     return true;
-  if (CP_INTEGRAL_TYPE_P (TREE_TYPE (t)))
+
+  if (cxx_dialect >= cxx11)
     {
       /* Core issue 903 says only literal 0 is a null pointer constant.  */
-      if (cxx_dialect < cxx11)
-	t = fold_non_dependent_expr (t);
+      if (TREE_CODE (type) == INTEGER_TYPE)
+	{
+	  STRIP_NOPS (t);
+	  if (integer_zerop (t) && !TREE_OVERFLOW (t))
+	    return true;
+	}
+    }
+  else if (CP_INTEGRAL_TYPE_P (type))
+    {
+      t = fold_non_dependent_expr (t);
       STRIP_NOPS (t);
       if (integer_zerop (t) && !TREE_OVERFLOW (t))
 	return true;
     }
+
   return false;
 }
 
Index: testsuite/g++.dg/cpp0x/nullptr34.C
===================================================================
--- testsuite/g++.dg/cpp0x/nullptr34.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/nullptr34.C	(working copy)
@@ -0,0 +1,17 @@ 
+// PR c++/67216
+// { dg-do compile { target c++11 } }
+
+struct s {
+    s( long ) {}
+};
+
+struct t {
+    t( void * ) {}
+};
+
+void foo(s) {}
+void foo(t) {}
+
+int main() {
+    foo(false);
+}
Index: testsuite/g++.dg/warn/Wconversion2.C
===================================================================
--- testsuite/g++.dg/warn/Wconversion2.C	(revision 226939)
+++ testsuite/g++.dg/warn/Wconversion2.C	(working copy)
@@ -1,3 +1,4 @@ 
 // { dg-options "-Wconversion-null" }
 void foo(const char *); 
-void bar() { foo(false); } // { dg-warning "pointer type for argument" }
+void bar() { foo(false); } // { dg-warning "pointer type for argument" "" { target { ! c++11 } } }
+// { dg-error "cannot convert" "" { target c++11 } 3 }
Index: testsuite/g++.dg/warn/Wnull-conversion-1.C
===================================================================
--- testsuite/g++.dg/warn/Wnull-conversion-1.C	(revision 226939)
+++ testsuite/g++.dg/warn/Wnull-conversion-1.C	(working copy)
@@ -6,10 +6,13 @@ 
 void func1(int* ptr);
 
 void func2() {
-  int* t = false;             // { dg-warning "converting 'false' to pointer" }
+  int* t = false;             // { dg-warning "converting 'false' to pointer" "" { target { ! c++11 } } }
+// { dg-error "cannot convert" "" { target c++11 } 9 }
   int* p;
-  p = false;                  // { dg-warning "converting 'false' to pointer" }
+  p = false;                  // { dg-warning "converting 'false' to pointer" "" { target { ! c++11 } } }
+// { dg-error "cannot convert" "" { target c++11 } 12 }
   int* r = sizeof(char) / 2;  // { dg-error "invalid conversion from" "" { target c++11 } }
-  func1(false);               // { dg-warning "converting 'false' to pointer" }
+  func1(false);               // { dg-warning "converting 'false' to pointer" "" { target { ! c++11 } } }
+// { dg-error "cannot convert" "" { target c++11 } 15 }
   int i = NULL;               // { dg-warning "converting to non-pointer" }
 }
Index: testsuite/g++.old-deja/g++.other/null3.C
===================================================================
--- testsuite/g++.old-deja/g++.other/null3.C	(revision 226939)
+++ testsuite/g++.old-deja/g++.other/null3.C	(working copy)
@@ -2,5 +2,6 @@ 
 
 void x()
 {
- int* p = 1==0;	// { dg-warning "converting 'false' to pointer" }
+ int* p = 1==0;	// { dg-warning "converting 'false' to pointer" "" { target { ! c++11 } } }
+// { dg-error "cannot convert" "" { target c++11 } 5 } 
 }