Commit fdcce5ae authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook GitHub Bot

Mark invoker operator() as maybe-unused

Summary:
[Folly] Mark invoker `operator()` as `[[maybe_unused]]` when defined in macros.

If the macro is used in a `.cpp` but the generated `operator()` is not invoked, the compiler might warn.

This can easily happen in the following situation:

```
FOLLY_CREATE_MEMBER_INVOKER(invoke_foo_fn, foo);
FOLLY_CREATE_MEMBER_INVOKER(invoke_bar_fn, bar);

using invoke_one_fn = std::conditional_t<
    /* cond */,
    invoke_foo_fn,
    invoke_bar_fn>;
constexpr invoke_one_fn invoke_on;

template <typename T>
void go(T& t) {
  invoke_one(t);
}
```

In such a situation, either `invoke_foo_fn::operator()` is seen at a call-site or `invoke_bar_fn::operator()` is seen at the call-site, but not both - one of them is unused, and if the right warnings are enabled, will be warned as unused.

Reviewed By: luciang, markisaa

Differential Revision: D22570047

fbshipit-source-id: a4caa7a95ab74ea075cf41c26525935f3d9186c0
parent eeb59fc3
......@@ -77,10 +77,10 @@
* #endif
* }
*/
#if FOLLY_HAS_CPP_ATTRIBUTE(maybe_unused)
#if FOLLY_HAS_CPP_ATTRIBUTE(maybe_unused) && __cplusplus >= 201703L
#define FOLLY_MAYBE_UNUSED [[maybe_unused]]
#elif FOLLY_HAS_ATTRIBUTE(__unused__) || __GNUC__
#define FOLLY_MAYBE_UNUSED __attribute__((__unused__))
#elif FOLLY_HAS_CPP_ATTRIBUTE(gnu::unused) || __GNUC__
#define FOLLY_MAYBE_UNUSED [[gnu::unused]]
#else
#define FOLLY_MAYBE_UNUSED
#endif
......
......@@ -25,6 +25,7 @@
#include <boost/preprocessor/logical/not.hpp>
#include <boost/preprocessor/tuple/to_list.hpp>
#include <folly/CppAttributes.h>
#include <folly/Portability.h>
#include <folly/Preprocessor.h>
#include <folly/Traits.h>
......@@ -365,7 +366,8 @@ struct invoke_traits : detail::invoke_traits_base<Invoke> {
FOLLY_DETAIL_CREATE_FREE_INVOKE_TRAITS_USING(_, funcname, __VA_ARGS__) \
struct __folly_detail_invoke_obj { \
template <typename... Args> \
FOLLY_ERASE_HACK_GCC constexpr auto operator()(Args&&... args) const \
FOLLY_MAYBE_UNUSED FOLLY_ERASE_HACK_GCC constexpr auto operator()( \
Args&&... args) const \
noexcept(noexcept(funcname(static_cast<Args&&>(args)...))) \
-> decltype(funcname(static_cast<Args&&>(args)...)) { \
return funcname(static_cast<Args&&>(args)...); \
......@@ -415,16 +417,16 @@ struct invoke_traits : detail::invoke_traits_base<Invoke> {
* traits::is_nothrow_invocable_v<int, CanFoo, Car&&> // true
* traits::is_nothrow_invocable_v<char*, CanFoo, Car&&> // false
*/
#define FOLLY_CREATE_MEMBER_INVOKER(classname, membername) \
struct classname { \
template <typename O, typename... Args> \
FOLLY_ERASE_HACK_GCC constexpr auto operator()(O&& o, Args&&... args) \
const noexcept(noexcept( \
static_cast<O&&>(o).membername(static_cast<Args&&>(args)...))) \
-> decltype(static_cast<O&&>(o).membername( \
static_cast<Args&&>(args)...)) { \
return static_cast<O&&>(o).membername(static_cast<Args&&>(args)...); \
} \
#define FOLLY_CREATE_MEMBER_INVOKER(classname, membername) \
struct classname { \
template <typename O, typename... Args> \
FOLLY_MAYBE_UNUSED FOLLY_ERASE_HACK_GCC constexpr auto \
operator()(O&& o, Args&&... args) const noexcept(noexcept( \
static_cast<O&&>(o).membername(static_cast<Args&&>(args)...))) \
-> decltype( \
static_cast<O&&>(o).membername(static_cast<Args&&>(args)...)) { \
return static_cast<O&&>(o).membername(static_cast<Args&&>(args)...); \
} \
}
/***
......@@ -468,15 +470,15 @@ struct invoke_traits : detail::invoke_traits_base<Invoke> {
* traits::is_nothrow_invocable_v<int, Car&&> // true
* traits::is_nothrow_invocable_v<char*, Car&&> // false
*/
#define FOLLY_CREATE_STATIC_MEMBER_INVOKER(classname, membername) \
template <typename T> \
struct classname { \
template <typename... Args> \
FOLLY_ERASE constexpr auto operator()(Args&&... args) const \
noexcept(noexcept(T::membername(static_cast<Args&&>(args)...))) \
-> decltype(T::membername(static_cast<Args&&>(args)...)) { \
return T::membername(static_cast<Args&&>(args)...); \
} \
#define FOLLY_CREATE_STATIC_MEMBER_INVOKER(classname, membername) \
template <typename T> \
struct classname { \
template <typename... Args> \
FOLLY_MAYBE_UNUSED FOLLY_ERASE constexpr auto operator()(Args&&... args) \
const noexcept(noexcept(T::membername(static_cast<Args&&>(args)...))) \
-> decltype(T::membername(static_cast<Args&&>(args)...)) { \
return T::membername(static_cast<Args&&>(args)...); \
} \
}
namespace folly {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment