]> git.ipfire.org Git - thirdparty/gcc.git/commitdiff
c: Update nullptr_t comparison checks
authorJoseph Myers <joseph@codesourcery.com>
Thu, 2 Feb 2023 23:29:45 +0000 (23:29 +0000)
committerJoseph Myers <joseph@codesourcery.com>
Thu, 2 Feb 2023 23:29:45 +0000 (23:29 +0000)
WG14 has agreed to allow equality comparisons between pointers and
nullptr_t values that are not null pointer constants (this was
previously an exceptional case where such nullptr_t values were
handled differently from null pointer constants; other places in the
standard allowed nullptr_t values, whether or not those values are
null pointer constants, in the same contexts as null pointer
constants); see the wording at the end of N3077.  Update GCC's
implementation to match this change.

There are also changes to allow null pointer constants of integer or
pointer type to be converted to nullptr_t (by assignment, cast or
conversion as if by assignment), which I'll deal with separately.

Bootstrapped with no regressions for x86_64-pc-linux-gnu.

gcc/c/
* c-typeck.cc (build_binary_op): Allow comparisons between
pointers and nullptr_t values that are not null pointer constants.

gcc/testsuite/
* gcc.dg/c2x-constexpr-3.c: Do not expect comparison of nullptr_t
and pointer to be disallowed.
* gcc.dg/c2x-nullptr-1.c: Test comparisons of nullptr_t and
pointers are allowed.
* gcc.dg/c2x-nullptr-3.c: Do not test that comparisons of
nullptr_t and pointers are disallowed.

gcc/c/c-typeck.cc
gcc/testsuite/gcc.dg/c2x-constexpr-3.c
gcc/testsuite/gcc.dg/c2x-nullptr-1.c
gcc/testsuite/gcc.dg/c2x-nullptr-3.c

index 9d65130154da41a89d8e1dc2d199473883681b9a..224a9cbdc3d7625af3fde936a8fb78ea5e3c0970 100644 (file)
@@ -12749,12 +12749,16 @@ build_binary_op (location_t location, enum tree_code code,
          && (code1 == INTEGER_TYPE || code1 == REAL_TYPE
              || code1 == FIXED_POINT_TYPE || code1 == COMPLEX_TYPE))
        short_compare = 1;
-      else if (code0 == POINTER_TYPE && null_pointer_constant_p (orig_op1))
+      else if (code0 == POINTER_TYPE
+              && (code1 == NULLPTR_TYPE
+                  || null_pointer_constant_p (orig_op1)))
        {
          maybe_warn_for_null_address (location, op0, code);
          result_type = type0;
        }
-      else if (code1 == POINTER_TYPE && null_pointer_constant_p (orig_op0))
+      else if (code1 == POINTER_TYPE
+              && (code0 == NULLPTR_TYPE
+                  || null_pointer_constant_p (orig_op0)))
        {
          maybe_warn_for_null_address (location, op1, code);
          result_type = type1;
index 4f6b8ed67794a963a34dc19a0c9e4f6d26bf9d2e..44a3ed358e123a739a3239eea3a8a83ea5154995 100644 (file)
@@ -219,7 +219,6 @@ f0 ()
   (constexpr signed char []) { u8"\xff" }; /* { dg-error "'constexpr' initializer not representable in type of object" } */
   constexpr typeof (nullptr) not_npc = nullptr;
   int *ptr = 0;
-  (void) (ptr == not_npc); /* { dg-error "invalid operands" } */
   /* auto may only be used with another storage class specifier, such as
      constexpr, if the type is inferred.  */
   auto constexpr int a_c_t = 1; /* { dg-error "'auto' used with 'constexpr'" } */
index 9f2cb6c8256e1f52055140aef257434f4411aab5..04f9901bb121c95e169e45a4423426bdc0421b18 100644 (file)
@@ -141,6 +141,23 @@ test2 (int *p)
   (void) (p != _Generic(0, int : nullptr));
   (void) (_Generic(0, int : nullptr) == p);
   (void) (_Generic(0, int : nullptr) != p);
+
+  /* "(nullptr_t)nullptr" has type nullptr_t but isn't an NPC; these
+     comparisons are valid after C2X CD comments GB-071 and FR-073 were
+     resolved by the wording in N3077.  */
+  (void) ((nullptr_t)nullptr == p);
+  (void) ((nullptr_t)nullptr != p);
+  (void) (p == (nullptr_t)nullptr);
+  (void) (p != (nullptr_t)nullptr);
+  (void) (cmp () == p);
+  (void) (cmp () != p);
+  (void) (p == cmp ());
+  (void) (p != cmp ());
+  /* "(void *)nullptr" is not an NPC, either.  */
+  (void) ((void *)nullptr == cmp ());
+  (void) ((void *)nullptr != cmp ());
+  (void) (cmp () == (void *)nullptr);
+  (void) (cmp () != (void *)nullptr);
 }
 
 /* Test ?:.  */
index 34e3e03ba9d5dbe1f573597fe93786c24589ec5c..591ab7e6158e3121b3c8f1232401d4fc691aa6f7 100644 (file)
@@ -19,21 +19,6 @@ test1 (int *p)
   (void) (nullptr != 1); /* { dg-error "invalid operands" } */
   (void) (1 != nullptr); /* { dg-error "invalid operands" } */
   (void) (1 > nullptr); /* { dg-error "invalid operands" } */
-
-  /* "(nullptr_t)nullptr" has type nullptr_t but isn't an NPC.  */
-  (void) ((nullptr_t)nullptr == p); /* { dg-error "invalid operands" } */
-  (void) ((nullptr_t)nullptr != p); /* { dg-error "invalid operands" } */
-  (void) (p == (nullptr_t)nullptr); /* { dg-error "invalid operands" } */
-  (void) (p != (nullptr_t)nullptr); /* { dg-error "invalid operands" } */
-  (void) (cmp () == p); /* { dg-error "invalid operands" } */
-  (void) (cmp () != p); /* { dg-error "invalid operands" } */
-  (void) (p == cmp ()); /* { dg-error "invalid operands" } */
-  (void) (p != cmp ()); /* { dg-error "invalid operands" } */
-  /* "(void *)nullptr" is not an NPC, either.  */
-  (void) ((void *)nullptr == cmp ()); /* { dg-error "invalid operands" } */
-  (void) ((void *)nullptr != cmp ()); /* { dg-error "invalid operands" } */
-  (void) (cmp () == (void *)nullptr); /* { dg-error "invalid operands" } */
-  (void) (cmp () != (void *)nullptr); /* { dg-error "invalid operands" } */
 }
 
 void