[llvm-commits] [llvm] r173209 - in /llvm/trunk: include/llvm/Support/ErrorOr.h unittests/Support/ErrorOrTest.cpp
Michael J. Spencer
bigcheesegs at gmail.com
Tue Jan 22 16:18:31 PST 2013
Author: mspencer
Date: Tue Jan 22 18:18:31 2013
New Revision: 173209
URL: http://llvm.org/viewvc/llvm-project?rev=173209&view=rev
Log:
[Support][ErrorOr] Add optimized specialization of ErrorOr<void>.
ErrorOr<void> represents an operation that returns nothing, but can still fail.
It should be used in cases where you need the aditional user data that ErrorOr
provides over error_code.
Modified:
llvm/trunk/include/llvm/Support/ErrorOr.h
llvm/trunk/unittests/Support/ErrorOrTest.cpp
Modified: llvm/trunk/include/llvm/Support/ErrorOr.h
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/include/llvm/Support/ErrorOr.h?rev=173209&r1=173208&r2=173209&view=diff
==============================================================================
--- llvm/trunk/include/llvm/Support/ErrorOr.h (original)
+++ llvm/trunk/include/llvm/Support/ErrorOr.h Tue Jan 22 18:18:31 2013
@@ -16,6 +16,7 @@
#ifndef LLVM_SUPPORT_ERROR_OR_H
#define LLVM_SUPPORT_ERROR_OR_H
+#include "llvm/ADT/PointerIntPair.h"
#include "llvm/Support/AlignOf.h"
#include "llvm/Support/system_error.h"
#include "llvm/Support/type_traits.h"
@@ -257,6 +258,7 @@
return *this;
}
+#endif
~ErrorOr() {
if (!IsValid)
@@ -266,7 +268,6 @@
else
get()->~storage_type();
}
-#endif
template<class ET>
ET getError() const {
@@ -331,6 +332,102 @@
bool IsValid : 1;
};
+// ErrorOr specialization for void.
+template <>
+class ErrorOr<void> {
+public:
+ ErrorOr() : Error(nullptr, 0) {}
+
+ ErrorOr(llvm::error_code EC) : Error(nullptr, 0) {
+ if (EC == errc::success) {
+ Error.setInt(1);
+ return;
+ }
+ ErrorHolderBase *E = new ErrorHolderBase;
+ E->Error = EC;
+ E->HasUserData = false;
+ Error.setPointer(E);
+ }
+
+ template<class UserDataT>
+ ErrorOr(UserDataT UD, typename
+ enable_if_c<ErrorOrUserDataTraits<UserDataT>::value>::type* = 0)
+ : Error(nullptr, 0) {
+ ErrorHolderBase *E = new ErrorHolder<UserDataT>(llvm_move(UD));
+ E->Error = ErrorOrUserDataTraits<UserDataT>::error();
+ E->HasUserData = true;
+ Error.setPointer(E);
+ }
+
+ ErrorOr(const ErrorOr &Other) : Error(nullptr, 0) {
+ Error = Other.Error;
+ if (Other.Error.getPointer()->Error) {
+ Error.getPointer()->aquire();
+ }
+ }
+
+ ErrorOr &operator =(const ErrorOr &Other) {
+ if (this == &Other)
+ return *this;
+
+ this->~ErrorOr();
+ new (this) ErrorOr(Other);
+
+ return *this;
+ }
+
+#if LLVM_HAS_RVALUE_REFERENCES
+ ErrorOr(ErrorOr &&Other) : Error(nullptr) {
+ // Get other's error.
+ Error = Other.Error;
+ // Tell other not to do any destruction.
+ Other.Error.setPointer(nullptr);
+ }
+
+ ErrorOr &operator =(ErrorOr &&Other) {
+ if (this == &Other)
+ return *this;
+
+ this->~ErrorOr();
+ new (this) ErrorOr(std::move(Other));
+
+ return *this;
+ }
+#endif
+
+ ~ErrorOr() {
+ if (Error.getPointer())
+ Error.getPointer()->release();
+ }
+
+ template<class ET>
+ ET getError() const {
+ assert(ErrorOrUserDataTraits<ET>::error() == *this &&
+ "Incorrect user error data type for error!");
+ if (!Error.getPointer()->HasUserData)
+ return ET();
+ return reinterpret_cast<const ErrorHolder<ET> *>(
+ Error.getPointer())->UserData;
+ }
+
+ typedef void (*unspecified_bool_type)();
+ static void unspecified_bool_true() {}
+
+ /// \brief Return false if there is an error.
+ operator unspecified_bool_type() const {
+ return Error.getInt() ? unspecified_bool_true : 0;
+ }
+
+ operator llvm::error_code() const {
+ return Error.getInt() ? make_error_code(errc::success)
+ : Error.getPointer()->Error;
+ }
+
+private:
+ // If the bit is 1, the error is success.
+ llvm::PointerIntPair<ErrorHolderBase *, 1> Error;
+};
+
template<class T, class E>
typename enable_if_c<is_error_code_enum<E>::value ||
is_error_condition_enum<E>::value, bool>::type
Modified: llvm/trunk/unittests/Support/ErrorOrTest.cpp
URL: http://llvm.org/viewvc/llvm-project/llvm/trunk/unittests/Support/ErrorOrTest.cpp?rev=173209&r1=173208&r2=173209&view=diff
==============================================================================
--- llvm/trunk/unittests/Support/ErrorOrTest.cpp (original)
+++ llvm/trunk/unittests/Support/ErrorOrTest.cpp Tue Jan 22 18:18:31 2013
@@ -45,6 +45,9 @@
*a = 42;
EXPECT_EQ(42, x);
+ EXPECT_FALSE(ErrorOr<void>(make_error_code(errc::broken_pipe)));
+ EXPECT_TRUE(ErrorOr<void>(make_error_code(errc::success)));
+
#if LLVM_HAS_CXX11_STDLIB
// Move only types.
EXPECT_EQ(3, **t3());
@@ -71,10 +74,18 @@
return InvalidArgError("adena");
}
+ErrorOr<void> t5() {
+ return InvalidArgError("pie");
+}
+
namespace {
TEST(ErrorOr, UserErrorData) {
ErrorOr<int> a = t4();
EXPECT_EQ(errc::invalid_argument, a);
EXPECT_EQ("adena", t4().getError<InvalidArgError>().ArgName);
+
+ ErrorOr<void> b = t5();
+ EXPECT_EQ(errc::invalid_argument, b);
+ EXPECT_EQ("pie", b.getError<InvalidArgError>().ArgName);
}
} // end anon namespace
More information about the llvm-commits
mailing list