On Wed, 9 Feb 2022, Jakub Jelinek wrote:

> On Wed, Feb 09, 2022 at 11:19:25AM +0100, Richard Biener wrote:
> > That does look like bogus abstraction though - I'd rather have
> > the target be specific w/o option checks and replace 
> > targetm.zero_addres_valid uses with a wrapper (like you do for
> > flag_delete_null_pointer_checks), if we think that the specific
> > query should be adjusted by sanitize flags (why?) or
> > folding_initializer (why?).
> 
> Based on discussions on IRC, here is a WIP patch.
> 
> Unfortunately, there are 3 unresolved issues:
> 1) ipa-icf.cc uses
>       && opt_for_fn (decl, flag_delete_null_pointer_checks))
>    there is a pointer type, but I guess we'd need to adjust the
>    target hook to take a defaulted fndecl argument and use that
>    for the options

Yeah, I'd use a struct function arg tho, not a decl.

> 2) rtlanal.cc has:
>     case SYMBOL_REF:
>       return flag_delete_null_pointer_checks && !SYMBOL_REF_WEAK (x);
>    Is there any way how to find out address space of a SYMBOL_REF?

TYPE_ADDR_SPACE (TREE_TYPE (SYMBOL_REF_DECL ())) I guess.

>    Or shall it hardcode ADDR_SPACE_GENERIC?
> 3) tree-ssa-structalias.cc has:
>   if ((TREE_CODE (t) == INTEGER_CST
>        && integer_zerop (t))
>       /* The only valid CONSTRUCTORs in gimple with pointer typed
>          elements are zero-initializer.  But in IPA mode we also
>          process global initializers, so verify at least.  */
>       || (TREE_CODE (t) == CONSTRUCTOR
>           && CONSTRUCTOR_NELTS (t) == 0))
>     {
>       if (flag_delete_null_pointer_checks)
>         temp.var = nothing_id;
>       else
>         temp.var = nonlocal_id;
>       temp.type = ADDRESSOF;
>       temp.offset = 0;
>       results->safe_push (temp);
>       return;
>     }
>    mpt really sure where to get the address space from in that case
> 
> And perhaps I didn't do it right in some other spots too.

This case is really difficult since we track pointers through integers
(mind the missing POINTER_TYPE_P check above).  Of course we have
no idea what address-space the integer was converted from or will
be converted to so what the above wants to check is whether
there is _any_ address-space that could have a zero pointer pointing
to a valid object ...

