Commit 1bdec475 authored by Christopher Dykes's avatar Christopher Dykes Committed by Facebook Github Bot

Fix folly::Function under C++17 exception specifier rules

Summary: Under C++17's exception specifier rules (http://www.open-std.org/jtc1/sc22/wg21/docs/papers/2015/p0012r1.html) we need additional specializations to achieve the desired effect.

Reviewed By: yfeldblum

Differential Revision: D6214359

fbshipit-source-id: a007c2fcea1496bdfe4fdf923b39c1611c6ad9bc
parent e75cf21f
......@@ -237,6 +237,12 @@ template <typename ReturnType, typename... Args>
Function<ReturnType(Args...) const> constCastFunction(
Function<ReturnType(Args...)>&&) noexcept;
#if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE
template <typename ReturnType, typename... Args>
Function<ReturnType(Args...) const noexcept> constCastFunction(
Function<ReturnType(Args...) noexcept>&&) noexcept;
#endif
namespace detail {
namespace function {
......@@ -371,6 +377,98 @@ struct FunctionTraits<ReturnType(Args...) const> {
};
};
#if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE
template <typename ReturnType, typename... Args>
struct FunctionTraits<ReturnType(Args...) noexcept> {
using Call = ReturnType (*)(Data&, Args&&...) noexcept;
using IsConst = std::false_type;
using ConstSignature = ReturnType(Args...) const noexcept;
using NonConstSignature = ReturnType(Args...) noexcept;
using OtherSignature = ConstSignature;
template <typename F, typename G = typename std::decay<F>::type>
using ResultOf = decltype(
static_cast<ReturnType>(std::declval<G&>()(std::declval<Args>()...)));
template <typename Fun>
static ReturnType callSmall(Data& p, Args&&... args) noexcept {
return static_cast<ReturnType>((*static_cast<Fun*>(
static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...));
}
template <typename Fun>
static ReturnType callBig(Data& p, Args&&... args) noexcept {
return static_cast<ReturnType>(
(*static_cast<Fun*>(p.big))(static_cast<Args&&>(args)...));
}
static ReturnType uninitCall(Data&, Args&&...) noexcept {
throw std::bad_function_call();
}
ReturnType operator()(Args... args) noexcept {
auto& fn = *static_cast<Function<NonConstSignature>*>(this);
return fn.call_(fn.data_, static_cast<Args&&>(args)...);
}
class SharedProxy {
std::shared_ptr<Function<NonConstSignature>> sp_;
public:
explicit SharedProxy(Function<NonConstSignature>&& func)
: sp_(std::make_shared<Function<NonConstSignature>>(std::move(func))) {}
ReturnType operator()(Args&&... args) const {
return (*sp_)(static_cast<Args&&>(args)...);
}
};
};
template <typename ReturnType, typename... Args>
struct FunctionTraits<ReturnType(Args...) const noexcept> {
using Call = ReturnType (*)(Data&, Args&&...) noexcept;
using IsConst = std::true_type;
using ConstSignature = ReturnType(Args...) const noexcept;
using NonConstSignature = ReturnType(Args...) noexcept;
using OtherSignature = NonConstSignature;
template <typename F, typename G = typename std::decay<F>::type>
using ResultOf = decltype(static_cast<ReturnType>(
std::declval<const G&>()(std::declval<Args>()...)));
template <typename Fun>
static ReturnType callSmall(Data& p, Args&&... args) noexcept {
return static_cast<ReturnType>((*static_cast<const Fun*>(
static_cast<void*>(&p.tiny)))(static_cast<Args&&>(args)...));
}
template <typename Fun>
static ReturnType callBig(Data& p, Args&&... args) noexcept {
return static_cast<ReturnType>(
(*static_cast<const Fun*>(p.big))(static_cast<Args&&>(args)...));
}
static ReturnType uninitCall(Data&, Args&&...) noexcept {
throw std::bad_function_call();
}
ReturnType operator()(Args... args) const noexcept {
auto& fn = *static_cast<const Function<ConstSignature>*>(this);
return fn.call_(fn.data_, static_cast<Args&&>(args)...);
}
class SharedProxy {
std::shared_ptr<Function<ConstSignature>> sp_;
public:
explicit SharedProxy(Function<ConstSignature>&& func)
: sp_(std::make_shared<Function<ConstSignature>>(std::move(func))) {}
ReturnType operator()(Args&&... args) const {
return (*sp_)(static_cast<Args&&>(args)...);
}
};
};
#endif
template <typename Fun>
bool execSmall(Op o, Data* src, Data* dst) {
switch (o) {
......@@ -743,6 +841,21 @@ Function<ReturnType(Args...) const> constCastFunction(
return std::move(that);
}
#if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE
template <typename ReturnType, typename... Args>
Function<ReturnType(Args...) const noexcept> constCastFunction(
Function<ReturnType(Args...) noexcept>&& that) noexcept {
return Function<ReturnType(Args...) const noexcept>{
std::move(that), detail::function::CoerceTag{}};
}
template <typename ReturnType, typename... Args>
Function<ReturnType(Args...) const noexcept> constCastFunction(
Function<ReturnType(Args...) const noexcept>&& that) noexcept {
return std::move(that);
}
#endif
namespace detail {
namespace function {
template <typename Fun, typename FunctionType, typename = void>
......
......@@ -429,3 +429,8 @@ constexpr auto kMscVer = 0;
#if __cpp_coroutines >= 201703L || (_MSC_VER && _RESUMABLE_FUNCTIONS_SUPPORTED)
#define FOLLY_HAS_COROUTINES 1
#endif
// MSVC 2017.5
#if __cpp_noexcept_function_type >= 201510 || _MSC_FULL_VER >= 191225816
#define FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE 1
#endif
......@@ -66,16 +66,20 @@ void moveTopException(StackTraceStack& from, StackTraceStack& to) {
struct Initializer {
Initializer() {
registerCxaThrowCallback(
[](void*, std::type_info*, void (*)(void*)) { addActiveException(); });
registerCxaThrowCallback([](
void*, std::type_info*, void (*)(void*)) noexcept {
addActiveException();
});
registerCxaBeginCatchCallback(
[](void*) { moveTopException(activeExceptions, caughtExceptions); });
registerCxaBeginCatchCallback([](void*) noexcept {
moveTopException(activeExceptions, caughtExceptions);
});
registerCxaRethrowCallback(
[]() { moveTopException(caughtExceptions, activeExceptions); });
registerCxaRethrowCallback([]() noexcept {
moveTopException(caughtExceptions, activeExceptions);
});
registerCxaEndCatchCallback([]() {
registerCxaEndCatchCallback([]() noexcept {
if (invalid) {
return;
}
......@@ -97,8 +101,9 @@ struct Initializer {
}
});
registerRethrowExceptionCallback(
[](std::exception_ptr) { addActiveException(); });
registerRethrowExceptionCallback([](std::exception_ptr) noexcept {
addActiveException();
});
try {
::folly::exception_tracer::installHandlers();
......
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