[llvm] 4bb0ca6 - [Support] Introduce formatv variant of createStringError (#80493)

via llvm-commits llvm-commits at lists.llvm.org
Fri Feb 16 16:26:18 PST 2024


Author: Alex Langford
Date: 2024-02-16T16:26:14-08:00
New Revision: 4bb0ca655bb65aae0a1d251ba5053aadff678101

URL: https://github.com/llvm/llvm-project/commit/4bb0ca655bb65aae0a1d251ba5053aadff678101
DIFF: https://github.com/llvm/llvm-project/commit/4bb0ca655bb65aae0a1d251ba5053aadff678101.diff

LOG: [Support] Introduce formatv variant of createStringError (#80493)

Many times I have found myself wanting to create a StringError with the
ability to interpolate a StringRef into the error string. This can be
achieved with:

StringRef Foo("...");
auto Err = createStringError(..., "Something went wrong: %s",
Foo.str().c_str());

However, this requires us to construct a temporary std::string (which
may perform a memory allocation if large enough).

I propose a new variant of `createStringError` called
`createStringErrorV` which uses `formatv` under the hood. This allows
the above example to become:

StringRef Foo("...");
auto Err = createStringErrorV(..., "Something went wrong: {0}", Foo);

Added: 
    

Modified: 
    llvm/include/llvm/Support/Error.h
    llvm/unittests/Support/ErrorTest.cpp

Removed: 
    


################################################################################
diff  --git a/llvm/include/llvm/Support/Error.h b/llvm/include/llvm/Support/Error.h
index bb4f38f7ec355e..ddc1afb9623097 100644
--- a/llvm/include/llvm/Support/Error.h
+++ b/llvm/include/llvm/Support/Error.h
@@ -22,6 +22,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>
@@ -1261,6 +1262,15 @@ inline Error createStringError(std::errc EC, char const *Fmt,
   return createStringError(std::make_error_code(EC), Fmt, Vals...);
 }
 
+template <typename... Ts>
+inline Error createStringErrorV(std::error_code EC, const char *Fmt,
+                                const Ts &...Vals) {
+  std::string Buffer;
+  raw_string_ostream Stream(Buffer);
+  Stream << formatv(Fmt, Vals...);
+  return make_error<StringError>(Stream.str(), EC);
+}
+
 /// 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 11f93203597bf0..a700a50e1d4337 100644
--- a/llvm/unittests/Support/ErrorTest.cpp
+++ b/llvm/unittests/Support/ErrorTest.cpp
@@ -472,6 +472,23 @@ TEST(Error, createStringError) {
     << "Failed to convert createStringError() result to error_code.";
 }
 
+TEST(Error, createStringErrorV) {
+  static llvm::StringRef 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(S.str(), "foobar10xff\n")
+      << "Unexpected createStringErrorV() log result";
+
+  S.flush();
+  Msg.clear();
+  auto Res = errorToErrorCode(createStringErrorV(EC, "foo{0}", Bar));
+  EXPECT_EQ(Res, EC)
+      << "Failed to convert createStringErrorV() result to error_code.";
+}
+
 // Test that the ExitOnError utility works as expected.
 TEST(ErrorDeathTest, ExitOnError) {
   ExitOnError ExitOnErr;


        


More information about the llvm-commits mailing list