On Wed, 9 Feb 2022, Jakub Jelinek wrote:

> Hi!
> 
> The 3 ubsan -fsanitize={null,{,returns-}nonnull-attribute} sanitizers were
> setting implicitly -fno-delete-null-pointer-exceptions, so that
> optimizations don't optimize away its checks whether some pointers are NULL.
> Unfortunately by doing that there is no way to find out if
> flag_delete_null_pointer_checks is 0 or 1 because the target usually allows
> variables or functions at the start of address space, or user asked for
> that option or whether it was because of sanitization or a combination of
> those.
> 
> Unfortunately Variable in *.opt files can't be PerFunction or Optimization,
> so there is no easy way to have some global_options.x_* be combined from
> other Optimization flags.
> 
> So, the following patch instead introduces an inline function that should be
> used in most places, and for the folding_initializer case ignores
> sanitization and honors just target's or user
> -fno-delete-null-pointer-checks.
> 
> Another possibility would be to invert the meaning of the variable,
> change flag_delete_null_pointer_checks into
> flag_dont_delete_null_pointer_checks and use separate values for the var
> originating from command line or target's decision (e.g. 1) and from

I see there are still targets doing sth like

static void
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;

it would be very nice to instead have those override the 
zero_address_valid target hook (only i386.cc does that at the moment).
It probably doesn't remove much of the complication.

Then at the same time you add the delete_null_pointer_checks ()
abstraction we should add a zero_address_valid (type/as) abstraction
in case we want -fno-delete-null-pointer-checks be a user accessible
way to override the target here.

> sanitization (e.g. 2), but it would be a small nightmare to encode that
> into *.opt.
> 
> A separate issue not solved in this patch is whether addresses of automatic
> variables can be assumed to be non-NULL even in the
> -fno-delete-null-pointer-checks case (whether no target actually places its
> stack at the very start of the address space (especially growing up)).

True - but not sure if worth optimizing ... (the zero_address_valid
could get a decl overload as well).

Did you replace all flag_delete_null_pointer_checks uses?  Can you
rename the flag just to be sure?

Thanks,
Richard.

