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

Steve Downey <sdowney at gmail dot com> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
                 CC|                            |sdowney at gmail dot com

--- Comment #10 from Steve Downey <sdowney at gmail dot com> ---
Still present in GCC 16.2.1 (20260926). It's also reachable without writing
a member pointer call yourself: libstdc++'s type-erased call wrappers hit it
when holding a pointer to member function. std::move_only_function and
std::copyable_function warn at -O2, std::function at -O3.

```
#include <functional>

struct S {
    int total = 0;
    int add(int x) { return total += x; }
};

int via_move_only_function() {
    S s;
    std::move_only_function<int(S&, int)> f = &S::add;
    f(s, 4);
    return f(s, 5);
}

int via_function() {
    S s;
    std::function<int(S&, int)> f = &S::add;
    f(s, 4);
    return f(s, 5);
}
```

`g++ -std=c++23 -O2 -Wall -c pr111750.cpp`:

```
In function 'constexpr _Res std::__invoke_impl(__invoke_memfun_ref, _MemFun&&,
_Tp&&, _Args&& ...) [with _Res = int; _MemFun = int (S::*)(int); _Tp = S&;
_Args = {int}]',
    inlined from [...] 'std::__polyfunc::_Base_invoker<_Noex, _Ret,
_Args>::_S_call_storage(...)' at bits/funcwrap.h:190:29,
    inlined from '_Res std::move_only_function<_Res(_ArgTypes ...) noexcept
(_Noex)>::operator()(_ArgTypes ...) [...]' at bits/mofunc_impl.h:214:9,
    inlined from 'int via_move_only_function()' at pr111750.cpp:12:13:
bits/invoke.h:69:39: warning: array subscript 'int (**)(...)[0]' is partly
outside array bounds of 'S [1]' [-Warray-bounds=]
   69 |     { return (__invfwd<_Tp>(__t).*__f)(std::forward<_Args>(__args)...);
}
      |              ~~~~~~~~~~~~~~~~~~~~~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
pr111750.cpp: In function 'int via_move_only_function()':
pr111750.cpp:9:7: note: object 's' of size 4
```

At -O3, via_function() gives the same warning, at the same line.

The second call matters: with only one call, or with two calls to a
member function that takes no arguments, neither function warns. That seems
to fit comment 1: once the call wrapper's storage has been through one call,
the object is known but the pointer to member isn't yet, so the virtual
arm's vtable load survives into the warning.

Users of these wrappers see a warning in invoke.h for code that doesn't
contain an array, and the only local fix is a pragma around the caller.

Reply via email to