From: Christopher Dykes Date: Thu, 2 Nov 2017 03:33:39 +0000 (-0700) Subject: Fix folly::Function under C++17 exception specifier rules X-Git-Tag: v2017.11.06.00~14 X-Git-Url: http://plrg.eecs.uci.edu/git/?p=folly.git;a=commitdiff_plain;h=1bdec475acac176a9692b6e506564c8c0ccd1984 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 --- diff --git a/folly/Function.h b/folly/Function.h index 0ad01582..b8a287dd 100644 --- a/folly/Function.h +++ b/folly/Function.h @@ -237,6 +237,12 @@ template Function constCastFunction( Function&&) noexcept; +#if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE +template +Function constCastFunction( + Function&&) noexcept; +#endif + namespace detail { namespace function { @@ -371,6 +377,98 @@ struct FunctionTraits { }; }; +#if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE +template +struct FunctionTraits { + 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 ::type> + using ResultOf = decltype( + static_cast(std::declval()(std::declval()...))); + + template + static ReturnType callSmall(Data& p, Args&&... args) noexcept { + return static_cast((*static_cast( + static_cast(&p.tiny)))(static_cast(args)...)); + } + + template + static ReturnType callBig(Data& p, Args&&... args) noexcept { + return static_cast( + (*static_cast(p.big))(static_cast(args)...)); + } + + static ReturnType uninitCall(Data&, Args&&...) noexcept { + throw std::bad_function_call(); + } + + ReturnType operator()(Args... args) noexcept { + auto& fn = *static_cast*>(this); + return fn.call_(fn.data_, static_cast(args)...); + } + + class SharedProxy { + std::shared_ptr> sp_; + + public: + explicit SharedProxy(Function&& func) + : sp_(std::make_shared>(std::move(func))) {} + ReturnType operator()(Args&&... args) const { + return (*sp_)(static_cast(args)...); + } + }; +}; + +template +struct FunctionTraits { + 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 ::type> + using ResultOf = decltype(static_cast( + std::declval()(std::declval()...))); + + template + static ReturnType callSmall(Data& p, Args&&... args) noexcept { + return static_cast((*static_cast( + static_cast(&p.tiny)))(static_cast(args)...)); + } + + template + static ReturnType callBig(Data& p, Args&&... args) noexcept { + return static_cast( + (*static_cast(p.big))(static_cast(args)...)); + } + + static ReturnType uninitCall(Data&, Args&&...) noexcept { + throw std::bad_function_call(); + } + + ReturnType operator()(Args... args) const noexcept { + auto& fn = *static_cast*>(this); + return fn.call_(fn.data_, static_cast(args)...); + } + + class SharedProxy { + std::shared_ptr> sp_; + + public: + explicit SharedProxy(Function&& func) + : sp_(std::make_shared>(std::move(func))) {} + ReturnType operator()(Args&&... args) const { + return (*sp_)(static_cast(args)...); + } + }; +}; +#endif + template bool execSmall(Op o, Data* src, Data* dst) { switch (o) { @@ -743,6 +841,21 @@ Function constCastFunction( return std::move(that); } +#if FOLLY_HAVE_NOEXCEPT_FUNCTION_TYPE +template +Function constCastFunction( + Function&& that) noexcept { + return Function{ + std::move(that), detail::function::CoerceTag{}}; +} + +template +Function constCastFunction( + Function&& that) noexcept { + return std::move(that); +} +#endif + namespace detail { namespace function { template diff --git a/folly/Portability.h b/folly/Portability.h index be5960d2..15f393e0 100644 --- a/folly/Portability.h +++ b/folly/Portability.h @@ -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 diff --git a/folly/experimental/exception_tracer/ExceptionStackTraceLib.cpp b/folly/experimental/exception_tracer/ExceptionStackTraceLib.cpp index 57f0fd68..cd569b5e 100644 --- a/folly/experimental/exception_tracer/ExceptionStackTraceLib.cpp +++ b/folly/experimental/exception_tracer/ExceptionStackTraceLib.cpp @@ -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();