> Bootstrapped/regtested on x86_64-linux and i686-linux, ok for trunk?
> 
> 2022-02-08  Jakub Jelinek  <ja...@redhat.com>
> 
>       PR c++/67762
>       PR c++/71962
>       PR c++/104426
> gcc/
>       * asan.h (delete_null_pointer_checks): New function.
>       * opts.cc (finish_options): Don't clear
>       opts->x_flag_delete_null_pointer_checks for -fsanitize=null,
>       -fsanitize=nonnull-attribute and/or
>       -fsanitize=returns-nonnull-attribute.
>       * tree.cc: Include asan.h.
>       (nonnull_arg_p): Use delete_null_pointer_checks () instead of
>       flag_delete_null_pointer_checks.
>       * range-op.cc: Include attribs.h and asan.h.
>       (pointer_plus_operator::wi_fold): Use delete_null_pointer_checks ()
>       instead of flag_delete_null_pointer_checks.
>       * gimple-range-fold.cc: Include attribs.h and asan.h.
>       (fold_using_range::range_of_address): Use
>       delete_null_pointer_checks () instead of
>       flag_delete_null_pointer_checks.
>       * tree-ssa-structalias.cc: Include asan.h.
>       (get_constraint_for_1, find_func_aliases_for_builtin_call): Use
>       delete_null_pointer_checks () instead of
>       flag_delete_null_pointer_checks.
>       * symtab.cc: Include asan.h.
>       (symtab_node::nonzero_address): If !folding_initializer, use
>       delete_null_pointer_checks () instead of
>       flag_delete_null_pointer_checks.
>       * ipa-fnsummary.cc: Include asan.h.
>       (points_to_local_or_readonly_memory_p): Use
>       delete_null_pointer_checks () instead of
>       flag_delete_null_pointer_checks.
>       * tree-ssa-alias.cc: Include attribs.h and asan.h.
>       (modref_may_conflict): Use delete_null_pointer_checks () instead of
>       flag_delete_null_pointer_checks.
>       * ubsan.cc (instrument_nonnull_arg, instrument_nonnull_return):
>       Instead of temporarily setting flag_delete_null_pointer_checks
>       temporarily clear SANITIZE_NULL, SANITIZE_NONNULL_ATTRIBUTE and
>       SANITIZE_RETURNS_NONNULL_ATTRIBUTE bits from flag_sanitize.
>       * tree-vrp.cc: Include attribs.h and asan.h.
>       (extract_range_from_pointer_plus_expr): Use
>       delete_null_pointer_checks () instead of
>       flag_delete_null_pointer_checks.
>       * vr-values.cc: Include asan.h.
>       (vr_values::vrp_stmt_computes_nonzero): Use
>       delete_null_pointer_checks () instead of
>       flag_delete_null_pointer_checks.
>       * tree-ssa-loop-niter.cc: Include attribs.h and asan.h.
>       (infer_loop_bounds_from_pointer_arith): Use
>       delete_null_pointer_checks () instead of
>       flag_delete_null_pointer_checks.
>       * ipa-pure-const.cc: Include attribs.h and asan.h.
>       (malloc_candidate_p): Use delete_null_pointer_checks () instead of
>       flag_delete_null_pointer_checks.
>       * gimple.cc (gimple_call_nonnull_result_p,
>       infer_nonnull_range_by_dereference, infer_nonnull_range_by_attribute):
>       Use delete_null_pointer_checks () instead of
>       flag_delete_null_pointer_checks.
>       * fold-const.cc (tree_expr_nonzero_warnv_p): Use
>       delete_null_pointer_checks () instead of
>       flag_delete_null_pointer_checks.
>       * rtlanal.cc: Include stringpool.h, attribs.h and asan.h.
>       (nonzero_address_p): Use delete_null_pointer_checks () instead of
>       flag_delete_null_pointer_checks.
> gcc/c-family/
>       * c-ubsan.cc (ubsan_maybe_instrument_reference_or_call): Instead of
>       temporarily setting flag_delete_null_pointer_checks temporarily clear
>       SANITIZE_NULL, SANITIZE_NONNULL_ATTRIBUTE and
>       SANITIZE_RETURNS_NONNULL_ATTRIBUTE bits from flag_sanitize.
> gcc/cp/
>       * typeck.cc (build_static_cast_1): Use delete_null_pointer_checks ()
>       instead of flag_delete_null_pointer_checks.
> gcc/testsuite/
>       * g++.dg/ubsan/pr71962.C: New test.
>       * g++.dg/ubsan/pr104426.C: New test.
> 
> --- gcc/asan.h.jj     2022-01-11 23:11:21.542302070 +0100
> +++ gcc/asan.h        2022-02-08 10:26:18.695464165 +0100
> @@ -260,4 +260,12 @@ sanitize_coverage_p (const_tree fn = cur
>                                  DECL_ATTRIBUTES (fn)) == NULL_TREE));
>  }
>  
> +static inline bool
> +delete_null_pointer_checks (const_tree fn = current_function_decl)
> +{
> +  return (flag_delete_null_pointer_checks
> +       && !sanitize_flags_p (SANITIZE_NULL | SANITIZE_NONNULL_ATTRIBUTE
> +                             | SANITIZE_RETURNS_NONNULL_ATTRIBUTE, fn));
> +}
> +
>  #endif /* TREE_ASAN */
> --- gcc/opts.cc.jj    2022-02-04 14:36:55.440599224 +0100
> +++ gcc/opts.cc       2022-02-08 10:33:23.128566415 +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/tree.cc.jj    2022-02-04 14:36:56.380586095 +0100
> +++ gcc/tree.cc       2022-02-08 11:04:17.937686466 +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,12 @@ 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)
> +      && delete_null_pointer_checks ())
>      return true;
>  
>    /* Values passed by reference are always non-NULL.  */
>    if (TREE_CODE (TREE_TYPE (arg)) == REFERENCE_TYPE
> -      && flag_delete_null_pointer_checks)
> +      && delete_null_pointer_checks ())
>      return true;
>  
>    fntype = TREE_TYPE (cfun->decl);
> --- gcc/range-op.cc.jj        2022-02-04 14:36:55.500598385 +0100
> +++ gcc/range-op.cc   2022-02-08 11:03:26.136410211 +0100
> @@ -46,6 +46,8 @@ along with GCC; see the file COPYING3.
>  #include "wide-int.h"
>  #include "value-relation.h"
>  #include "range-op.h"
> +#include "attribs.h"
> +#include "asan.h"
>  
>  // Return the upper limit for a type.
>  
> @@ -3870,7 +3872,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
> +      && (delete_null_pointer_checks ()
>         || !wi::sign_mask (rh_ub)))
>      r = range_nonzero (type);
>    else if (lh_lb == lh_ub && lh_lb == 0
> --- gcc/gimple-range-fold.cc.jj       2022-02-04 14:36:55.198602603 +0100
> +++ gcc/gimple-range-fold.cc  2022-02-08 10:57:57.461002325 +0100
> @@ -43,6 +43,9 @@ along with GCC; see the file COPYING3.
>  #include "value-query.h"
>  #include "range-op.h"
>  #include "gimple-range.h"
> +#include "attribs.h"
> +#include "asan.h"
> +
>  // Construct a fur_source, and set the m_query field.
>  
>  fur_source::fur_source (range_query *q)
> @@ -721,7 +724,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 (delete_null_pointer_checks ()
>              && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr)))
>       {
>         /* For -fdelete-null-pointer-checks -fno-wrapv-pointer we don't
> @@ -741,7 +744,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)))
> +       && (delete_null_pointer_checks () || known_gt (off, 0)))
>       {
>         r = range_nonzero (TREE_TYPE (gimple_assign_rhs1 (stmt)));
>         return true;
> --- gcc/tree-ssa-structalias.cc.jj    2022-01-18 11:59:00.093974757 +0100
> +++ gcc/tree-ssa-structalias.cc       2022-02-08 11:02:47.128955208 +0100
> @@ -47,6 +47,7 @@
>  #include "ipa-modref-tree.h"
>  #include "ipa-modref.h"
>  #include "attr-fnspec.h"
> +#include "asan.h"
>  
>  /* The idea behind this analyzer is to generate set constraints from the
>     program, then solve the resulting constraints in order to generate the
> @@ -3531,7 +3532,7 @@ get_constraint_for_1 (tree t, vec<ce_s>
>        || (TREE_CODE (t) == CONSTRUCTOR
>         && CONSTRUCTOR_NELTS (t) == 0))
>      {
> -      if (flag_delete_null_pointer_checks)
> +      if (delete_null_pointer_checks ())
>       temp.var = nothing_id;
>        else
>       temp.var = nonlocal_id;
> @@ -4591,7 +4592,7 @@ 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
> +       if (delete_null_pointer_checks ()
>             && integer_zerop (gimple_call_arg (t, 1)))
>           {
>             ac.type = ADDRESSOF;
> --- gcc/symtab.cc.jj  2022-01-18 11:58:59.892977628 +0100
> +++ gcc/symtab.cc     2022-02-08 10:57:00.150803038 +0100
> @@ -39,6 +39,7 @@ along with GCC; see the file COPYING3.
>  #include "attribs.h"
>  #include "builtins.h"
>  #include "fold-const.h"
> +#include "asan.h"
>  
>  static const char *ipa_ref_use_name[] = {"read","write","addr","alias"};
>  
> @@ -2117,6 +2118,13 @@ symtab_node::get_partitioning_class (voi
>  bool
>  symtab_node::nonzero_address ()
>  {
> +  /* When folding initializers, only look at -fdelete-null-pointer-checks,
> +     otherwise also consider UBSan.  */
> +  bool do_delete_null_pointer_checks
> +    = (folding_initializer
> +       ? flag_delete_null_pointer_checks
> +       : delete_null_pointer_checks ());
> +
>    /* Weakrefs may be NULL when their target is not defined.  */
>    if (alias && weakref)
>      {
> @@ -2135,11 +2143,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)
> +           && do_delete_null_pointer_checks)
>           return true;
>         return false;
>       }
> @@ -2156,7 +2164,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)
> +      && do_delete_null_pointer_checks)
>      {
>        refuse_visibility_changes = true;
>        return true;
> @@ -2167,7 +2175,7 @@ symtab_node::nonzero_address ()
>       Play safe for flag_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)))
> +      && (do_delete_null_pointer_checks || !DECL_WEAK (decl)))
>      {
>        if (!DECL_WEAK (decl))
>          refuse_visibility_changes = true;
> @@ -2178,7 +2186,7 @@ symtab_node::nonzero_address ()
>    if (resolution != LDPR_UNKNOWN
>        && resolution != LDPR_UNDEF
>        && !can_be_discarded_p ()
> -      && flag_delete_null_pointer_checks)
> +      && do_delete_null_pointer_checks)
>      return true;
>    return false;
>  }
> --- gcc/ipa-fnsummary.cc.jj   2022-02-04 14:36:55.259601752 +0100
> +++ gcc/ipa-fnsummary.cc      2022-02-08 10:58:17.435723245 +0100
> @@ -88,6 +88,7 @@ along with GCC; see the file COPYING3.
>  #include "symtab-clones.h"
>  #include "gimple-range.h"
>  #include "tree-dfa.h"
> +#include "asan.h"
>  
>  /* Summaries.  */
>  fast_function_summary <ipa_fn_summary *, va_gc> *ipa_fn_summaries;
> @@ -2573,7 +2574,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 delete_null_pointer_checks ();
>    if (TREE_CODE (t) == SSA_NAME)
>      {
>        /* For IPA passes we can consinder accesses to return slot local
> --- gcc/tree-ssa-alias.cc.jj  2022-01-18 11:58:59.992976199 +0100
> +++ gcc/tree-ssa-alias.cc     2022-02-08 11:03:40.523209202 +0100
> @@ -47,6 +47,8 @@ along with GCC; see the file COPYING3.
>  #include "print-tree.h"
>  #include "tree-ssa-alias-compare.h"
>  #include "builtins.h"
> +#include "attribs.h"
> +#include "asan.h"
>  
>  /* Broad overview of how alias analysis on gimple works:
>  
> @@ -2644,7 +2646,7 @@ modref_may_conflict (const gcall *stmt,
>  
>             alias_stats.modref_baseptr_tests++;
>  
> -           if (integer_zerop (arg) && flag_delete_null_pointer_checks)
> +           if (integer_zerop (arg) && delete_null_pointer_checks ())
>               continue;
>  
>             /* PTA oracle will be unhapy of arg is not an pointer.  */
> --- gcc/ubsan.cc.jj   2022-01-18 11:59:00.252972485 +0100
> +++ gcc/ubsan.cc      2022-02-08 10:45:35.882359636 +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 delete_null_pointer_checks () 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 delete_null_pointer_checks () 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-01-18 11:59:00.249972528 +0100
> +++ gcc/tree-vrp.cc   2022-02-08 11:04:47.829268939 +0100
> @@ -50,6 +50,8 @@ along with GCC; see the file COPYING3.
>  #include "gimple-range-path.h"
>  #include "value-pointer-equiv.h"
>  #include "gimple-fold.h"
> +#include "attribs.h"
> +#include "asan.h"
>  
>  /* Set of SSA names found live during the RPO traversal of the function
>     for still active basic-blocks.  */
> @@ -732,7 +734,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
> +      && (delete_null_pointer_checks ()
>         || (range_int_cst_p (vr1)
>             && !tree_int_cst_sign_bit (vr1->max ()))))
>      vr->set_nonzero (expr_type);
> --- gcc/vr-values.cc.jj       2022-01-18 11:59:00.255972442 +0100
> +++ gcc/vr-values.cc  2022-02-08 11:04:05.241863846 +0100
> @@ -51,6 +51,7 @@ along with GCC; see the file COPYING3.
>  #include "cfghooks.h"
>  #include "range-op.h"
>  #include "gimple-range.h"
> +#include "asan.h"
>  
>  /* Set value range VR to a non-negative range of type TYPE.  */
>  
> @@ -426,7 +427,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
> +           || (delete_null_pointer_checks ()
>                 && !TYPE_OVERFLOW_WRAPS (TREE_TYPE (expr))))
>           {
>             const value_range_equiv *vr
> @@ -440,7 +441,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)))
> +           && (delete_null_pointer_checks () || known_gt (off, 0)))
>           return true;
>       }
>      }
> --- gcc/tree-ssa-loop-niter.cc.jj     2022-02-04 18:30:34.697003947 +0100
> +++ gcc/tree-ssa-loop-niter.cc        2022-02-08 11:03:14.416573955 +0100
> @@ -43,6 +43,8 @@ along with GCC; see the file COPYING3.
>  #include "tree-scalar-evolution.h"
>  #include "tree-dfa.h"
>  #include "gimple-range.h"
> +#include "attribs.h"
> +#include "asan.h"
>  
>  
>  /* The maximum number of dominator BBs we search for conditions
> @@ -3899,7 +3901,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 (delete_null_pointer_checks () && 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/ipa-pure-const.cc.jj  2022-01-18 11:58:59.655981014 +0100
> +++ gcc/ipa-pure-const.cc     2022-02-08 10:59:22.325816627 +0100
> @@ -63,6 +63,8 @@ along with GCC; see the file COPYING3.
>  #include "ipa-fnsummary.h"
>  #include "symtab-thunks.h"
>  #include "dbgcnt.h"
> +#include "attribs.h"
> +#include "asan.h"
>  
>  /* Lattice values for const and pure functions.  Everything starts out
>     being const, then may drop to pure and then neither depending on
> @@ -972,7 +974,7 @@ malloc_candidate_p (function *fun, bool
>    cgraph_node *node = cgraph_node::get_create (fun->decl);
>  
>    if (EDGE_COUNT (exit_block->preds) == 0
> -      || !flag_delete_null_pointer_checks)
> +      || !delete_null_pointer_checks ())
>      return false;
>  
>    auto_bitmap visited;
> --- gcc/gimple.cc.jj  2022-02-04 14:36:55.217602338 +0100
> +++ gcc/gimple.cc     2022-02-08 10:29:43.887620018 +0100
> @@ -1673,17 +1673,18 @@ 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 (delete_null_pointer_checks ()
> +      && !flag_check_new
>        && DECL_IS_OPERATOR_NEW_P (fndecl)
>        && !TREE_NOTHROW (fndecl))
>      return true;
>  
>    /* References are always non-NULL.  */
> -  if (flag_delete_null_pointer_checks
> +  if (delete_null_pointer_checks ()
>        && TREE_CODE (TREE_TYPE (fndecl)) == REFERENCE_TYPE)
>      return true;
>  
> -  if (flag_delete_null_pointer_checks
> +  if (delete_null_pointer_checks ()
>        && lookup_attribute ("returns_nonnull",
>                          TYPE_ATTRIBUTES (gimple_call_fntype (call))))
>      return true;
> @@ -3033,7 +3034,7 @@ 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
> +  if (!delete_null_pointer_checks ()
>        || !POINTER_TYPE_P (TREE_TYPE (op))
>        || gimple_code (stmt) == GIMPLE_ASM
>        || gimple_clobber_p (stmt))
> @@ -3053,7 +3054,7 @@ 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
> +  if (!delete_null_pointer_checks ()
>        || !POINTER_TYPE_P (TREE_TYPE (op))
>        || gimple_code (stmt) == GIMPLE_ASM)
>      return false;
> --- gcc/fold-const.cc.jj      2022-02-06 11:16:22.352814445 +0100
> +++ gcc/fold-const.cc 2022-02-08 10:30:08.237281118 +0100
> @@ -10713,11 +10713,12 @@ 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 (delete_null_pointer_checks ()
> +         && !flag_check_new
>           && DECL_IS_OPERATOR_NEW_P (fndecl)
>           && !TREE_NOTHROW (fndecl))
>         return true;
> -     if (flag_delete_null_pointer_checks
> +     if (delete_null_pointer_checks ()
>           && lookup_attribute ("returns_nonnull",
>                TYPE_ATTRIBUTES (TREE_TYPE (fndecl))))
>         return true;
> --- gcc/rtlanal.cc.jj 2022-01-18 11:58:59.886977714 +0100
> +++ gcc/rtlanal.cc    2022-02-08 11:00:01.568268352 +0100
> @@ -38,6 +38,9 @@ along with GCC; see the file COPYING3.
>  #include "rtl-iter.h"
>  #include "hard-reg-set.h"
>  #include "function-abi.h"
> +#include "stringpool.h"
> +#include "attribs.h"
> +#include "asan.h"
>  
>  /* Forward declarations */
>  static void set_of_1 (rtx, const_rtx, void *);
> @@ -721,7 +724,7 @@ nonzero_address_p (const_rtx x)
>    switch (code)
>      {
>      case SYMBOL_REF:
> -      return flag_delete_null_pointer_checks && !SYMBOL_REF_WEAK (x);
> +      return delete_null_pointer_checks () && !SYMBOL_REF_WEAK (x);
>  
>      case LABEL_REF:
>        return true;
> --- gcc/c-family/c-ubsan.cc.jj        2022-01-18 11:58:58.885992014 +0100
> +++ gcc/c-family/c-ubsan.cc   2022-02-08 10:50:50.620965960 +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 !delete-null-pointer-checks (),
>            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/cp/typeck.cc.jj       2022-02-04 14:36:54.818607910 +0100
> +++ gcc/cp/typeck.cc  2022-02-08 10:49:17.747263557 +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=*/delete_null_pointer_checks (),
>                             complain);
>  
>        /* Convert the pointer to a reference -- but then remember that
> --- gcc/testsuite/g++.dg/ubsan/pr71962.C.jj   2022-02-08 11:19:18.985101982 
> +0100
> +++ gcc/testsuite/g++.dg/ubsan/pr71962.C      2022-02-08 11:12:59.582400892 
> +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/testsuite/g++.dg/ubsan/pr104426.C.jj  2022-02-08 11:11:28.323675454 
> +0100
> +++ gcc/testsuite/g++.dg/ubsan/pr104426.C     2022-02-08 11:11:15.280857618 
> +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 ());
> +}
> 
>       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