[PATCH] c++: Consider addresses of heap artificial vars always non-NULL [PR98988]

Jakub Jelinek jakub@redhat.com
Tue Feb 9 08:25:04 GMT 2021


Hi!

With -fno-delete-null-pointer-checks which is e.g. implied by
-fsanitize=undefined or default on some embedded targets, the middle-end
folder doesn't consider addresses of global VAR_DECLs to be non-NULL, as one
of them could have address 0.  Still, I think malloc/operator new (at least
the nonthrowing) relies on NULL returns meaning allocation failure rather
than success.  Furthermore, the artificial VAR_DECLs we create for
constexpr new never actually live in the address space of the program,
so we can pretend they will never be NULL too.

The following patch does that, so that one can actually use constexpr
new/delete even with -fno-delete-null-pointer-checks or sanitizers
- otherwise delete itself tests whether the passed address is non-NULL and
that wouldn't fold to true if the pointer has been allocated with constexpr
new.

Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?

2021-02-09  Jakub Jelinek  <jakub@redhat.com>

	PR c++/98988
	* constexpr.c (cxx_eval_binary_expression): Fold equality comparison
	of address of heap artificial VAR_DECL against nullptr.

	* g++.dg/cpp2a/constexpr-new16.C: New test.

--- gcc/cp/constexpr.c.jj	2021-02-02 09:52:10.535234056 +0100
+++ gcc/cp/constexpr.c	2021-02-08 17:24:28.774467744 +0100
@@ -3157,6 +3157,32 @@ cxx_eval_binary_expression (const conste
 	lhs = cplus_expand_constant (lhs);
       else if (TREE_CODE (rhs) == PTRMEM_CST)
 	rhs = cplus_expand_constant (rhs);
+      if (r == NULL_TREE && POINTER_TYPE_P (TREE_TYPE (lhs)))
+	{
+	  tree op0 = lhs;
+	  tree op1 = rhs;
+	  if (integer_zerop (op0))
+	    std::swap (op0, op1);
+	  /* With -fno-delete-null-pointer-checks, generic folders
+	     assume addresses of non-automatic VAR_DECLs could be NULL.
+	     For constexpr new, as the vars aren't really living in
+	     target memory, assume they will never be NULL.  */
+	  if (integer_zerop (op1))
+	    {
+	      STRIP_NOPS (op0);
+	      if (TREE_CODE (op0) == ADDR_EXPR)
+		{
+		  op0 = get_base_address (TREE_OPERAND (op0, 0));
+		  if (op0
+		      && VAR_P (op0)
+		      && (DECL_NAME (op0) == heap_identifier
+			  || DECL_NAME (op0) == heap_uninit_identifier
+			  || DECL_NAME (op0) == heap_vec_identifier
+			  || DECL_NAME (op0) == heap_vec_uninit_identifier))
+		    r = constant_boolean_node (!is_code_eq, type);
+		}
+	    }
+	}
     }
   if (code == POINTER_PLUS_EXPR && !*non_constant_p
       && integer_zerop (lhs) && !integer_zerop (rhs))
--- gcc/testsuite/g++.dg/cpp2a/constexpr-new16.C.jj	2021-02-08 17:25:37.130699213 +0100
+++ gcc/testsuite/g++.dg/cpp2a/constexpr-new16.C	2021-02-08 17:26:49.175889198 +0100
@@ -0,0 +1,13 @@
+// PR c++/98988
+// { dg-do compile { target c++20 } }
+// { dg-options "-fno-delete-null-pointer-checks" }
+
+constexpr bool
+foo ()
+{
+  auto ptr = new int();
+  delete ptr;
+  return true;
+}
+
+static_assert (foo ());

	Jakub



More information about the Gcc-patches mailing list