> --- gcc/targhooks.cc.jj       2022-01-18 11:58:59.919977242 +0100
> +++ gcc/targhooks.cc  2022-02-09 13:21:08.958835833 +0100
> @@ -1598,7 +1598,7 @@ default_addr_space_subset_p (addr_space_
>  bool
>  default_addr_space_zero_address_valid (addr_space_t as ATTRIBUTE_UNUSED)
>  {
> -  return false;
> +  return !flag_delete_null_pointer_checks_;

As said, I'd not do that, but check it in zero_address_valid only.
Otherwise all targets overriding the hook have to remember to check
this flag.  I suppose we'd then do

  if (option_set (flag_delete_null_pointer_check))
    use flag_delete_null_pointer_check;
  else
    use targetm.zero_address_valid;

possibly only for the default address-space.

>  }
>  
>  /* The default hook for debugging the address space is to return the
> --- gcc/tree.cc.jj    2022-02-08 20:08:04.001539492 +0100
> +++ gcc/tree.cc       2022-02-09 14:44:01.602693848 +0100
> @@ -69,6 +69,7 @@ along with GCC; see the file COPYING3.
>  #include "gimple-fold.h"
>  #include "escaped_string.h"
>  #include "gimple-range.h"
> +#include "asan.h"
>  
>  /* Tree code classes.  */
>  
> @@ -13937,12 +13938,13 @@ nonnull_arg_p (const_tree arg)
>    /* THIS argument of method is always non-NULL.  */
>    if (TREE_CODE (TREE_TYPE (cfun->decl)) == METHOD_TYPE
>        && arg == DECL_ARGUMENTS (cfun->decl)
> -      && flag_delete_null_pointer_checks)
> +      && POINTER_TYPE_P (TREE_TYPE (arg))
> +      && !zero_address_valid (TREE_TYPE (arg)))
>      return true;
>  
>    /* Values passed by reference are always non-NULL.  */
>    if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE
> -      && flag_delete_null_pointer_checks)
> +      && !zero_address_valid (TREE_TYPE (arg)))
>      return true;
>  
>    fntype = TREE_TYPE (cfun->decl);
> @@ -14549,6 +14551,24 @@ get_attr_nonstring_decl (tree expr, tree
>    return NULL_TREE;
>  }
>  
> +/* Return true if NULL is a valid address in AS.  */
> +
> +bool
> +zero_address_valid (addr_space_t as)
> +{
> +  if (targetm.addr_space.zero_address_valid (as))
> +    return true;
> +  /* -fsanitize={null,{,returns-}nonnull-attribute sanitizers need
> +     NULL pointer checks to be preserved, so pretend NULL addresses
> +     are valid for it as well.
> +     But don't do that in constant expressions or initializers.  */
> +  if (folding_initializer)
> +    return false;
> +  return sanitize_flags_p (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE        
>                                                                               
>                            
> +                        | SANITIZE_RETURNS_NONNULL_ATTRIBUTE,
> +                        current_function_decl);
> +}
> +
>  #if CHECKING_P
>  
>  namespace selftest {
> --- gcc/config/i386/i386.cc.jj        2022-02-09 12:55:50.716774241 +0100
> +++ gcc/config/i386/i386.cc   2022-02-09 13:23:01.041272540 +0100
> @@ -23804,7 +23804,9 @@ ix86_gen_scratch_sse_rtx (machine_mode m
>  static bool
>  ix86_addr_space_zero_address_valid (addr_space_t as)
>  {
> -  return as != ADDR_SPACE_GENERIC;
> +  if (as != ADDR_SPACE_GENERIC)
> +    return true;

so this makes it not possibel to use -fdelete-null-pointer-checks to
override the non-default address space behavior (on x86)

> +  return default_addr_space_zero_address_valid (as);
>  }
>  
>  static void
> --- gcc/config/nios2/elf.h.jj 2022-01-11 23:11:21.915296829 +0100
> +++ gcc/config/nios2/elf.h    2022-02-09 13:04:42.643433282 +0100
> @@ -57,5 +57,5 @@
>     vector).  Users can override this on the command line to get the
>     additional optimizations it enables.  */
>  #define SUBTARGET_OVERRIDE_OPTIONS           \
> -  if (flag_delete_null_pointer_checks < 0)   \
> -    flag_delete_null_pointer_checks = 0
> +  if (flag_delete_null_pointer_checks_ < 0)  \
> +    flag_delete_null_pointer_checks_ = 0
> --- gcc/config/msp430/msp430.cc.jj    2022-02-04 14:36:54.410613609 +0100
> +++ gcc/config/msp430/msp430.cc       2022-02-09 13:04:09.372888416 +0100
> @@ -161,7 +161,7 @@ msp430_option_override (void)
>  {
>    /* The MSP430 architecture can safely dereference a NULL pointer.  In fact,
>       there are memory mapped registers there.  */
> -  flag_delete_null_pointer_checks = 0;
> +  flag_delete_null_pointer_checks_ = 0;

I'd use the target hook to return false and let 
-fdelete-null-pointer-checks override it.

>    init_machine_status = msp430_init_machine_status;
>  
> --- gcc/config/cr16/cr16.cc.jj        2022-01-18 11:58:59.076989285 +0100
> +++ gcc/config/cr16/cr16.cc   2022-02-09 13:03:47.292190471 +0100
> @@ -277,7 +277,7 @@ cr16_override_options (void)
>       Programs which rely on NULL pointer dereferences _not_ halting the 
>       program may not work properly with this option. So disable this 
>       option.  */
> -  flag_delete_null_pointer_checks = 0;
> +  flag_delete_null_pointer_checks_ = 0;
>  
>    /* FIXME: To avoid spill_failure ICE during exception handling,
>     * disable cse_fllow_jumps. The spill error occurs when compiler
> --- gcc/range-op.cc.jj        2022-02-08 20:08:03.888541042 +0100
> +++ gcc/range-op.cc   2022-02-09 14:01:50.561978439 +0100
> @@ -3870,8 +3870,7 @@ pointer_plus_operator::wi_fold (irange &
>    if ((!wi_includes_zero_p (type, lh_lb, lh_ub)
>         || !wi_includes_zero_p (type, rh_lb, rh_ub))
>        && !TYPE_OVERFLOW_WRAPS (type)
> -      && (flag_delete_null_pointer_checks
> -       || !wi::sign_mask (rh_ub)))
> +      && (!zero_address_valid (type) || !wi::sign_mask (rh_ub)))
>      r = range_nonzero (type);
>    else if (lh_lb == lh_ub && lh_lb == 0
>          && rh_lb == rh_ub && rh_lb == 0)
> --- gcc/gimple-range-fold.cc.jj       2022-02-08 20:08:03.829541850 +0100
> +++ gcc/gimple-range-fold.cc  2022-02-09 13:53:24.595030465 +0100
> @@ -721,7 +721,7 @@ fold_using_range::range_of_address (iran
>        /* If &X->a is equal to X, the range of X is the result.  */
>        if (off_cst && known_eq (off, 0))
>       return true;
> -      else if (flag_delete_null_pointer_checks
> +      else if (!zero_address_valid (TREE_TYPE (expr))
>              && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr)))
>       {
>         /* For -fdelete-null-pointer-checks -fno-wrapv-pointer we don't
> @@ -741,7 +741,7 @@ fold_using_range::range_of_address (iran
>        if (!TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr))
>         && off_cst
>         && known_ne (off, 0)
> -       && (flag_delete_null_pointer_checks || known_gt (off, 0)))
> +       && (!zero_address_valid (TREE_TYPE (expr)) || known_gt (off, 0)))
>       {
>         r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
>         return true;
> --- gcc/cp/typeck.cc.jj       2022-02-08 20:08:03.783542481 +0100
> +++ gcc/cp/typeck.cc  2022-02-09 14:47:47.552526504 +0100
> @@ -7917,7 +7917,7 @@ build_static_cast_1 (location_t loc, tre
>        that expr is NULL, if the static_cast is to a reference type,
>        it is UB if it would be NULL, so omit the non-NULL check.  */
>        expr = build_base_path (MINUS_EXPR, expr, base,
> -                           /*nonnull=*/flag_delete_null_pointer_checks,
> +                           /*nonnull=*/!zero_address_valid (type),
>                             complain);
>  
>        /* Convert the pointer to a reference -- but then remember that
> --- gcc/tree-ssa-structalias.cc.jj    2022-02-08 20:08:03.952540164 +0100
> +++ gcc/tree-ssa-structalias.cc       2022-02-09 14:32:39.127226322 +0100
> @@ -4591,8 +4591,10 @@ find_func_aliases_for_builtin_call (stru
>           }
>         get_constraint_for_ptr_offset (dest, NULL_TREE, &lhsc);
>         do_deref (&lhsc);
> -       if (flag_delete_null_pointer_checks
> -           && integer_zerop (gimple_call_arg (t, 1)))
> +       tree arg1 = gimple_call_arg (t, 1);
> +       if (integer_zerop (arg1)
> +           && POINTER_TYPE_P (TREE_TYPE (arg1))
> +           && !zero_address_valid (TREE_TYPE (arg1)))
>           {
>             ac.type = ADDRESSOF;
>             ac.var = nothing_id;
> --- gcc/testsuite/g++.dg/ubsan/pr104426.C.jj  2022-02-09 13:20:26.419429166 
> +0100
> +++ gcc/testsuite/g++.dg/ubsan/pr104426.C     2022-02-09 13:20:26.419429166 
> +0100
> @@ -0,0 +1,29 @@
> +// PR c++/104426
> +// { dg-do compile }
> +// { dg-options "-std=c++17 -fsanitize=undefined" }
> +
> +struct category
> +{
> +  constexpr bool failed () const noexcept { return true; }
> +};
> +
> +inline constexpr category s_cat;
> +
> +struct condition
> +{
> +  category const *cat_;
> +  constexpr bool failed () const noexcept
> +  {
> +    if (cat_)
> +      return cat_->failed ();
> +    else
> +      return false;
> +  }
> +};
> +
> +int
> +main ()
> +{
> +  constexpr condition cond { &s_cat };
> +  static_assert (cond.failed ());
> +}
> --- gcc/testsuite/g++.dg/ubsan/pr71962.C.jj   2022-02-09 13:20:26.419429166 
> +0100
> +++ gcc/testsuite/g++.dg/ubsan/pr71962.C      2022-02-09 13:20:26.419429166 
> +0100
> @@ -0,0 +1,17 @@
> +// PR c++/71962
> +// { dg-do compile }
> +// { dg-options "-std=c++14 -fsanitize=undefined" }
> +
> +struct P {
> +  constexpr P (const int *p) : p(p) { }
> +  const int *p;
> +  explicit constexpr operator bool() const { return (bool) p; }
> +};
> +
> +int
> +main ()
> +{
> +  static constexpr int x{1};
> +  constexpr P p{&x};
> +  static_assert ((bool)p, "");
> +}
> --- gcc/symtab.cc.jj  2022-02-08 20:08:03.913540699 +0100
> +++ gcc/symtab.cc     2022-02-09 14:10:50.866452450 +0100
> @@ -2135,11 +2135,11 @@ symtab_node::nonzero_address ()
>            could be useful to eliminate the NULL pointer checks in LTO
>            programs.  */
>         if (target->definition && !DECL_EXTERNAL (target->decl))
> -           return true;
> +         return true;
>         if (target->resolution != LDPR_UNKNOWN
>             && target->resolution != LDPR_UNDEF
>             && !target->can_be_discarded_p ()
> -           && flag_delete_null_pointer_checks)
> +           && !zero_address_valid (TYPE_ADDR_SPACE (TREE_TYPE (decl))))
>           return true;
>         return false;
>       }
> @@ -2147,7 +2147,7 @@ symtab_node::nonzero_address ()
>          return false;
>      }
>  
> -  /* With !flag_delete_null_pointer_checks we assume that symbols may
> +  /* With -fno-delete-null-pointer-checks we assume that symbols may
>       bind to NULL. This is on by default on embedded targets only.
>  
>       Otherwise all non-WEAK symbols must be defined and thus non-NULL or
> @@ -2156,7 +2156,7 @@ symtab_node::nonzero_address ()
>  
>       When parsing, beware the cases when WEAK attribute is added later.  */
>    if ((!DECL_WEAK (decl) || DECL_COMDAT (decl))
> -      && flag_delete_null_pointer_checks)
> +      && !zero_address_valid (TYPE_ADDR_SPACE (TREE_TYPE (decl))))
>      {
>        refuse_visibility_changes = true;
>        return true;
> @@ -2164,10 +2164,11 @@ symtab_node::nonzero_address ()
>  
>    /* If target is defined and not extern, we know it will be
>       output and thus it will bind to non-NULL.
> -     Play safe for flag_delete_null_pointer_checks where weak definition may
> +     Play safe for -fno-delete-null-pointer-checks where weak definition may
>       be re-defined by NULL.  */
>    if (definition && !DECL_EXTERNAL (decl)
> -      && (flag_delete_null_pointer_checks || !DECL_WEAK (decl)))
> +      && (!zero_address_valid (TYPE_ADDR_SPACE (TREE_TYPE (decl)))
> +       || !DECL_WEAK (decl)))
>      {
>        if (!DECL_WEAK (decl))
>          refuse_visibility_changes = true;
> @@ -2178,7 +2179,7 @@ symtab_node::nonzero_address ()
>    if (resolution != LDPR_UNKNOWN
>        && resolution != LDPR_UNDEF
>        && !can_be_discarded_p ()
> -      && flag_delete_null_pointer_checks)
> +      && !zero_address_valid (TYPE_ADDR_SPACE (TREE_TYPE (decl))))
>      return true;
>    return false;
>  }
> --- gcc/ipa-fnsummary.cc.jj   2022-02-08 20:08:03.855541494 +0100
> +++ gcc/ipa-fnsummary.cc      2022-02-09 13:54:40.594971201 +0100
> @@ -2573,7 +2573,7 @@ points_to_local_or_readonly_memory_p (tr
>  {
>    /* See if memory location is clearly invalid.  */
>    if (integer_zerop (t))
> -    return flag_delete_null_pointer_checks;
> +    return !zero_address_valid (TREE_TYPE (t));
>    if (TREE_CODE (t) == SSA_NAME)
>      {
>        /* For IPA passes we can consinder accesses to return slot local
> --- gcc/tree.h.jj     2022-02-04 14:36:56.382586067 +0100
> +++ gcc/tree.h        2022-02-09 13:37:22.944332825 +0100
> @@ -6579,4 +6579,14 @@ extern unsigned fndecl_dealloc_argno (tr
>     object or pointer.  Otherwise return null.  */
>  extern tree get_attr_nonstring_decl (tree, tree * = NULL);
>  
> +/* Return true if NULL is a valid address in AS.  */
> +extern bool zero_address_valid (addr_space_t);
> +
> +inline bool
> +zero_address_valid (tree type)
> +{
> +  gcc_checking_assert (POINTER_TYPE_P (type));
> +  return zero_address_valid (TYPE_ADDR_SPACE (TREE_TYPE (type)));
> +}
> +
>  #endif  /* GCC_TREE_H  */
> --- gcc/tree-ssa-alias.cc.jj  2022-02-08 20:08:03.917540644 +0100
> +++ gcc/tree-ssa-alias.cc     2022-02-09 14:16:14.231951242 +0100
> @@ -2644,13 +2644,13 @@ modref_may_conflict (const gcall *stmt,
>  
>             alias_stats.modref_baseptr_tests++;
>  
> -           if (integer_zerop (arg) && flag_delete_null_pointer_checks)
> -             continue;
> -
> -           /* PTA oracle will be unhapy of arg is not an pointer.  */
> +           /* PTA oracle will be unhapy if arg is not an pointer.  */
>             if (!POINTER_TYPE_P (TREE_TYPE (arg)))
>               return true;
>  
> +           if (integer_zerop (arg) && !zero_address_valid (TREE_TYPE (arg)))
> +             continue;
> +
>             /* If we don't have base pointer, give up.  */
>             if (!ref->ref && !ref->base)
>               continue;
> --- gcc/opts.cc.jj    2022-02-08 20:08:03.873541247 +0100
> +++ gcc/opts.cc       2022-02-09 13:20:26.418429180 +0100
> @@ -1224,12 +1224,6 @@ finish_options (struct gcc_options *opts
>        error_at (loc, "%<-fsanitize-recover=%s%> is not supported",
>               sanitizer_opts[i].name);
>  
> -  /* When instrumenting the pointers, we don't want to remove
> -     the null pointer checks.  */
> -  if (opts->x_flag_sanitize & (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
> -                             | SANITIZE_RETURNS_NONNULL_ATTRIBUTE))
> -    opts->x_flag_delete_null_pointer_checks = 0;
> -
>    /* Aggressive compiler optimizations may cause false negatives.  */
>    if (opts->x_flag_sanitize & ~(SANITIZE_LEAK | SANITIZE_UNREACHABLE))
>      opts->x_flag_aggressive_loop_optimizations = 0;
> --- gcc/ubsan.cc.jj   2022-02-08 20:08:04.001539492 +0100
> +++ gcc/ubsan.cc      2022-02-09 13:20:26.419429166 +0100
> @@ -1946,10 +1946,11 @@ instrument_nonnull_arg (gimple_stmt_iter
>  {
>    gimple *stmt = gsi_stmt (*gsi);
>    location_t loc[2];
> -  /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
> +  /* infer_nonnull_range needs zero_address_valid true,
>       while for nonnull sanitization it is clear.  */
> -  int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
> -  flag_delete_null_pointer_checks = 1;
> +  int save_flag_sanitize = flag_sanitize;
> +  flag_sanitize &= ~(SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
> +                  | SANITIZE_RETURNS_NONNULL_ATTRIBUTE);
>    loc[0] = gimple_location (stmt);
>    loc[1] = UNKNOWN_LOCATION;
>    for (unsigned int i = 0; i < gimple_call_num_args (stmt); i++)
> @@ -2001,7 +2002,7 @@ instrument_nonnull_arg (gimple_stmt_iter
>       }
>        *gsi = gsi_for_stmt (stmt);
>      }
> -  flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
> +  flag_sanitize = save_flag_sanitize;
>  }
>  
>  /* Instrument returns in functions with returns_nonnull attribute.  */
> @@ -2012,10 +2013,11 @@ instrument_nonnull_return (gimple_stmt_i
>    greturn *stmt = as_a <greturn *> (gsi_stmt (*gsi));
>    location_t loc[2];
>    tree arg = gimple_return_retval (stmt);
> -  /* infer_nonnull_range needs flag_delete_null_pointer_checks set,
> -     while for nonnull return sanitization it is clear.  */
> -  int save_flag_delete_null_pointer_checks = flag_delete_null_pointer_checks;
> -  flag_delete_null_pointer_checks = 1;
> +  /* infer_nonnull_range needs zero_address_valid true,
> +     while for nonnull sanitization it is clear.  */
> +  int save_flag_sanitize = flag_sanitize;
> +  flag_sanitize &= ~(SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
> +                  | SANITIZE_RETURNS_NONNULL_ATTRIBUTE);
>    loc[0] = gimple_location (stmt);
>    loc[1] = UNKNOWN_LOCATION;
>    if (arg
> @@ -2056,7 +2058,7 @@ instrument_nonnull_return (gimple_stmt_i
>        ubsan_create_edge (g);
>        *gsi = gsi_for_stmt (stmt);
>      }
> -  flag_delete_null_pointer_checks = save_flag_delete_null_pointer_checks;
> +  flag_sanitize = save_flag_sanitize;
>  }
>  
>  /* Instrument memory references.  Here we check whether the pointer
> --- gcc/tree-vrp.cc.jj        2022-02-08 20:08:03.977539821 +0100
> +++ gcc/tree-vrp.cc   2022-02-09 14:33:26.884560195 +0100
> @@ -732,7 +732,7 @@ extract_range_from_pointer_plus_expr (va
>    if ((!range_includes_zero_p (vr0)
>         || !range_includes_zero_p (vr1))
>        && !TYPE_OVERFLOW_WRAPS (expr_type)
> -      && (flag_delete_null_pointer_checks
> +      && (!zero_address_valid (expr_type)
>         || (range_int_cst_p (vr1)
>             && !tree_int_cst_sign_bit (vr1->max ()))))
>      vr->set_nonzero (expr_type);
> --- gcc/vr-values.cc.jj       2022-02-08 20:08:04.001539492 +0100
> +++ gcc/vr-values.cc  2022-02-09 14:34:32.257648360 +0100
> @@ -426,7 +426,7 @@ vr_values::vrp_stmt_computes_nonzero (gi
>            For -fdelete-null-pointer-checks -fno-wrapv-pointer we don't
>            allow going from non-NULL pointer to NULL.  */
>         if ((off_cst && known_eq (off, 0))
> -           || (flag_delete_null_pointer_checks
> +           || (!zero_address_valid (TREE_TYPE (expr))
>                 && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr))))
>           {
>             const value_range_equiv *vr
> @@ -440,7 +440,7 @@ vr_values::vrp_stmt_computes_nonzero (gi
>         if (!TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr))
>             && off_cst
>             && known_ne (off, 0)
> -           && (flag_delete_null_pointer_checks || known_gt (off, 0)))
> +           && (!zero_address_valid (TREE_TYPE (expr)) || known_gt (off, 0)))
>           return true;
>       }
>      }
> --- gcc/tree-ssa-loop-niter.cc.jj     2022-02-08 20:08:03.952540164 +0100
> +++ gcc/tree-ssa-loop-niter.cc        2022-02-09 14:17:40.614748806 +0100
> @@ -3899,7 +3899,7 @@ infer_loop_bounds_from_pointer_arith (cl
>       NULL pointer since that would mean wrapping, which we assume here not to
>       happen.  So, we can exclude NULL from the valid range of pointer
>       arithmetic.  */
> -  if (flag_delete_null_pointer_checks && int_cst_value (low) == 0)
> +  if (!zero_address_valid (type) && int_cst_value (low) == 0)
>      low = build_int_cstu (TREE_TYPE (low), TYPE_ALIGN_UNIT (TREE_TYPE 
> (type)));
>  
>    record_nonwrapping_iv (loop, base, step, stmt, low, high, false, true);
> --- gcc/common.opt.jj 2022-02-08 20:08:03.655544236 +0100
> +++ gcc/common.opt    2022-02-09 13:02:46.907016534 +0100
> @@ -1288,7 +1288,7 @@ Common Var(flag_delete_dead_exceptions)
>  Delete dead instructions that may throw exceptions.
>  
>  fdelete-null-pointer-checks
> -Common Var(flag_delete_null_pointer_checks) Init(-1) Optimization
> +Common Var(flag_delete_null_pointer_checks_) Init(-1) Optimization
>  Delete useless null pointer checks.
>  
>  fdevirtualize-at-ltrans
> --- gcc/c-family/c-ubsan.cc.jj        2022-02-08 20:08:03.611544839 +0100
> +++ gcc/c-family/c-ubsan.cc   2022-02-09 13:20:26.419429166 +0100
> @@ -464,17 +464,16 @@ ubsan_maybe_instrument_reference_or_call
>       {
>         bool strict_overflow_p = false;
>         /* tree_single_nonzero_warnv_p will not return true for non-weak
> -          non-automatic decls with -fno-delete-null-pointer-checks,
> +          non-automatic decls with !zero_address_valid,
>            which is disabled during -fsanitize=null.  We don't want to
>            instrument those, just weak vars though.  */
> -       int save_flag_delete_null_pointer_checks
> -         = flag_delete_null_pointer_checks;
> -       flag_delete_null_pointer_checks = 1;
> +       int save_flag_sanitize = flag_sanitize;
> +       flag_sanitize &= ~(SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
> +                          | SANITIZE_RETURNS_NONNULL_ATTRIBUTE);
>         if (!tree_single_nonzero_warnv_p (op, &strict_overflow_p)
>             || strict_overflow_p)
>           instrument = true;
> -       flag_delete_null_pointer_checks
> -         = save_flag_delete_null_pointer_checks;
> +       flag_sanitize = save_flag_sanitize;
>       }
>        else if (sanitize_flags_p (SANITIZE_NULL))
>       instrument = true;
> --- gcc/ipa-pure-const.cc.jj  2022-02-08 20:08:03.856541480 +0100
> +++ gcc/ipa-pure-const.cc     2022-02-09 14:00:45.161889970 +0100
> @@ -971,8 +971,7 @@ malloc_candidate_p (function *fun, bool
>    edge_iterator ei;
>    cgraph_node *node = cgraph_node::get_create (fun->decl);
>  
> -  if (EDGE_COUNT (exit_block->preds) == 0
> -      || !flag_delete_null_pointer_checks)
> +  if (EDGE_COUNT (exit_block->preds) == 0)
>      return false;
>  
>    auto_bitmap visited;
> @@ -992,6 +991,9 @@ malloc_candidate_p (function *fun, bool
>         || TREE_CODE (TREE_TYPE (retval)) != POINTER_TYPE)
>       DUMP_AND_RETURN("Return value is not SSA_NAME or not a pointer type.")
>  
> +      if (zero_address_valid (TREE_TYPE (retval)))
> +     return false;
> +
>        if (!malloc_candidate_p_1 (fun, retval, ret_stmt, ipa, visited))
>       return false;
>      }
> --- gcc/gimple.cc.jj  2022-02-08 20:08:03.851541549 +0100
> +++ gcc/gimple.cc     2022-02-09 13:47:54.762626732 +0100
> @@ -1673,19 +1673,22 @@ gimple_call_nonnull_result_p (gcall *cal
>    tree fndecl = gimple_call_fndecl (call);
>    if (!fndecl)
>      return false;
> -  if (flag_delete_null_pointer_checks && !flag_check_new
> +  if (!flag_check_new
>        && DECL_IS_OPERATOR_NEW_P (fndecl)
> -      && !TREE_NOTHROW (fndecl))
> +      && !TREE_NOTHROW (fndecl)
> +      && POINTER_TYPE_P (TREE_TYPE (fndecl))
> +      && !zero_address_valid (TREE_TYPE (fndecl)))
>      return true;
>  
>    /* References are always non-NULL.  */
> -  if (flag_delete_null_pointer_checks
> -      && TREE_CODE (TREE_TYPE (fndecl)) == REFERENCE_TYPE)
> +  if (TREE_CODE (TREE_TYPE (fndecl)) == REFERENCE_TYPE
> +      && !zero_address_valid (TREE_TYPE (fndecl)))
>      return true;
>  
> -  if (flag_delete_null_pointer_checks
> -      && lookup_attribute ("returns_nonnull",
> -                        TYPE_ATTRIBUTES (gimple_call_fntype (call))))
> +  tree fntype = gimple_call_fntype (call);
> +  if (lookup_attribute ("returns_nonnull", TYPE_ATTRIBUTES (fntype))
> +      && POINTER_TYPE_P (TREE_TYPE (fntype))
> +      && !zero_address_valid (TREE_TYPE (fntype)))
>      return true;
>    return gimple_alloca_call_p (call);
>  }
> @@ -3033,10 +3036,10 @@ infer_nonnull_range_by_dereference (gimp
>  {
>    /* We can only assume that a pointer dereference will yield
>       non-NULL if -fdelete-null-pointer-checks is enabled.  */
> -  if (!flag_delete_null_pointer_checks
> -      || !POINTER_TYPE_P (TREE_TYPE (op))
> +  if (!POINTER_TYPE_P (TREE_TYPE (op))
>        || gimple_code (stmt) == GIMPLE_ASM
> -      || gimple_clobber_p (stmt))
> +      || gimple_clobber_p (stmt)
> +      || zero_address_valid (TREE_TYPE (TREE_TYPE (op))))
>      return false;
>  
>    if (walk_stmt_load_store_ops (stmt, (void *)op,
> @@ -3053,9 +3056,9 @@ infer_nonnull_range_by_attribute (gimple
>  {
>    /* We can only assume that a pointer dereference will yield
>       non-NULL if -fdelete-null-pointer-checks is enabled.  */
> -  if (!flag_delete_null_pointer_checks
> -      || !POINTER_TYPE_P (TREE_TYPE (op))
> -      || gimple_code (stmt) == GIMPLE_ASM)
> +  if (!POINTER_TYPE_P (TREE_TYPE (op))
> +      || gimple_code (stmt) == GIMPLE_ASM
> +      || zero_address_valid (TREE_TYPE (TREE_TYPE (op))))
>      return false;
>  
>    if (is_gimple_call (stmt) && !gimple_call_internal_p (stmt))
> --- gcc/fold-const.cc.jj      2022-02-08 20:08:03.800542248 +0100
> +++ gcc/fold-const.cc 2022-02-09 13:43:49.947029100 +0100
> @@ -10713,13 +10713,16 @@ tree_expr_nonzero_warnv_p (tree t, bool
>        {
>       tree fndecl = get_callee_fndecl (t);
>       if (!fndecl) return false;
> -     if (flag_delete_null_pointer_checks && !flag_check_new
> +     if (!flag_check_new
>           && DECL_IS_OPERATOR_NEW_P (fndecl)
> -         && !TREE_NOTHROW (fndecl))
> +         && !TREE_NOTHROW (fndecl)
> +         && POINTER_TYPE_P (TREE_TYPE (fndecl))
> +         && !zero_address_valid (TREE_TYPE (fndecl)))
>         return true;
> -     if (flag_delete_null_pointer_checks
> -         && lookup_attribute ("returns_nonnull",
> -              TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
> +     if (lookup_attribute ("returns_nonnull",
> +              TYPE_ATTRIBUTES (TREE_TYPE (fndecl)))
> +         && POINTER_TYPE_P (TREE_TYPE (fndecl))
> +         && !zero_address_valid (TREE_TYPE (fndecl)))
>         return true;
>       return alloca_call_p (t);
>        }
> 
> 
>       Jakub
> 
> 

-- 
Richard Biener <rguent...@suse.de>
SUSE Software Solutions Germany GmbH, Maxfeldstrasse 5, 90409 Nuernberg,
Germany; GF: Ivo Totev; HRB 36809 (AG Nuernberg)

Reply via email to