Skip to content

Commit 4bb0ca6

Browse files
authored
[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);
1 parent 3d67cf6 commit 4bb0ca6

File tree

2 files changed

+27
-0
lines changed

2 files changed

+27
-0
lines changed

llvm/include/llvm/Support/Error.h

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include "llvm/Support/ErrorHandling.h"
2323
#include "llvm/Support/ErrorOr.h"
2424
#include "llvm/Support/Format.h"
25+
#include "llvm/Support/FormatVariadic.h"
2526
#include "llvm/Support/raw_ostream.h"
2627
#include <cassert>
2728
#include <cstdint>
@@ -1261,6 +1262,15 @@ inline Error createStringError(std::errc EC, char const *Fmt,
12611262
return createStringError(std::make_error_code(EC), Fmt, Vals...);
12621263
}
12631264

1265+
template <typename... Ts>
1266+
inline Error createStringErrorV(std::error_code EC, const char *Fmt,
1267+
const Ts &...Vals) {
1268+
std::string Buffer;
1269+
raw_string_ostream Stream(Buffer);
1270+
Stream << formatv(Fmt, Vals...);
1271+
return make_error<StringError>(Stream.str(), EC);
1272+
}
1273+
12641274
/// This class wraps a filename and another Error.
12651275
///
12661276
/// In some cases, an error needs to live along a 'source' name, in order to

llvm/unittests/Support/ErrorTest.cpp

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -472,6 +472,23 @@ TEST(Error, createStringError) {
472472
<< "Failed to convert createStringError() result to error_code.";
473473
}
474474

475+
TEST(Error, createStringErrorV) {
476+
static llvm::StringRef Bar("bar");
477+
static const std::error_code EC = errc::invalid_argument;
478+
std::string Msg;
479+
raw_string_ostream S(Msg);
480+
logAllUnhandledErrors(createStringErrorV(EC, "foo{0}{1}{2:x}", Bar, 1, 0xff),
481+
S);
482+
EXPECT_EQ(S.str(), "foobar10xff\n")
483+
<< "Unexpected createStringErrorV() log result";
484+
485+
S.flush();
486+
Msg.clear();
487+
auto Res = errorToErrorCode(createStringErrorV(EC, "foo{0}", Bar));
488+
EXPECT_EQ(Res, EC)
489+
<< "Failed to convert createStringErrorV() result to error_code.";
490+
}
491+
475492
// Test that the ExitOnError utility works as expected.
476493
TEST(ErrorDeathTest, ExitOnError) {
477494
ExitOnError ExitOnErr;

0 commit comments

Comments
 (0)