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)

Reply via email to