Ping.  https://gcc.gnu.org/pipermail/gcc-patches/2026-September/730074.html

Small fix in cxx_eval_builtin_function_call for constexpr
memchr/strchr/strrchr/strstr counting a nonzero first-argument offset
twice ([14/15/16/17 Regression] PR c++/127218), plus a testcase.
Bootstrapped and regtested on x86_64-pc-linux-gnu; still applies to
current trunk.

OK for trunk?

On Fri, Sep 4, 2026 at 8:48 PM Steve Sudit <[email protected]> wrote:
>
> This patch was written with the assistance of an LLM (Claude Fable 5.1,
> Anthropic), hence the Assisted-by: tag per
> https://gcc.gnu.org/ai-policy.html.  I directed the analysis, reviewed
> every line, ran the testing below and take responsibility for it.
>
> Bootstrapped and regression-tested on x86_64-pc-linux-gnu against trunk
> r17-3939-g08794c636095 (default languages, --disable-multilib), with the
> g++ testsuite run in all standard levels (98, 11, 14, 17, 20, 23, 26 and
> 26 -fimplicit-constexpr, as check-c++-all does).  compare_tests against
> an unpatched run of the same revision shows no regressions; the new test
> passes in every level from C++11 up.
>
> OK for trunk?  The bug is present on all open release branches (13
> through 16), so backports after a soak on trunk would be welcome.
>
> Since r10-5927 (PR c++/80265) cxx_eval_builtin_function_call replaces
> the string arguments of the str/mem builtins with the address of a
> STRING_CST before folding, and for the pointer-returning ones (memchr,
> strchr, strrchr, strstr) it afterwards puts the original argument back
> as the base of the folded POINTER_PLUS_EXPR.  That re-basing is
> unconditional, but the replacement only happens when the evaluated
> argument is a bare ADDR_EXPR (offset 0).  When the argument already
> carries an offset, for instance memchr (a + 1, c, n), the argument is
> passed to fold as-is, fold_builtin_call_array merges the offset into
> the result (a + 10), and the re-basing then rewrites that result to
> (a + 1) + 10, counting the offset twice.
>
>   constexpr const char a[] = "abcdefghijabxdefghijaaa";
>   static_assert (__builtin_memchr (a + 1, 'a', 22) == a + 10, "");
>
> fails since GCC 10 in every dialect; &a[1] is unaffected because the
> evaluated argument is an ADDR_EXPR.  C++26 exposes this to ordinary
> code: P2738 makes void* -> T* casts constant expressions, so the front
> end now folds char_traits<char>::find on constant haystacks and
> std::string_view::find (c, pos) returns pos too much.
>
> Fix by remembering which argument was replaced and re-basing only in
> that case; otherwise the folded result is already relative to the
> evaluated argument.
>
> Assisted-by: Claude Fable 5.1 (Anthropic)
>
> PR c++/127218
>
> gcc/cp/ChangeLog:
>
> * constexpr.cc (cxx_eval_builtin_function_call): Remember the
> argument replaced by the address of a STRING_CST in STRRET_OP and
> re-base the folded result on it only when that replacement
> happened.
>
> gcc/testsuite/ChangeLog:
>
> * g++.dg/cpp0x/constexpr-memchr2.C: New test.
>
> Signed-off-by: Steven Sudit <[email protected]>
>
> Patch attached (also applies with git am).

Reply via email to