Index: llvm/include/llvm/Support/Error.h =================================================================== --- llvm/include/llvm/Support/Error.h +++ llvm/include/llvm/Support/Error.h @@ -587,6 +587,20 @@ return takeError(); } + /// Returns \a takeError() after emplacing the held T into \p MaybeValue, or + /// resetting it if there is none. + template + Error + emplaceInto(Optional &MaybeValue, + std::enable_if_t::value> * = + nullptr) { + if (*this) + MaybeValue.emplace(std::move(get())); + else + MaybeValue.reset(); + return takeError(); + } + /// Check that this Expected is an error of type ErrT. template bool errorIsA() const { return HasError && (*getErrorStorage())->template isA(); Index: llvm/unittests/Support/ErrorTest.cpp =================================================================== --- llvm/unittests/Support/ErrorTest.cpp +++ llvm/unittests/Support/ErrorTest.cpp @@ -1099,4 +1099,75 @@ } } +struct ConstructOnlyBox { + Optional Box; + + explicit ConstructOnlyBox(int I) : Box(I) {} + ConstructOnlyBox(ConstructOnlyBox &&) = default; + + ConstructOnlyBox() = delete; + ConstructOnlyBox &operator=(ConstructOnlyBox &&) = delete; + + operator MoveOnlyBox() const { + return Box ? MoveOnlyBox(*Box) : MoveOnlyBox(); + } + + bool operator==(const ConstructOnlyBox &RHS) const { + if (bool(Box) != bool(RHS.Box)) + return false; + return Box ? *Box == *RHS.Box : false; + } +}; + +TEST(Error, emplaceInto) { + // Use ConstructOnlyBox as the T in Expected. Extract it into an Optional. + auto make = [](int I) -> Expected { + return ConstructOnlyBox(I); + }; + auto makeFailure = []() -> Expected { + return createAnyError(); + }; + + { + Optional V; + + // Failure with no prior value. + EXPECT_THAT_ERROR(makeFailure().emplaceInto(V), Failed()); + EXPECT_EQ(None, V); + + // Success with no prior value. + EXPECT_THAT_ERROR(make(5).emplaceInto(V), Succeeded()); + EXPECT_EQ(ConstructOnlyBox(5), V); + + // Success with an existing value. + EXPECT_THAT_ERROR(make(7).emplaceInto(V), Succeeded()); + EXPECT_EQ(ConstructOnlyBox(7), V); + + // Failure with an existing value. + EXPECT_THAT_ERROR(makeFailure().emplaceInto(V), Failed()); + EXPECT_EQ(None, V); + } + + // Check that this works with another T. + { + Optional V; + + // Failure with no prior value. + EXPECT_THAT_ERROR(makeFailure().emplaceInto(V), Failed()); + EXPECT_EQ(None, V); + + // Success with no prior value. + EXPECT_THAT_ERROR(make(5).emplaceInto(V), Succeeded()); + EXPECT_EQ(MoveOnlyBox(5), V); + + // Success with an existing value. + EXPECT_THAT_ERROR(make(7).emplaceInto(V), Succeeded()); + EXPECT_EQ(MoveOnlyBox(7), V); + + // Failure with an existing value. + EXPECT_THAT_ERROR(makeFailure().emplaceInto(V), Failed()); + EXPECT_EQ(None, V); + } +} + } // namespace