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

Jonathan Wakely <redi at gcc dot gnu.org> changed:

           What    |Removed                     |Added
----------------------------------------------------------------------------
   Last reconfirmed|                            |2025-05-28
     Ever confirmed|0                           |1
             Status|UNCONFIRMED                 |NEW

--- Comment #2 from Jonathan Wakely <redi at gcc dot gnu.org> ---
This variation doesn't warn even with -Wsystem-headers

#include <functional>

[[nodiscard]] int f();

void g() {
  std::invoke_r<void>(f);
}


That's because where the call to f() happens the return value is propagated to
the caller:

  template<typename _Res, typename _Fn, typename... _Args>
    constexpr _Res
    __invoke_impl(__invoke_other, _Fn&& __f, _Args&&... __args)
    { return std::forward<_Fn>(__f)(std::forward<_Args>(__args)...); }


But then that caller discards it:

      if constexpr (is_void_v<_Res>)
        std::__invoke_impl<__type>(__tag{}, std::forward<_Callable>(__fn),
                                        std::forward<_Args>(__args)...);

I don't think [[nodiscard]] on the function can work here. The caller doesn't
know that the int shouldn't be discarded, it's just an int by that point.

For Avi's original example, the A object carries the [[nodiscard]] with it so
that there's still a warning if/when it is ever discarded. But I agree that
it's a limitation of the front-end. I don't think we need to worry about
badly-written system headers that are discarding [[nodiscard]] results, because
any headers using [[nodiscard]] are probably quite new C++ code and probably
still maintained, and could be fixed to cast to void if needed.

Reply via email to