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

            Bug ID: 111273
           Summary: Spurious array-bounds error when copying data using
                    _GLIBCXX_DEBUG iterators
           Product: gcc
           Version: 13.2.0
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: jgrossma at qti dot qualcomm.com
  Target Milestone: ---

When compiling with -Warray-bounds and -D_GLIBCXX_DEBUG on g++ 13.2.0, copying
from a vector to an array throws the Warray-bounds error during compilation.

Source:

#include <vector>
#include <array>
#include <algorithm>

static const int N = 1;

int func(std::vector<int> const &v) {
    std::array<int, N> a;
    std::copy_n(v.begin(), N, a.begin());
    return a[0];
}


Program should not have any problems at compile time. Copies 1 location to a 1
element array. Changing N=2 doesn't show the error. 

Compile options:

-Werror -O3 -Warray-bounds -D_GLIBCXX_DEBUG -std=c++20


Disabling -D_GLIBCXX_DEBUG doesn't show the error.


Output:

---

In file included from
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/vector:62,
                 from <source>:1:
In static member function 'static constexpr _Up* std::__copy_move<_IsMove,
true, std::random_access_iterator_tag>::__copy_m(_Tp*, _Tp*, _Up*) [with _Tp =
const int; _Up = int; bool _IsMove = false]',
    inlined from 'constexpr _OI std::__copy_move_a2(_II, _II, _OI) [with bool
_IsMove = false; _II = const int*; _OI = int*]' at
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:506:30,
    inlined from 'constexpr _OI std::__copy_move_a1(_II, _II, _OI) [with bool
_IsMove = false; _II = const int*; _OI = int*]' at
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:533:42,
    inlined from 'constexpr _OI std::__copy_move_a(_II, _II, _OI) [with bool
_IsMove = false; _II = __gnu_cxx::__normal_iterator<const int*,
__cxx1998::vector<int, allocator<int> > >; _OI = int*]' at
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:540:31,
    inlined from '_OI std::__copy_move_a(const
__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, const
__gnu_debug::_Safe_iterator<_Ite, _Seq, _Cat>&, _OI) [with bool _IsMove =
false; _Ite = __gnu_cxx::__normal_iterator<const int*, __cxx1998::vector<int,
allocator<int> > >; _Seq = __debug::vector<int>; _Cat =
random_access_iterator_tag; _OI = int*]' at
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/debug/safe_iterator.tcc:257:36,
    inlined from 'constexpr _OI std::copy(_II, _II, _OI) [with _II =
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<const int*,
__cxx1998::vector<int, allocator<int> > >, __debug::vector<int>,
random_access_iterator_tag>; _OI = int*]' at
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:633:7,
    inlined from 'constexpr _OutputIterator
std::__copy_n(_RandomAccessIterator, _Size, _OutputIterator,
random_access_iterator_tag) [with _RandomAccessIterator =
__gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<const int*,
__cxx1998::vector<int, allocator<int> > >, __debug::vector<int>,
random_access_iterator_tag>; _Size = int; _OutputIterator = int*]' at
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algo.h:731:23,
    inlined from 'constexpr _OIter std::copy_n(_IIter, _Size, _OIter) [with
_IIter = __gnu_debug::_Safe_iterator<__gnu_cxx::__normal_iterator<const int*,
__cxx1998::vector<int, allocator<int> > >, __debug::vector<int>,
random_access_iterator_tag>; _Size = int; _OIter = int*]' at
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algo.h:763:27,
    inlined from 'int func(const std::__debug::vector<int>&)' at <source>:9:16:
/opt/compiler-explorer/gcc-13.2.0/include/c++/13.2.0/bits/stl_algobase.h:437:30:
error: 'void* __builtin_memcpy(void*, const void*, long unsigned int)' forming
offset 4 is out of the bounds [0, 4] of object 'a' with type 'std::array<int,
1>' [-Werror=array-bounds=]
  437 |             __builtin_memmove(__result, __first, sizeof(_Tp) * _Num);
      |             ~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
<source>: In function 'int func(const std::__debug::vector<int>&)':
<source>:8:24: note: 'a' declared here
    8 |     std::array<int, N> a;
      |                        ^
cc1plus: all warnings being treated as errors
Compiler returned: 1

---

Interestingly, the error location should not even be hit for a 1 element copy
as it's inside a check for length>1.


Godbolt link shows as well: https://godbolt.org/z/v8GK4nzde


GCC 12 does not seem to show this issue.

Seems related to this one: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=107852

Reply via email to