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)