[llvm] [Support] Add WrappedError class (PR #191706)
via llvm-commits
llvm-commits at lists.llvm.org
Thu Apr 16 06:59:01 PDT 2026
https://github.com/aokblast updated https://github.com/llvm/llvm-project/pull/191706
>From 8a9d0f98a88e398947a6181f93a3017256d10999 Mon Sep 17 00:00:00 2001
From: ShengYi Hung <aokblast at FreeBSD.org>
Date: Sun, 12 Apr 2026 20:13:20 +0800
Subject: [PATCH] [Support] Add WrappedError class
The error consumer filters duplicate errors based on a portion of the
error message. Introduce a new Error kind that carries a prefix string
to support this use case.
---
llvm/include/llvm/Support/Error.h | 47 ++++++++++++++++++++++++++++
llvm/lib/Support/Error.cpp | 6 ++++
llvm/unittests/Support/ErrorTest.cpp | 29 +++++++++++++++++
3 files changed, 82 insertions(+)
diff --git a/llvm/include/llvm/Support/Error.h b/llvm/include/llvm/Support/Error.h
index c9fd16fdb7c2b..8e414428c8286 100644
--- a/llvm/include/llvm/Support/Error.h
+++ b/llvm/include/llvm/Support/Error.h
@@ -1497,6 +1497,53 @@ inline Error unwrap(LLVMErrorRef ErrRef) {
reinterpret_cast<ErrorInfoBase *>(ErrRef)));
}
+class LLVM_ABI ContextualizedError : public ErrorInfo<ContextualizedError> {
+public:
+ ContextualizedError(std::unique_ptr<ErrorInfoBase> E,
+ const Twine &Prefix = "")
+ : Err(std::move(E)), Context(Prefix.str()) {}
+
+ void log(raw_ostream &OS) const override {
+ assert(Err && "Trying to log after takeError().");
+ if (Context.size())
+ OS << Context << ": ";
+ Err->log(OS);
+ }
+
+ Error takeError() { return Error(std::move(Err)); }
+
+ const std::string &getContext() const { return Context; }
+
+ std::string getMessageWithoutContext() const {
+ std::string Msg;
+ raw_string_ostream OS(Msg);
+ Err->log(OS);
+ return Msg;
+ }
+
+ std::error_code convertToErrorCode() const override;
+
+ static Error build(Error E, const Twine &Prefix) {
+ std::unique_ptr<ErrorInfoBase> Payload;
+ handleAllErrors(std::move(E),
+ [&](std::unique_ptr<ErrorInfoBase> EIB) -> Error {
+ Payload = std::move(EIB);
+ return Error::success();
+ });
+ return Error(std::unique_ptr<ContextualizedError>(
+ new ContextualizedError(std::move(Payload), Prefix)));
+ }
+
+ static char ID;
+
+private:
+ std::unique_ptr<ErrorInfoBase> Err;
+ std::string Context;
+};
+
+inline Error createContextualizedError(Error E, const Twine &Prefix = "") {
+ return ContextualizedError::build(std::move(E), Prefix);
+}
} // end namespace llvm
#endif // LLVM_SUPPORT_ERROR_H
diff --git a/llvm/lib/Support/Error.cpp b/llvm/lib/Support/Error.cpp
index c6743155ced85..aabb701b9b999 100644
--- a/llvm/lib/Support/Error.cpp
+++ b/llvm/lib/Support/Error.cpp
@@ -205,3 +205,9 @@ LLVMErrorTypeId LLVMGetStringErrorTypeId() {
LLVMErrorRef LLVMCreateStringError(const char *ErrMsg) {
return wrap(make_error<StringError>(ErrMsg, inconvertibleErrorCode()));
}
+
+char ContextualizedError::ID = 0;
+
+std::error_code ContextualizedError::convertToErrorCode() const {
+ return Err->convertToErrorCode();
+}
diff --git a/llvm/unittests/Support/ErrorTest.cpp b/llvm/unittests/Support/ErrorTest.cpp
index 45c0a4f450b51..4ce269d6b71b0 100644
--- a/llvm/unittests/Support/ErrorTest.cpp
+++ b/llvm/unittests/Support/ErrorTest.cpp
@@ -18,6 +18,8 @@
#include "gtest/gtest-spi.h"
#include "gtest/gtest.h"
#include <memory>
+#include <string>
+#include <unordered_set>
using namespace llvm;
@@ -1219,4 +1221,31 @@ TEST(Error, ForwardToExpected) {
EXPECT_THAT_ERROR(ExpectedReturningFct(false).moveInto(MaybeV), Succeeded());
EXPECT_EQ(*MaybeV, 42);
}
+
+TEST(Error, DeduplicateByContextualized) {
+ std::unordered_set<std::string> Visit;
+
+ auto InsertError = [&](Error E) {
+ std::string InnerErrorStr;
+ EXPECT_THAT_ERROR(handleErrors(std::move(E),
+ [&](const ContextualizedError &E) {
+ InnerErrorStr =
+ E.getMessageWithoutContext();
+ }),
+ Succeeded());
+ return Visit.insert(InnerErrorStr).second;
+ };
+ EXPECT_EQ(
+ InsertError(createContextualizedError(
+ createStringError("failed to execute operation A"), "Context A")),
+ true);
+ EXPECT_EQ(
+ InsertError(createContextualizedError(
+ createStringError("failed to execute operation B"), "Context A")),
+ true);
+ EXPECT_EQ(
+ InsertError(createContextualizedError(
+ createStringError("failed to execute operation A"), "Context B")),
+ false);
+}
} // namespace
More information about the llvm-commits
mailing list