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