diff options
author | Lang Hames <lhames@gmail.com> | 2017-02-27 21:09:47 +0000 |
---|---|---|
committer | Lang Hames <lhames@gmail.com> | 2017-02-27 21:09:47 +0000 |
commit | fd4de9108e1c852633bc2ca74c8d16bf8edec9c4 (patch) | |
tree | 53eab8abc0c1acbcf4cad239d238fcd792dac399 /llvm/unittests/Support/ErrorTest.cpp | |
parent | 9a651672d03132442d2159b2128631b5a5fe6e70 (diff) | |
download | llvm-fd4de9108e1c852633bc2ca74c8d16bf8edec9c4.zip llvm-fd4de9108e1c852633bc2ca74c8d16bf8edec9c4.tar.gz llvm-fd4de9108e1c852633bc2ca74c8d16bf8edec9c4.tar.bz2 |
[Support][Error] Add a 'cantFail' utility function for known-safe calls to
fallible functions.
Some fallible functions (those returning Error or Expected<T>) may only fail
for a subset of their inputs. For example, a "safe" square root function will
succeed for all finite positive inputs:
Expected<double> safeSqrt(double d) {
if (d < 0 && !isnan(d) && !isinf(d))
return make_error<...>("Cannot sqrt -ve values, nans or infs");
return sqrt(d);
}
At a safe callsite for such a function, checking the error return value is
redundant:
if (auto ValOrErr = safeSqrt(42.0)) {
// use *ValOrErr.
} else
llvm_unreachable("safeSqrt should always succeed for +ve values");
The cantFail function wraps this check and extracts the contained value,
simplifying control flow:
double Result = cantFail(safeSqrt(42.0));
This function should be used with care: it is a programmatic error to wrap a
call with cantFail if it can in fact fail. For debug builds this will
result in llvm_unreachable being called. For release builds the behavior is
undefined.
Use of this function is likely to be rare in library code, but more common
for tool and unit-test code where inputs and mock functions may be known to be
safe.
llvm-svn: 296384
Diffstat (limited to 'llvm/unittests/Support/ErrorTest.cpp')
-rw-r--r-- | llvm/unittests/Support/ErrorTest.cpp | 28 |
1 files changed, 28 insertions, 0 deletions
diff --git a/llvm/unittests/Support/ErrorTest.cpp b/llvm/unittests/Support/ErrorTest.cpp index 29a173a..382346c 100644 --- a/llvm/unittests/Support/ErrorTest.cpp +++ b/llvm/unittests/Support/ErrorTest.cpp @@ -469,6 +469,34 @@ TEST(Error, ExitOnError) { << "exitOnError returned an unexpected error result"; } +// Test that the ExitOnError utility works as expected. +TEST(Error, CantFailSuccess) { + cantFail(Error::success()); + + int X = cantFail(Expected<int>(42)); + EXPECT_EQ(X, 42) << "Expected value modified by cantFail"; +} + +// Test that cantFail results in a crash if you pass it a failure value. +#if LLVM_ENABLE_ABI_BREAKING_CHECKS +TEST(Error, CantFailDeath) { + EXPECT_DEATH( + cantFail(make_error<StringError>("foo", inconvertibleErrorCode())), + "Failure value returned from cantFail wrapped call") + << "cantFail(Error) did not cause an abort for failure value"; + + EXPECT_DEATH( + { + auto IEC = inconvertibleErrorCode(); + int X = cantFail(Expected<int>(make_error<StringError>("foo", IEC))); + (void)X; + }, + "Failure value returned from cantFail wrapped call") + << "cantFail(Expected<int>) did not cause an abort for failure value"; +} +#endif + + // Test Checked Expected<T> in success mode. TEST(Error, CheckedExpectedInSuccessMode) { Expected<int> A = 7; |