The middle-end does not fully understand NULLPTR_TYPE. So it gets confused a lot of the time when dealing with it. This adds the folding that is similarly done in the C++ front-end already. In some cases it should produce slightly better code as there is no reason to load from a nullptr_t variable as it is always NULL.
The following is handled: nullptr_v ==/!= nullptr_v -> true/false (ptr)nullptr_v -> (ptr)0, nullptr_v f(nullptr_v) -> f ((nullptr, nullptr_v)) The last one is for conversion inside ... . Bootstrapped and tested on x86_64-linux-gnu. PR c/121478 gcc/c/ChangeLog: * c-fold.cc (c_fully_fold_internal): Fold nullptr_t ==/!= nullptr_t. * c-typeck.cc (convert_arguments): Handle conversion from nullptr_t for varargs. (convert_for_assignment): Handle conversions from nullptr_t to pointer type specially. gcc/testsuite/ChangeLog: * gcc.dg/torture/pr121478-1.c: New test. Signed-off-by: Andrew Pinski <andrew.pin...@oss.qualcomm.com> --- gcc/c/c-fold.cc | 20 +++++++++++++- gcc/c/c-typeck.cc | 9 +++++-- gcc/testsuite/gcc.dg/torture/pr121478-1.c | 32 +++++++++++++++++++++++ 3 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 gcc/testsuite/gcc.dg/torture/pr121478-1.c diff --git a/gcc/c/c-fold.cc b/gcc/c/c-fold.cc index d54ab3cf479..3f6e4b469b9 100644 --- a/gcc/c/c-fold.cc +++ b/gcc/c/c-fold.cc @@ -369,7 +369,25 @@ c_fully_fold_internal (tree expr, bool in_init, bool *maybe_const_operands, || TREE_CODE (op1) != INTEGER_CST)) goto out; - if (op0 != orig_op0 || op1 != orig_op1 || in_init) + if (TREE_CODE_CLASS (code) == tcc_comparison + && TREE_CODE (TREE_TYPE (op0)) == NULLPTR_TYPE + && TREE_CODE (TREE_TYPE (op1)) == NULLPTR_TYPE) + { + switch (code) + { + case EQ_EXPR: + ret = constant_boolean_node (true, TREE_TYPE (expr)); + break; + case NE_EXPR: + ret = constant_boolean_node (false, TREE_TYPE (expr)); + break; + default: + gcc_unreachable (); + } + ret = omit_two_operands_loc (loc, TREE_TYPE (expr), ret, + op0, op1); + } + else if (op0 != orig_op0 || op1 != orig_op1 || in_init) ret = in_init ? fold_build2_initializer_loc (loc, code, TREE_TYPE (expr), op0, op1) : fold_build2_loc (loc, code, TREE_TYPE (expr), op0, op1); diff --git a/gcc/c/c-typeck.cc b/gcc/c/c-typeck.cc index 3c6f7d996e9..6a08fcd396a 100644 --- a/gcc/c/c-typeck.cc +++ b/gcc/c/c-typeck.cc @@ -4679,6 +4679,9 @@ convert_arguments (location_t loc, vec<location_t> arg_loc, tree fntype, val, valtype, npc, rname, parmnum, argnum, excess_precision, 0); } + /* A NULLPTR type is just a nullptr always. */ + else if (TREE_CODE (TREE_TYPE (val)) == NULLPTR_TYPE) + parmval = omit_one_operand_loc (ploc, TREE_TYPE (val), nullptr_node, val); else if (promote_float_arg) { if (type_generic) @@ -8983,11 +8986,13 @@ convert_for_assignment (location_t location, location_t expr_loc, tree type, && coder == INTEGER_TYPE) warning_at (location, OPT_Wzero_as_null_pointer_constant, "zero as null pointer constant"); - + /* A NULLPTR type is just a nullptr always. */ + if (coder == NULLPTR_TYPE) + return omit_one_operand_loc (expr_loc, type, nullptr_node, rhs); /* An explicit constant 0 or type nullptr_t can convert to a pointer, or one that results from arithmetic, even including a cast to integer type. */ - if (!null_pointer_constant && coder != NULLPTR_TYPE) + else if (!null_pointer_constant) switch (errtype) { case ic_argpass: diff --git a/gcc/testsuite/gcc.dg/torture/pr121478-1.c b/gcc/testsuite/gcc.dg/torture/pr121478-1.c new file mode 100644 index 00000000000..1dda01c6241 --- /dev/null +++ b/gcc/testsuite/gcc.dg/torture/pr121478-1.c @@ -0,0 +1,32 @@ +/* { dg-do compile } */ +/* { dg-options "-std=gnu23" } */ + +#include <stddef.h> +#include <stdlib.h> +typedef struct { + int data[5]; + nullptr_t np; +} container_t; +void process_array(int *arr, size_t len, nullptr_t nullp) { + for (size_t i = 0; i < len; ++i) { + switch (arr[i] % 4) { + case 1: + if (nullp == nullptr) { + arr[i] *= -1; + [[fallthrough]]; + } + case 2: + arr[i] = abs(arr[i]); + break; + default: + arr[i] = 0; + } + } +} +int main(void) { + container_t c = { + .data = { -3, 1, 4, 2, 7 }, + .np = nullptr + }; + process_array(c.data, 5, c.np); +} -- 2.43.0