Commit 19292278 authored by Yedidya Feldblum's avatar Yedidya Feldblum Committed by Facebook Github Bot

Support -fno-exceptions in folly/dynamic.h

Summary: [folly] Support `-fno-exceptions` in `folly/dynamic.h` and in its dependencies.

Reviewed By: Orvid

Differential Revision: D13018170

fbshipit-source-id: 4d16049821f3a8628d63ee20f412c4df3dcee37e
parent 21be7c3d
...@@ -63,12 +63,12 @@ std::system_error makeSystemError(Args&&... args) { ...@@ -63,12 +63,12 @@ std::system_error makeSystemError(Args&&... args) {
// Helper to throw std::system_error // Helper to throw std::system_error
[[noreturn]] inline void throwSystemErrorExplicit(int err, const char* msg) { [[noreturn]] inline void throwSystemErrorExplicit(int err, const char* msg) {
throw makeSystemErrorExplicit(err, msg); throw_exception(makeSystemErrorExplicit(err, msg));
} }
template <class... Args> template <class... Args>
[[noreturn]] void throwSystemErrorExplicit(int err, Args&&... args) { [[noreturn]] void throwSystemErrorExplicit(int err, Args&&... args) {
throw makeSystemErrorExplicit(err, std::forward<Args>(args)...); throw_exception(makeSystemErrorExplicit(err, std::forward<Args>(args)...));
} }
// Helper to throw std::system_error from errno and components of a string // Helper to throw std::system_error from errno and components of a string
...@@ -132,11 +132,11 @@ void checkFopenErrorExplicit(FILE* fp, int savedErrno, Args&&... args) { ...@@ -132,11 +132,11 @@ void checkFopenErrorExplicit(FILE* fp, int savedErrno, Args&&... args) {
* If cond is not true, raise an exception of type E. E must have a ctor that * If cond is not true, raise an exception of type E. E must have a ctor that
* works with const char* (a description of the failure). * works with const char* (a description of the failure).
*/ */
#define CHECK_THROW(cond, E) \ #define CHECK_THROW(cond, E) \
do { \ do { \
if (!(cond)) { \ if (!(cond)) { \
throw E("Check failed: " #cond); \ folly::throw_exception<E>("Check failed: " #cond); \
} \ } \
} while (0) } while (0)
} // namespace folly } // namespace folly
...@@ -46,13 +46,19 @@ inline fbstring exceptionStr(const std::exception& e) { ...@@ -46,13 +46,19 @@ inline fbstring exceptionStr(const std::exception& e) {
#if defined(__GNUC__) && defined(__GCC_ATOMIC_INT_LOCK_FREE) && \ #if defined(__GNUC__) && defined(__GCC_ATOMIC_INT_LOCK_FREE) && \
__GCC_ATOMIC_INT_LOCK_FREE > 1 __GCC_ATOMIC_INT_LOCK_FREE > 1
inline fbstring exceptionStr(std::exception_ptr ep) { inline fbstring exceptionStr(std::exception_ptr ep) {
try { if (!kHasExceptions) {
std::rethrow_exception(ep); return "Exception (catch unavailable)";
} catch (const std::exception& e) {
return exceptionStr(e);
} catch (...) {
return "<unknown exception>";
} }
catch_exception(
[&]() -> fbstring {
return catch_exception<std::exception const&>(
[&]() -> fbstring {
std::rethrow_exception(ep);
assume_unreachable();
},
[](auto&& e) { return exceptionStr(e); });
},
[]() -> fbstring { return "<unknown exception>"; });
} }
#endif #endif
...@@ -63,7 +69,7 @@ auto exceptionStr(const E& e) -> typename std:: ...@@ -63,7 +69,7 @@ auto exceptionStr(const E& e) -> typename std::
return demangle(typeid(e)); return demangle(typeid(e));
#else #else
(void)e; (void)e;
return "Exception (no RTTI available) "; return "Exception (no RTTI available)";
#endif #endif
} }
......
...@@ -260,11 +260,9 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()( ...@@ -260,11 +260,9 @@ void BaseFormatter<Derived, containerMode, Args...>::operator()(
arg.width = asDerived().getSizeArg(size_t(arg.widthIndex), arg); arg.width = asDerived().getSizeArg(size_t(arg.widthIndex), arg);
} }
try { auto result = tryTo<int>(piece);
argIndex = to<int>(piece); arg.enforce(result, "argument index must be integer");
} catch (const std::out_of_range&) { argIndex = *result;
arg.error("argument index must be integer");
}
arg.enforce(argIndex >= 0, "argument index must be non-negative"); arg.enforce(argIndex >= 0, "argument index must be non-negative");
hasExplicitArgIndex = true; hasExplicitArgIndex = true;
} }
......
...@@ -72,8 +72,9 @@ struct FormatArg { ...@@ -72,8 +72,9 @@ struct FormatArg {
* message will contain the argument string as well as any passed-in * message will contain the argument string as well as any passed-in
* arguments to enforce, formatted using folly::to<std::string>. * arguments to enforce, formatted using folly::to<std::string>.
*/ */
template <typename... Args> template <typename Check, typename... Args>
void enforce(bool v, Args&&... args) const { void enforce(Check const& v, Args&&... args) const {
static_assert(std::is_constructible<bool, Check>::value, "not castable");
if (UNLIKELY(!v)) { if (UNLIKELY(!v)) {
error(std::forward<Args>(args)...); error(std::forward<Args>(args)...);
} }
...@@ -268,12 +269,9 @@ inline int FormatArg::splitIntKey() { ...@@ -268,12 +269,9 @@ inline int FormatArg::splitIntKey() {
nextKeyMode_ = NextKeyMode::NONE; nextKeyMode_ = NextKeyMode::NONE;
return nextIntKey_; return nextIntKey_;
} }
try { auto result = tryTo<int>(doSplitKey<true>());
return to<int>(doSplitKey<true>()); enforce(result, "integer key required");
} catch (const std::out_of_range&) { return *result;
error("integer key required");
return 0; // unreached
}
} }
} // namespace folly } // namespace folly
...@@ -320,7 +320,7 @@ struct FunctionTraits<ReturnType(Args...)> { ...@@ -320,7 +320,7 @@ struct FunctionTraits<ReturnType(Args...)> {
} }
static ReturnType uninitCall(Data&, Args&&...) { static ReturnType uninitCall(Data&, Args&&...) {
throw std::bad_function_call(); throw_exception<std::bad_function_call>();
} }
ReturnType operator()(Args... args) { ReturnType operator()(Args... args) {
...@@ -366,7 +366,7 @@ struct FunctionTraits<ReturnType(Args...) const> { ...@@ -366,7 +366,7 @@ struct FunctionTraits<ReturnType(Args...) const> {
} }
static ReturnType uninitCall(Data&, Args&&...) { static ReturnType uninitCall(Data&, Args&&...) {
throw std::bad_function_call(); throw_exception<std::bad_function_call>();
} }
ReturnType operator()(Args... args) const { ReturnType operator()(Args... args) const {
...@@ -458,7 +458,7 @@ struct FunctionTraits<ReturnType(Args...) const noexcept> { ...@@ -458,7 +458,7 @@ struct FunctionTraits<ReturnType(Args...) const noexcept> {
} }
static ReturnType uninitCall(Data&, Args&&...) noexcept { static ReturnType uninitCall(Data&, Args&&...) noexcept {
throw std::bad_function_call(); throw_exception<std::bad_function_call>();
} }
ReturnType operator()(Args... args) const noexcept { ReturnType operator()(Args... args) const noexcept {
...@@ -897,7 +897,7 @@ class FunctionRef<ReturnType(Args...)> final { ...@@ -897,7 +897,7 @@ class FunctionRef<ReturnType(Args...)> final {
using Call = ReturnType (*)(void*, Args&&...); using Call = ReturnType (*)(void*, Args&&...);
static ReturnType uninitCall(void*, Args&&...) { static ReturnType uninitCall(void*, Args&&...) {
throw std::bad_function_call(); throw_exception<std::bad_function_call>();
} }
template <typename Fun> template <typename Fun>
......
...@@ -76,7 +76,7 @@ const typename Map::mapped_type& get_or_throw( ...@@ -76,7 +76,7 @@ const typename Map::mapped_type& get_or_throw(
if (pos != map.end()) { if (pos != map.end()) {
return pos->second; return pos->second;
} }
throw E(folly::to<std::string>(exceptionStrPrefix, key)); throw_exception<E>(folly::to<std::string>(exceptionStrPrefix, key));
} }
template < template <
...@@ -91,7 +91,7 @@ typename Map::mapped_type& get_or_throw( ...@@ -91,7 +91,7 @@ typename Map::mapped_type& get_or_throw(
if (pos != map.end()) { if (pos != map.end()) {
return pos->second; return pos->second;
} }
throw E(folly::to<std::string>(exceptionStrPrefix, key)); throw_exception<E>(folly::to<std::string>(exceptionStrPrefix, key));
} }
/** /**
......
...@@ -265,6 +265,15 @@ constexpr auto kIsDebug = true; ...@@ -265,6 +265,15 @@ constexpr auto kIsDebug = true;
#endif #endif
} // namespace folly } // namespace folly
// Exceptions
namespace folly {
#if FOLLY_HAS_EXCEPTIONS
constexpr auto kHasExceptions = true;
#else
constexpr auto kHasExceptions = false;
#endif
} // namespace folly
// Endianness // Endianness
namespace folly { namespace folly {
#ifdef _MSC_VER #ifdef _MSC_VER
......
...@@ -26,6 +26,7 @@ ...@@ -26,6 +26,7 @@
#include <folly/Portability.h> #include <folly/Portability.h>
#include <folly/Preprocessor.h> #include <folly/Preprocessor.h>
#include <folly/Utility.h> #include <folly/Utility.h>
#include <folly/lang/Exception.h>
#include <folly/lang/UncaughtExceptions.h> #include <folly/lang/UncaughtExceptions.h>
namespace folly { namespace folly {
...@@ -120,12 +121,9 @@ class ScopeGuardImpl : public ScopeGuardImplBase { ...@@ -120,12 +121,9 @@ class ScopeGuardImpl : public ScopeGuardImplBase {
void execute() noexcept(InvokeNoexcept) { void execute() noexcept(InvokeNoexcept) {
if (InvokeNoexcept) { if (InvokeNoexcept) {
try { using R = decltype(function_());
function_(); auto catcher = []() -> R { warnAboutToCrash(), std::terminate(); };
} catch (...) { catch_exception(function_, catcher);
warnAboutToCrash();
std::terminate();
}
} else { } else {
function_(); function_();
} }
......
...@@ -99,7 +99,7 @@ void cUnescape(StringPiece str, String& out, bool strict) { ...@@ -99,7 +99,7 @@ void cUnescape(StringPiece str, String& out, bool strict) {
++p; ++p;
if (p == str.end()) { // backslash at end of string if (p == str.end()) { // backslash at end of string
if (strict) { if (strict) {
throw std::invalid_argument("incomplete escape sequence"); throw_exception<std::invalid_argument>("incomplete escape sequence");
} }
out.push_back('\\'); out.push_back('\\');
last = p; last = p;
...@@ -119,7 +119,8 @@ void cUnescape(StringPiece str, String& out, bool strict) { ...@@ -119,7 +119,8 @@ void cUnescape(StringPiece str, String& out, bool strict) {
++p; ++p;
if (p == str.end()) { // \x at end of string if (p == str.end()) { // \x at end of string
if (strict) { if (strict) {
throw std::invalid_argument("incomplete hex escape sequence"); throw_exception<std::invalid_argument>(
"incomplete hex escape sequence");
} }
out.append("\\x"); out.append("\\x");
last = p; last = p;
...@@ -137,7 +138,7 @@ void cUnescape(StringPiece str, String& out, bool strict) { ...@@ -137,7 +138,7 @@ void cUnescape(StringPiece str, String& out, bool strict) {
last = p; last = p;
} else if (e == 'I') { // invalid } else if (e == 'I') { // invalid
if (strict) { if (strict) {
throw std::invalid_argument("invalid escape sequence"); throw_exception<std::invalid_argument>("invalid escape sequence");
} }
out.push_back('\\'); out.push_back('\\');
out.push_back(*p); out.push_back(*p);
...@@ -209,12 +210,14 @@ void uriUnescape(StringPiece str, String& out, UriEscapeMode mode) { ...@@ -209,12 +210,14 @@ void uriUnescape(StringPiece str, String& out, UriEscapeMode mode) {
switch (c) { switch (c) {
case '%': { case '%': {
if (UNLIKELY(std::distance(p, str.end()) < 3)) { if (UNLIKELY(std::distance(p, str.end()) < 3)) {
throw std::invalid_argument("incomplete percent encode sequence"); throw_exception<std::invalid_argument>(
"incomplete percent encode sequence");
} }
auto h1 = detail::hexTable[static_cast<unsigned char>(p[1])]; auto h1 = detail::hexTable[static_cast<unsigned char>(p[1])];
auto h2 = detail::hexTable[static_cast<unsigned char>(p[2])]; auto h2 = detail::hexTable[static_cast<unsigned char>(p[2])];
if (UNLIKELY(h1 == 16 || h2 == 16)) { if (UNLIKELY(h1 == 16 || h2 == 16)) {
throw std::invalid_argument("invalid percent encode sequence"); throw_exception<std::invalid_argument>(
"invalid percent encode sequence");
} }
out.append(&*last, size_t(p - last)); out.append(&*last, size_t(p - last));
out.push_back((h1 << 4) | h2); out.push_back((h1 << 4) | h2);
......
...@@ -260,7 +260,7 @@ OutputString hexlify(ByteRange input) { ...@@ -260,7 +260,7 @@ OutputString hexlify(ByteRange input) {
OutputString output; OutputString output;
if (!hexlify(input, output)) { if (!hexlify(input, output)) {
// hexlify() currently always returns true, so this can't really happen // hexlify() currently always returns true, so this can't really happen
throw std::runtime_error("hexlify failed"); throw_exception<std::runtime_error>("hexlify failed");
} }
return output; return output;
} }
...@@ -283,7 +283,7 @@ OutputString unhexlify(StringPiece input) { ...@@ -283,7 +283,7 @@ OutputString unhexlify(StringPiece input) {
if (!unhexlify(input, output)) { if (!unhexlify(input, output)) {
// unhexlify() fails if the input has non-hexidecimal characters, // unhexlify() fails if the input has non-hexidecimal characters,
// or if it doesn't consist of a whole number of bytes // or if it doesn't consist of a whole number of bytes
throw std::domain_error("unhexlify() called with non-hex input"); throw_exception<std::domain_error>("unhexlify() called with non-hex input");
} }
return output; return output;
} }
......
...@@ -461,7 +461,7 @@ TEST(Format, BogusFormatString) { ...@@ -461,7 +461,7 @@ TEST(Format, BogusFormatString) {
// This one fails in detail::enforceWhitespace(), which throws // This one fails in detail::enforceWhitespace(), which throws
// std::range_error // std::range_error
EXPECT_THROW_STR(sformat("{0[test}"), std::range_error, "Non-whitespace"); EXPECT_FORMAT_ERROR(sformat("{0[test}"), "argument index must be integer");
} }
template <bool containerMode, class... Args> template <bool containerMode, class... Args>
......
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