diff --git a/llvm/include/llvm/Support/Error.h b/llvm/include/llvm/Support/Error.h --- a/llvm/include/llvm/Support/Error.h +++ b/llvm/include/llvm/Support/Error.h @@ -366,6 +366,8 @@ friend Error joinErrors(Error, Error); public: + ErrorList() = default; + void log(raw_ostream &OS) const override { OS << "Multiple errors:\n"; for (auto &ErrPayload : Payloads) { @@ -376,6 +378,17 @@ std::error_code convertToErrorCode() const override; + void push_back(Error Other) { + if (Other.isA()) { + auto OtherPayload = Other.takePayload(); + auto &OtherErrorList = static_cast(*OtherPayload); + for (std::unique_ptr &P : OtherErrorList.Payloads) + Payloads.push_back(std::move(P)); + } else { + Payloads.push_back(Other.takePayload()); + } + } + // Used by ErrorInfo::classID. static char ID; diff --git a/llvm/unittests/Support/ErrorTest.cpp b/llvm/unittests/Support/ErrorTest.cpp --- a/llvm/unittests/Support/ErrorTest.cpp +++ b/llvm/unittests/Support/ErrorTest.cpp @@ -17,6 +17,7 @@ #include "gtest/gtest-spi.h" #include "gtest/gtest.h" #include +#include using namespace llvm; @@ -367,6 +368,37 @@ } } +// Test direct usage of ErrorList. +static Error parseInts(std::vector Is, void (*H)(int)) { + ErrorList Errs; + for (const std::string &I : Is) { + int Result; + std::istringstream SStream(I); + SStream >> Result; + + if (SStream.fail()) { + Errs.push_back(make_error("Failed to parse int: " + I, + inconvertibleErrorCode())); + } else if (!SStream.eof()) { + Errs.push_back( + make_error("Failed to parse full string as int: " + I, + inconvertibleErrorCode())); + } else { + H(Result); + } + } + return make_error(std::move(Errs)); +} + +TEST(Error, CheckErrorListIdiomatic) { + unsigned Count = 0; + Error Err = parseInts({"_", "42", "-0", "1a", "+4", "b5"}, [](int N) { + EXPECT_TRUE(N == 42 || N == 0 || N == 4); + }); + handleAllErrors(std::move(Err), [&Count](const StringError &E) { Count++; }); + EXPECT_EQ(Count, 3u); +} + // Test that we can consume success values. TEST(Error, ConsumeSuccess) { Error E = Error::success();