https://gcc.gnu.org/bugzilla/show_bug.cgi?id=127218

--- Comment #7 from GCC Commits <cvs-commit at gcc dot gnu.org> ---
The trunk branch has been updated by Jason Merrill <[email protected]>:

https://gcc.gnu.org/g:8b93d6bf0706bdf7f5116c79a051eb31f0fbab22

commit r17-4696-g8b93d6bf0706bdf7f5116c79a051eb31f0fbab22
Author: Steven Sudit <[email protected]>
Date:   Sat Sep 26 13:49:21 2026 -0400

    c++: Don't re-base a folded string builtin on an offset argument [PR127218]

    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 clearing STRRET when the argument it refers to didn't end up as
    the address of a STRING_CST, so the folded result is re-based only when
    the replacement happened; otherwise it 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): Clear STRRET
            when the argument it refers to is not replaced by the address of
            a STRING_CST, so the folded result is re-based on the original
            argument only when that replacement happened.

    gcc/testsuite/ChangeLog:

            * g++.dg/cpp0x/constexpr-memchr2.C: New test.

    Signed-off-by: Steven Sudit <[email protected]>

Reply via email to