Package: g++-14
Version: 14.2.0-8
Severity: normal

1) Consider a program with a known-at-compile length structure of
   length strictly less than 16, e.g. an array.

2) Call std::sort on it in a way that, at execution time, ensures the
   arguments are within the bounds of the structure, but so that g++
   cannot statically guarantee it; e.g. the end position is determined
   by a call to a function in another compilation unit, in a library,
   ...

g++ +Warray-bounds emits a warning on libstdc++ std::sort code,
because it has a branch calling a different algorithm on the first 16
elements and on the rest, from /usr/include/c++/14/bits/stl_algo.h

  enum { _S_threshold = 16 };

    __final_insertion_sort(_RandomAccessIterator __first,
                           _RandomAccessIterator __last, _Compare __comp)
    {
      if (__last - __first > int(_S_threshold))
        {
          std::__insertion_sort(__first, __first + int(_S_threshold), __comp);
          std::__unguarded_insertion_sort(__first + int(_S_threshold), __last,
                                          __comp);
        }
      else
        std::__insertion_sort(__first, __last, __comp);
    }

This is not an actual issue, because "__first + int(_S_threshold)",
that is "__first + 16" will not be called (computed) as the if
condition will not be fulfilled, as std::sort is called only with
valid values (__last is not outside of the structure).

Since the code being warned about is not user code, but standard
library code, that should really not happen, there is nothing the user
can do about this. Not sure if the responsibility of the solution is
in g++ (heuristic/more intelligent analysis?) or in libstdc++ (use
diagnostic pragmas to silence that?).


Reproduced with g++-12 and g++-13 also.

Concrete example attached.

$ g++ -Os -Warray-bounds -Werror -c foo.cpp -o foo.o
In file included from /usr/include/c++/14/algorithm:61,
                 from foo.cpp:1:
In function ‘void std::__final_insertion_sort(_RandomAccessIterator, 
_RandomAccessIterator, _Compare) [with _RandomAccessIterator = int*; _Compare = 
__gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const int&, const int&)>]’,
    inlined from ‘void std::__sort(_RandomAccessIterator, 
_RandomAccessIterator, _Compare) [with _RandomAccessIterator = int*; _Compare = 
__gnu_cxx::__ops::_Iter_comp_iter<bool (*)(const int&, const int&)>]’ at 
/usr/include/c++/14/bits/stl_algo.h:1908:31,
    inlined from ‘void std::sort(_RAIter, _RAIter, _Compare) [with _RAIter = 
int*; _Compare = bool (*)(const int&, const int&)]’ at 
/usr/include/c++/14/bits/stl_algo.h:4804:18,
    inlined from ‘int main(int, char**)’ at foo.cpp:17:12:
/usr/include/c++/14/bits/stl_algo.h:1817:32: error: array subscript 16 is 
outside array bounds of ‘int [9]’ [-Werror=array-bounds=]
 1817 |           std::__insertion_sort(__first, __first + int(_S_threshold), 
__comp);
      |           
~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
foo.cpp: In function ‘int main(int, char**)’:
foo.cpp:5:5: note: at offset 64 into object ‘a’ of size 36
    5 | int a[maxA];
      |     ^
cc1plus: all warnings being treated as errors



-- System Information:
Debian Release: trixie/sid
  APT prefers stable-updates
  APT policy: (500, 'stable-updates'), (500, 'stable-security'), (500, 
'stable'), (400, 'testing'), (300, 'unstable'), (1, 'experimental')
Architecture: amd64 (x86_64)

Kernel: Linux 6.1.0-26-amd64 (SMP w/8 CPU threads; PREEMPT)
Locale: LANG=fr_LU.UTF-8, LC_CTYPE=fr_LU.UTF-8 (charmap=UTF-8), LANGUAGE not set
Shell: /bin/sh linked to /usr/bin/dash
Init: systemd (via /run/systemd/system)
LSM: AppArmor: enabled

Versions of packages g++-14 depends on:
ii  g++-14-x86-64-linux-gnu  14.2.0-8
ii  gcc-14                   14.2.0-8
ii  gcc-14-base              14.2.0-8

g++-14 recommends no packages.

Versions of packages g++-14 suggests:
pn  g++-14-multilib  <none>
pn  gcc-14-doc       <none>

-- no debconf information
#include <algorithm>
#include <cstdlib>

constexpr size_t maxA(9);
int a[maxA];

bool cmp(const int&lhs, const int&rhs)
{
  return lhs < rhs;
}

int search(int *stack, int needle, size_t stack_size);

int main(int argc, char *argv[])
{
  size_t i=search(a, 5, maxA);
  std::sort(a, a+i, cmp);
}

Reply via email to