[llvm] [llvm][Support] Create llvm::formatv variant of llvm::createStringError (PR #176407)

Michael Buch via llvm-commits llvm-commits at lists.llvm.org
Fri Jan 16 07:55:58 PST 2026


https://github.com/Michael137 updated https://github.com/llvm/llvm-project/pull/176407

>From 823144669e583f38cfcb66b4c8d04b2ec523dea4 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 16 Jan 2026 15:26:58 +0000
Subject: [PATCH 1/3] [llvm][Support] Create llvm::formatv variant of
 llvm::createStringError

Currently `llvm::createStringError` only supports printf format specifiers because it forwards to `llvm::format`.

In LLDB we've been using `llvm::createStringError(llvm::formatv(...),
...` to work around this. It would be convenient to have a version of
the API that takes LLVM format specifiers, so we benefit from the
advantages that come with those.

This patch adds a new `llvm::createStringErrorV` which forwards to
`llvm::formatv` (hence the `V` suffix in the name). I only implemented
`V` variants for the `llvm::createStringError` APIs that take a format
string argument.

As a side-note, `llvm/lib/Frontend/Offloading/PropertySet.cpp`
implements it's own variant of this function (and also calls it
`createStringErrorV`). This patch would allow us to clean that up as
well.
---
 llvm/include/llvm/Support/Error.h    | 17 +++++++++++++++++
 llvm/unittests/Support/ErrorTest.cpp | 21 +++++++++++++++++++++
 2 files changed, 38 insertions(+)

diff --git a/llvm/include/llvm/Support/Error.h b/llvm/include/llvm/Support/Error.h
index c9fd16fdb7c2b..4e2753272514b 100644
--- a/llvm/include/llvm/Support/Error.h
+++ b/llvm/include/llvm/Support/Error.h
@@ -21,6 +21,7 @@
 #include "llvm/Support/ErrorHandling.h"
 #include "llvm/Support/ErrorOr.h"
 #include "llvm/Support/Format.h"
+#include "llvm/Support/FormatVariadic.h"
 #include "llvm/Support/raw_ostream.h"
 #include <cassert>
 #include <cstdint>
@@ -1335,6 +1336,22 @@ inline Error createStringError(std::errc EC, char const *Fmt,
   return createStringError(std::make_error_code(EC), Fmt, Vals...);
 }
 
+// LLVM formatv versions of llvm::createStringError
+
+template <typename... Ts>
+inline Error createStringErrorV(std::error_code EC, char const *Fmt,
+                                Ts &&...Vals) {
+  std::string Buffer;
+  raw_string_ostream(Buffer) << formatv(Fmt, std::forward<Ts>(Vals)...);
+  return make_error<StringError>(std::move(Buffer), EC, true);
+}
+
+template <typename... Ts>
+inline Error createStringErrorV(char const *Fmt, Ts &&...Vals) {
+  return createStringErrorV(llvm::inconvertibleErrorCode(), Fmt,
+                            std::forward<Ts>(Vals)...);
+}
+
 /// This class wraps a filename and another Error.
 ///
 /// In some cases, an error needs to live along a 'source' name, in order to
diff --git a/llvm/unittests/Support/ErrorTest.cpp b/llvm/unittests/Support/ErrorTest.cpp
index 00c562ecc059d..8454bae666fcb 100644
--- a/llvm/unittests/Support/ErrorTest.cpp
+++ b/llvm/unittests/Support/ErrorTest.cpp
@@ -471,6 +471,27 @@ TEST(Error, createStringError) {
     << "Failed to convert createStringError() result to error_code.";
 }
 
+TEST(Error, createStringErrorV) {
+  static const char *Bar = "bar";
+  static const std::error_code EC = errc::invalid_argument;
+  std::string Msg;
+  raw_string_ostream S(Msg);
+  logAllUnhandledErrors(createStringErrorV(EC, "foo{0}{1}{2:x}", Bar, 1, 0xff),
+                        S);
+  EXPECT_EQ(Msg, "foobar10xff\n")
+      << "Unexpected createStringError() log result";
+
+  Msg.clear();
+  auto Res = errorToErrorCode(createStringError(EC, "foo{0}", Bar));
+  EXPECT_EQ(Res, EC)
+      << "Failed to convert createStringError() result to error_code.";
+
+  Msg.clear();
+  logAllUnhandledErrors(createStringErrorV("foo{0}{1}{2:x}", Bar, 1, 0xff), S);
+  EXPECT_EQ(Msg, "foobar10xff\n")
+      << "Unexpected createStringError() (no EC overload) log result";
+}
+
 // Test that the ExitOnError utility works as expected.
 TEST(ErrorDeathTest, ExitOnError) {
   ExitOnError ExitOnErr;

>From 6d8b45d6c030ccceccd4a78eab7bcdd7566d5a97 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 16 Jan 2026 15:51:54 +0000
Subject: [PATCH 2/3] fixup! don't use intermediate std::string buffer

Co-authored-by: Jakub Kuderski <kubakuderski at gmail.com>
---
 llvm/include/llvm/Support/Error.h | 4 +---
 1 file changed, 1 insertion(+), 3 deletions(-)

diff --git a/llvm/include/llvm/Support/Error.h b/llvm/include/llvm/Support/Error.h
index 4e2753272514b..828d1075c99f2 100644
--- a/llvm/include/llvm/Support/Error.h
+++ b/llvm/include/llvm/Support/Error.h
@@ -1341,9 +1341,7 @@ inline Error createStringError(std::errc EC, char const *Fmt,
 template <typename... Ts>
 inline Error createStringErrorV(std::error_code EC, char const *Fmt,
                                 Ts &&...Vals) {
-  std::string Buffer;
-  raw_string_ostream(Buffer) << formatv(Fmt, std::forward<Ts>(Vals)...);
-  return make_error<StringError>(std::move(Buffer), EC, true);
+  return make_error<StringError>(formatv(Fmt, std::forward<Ts>(Vals)...).str(), EC, true);
 }
 
 template <typename... Ts>

>From 07e384291719af6ddd80654e2491762c636d09d5 Mon Sep 17 00:00:00 2001
From: Michael Buch <michaelbuch12 at gmail.com>
Date: Fri, 16 Jan 2026 15:55:45 +0000
Subject: [PATCH 3/3] fixup! clang-format

---
 llvm/include/llvm/Support/Error.h | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/llvm/include/llvm/Support/Error.h b/llvm/include/llvm/Support/Error.h
index 828d1075c99f2..6638c919e2965 100644
--- a/llvm/include/llvm/Support/Error.h
+++ b/llvm/include/llvm/Support/Error.h
@@ -1341,7 +1341,8 @@ inline Error createStringError(std::errc EC, char const *Fmt,
 template <typename... Ts>
 inline Error createStringErrorV(std::error_code EC, char const *Fmt,
                                 Ts &&...Vals) {
-  return make_error<StringError>(formatv(Fmt, std::forward<Ts>(Vals)...).str(), EC, true);
+  return make_error<StringError>(formatv(Fmt, std::forward<Ts>(Vals)...).str(),
+                                 EC, true);
 }
 
 template <typename... Ts>



More information about the llvm-commits mailing list