On Mon, 21 Apr 2025, Jason Merrill wrote: > Tested x86_64-pc-linux-gnu, OK for trunk? > > -- 8< -- > > While working on PR119162 it occurred to me that it would be simpler to > detect the problem of a value referring to a heap allocation if we stopped > setting TREE_STATIC on them so they naturally are not considered to have a > constant address. With that change we no longer need to specifically avoid > caching a value that refers to a deleted pointer. > > But with this change maybe_nonzero_address is not sure whether the variable > could have address zero. I don't understand why it returns 1 only for > variables in the current function, rather than all non-symtab decls; an auto > variable from some other function also won't have address zero. Maybe this > made more sense when it was in tree_single_nonzero_warnv_p before r7-5868? > > But assuming there is some reason for the current behavior, this patch only > changes the handling of non-symtab decls when folding_cxx_constexpr.
FWIW the maybe_nonzero_address change seems to fix PR85944, yay! Except for the PR115207 dup, which we still reject with 115207.C:11:18: error: ‘(((const value*)(&<anonymous>)) != ((const value*)(& test.array<4>::_items)))’ is not a constant expression 11 | if (this != &other) { | ~~~~~^~~~~~~~~ Could this mean another spot in the middle-end needs relaxing in order to handle address comparisons of context-less local vars? > > PR c++/119162 > > gcc/cp/ChangeLog: > > * constexpr.cc (find_deleted_heap_var): Remove. > (cxx_eval_call_expression): Don't call it. Don't set TREE_STATIC on > heap vars. > (cxx_eval_outermost_constant_expr): Don't mess with varpool. > > gcc/ChangeLog: > > * fold-const.cc (maybe_nonzero_address): Return 1 for non-symtab > vars if folding_cxx_constexpr. > --- > gcc/cp/constexpr.cc | 29 ----------------------------- > gcc/fold-const.cc | 25 ++++++++++++++++--------- > 2 files changed, 16 insertions(+), 38 deletions(-) > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc > index 8a11e6265f2..5b7b70f7e65 100644 > --- a/gcc/cp/constexpr.cc > +++ b/gcc/cp/constexpr.cc > @@ -1550,7 +1550,6 @@ static tree cxx_eval_bare_aggregate (const > constexpr_ctx *, tree, > static tree cxx_fold_indirect_ref (const constexpr_ctx *, location_t, tree, > tree, > bool * = NULL); > static tree find_heap_var_refs (tree *, int *, void *); > -static tree find_deleted_heap_var (tree *, int *, void *); > > /* Attempt to evaluate T which represents a call to a builtin function. > We assume here that all builtin functions evaluate to scalar types > @@ -2975,14 +2974,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, > tree t, > : heap_uninit_identifier, > type); > DECL_ARTIFICIAL (var) = 1; > - TREE_STATIC (var) = 1; > - // Temporarily register the artificial var in varpool, > - // so that comparisons of its address against NULL are folded > - // through nonzero_address even with > - // -fno-delete-null-pointer-checks or that comparison of > - // addresses of different heap artificial vars is folded too. > - // See PR98988 and PR99031. > - varpool_node::finalize_decl (var); > ctx->global->heap_vars.safe_push (var); > ctx->global->put_value (var, NULL_TREE); > return fold_convert (ptr_type_node, build_address (var)); > @@ -3454,11 +3445,6 @@ cxx_eval_call_expression (const constexpr_ctx *ctx, > tree t, > cacheable = false; > break; > } > - /* And don't cache a ref to a deleted heap variable (119162). */ > - if (cacheable > - && (cp_walk_tree_without_duplicates > - (&result, find_deleted_heap_var, NULL))) > - cacheable = false; > } > > /* Rewrite all occurrences of the function's RESULT_DECL with the > @@ -9025,20 +9011,6 @@ find_heap_var_refs (tree *tp, int *walk_subtrees, void > */*data*/) > return NULL_TREE; > } > > -/* Look for deleted heap variables in the expression *TP. */ > - > -static tree > -find_deleted_heap_var (tree *tp, int *walk_subtrees, void */*data*/) > -{ > - if (VAR_P (*tp) > - && DECL_NAME (*tp) == heap_deleted_identifier) > - return *tp; > - > - if (TYPE_P (*tp)) > - *walk_subtrees = 0; > - return NULL_TREE; > -} > - > /* Find immediate function decls in *TP if any. */ > > static tree > @@ -9275,7 +9247,6 @@ cxx_eval_outermost_constant_expr (tree t, bool > allow_non_constant, > r = t; > non_constant_p = true; > } > - varpool_node::get (heap_var)->remove (); > } > } > > diff --git a/gcc/fold-const.cc b/gcc/fold-const.cc > index c9471ea44b0..35fcf5087fb 100644 > --- a/gcc/fold-const.cc > +++ b/gcc/fold-const.cc > @@ -9917,22 +9917,29 @@ pointer_may_wrap_p (tree base, tree offset, > poly_int64 bitpos) > static int > maybe_nonzero_address (tree decl) > { > + if (!DECL_P (decl)) > + return -1; > + > /* Normally, don't do anything for variables and functions before symtab is > built; it is quite possible that DECL will be declared weak later. > But if folding_initializer, we need a constant answer now, so create > the symtab entry and prevent later weak declaration. */ > - if (DECL_P (decl) && decl_in_symtab_p (decl)) > - if (struct symtab_node *symbol > - = (folding_initializer > - ? symtab_node::get_create (decl) > - : symtab_node::get (decl))) > - return symbol->nonzero_address (); > + if (decl_in_symtab_p (decl)) > + { > + if (struct symtab_node *symbol > + = (folding_initializer > + ? symtab_node::get_create (decl) > + : symtab_node::get (decl))) > + return symbol->nonzero_address (); > + } > + else if (folding_cxx_constexpr) > + /* Anything that doesn't go in the symtab has non-zero address. */ > + return 1; > > /* Function local objects are never NULL. */ > - if (DECL_P (decl) > - && (DECL_CONTEXT (decl) > + if (DECL_CONTEXT (decl) > && TREE_CODE (DECL_CONTEXT (decl)) == FUNCTION_DECL > - && auto_var_in_fn_p (decl, DECL_CONTEXT (decl)))) > + && auto_var_in_fn_p (decl, DECL_CONTEXT (decl))) > return 1; > > return -1; > > base-commit: 9ac98b5742ebce41d7da9fda10852a0bc958f1cb > -- > 2.49.0 > >