Skip to content

Avoid GCC -Warray-bounds false positive on fixed-size shape copies - #2946

Open
gouarin wants to merge 1 commit into
xtensor-stack:masterfrom
gouarin:fix-array-bounds
Open

gouarin wants to merge 1 commit into
xtensor-stack:masterfrom
gouarin:fix-array-bounds

Conversation

@gouarin

@gouarin gouarin commented Oct 29, 2026 •

Copy link
Copy Markdown
Member

Description

GCC 13 and 15 emit -Warray-bounds at -O2/-O3 on ordinary code using fixed-rank containers, for example assigning 0.5 * (even + odd) to a 1-D xtensor view. The warning comes from a std::copy between two std::array<std::size_t, 1> when the source is a member at a non-zero offset. GCC does not fold the length of the range and warns on the memmove branch that libstdc++ keeps for ranges of more than one element. That branch never runs. Reproducer without xtensor:

struct holder { std::size_t m_size; std::array<std::size_t, 1> m_shape; };
std::array<std::size_t, 1> f(const holder& h)
{
    std::array<std::size_t, 1> s;
    std::copy(h.m_shape.cbegin(), h.m_shape.cend(), s.begin());
    return s;
}

These copies now use std::copy_n(src.begin(), src.size(), dst.begin()). size() is a constant for std::array, so GCC drops the branch. At each site the destination is sized from the same source, so the copied elements do not change. Changed sites: xfunction::broadcast_shape, the xbroadcast constructor, flip (shape and strides), and average with multi-dimensional weights. std::copy(data(), data() + size()) and std::ranges::copy still warn.

No unit test, since this is a compile-time warning and CI does not build with -Wall on GCC. A file using 1-D, 2-D and 3-D views, reductions, broadcasting, flip and xtensor_fixed now compiles without warnings with GCC 13.4 and 15.3 at -O2 and -O3 with -Wall -Wextra, with and without xsimd.

GCC 13 and 15 emit -Warray-bounds at -O2/-O3 on a std::copy from a
std::array<std::size_t, 1> member into another std::array<std::size_t, 1>.
When the array is a member at a non-zero offset, GCC does not fold the
length of the source range and warns on the memmove branch that libstdc++
keeps for ranges of more than one element. That branch never runs. User
code as simple as assigning 0.5 * (even + odd) to a 1-D view gets the
warning.

Minimal reproducer without xtensor:

    struct holder { std::size_t m_size; std::array<std::size_t, 1> m_shape; };
    std::array<std::size_t, 1> f(const holder& h)
    {
        std::array<std::size_t, 1> s;
        std::copy(h.m_shape.cbegin(), h.m_shape.cend(), s.begin());
        return s;
    }

std::copy_n takes the count directly, and size() is a constant for
std::array, so GCC drops the branch. In each changed site the destination
is sized from the same source, so the number of copied elements does not
change. Changed sites: xfunction::broadcast_shape, the xbroadcast
constructor, flip (shape and strides) and average with multi-dimensional
weights.
@codspeed

codspeed Bot commented Oct 29, 2026

Copy link
Copy Markdown
Contributor

Merging this PR will not alter performance

1 warning

⚠️ Unable to measure the execution of 1 benchmark

This benchmark measured no execution time, so its result is not comparable and counts as unchanged. This usually happens when the compiler removes the code under test.

Prevent compiler optimizations

See affected benchmarks

✅ 255 untouched benchmarks


Comparing gouarin:fix-array-bounds (5a967e3) with master (57f3d07)

Open in CodSpeed

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant