From: Nick Lewycky Date: Tue, 9 Feb 2016 04:47:58 +0000 (+0000) Subject: Use std::forward to make ErrorOr constructible from a value that has a user-define... X-Git-Tag: llvmorg-3.9.0-rc1~14760 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e5fa25a094f040353891a953d0b35a89d75e5cb8;p=platform%2Fupstream%2Fllvm.git Use std::forward to make ErrorOr constructible from a value that has a user-defined conversion to T. No functionality change intended. llvm-svn: 260196 --- diff --git a/llvm/include/llvm/Support/ErrorOr.h b/llvm/include/llvm/Support/ErrorOr.h index 7fe1d5a..877f406 100644 --- a/llvm/include/llvm/Support/ErrorOr.h +++ b/llvm/include/llvm/Support/ErrorOr.h @@ -23,20 +23,6 @@ #include namespace llvm { -template -typename std::enable_if< std::is_constructible::value - , typename std::remove_reference::type>::type && - moveIfMoveConstructible(V &Val) { - return std::move(Val); -} - -template -typename std::enable_if< !std::is_constructible::value - , typename std::remove_reference::type>::type & -moveIfMoveConstructible(V &Val) { - return Val; -} - /// \brief Stores a reference that can be changed. template class ReferenceStorage { @@ -107,8 +93,12 @@ public: new (getErrorStorage()) std::error_code(EC); } - ErrorOr(T Val) : HasError(false) { - new (getStorage()) storage_type(moveIfMoveConstructible(Val)); + template + ErrorOr(OtherT &&Val, + typename std::enable_if::value>::type + * = nullptr) + : HasError(false) { + new (getStorage()) storage_type(std::forward(Val)); } ErrorOr(const ErrorOr &Other) { diff --git a/llvm/unittests/Support/ErrorOrTest.cpp b/llvm/unittests/Support/ErrorOrTest.cpp index 73d0e3f..87dcab7 100644 --- a/llvm/unittests/Support/ErrorOrTest.cpp +++ b/llvm/unittests/Support/ErrorOrTest.cpp @@ -16,7 +16,7 @@ using namespace llvm; namespace { -ErrorOr t1() {return 1;} +ErrorOr t1() { return 1; } ErrorOr t2() { return errc::invalid_argument; } TEST(ErrorOr, SimpleValue) { @@ -71,6 +71,46 @@ TEST(ErrorOr, Comparison) { EXPECT_EQ(x, errc::no_such_file_or_directory); } +TEST(ErrorOr, ImplicitConversion) { + ErrorOr x("string literal"); + EXPECT_TRUE(!!x); +} + +TEST(ErrorOr, ImplicitConversionCausesMove) { + struct Source {}; + struct Destination { + Destination(const Source&) {} + Destination(Source&&) = delete; + }; + Source s; + ErrorOr x = s; + EXPECT_TRUE(!!x); +} + +TEST(ErrorOr, ImplicitConversionNoAmbiguity) { + struct CastsToErrorCode { + CastsToErrorCode() = default; + CastsToErrorCode(std::error_code) {} + operator std::error_code() { return errc::invalid_argument; } + } casts_to_error_code; + ErrorOr x1(casts_to_error_code); + ErrorOr x2 = casts_to_error_code; + ErrorOr x3 = {casts_to_error_code}; + ErrorOr x4{casts_to_error_code}; + ErrorOr x5(errc::no_such_file_or_directory); + ErrorOr x6 = errc::no_such_file_or_directory; + ErrorOr x7 = {errc::no_such_file_or_directory}; + ErrorOr x8{errc::no_such_file_or_directory}; + EXPECT_TRUE(!!x1); + EXPECT_TRUE(!!x2); + EXPECT_TRUE(!!x3); + EXPECT_TRUE(!!x4); + EXPECT_FALSE(x5); + EXPECT_FALSE(x6); + EXPECT_FALSE(x7); + EXPECT_FALSE(x8); +} + // ErrorOr x(nullptr); // ErrorOr> y = x; // invalid conversion static_assert(