[lldb] Implement llvm::formatv overload for Stream::operator << (#187462)

This will allow us to more conveniently use llvm::formatv in the
codebase.
This commit is contained in:
Felipe de Azevedo Piovezan 2026-03-20 08:08:48 +00:00 committed by GitHub
parent facc82de4f
commit 4df296733d
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
6 changed files with 36 additions and 10 deletions

View File

@ -225,6 +225,16 @@ public:
/// in one statement.
Stream &operator<<(char ch);
/// Output the result of a formatv expression to the stream.
///
/// \param[in] obj
/// A formatv_object_base produced by llvm::formatv().
///
/// \return
/// A reference to this class so multiple things can be streamed
/// in one statement.
Stream &operator<<(const llvm::formatv_object_base &obj);
Stream &operator<<(uint8_t uval) = delete;
Stream &operator<<(uint16_t uval) = delete;
Stream &operator<<(uint32_t uval) = delete;
@ -361,8 +371,10 @@ public:
size_t PrintfVarArg(const char *format, va_list args);
/// Forwards the arguments to llvm::formatv and writes to the stream.
/// FIXME: instead of this API, consider using llvm::formatv directly.
template <typename... Args> void Format(const char *format, Args &&... args) {
PutCString(llvm::formatv(format, std::forward<Args>(args)...).str());
*this << llvm::formatv(format, std::forward<Args>(args)...);
}
/// Output a quoted C string value to the stream.

View File

@ -55,7 +55,7 @@ void Properties::DumpAllPropertyValues(const ExecutionContext *exe_ctx,
bool is_json) {
if (is_json) {
llvm::json::Value json = m_collection_sp->ToJSON(exe_ctx);
strm.Printf("%s", llvm::formatv("{0:2}", json).str().c_str());
strm << llvm::formatv("{0:2}", json);
} else
m_collection_sp->DumpValue(exe_ctx, strm, dump_mask);
}

View File

@ -380,11 +380,9 @@ Status OptionValueProperties::DumpPropertyValue(const ExecutionContext *exe_ctx,
if (dump_mask & ~eDumpOptionName)
strm.PutChar(' ');
}
if (is_json) {
strm.Printf(
"%s",
llvm::formatv("{0:2}", value_sp->ToJSON(exe_ctx)).str().c_str());
} else
if (is_json)
strm << llvm::formatv("{0:2}", value_sp->ToJSON(exe_ctx));
else
value_sp->DumpValue(exe_ctx, strm, dump_mask);
}
return error;

View File

@ -156,9 +156,10 @@ public:
m_s.Format(" {0}: ", item.id);
if (m_options.show_timestamps) {
m_s.Format("[{0}] ", item.timestamp
? formatv("{0:3} ns", *item.timestamp).str()
: "unavailable");
if (item.timestamp)
m_s << formatv("[{0:3} ns]", *item.timestamp);
else
m_s << "[unavailable]";
}
if (item.event) {

View File

@ -183,6 +183,12 @@ Stream &Stream::operator<<(const void *p) {
return *this;
}
// Stream the result of a formatv expression to this stream.
Stream &Stream::operator<<(const llvm::formatv_object_base &obj) {
obj.format(m_forwarder);
return *this;
}
// Get the current indentation level
unsigned Stream::GetIndentLevel() const { return m_indent_level; }

View File

@ -7,6 +7,7 @@
//===----------------------------------------------------------------------===//
#include "lldb/Utility/StreamString.h"
#include "llvm/Support/FormatVariadic.h"
#include "gtest/gtest.h"
using namespace lldb_private;
@ -416,6 +417,14 @@ TEST_F(StreamTest, ShiftOperatorStrings) {
EXPECT_EQ("cstring\nllvm::StringRef\n", TakeValue());
}
TEST_F(StreamTest, ShiftOperatorFormatv) {
s << llvm::formatv("x{0}y", 42);
EXPECT_EQ("x42y", TakeValue());
s << llvm::formatv("{0} {1}", "hello", "world") << '!';
EXPECT_EQ("hello world!", TakeValue());
}
TEST_F(StreamTest, ShiftOperatorPtr) {
// This test is a bit tricky because pretty much everything related to
// pointer printing seems to lead to UB or IB. So let's make the most basic