On Thu, 3 Jul 2025, Jason Merrill wrote: > On 7/2/25 7:58 PM, Patrick Palka wrote: > > Bootstrapped and regtested on x86_64-pc-linux-gnu, does this look OK > > for trunk? > > > > -- >8 -- > > > > Here the flag -fno-delete-null-pointer-checks causes the trivial address > > comparison in > > > > inline int a, b; > > static_assert(&a != &b); > > > > to be rejected as non-constant because with the flag we can't assume > > such weak symbols are non-NULL, which causes symtab/fold-const.cc to > > punt on such comparisons. Note this also affects -fsanitize=undefined > > since it implies -fno-delete-null-pointer-checks. > > Right, the underlying problem is that we use the one flag to mean two things: > > 1) a static storage duration decl can live at address 0 > 2) do more careful checking for null pointers/lvalues (i.e. in > gimple_call_nonnull_result_p) > > Both cases are related to checking for null, but they are different situations > and really shouldn't depend on the same flag. > > Your patch seems wrong for #1 targets; on such a target 'a' might end up > allocated at address 0, so "&a != nullptr" is not decidable at compile time. > > OTOH such targets are a small minority, and I suspect they already have other > C++ issues with e.g. a conversion to base not adjusting a null pointer.
Yep, and normally I would not be so bold to propose making such a trade-off, but this seems to be exactly the trade-off we made in PR96862 for -frounding-math? The flag makes lossy floating-point operations depend on the run-time rounding mode and so not decidable at compile time, so we ended up disabling the flag during constexpr evaluation and using the default rounding mode. I don't immediately see why -frounding-math maybe be special. On a related note, I notice we accept [[gnu::weak]] inline int a, b; static_assert(&a != &b); with the default -fdelete-null-pointer-checks, which seems wrong, we probably should reject address comparisons of weak symbols as non-constant by default. > > Jakub, what do you think? It's been 9 years since you proposed a better fix > in the PR, but that hasn't happened yet. > > > This issue seems conceptually the same as PR96862 which was about > > -frounding-math breaking some constexpr floating point arithmetic, > > and we fixed that PR by disabling -frounding-math during manifestly > > constant evaluation. This patch proposes to do the same for > > -fno-delete-null-pointer-checks, disabling it during maniestly constant > > evaluation. I opted to disable it narrowly around the relevant > > fold_binary call which seems to address all reported constexpr failures, > > but we could consider it disabling it more broadly as well. > > > > PR c++/71962 > > > > gcc/cp/ChangeLog: > > > > * constexpr.cc (cxx_eval_binary_expression): Set > > flag_delete_null_pointer_checks alongside folding_cxx_constexpr > > during manifestly constant evaluation. > > > > gcc/testsuite/ChangeLog: > > > > * g++.dg/ext/constexpr-pr71962.C: New test. > > * g++.dg/ubsan/pr71962.C: New test. > > --- > > gcc/cp/constexpr.cc | 2 ++ > > gcc/testsuite/g++.dg/ext/constexpr-pr71962.C | 18 ++++++++++++++++++ > > gcc/testsuite/g++.dg/ubsan/pr71962.C | 5 +++++ > > 3 files changed, 25 insertions(+) > > create mode 100644 gcc/testsuite/g++.dg/ext/constexpr-pr71962.C > > create mode 100644 gcc/testsuite/g++.dg/ubsan/pr71962.C > > > > diff --git a/gcc/cp/constexpr.cc b/gcc/cp/constexpr.cc > > index 704d936f2ec3..e8426b40c543 100644 > > --- a/gcc/cp/constexpr.cc > > +++ b/gcc/cp/constexpr.cc > > @@ -4068,6 +4068,8 @@ cxx_eval_binary_expression (const constexpr_ctx *ctx, > > tree t, > > || TREE_CODE (type) != REAL_TYPE)) > > { > > auto ofcc = make_temp_override (folding_cxx_constexpr, true); > > + auto odnpc = make_temp_override (flag_delete_null_pointer_checks, > > + true); > > r = fold_binary_initializer_loc (loc, code, type, lhs, rhs); > > } > > else > > diff --git a/gcc/testsuite/g++.dg/ext/constexpr-pr71962.C > > b/gcc/testsuite/g++.dg/ext/constexpr-pr71962.C > > new file mode 100644 > > index 000000000000..57cb14ac804e > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/ext/constexpr-pr71962.C > > @@ -0,0 +1,18 @@ > > +// PR c++/71962 > > +// { dg-do compile { target c++11 } } > > +// { dg-additional-options "-fno-delete-null-pointer-checks" } > > + > > +struct A { void f(); }; > > +static_assert(&A::f != nullptr, ""); > > + > > +#if __cpp_inline_variables > > +inline int a, b; > > +static_assert(&a != &b, ""); > > +static_assert(&a != nullptr, ""); > > +#endif > > + > > +int main() { > > + static int x, y; > > + static_assert(&x != &y, ""); > > + static_assert(&x != nullptr, ""); > > +} > > diff --git a/gcc/testsuite/g++.dg/ubsan/pr71962.C > > b/gcc/testsuite/g++.dg/ubsan/pr71962.C > > new file mode 100644 > > index 000000000000..f17c825da449 > > --- /dev/null > > +++ b/gcc/testsuite/g++.dg/ubsan/pr71962.C > > @@ -0,0 +1,5 @@ > > +// PR c++/71962 > > +// { dg-do compile { target c++11 } } > > +// { dg-additional-options "-fsanitize=undefined" } > > + > > +#include "../ext/constexpr-pr71962.C" > >