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

Paolo Carlini paolo.carlini@oracle.com
Mon Aug 17 20:14:00 GMT 2015


Hi,

On 08/17/2015 09:26 PM, Jason Merrill wrote:
> 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.
Yeah, and like in many other places! Thanks. Thus I'm finishing testing 
the below, which handles correctly pr51313.C too. Note, I'm 
intentionally leaving the old c++98 path completely alone.

Thanks,
Paolo.
-------------- next part --------------
Index: cp/call.c
===================================================================
--- cp/call.c	(revision 226952)
+++ 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)
+	{
+	  if (TREE_CODE (t) == INTEGER_CST && 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: cp/pt.c
===================================================================
--- cp/pt.c	(revision 226952)
+++ cp/pt.c	(working copy)
@@ -22671,7 +22671,8 @@ resolve_typename_type (tree type, bool only_curren
     return type;
   /* If SCOPE isn't the template itself, it will not have a valid
      TYPE_FIELDS list.  */
-  if (same_type_p (scope, CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope)))
+  if (CLASS_TYPE_P (scope)
+      && same_type_p (scope, CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope)))
     /* scope is either the template itself or a compatible instantiation
        like X<T>, so look up the name in the original template.  */
     scope = CLASSTYPE_PRIMARY_TEMPLATE_TYPE (scope);
Index: testsuite/g++.dg/cpp0x/decltype63.C
===================================================================
--- testsuite/g++.dg/cpp0x/decltype63.C	(revision 0)
+++ testsuite/g++.dg/cpp0x/decltype63.C	(working copy)
@@ -0,0 +1,7 @@
+// PR c++/63693
+// { dg-do compile { target c++11 } }
+
+template<typename T>
+class C{
+ T t;
+ decltype(t)::a::  // { dg-error "expected" }
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/cpp0x/pr51313.C
===================================================================
--- testsuite/g++.dg/cpp0x/pr51313.C	(revision 226952)
+++ testsuite/g++.dg/cpp0x/pr51313.C	(working copy)
@@ -14,5 +14,5 @@ extern ostream cout;
 
 int main()
 {
-  cout << isdigit(0);
+  cout << isdigit(0);  // { dg-error "invalid conversion" }
 }
Index: testsuite/g++.dg/warn/Wconversion2.C
===================================================================
--- testsuite/g++.dg/warn/Wconversion2.C	(revision 226952)
+++ 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 226952)
+++ 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 226952)
+++ 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 } 
 }


More information about the Gcc-patches mailing list