Skip to content

Commit 5d75ad3

Browse files
authored
Avoid GCC -Warray-bounds false positive on fixed-size shape copies (#2946)
# 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: ```cpp 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.
1 parent 292f0c2 commit 5d75ad3

4 files changed

Lines changed: 5 additions & 5 deletions

File tree

‎include/xtensor/core/xfunction.hpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -712,7 +712,7 @@ namespace xt
712712
{
713713
if (m_cache.is_initialized && reuse_cache)
714714
{
715-
std::copy(m_cache.shape.cbegin(), m_cache.shape.cend(), shape.begin());
715+
std::copy_n(m_cache.shape.cbegin(), m_cache.shape.size(), shape.begin());
716716
return m_cache.is_trivial;
717717
}
718718
else

‎include/xtensor/core/xmath.hpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1960,7 +1960,7 @@ namespace xt
19601960
);
19611961
}
19621962

1963-
std::copy(e.shape().begin(), e.shape().end(), broadcast_shape.begin());
1963+
std::copy_n(e.shape().begin(), e.shape().size(), broadcast_shape.begin());
19641964
}
19651965

19661966
constexpr layout_type L = default_assignable_layout(std::decay_t<W>::static_layout);

‎include/xtensor/misc/xmanipulation.hpp‎

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -840,12 +840,12 @@ namespace xt
840840

841841
shape_type shape;
842842
resize_container(shape, e.shape().size());
843-
std::copy(e.shape().cbegin(), e.shape().cend(), shape.begin());
843+
std::copy_n(e.shape().cbegin(), e.shape().size(), shape.begin());
844844

845845
get_strides_t<shape_type> strides;
846846
decltype(auto) old_strides = detail::get_strides<XTENSOR_DEFAULT_LAYOUT>(e);
847847
resize_container(strides, old_strides.size());
848-
std::copy(old_strides.cbegin(), old_strides.cend(), strides.begin());
848+
std::copy_n(old_strides.cbegin(), old_strides.size(), strides.begin());
849849

850850
strides[axis] *= -1;
851851
std::size_t offset = static_cast<std::size_t>(

‎include/xtensor/views/xbroadcast.hpp‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -293,7 +293,7 @@ namespace xt
293293
XTENSOR_THROW(xt::broadcast_error, "Broadcast shape has fewer elements than original expression.");
294294
}
295295
xt::resize_container(m_shape, s.size());
296-
std::copy(s.begin(), s.end(), m_shape.begin());
296+
std::copy_n(s.begin(), s.size(), m_shape.begin());
297297
xt::broadcast_shape(m_e.shape(), m_shape);
298298
}
299299

0 commit comments

Comments
 (0)