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.