aboutsummaryrefslogtreecommitdiff
path: root/llvm/unittests/Support/ErrorTest.cpp
diff options
context:
space:
mode:
authorLang Hames <lhames@gmail.com>2017-02-27 21:09:47 +0000
committerLang Hames <lhames@gmail.com>2017-02-27 21:09:47 +0000
commitfd4de9108e1c852633bc2ca74c8d16bf8edec9c4 (patch)
tree53eab8abc0c1acbcf4cad239d238fcd792dac399 /llvm/unittests/Support/ErrorTest.cpp
parent9a651672d03132442d2159b2128631b5a5fe6e70 (diff)
downloadllvm-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.cpp28
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;