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)