Commit bdc1476f authored by Eric Niebler's avatar Eric Niebler Committed by Facebook Github Bot

Don't cast function call result to void as it can hide nodiscard warnings

Summary:
When assigning a function whose return type is marked `nodiscard` to a `Function<void(Args...)>`, the fact that we are internally explicitly casting the result of the function call to `void` hides the `nodiscard` warning.

For instance:

```
struct [[nodiscard]] DoNotIgnore {};
Function<void()> fn = [] { return DoNotIgnore{}; };
```

emits no warnings, and when `fn()` is invoked, the `DoNotIgnore` struct gets silently ignored.

This diff causes the warning to be emitted.

It is only enabled on compilers that support `if constexpr`. It could be supported on more compilers at the cost of one or more of the following:

* extra template instantiations
* an additional function dispatch
* SFINAE
* Spamming out 4 more specializations of the `FunctionTraits` template.

Reviewed By: yfeldblum

Differential Revision: D18668177

fbshipit-source-id: 0a2cd1366855a0582ab27bb157998d3a4bf4e5a0
parent eaeaa1fa
......@@ -381,14 +381,30 @@ struct FunctionTraits<ReturnType(Args...)> {
template <typename Fun>
static ReturnType callSmall(CallArg<Args>... args, Data& p) {
return static_cast<ReturnType>((*static_cast<Fun*>(
static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...));
auto& fn = *static_cast<Fun*>(static_cast<void*>(&p.tiny));
#if __cpp_if_constexpr >= 201606L
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
#else
return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
#endif
}
template <typename Fun>
static ReturnType callBig(CallArg<Args>... args, Data& p) {
return static_cast<ReturnType>(
(*static_cast<Fun*>(p.big))(static_cast<Args&&>(args)...));
auto& fn = *static_cast<Fun*>(p.big);
#if __cpp_if_constexpr >= 201606L
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
#else
return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
#endif
}
static ReturnType uninitCall(CallArg<Args>..., Data&) {
......@@ -418,14 +434,30 @@ struct FunctionTraits<ReturnType(Args...) const> {
template <typename Fun>
static ReturnType callSmall(CallArg<Args>... args, Data& p) {
return static_cast<ReturnType>((*static_cast<const Fun*>(
static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...));
auto& fn = *static_cast<const Fun*>(static_cast<void*>(&p.tiny));
#if __cpp_if_constexpr >= 201606L
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
#else
return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
#endif
}
template <typename Fun>
static ReturnType callBig(CallArg<Args>... args, Data& p) {
return static_cast<ReturnType>(
(*static_cast<const Fun*>(p.big))(static_cast<Args&&>(args)...));
auto& fn = *static_cast<const Fun*>(p.big);
#if __cpp_if_constexpr >= 201606L
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
#else
return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
#endif
}
static ReturnType uninitCall(CallArg<Args>..., Data&) {
......@@ -456,14 +488,30 @@ struct FunctionTraits<ReturnType(Args...) noexcept> {
template <typename Fun>
static ReturnType callSmall(CallArg<Args>... args, Data& p) noexcept {
return static_cast<ReturnType>((*static_cast<Fun*>(
static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...));
auto& fn = *static_cast<Fun*>(static_cast<void*>(&p.tiny));
#if __cpp_if_constexpr >= 201606L
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
#else
return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
#endif
}
template <typename Fun>
static ReturnType callBig(CallArg<Args>... args, Data& p) noexcept {
return static_cast<ReturnType>(
(*static_cast<Fun*>(p.big))(static_cast<Args&&>(args)...));
auto& fn = *static_cast<Fun*>(p.big);
#if __cpp_if_constexpr >= 201606L
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
#else
return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
#endif
}
static ReturnType uninitCall(CallArg<Args>..., Data&) noexcept {
......@@ -493,14 +541,30 @@ struct FunctionTraits<ReturnType(Args...) const noexcept> {
template <typename Fun>
static ReturnType callSmall(CallArg<Args>... args, Data& p) noexcept {
return static_cast<ReturnType>((*static_cast<const Fun*>(
static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...));
auto& fn = *static_cast<const Fun*>(static_cast<void*>(&p.tiny));
#if __cpp_if_constexpr >= 201606L
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
#else
return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
#endif
}
template <typename Fun>
static ReturnType callBig(CallArg<Args>... args, Data& p) noexcept {
return static_cast<ReturnType>(
(*static_cast<const Fun*>(p.big))(static_cast<Args&&>(args)...));
auto& fn = *static_cast<const Fun*>(p.big);
#if __cpp_if_constexpr >= 201606L
if constexpr (std::is_void<ReturnType>::value) {
fn(static_cast<Args&&>(args)...);
} else {
return fn(static_cast<Args&&>(args)...);
}
#else
return static_cast<ReturnType>(fn(static_cast<Args&&>(args)...));
#endif
}
static ReturnType uninitCall(CallArg<Args>..., Data&) noexcept {
......
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