https://gcc.gnu.org/bugzilla/show_bug.cgi?id=117067
Bug ID: 117067
Summary: false warning: array subscript 'int (**)(...)[ 0]' is
partly outside array bounds
Product: gcc
Version: 13.3.1
Status: UNCONFIRMED
Severity: normal
Priority: P3
Component: c++
Assignee: unassigned at gcc dot gnu.org
Reporter: lobel.krivic at proton dot me
Target Milestone: ---
The following source code:
```
#include <cstddef>
#include <functional>
#include <type_traits>
#include <utility>
#include <iostream>
///////////////////////////////////////////////////////
template <typename... Args>
class VTable
{
public:
virtual void func(Args...) = 0;
virtual ~VTable() = default;
};
template <typename T, typename... Args>
class Handler final : public VTable<Args...>
{
private:
T* _ptr;
public:
template <typename... CArgs>
Handler(CArgs&&... args) noexcept {
_ptr = new T(std::forward<CArgs>(args)...);
}
virtual void func(Args... args) final {
return std::invoke(*_ptr, std::forward<Args>(args)...);
}
~Handler() final { delete _ptr; }
};
///////////////////////////////////////////////////////
template <typename... Args>
struct F
{
using V = VTable<Args...>;
static constexpr int S = sizeof(void*) + sizeof(V);
std::byte _data[S];
template <typename T>
F(T&& t) {
static_assert(sizeof(Handler<std::decay_t<T>, Args...>) <= S);
::new (&_data[0]) Handler<std::decay_t<T>,
Args...>(std::forward<T>(t));
}
void func(Args... args) {
std::cout << "" << std::endl; // removing this line removes the
warning!
V& tmp = *static_cast<V*>(static_cast<void*>(&_data[0]));
return tmp.func(std::forward<Args>(args)...);
}
~F() { static_cast<V*>(static_cast<void*>(&_data[0]))->~V(); }
};
///////////////////////////////////////////////////////
struct Testor
{
// long y; // this removes the warning!
Testor() = default;
~Testor() = default;
void memfunc(int x) { std::cout << x << std::endl; }
};
///////////////////////////////////////////////////////
// warning: array subscript 'int (**)(...)[0]' is partly outside array bounds
of 'Testor [1]' [-Warray-bounds=]
// this happens for -O2/O3 -Wall (but not for -O0/-O1)
int main() {
Testor testor_small;
F<Testor&, int> f{&Testor::memfunc};
f.func(testor_small, 42);
return 0;
}
```
produces a probably false warning:
```
In file included from
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/tuple:41,
from
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/functional:53,
from ./bug.cpp:2:
In function 'constexpr _Res std::__invoke_impl(__invoke_memfun_ref, _MemFun&&,
_Tp&&, _Args&& ...) [with _Res = v
oid; _MemFun = void (Testor::*&)(int); _Tp = Testor&; _Args = {int}]',
inlined from 'constexpr typename std::__invoke_result<_Functor,
_ArgTypes>::type std::__invoke(_Callable&&, _
Args&& ...) [with _Callable = void (Testor::*&)(int); _Args = {Testor&, int}]'
at /usr/lib/gcc/x86_64-pc-linux-gn
u/13/include/g++-v13/bits/invoke.h:96:40,
inlined from 'std::invoke_result_t<_Callable, _Args ...>
std::invoke(_Callable&&, _Args&& ...) [with _Callabl
e = void (Testor::*&)(int); _Args = {Testor&, int}]' at
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/funct
ional:113:27,
inlined from 'void Handler<T, Args>::func(Args ...) [with T = void
(Testor::*)(int); Args = {Testor&, int}]'
at ./bug.cpp:31:21,
inlined from 'void F<Args>::func(Args ...) [with Args = {Testor&, int}]' at
./bug.cpp:57:18,
inlined from 'int main()' at ./bug.cpp:84:8:
/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13/bits/invoke.h:67:39:
warning: array subscript 'int (**)(...)[
0]' is partly outside array bounds of 'Testor [1]' [-Warray-bounds=]
67 | { return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...);
}
| ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
./bug.cpp: In function 'int main()':
./bug.cpp:82:16: note: object 'testor_small' of size 1
82 | Testor testor_small;
| ^~~~~~~~~~~~
```
when compiled with `O2` or `O3` and `Wall`, but not when compiled with `O0` or
`O1`. Also, `-fsanitize=undefined` removes the warning for `O2`, but not for
`O3`. All gcc versions prior to 12.1 do not emit any warnings. Clang does not
emit any warnings.
Here is the link to the source code: https://gcc.godbolt.org/z/WsfdsGb7M
The complete command line that triggers the bug:
`g++ -O2 -Wall ./bug.cpp`
Bug reports that may be related:
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=106247
https://gcc.gnu.org/bugzilla/show_bug.cgi?id=105523
Output of `gcc -v`:
Using built-in specs.
COLLECT_GCC=gcc
COLLECT_LTO_WRAPPER=/usr/libexec/gcc/x86_64-pc-linux-gnu/13/lto-wrapper
Target: x86_64-pc-linux-gnu
Configured with:
/var/tmp/portage/sys-devel/gcc-13.3.1_p20240614/work/gcc-13-20240614/configure
--host=x86_64-pc-
linux-gnu --build=x86_64-pc-linux-gnu --prefix=/usr
--bindir=/usr/x86_64-pc-linux-gnu/gcc-bin/13 --includedir=/us
r/lib/gcc/x86_64-pc-linux-gnu/13/include
--datadir=/usr/share/gcc-data/x86_64-pc-linux-gnu/13 --mandir=/usr/share
/gcc-data/x86_64-pc-linux-gnu/13/man
--infodir=/usr/share/gcc-data/x86_64-pc-linux-gnu/13/info --with-gxx-include
-dir=/usr/lib/gcc/x86_64-pc-linux-gnu/13/include/g++-v13 --disable-silent-rules
--disable-dependency-tracking --w
ith-python-dir=/share/gcc-data/x86_64-pc-linux-gnu/13/python
--enable-languages=c,c++,fortran --enable-obsolete -
-enable-secureplt --disable-werror --with-system-zlib --disable-nls
--disable-libunwind-exceptions --enable-check
ing=release --with-bugurl=https://bugs.gentoo.org/ --with-pkgversion='Gentoo
13.3.1_p20240614 p17' --with-gcc-maj
or-version-only --enable-libstdcxx-time --enable-lto --disable-libstdcxx-pch
--enable-shared --enable-threads=pos
ix --enable-__cxa_atexit --enable-clocale=gnu --disable-multilib
--with-multilib-list=m64 --disable-fixed-point -
-enable-targets=all --enable-libgomp --disable-libssp --disable-libada
--enable-cet --disable-systemtap --disable
-valgrind-annotations --disable-vtable-verify --disable-libvtv --with-zstd
--without-isl --enable-default-pie --e
nable-default-ssp --disable-fixincludes --with-build-config=bootstrap-cet
Thread model: posix
Supported LTO compression algorithms: zlib zstd
gcc version 13.3.1 20240614 (Gentoo 13.3.1_p20240614 p17)