[Lldb-commits] [lldb] [lldb] Implement llvm::formatv overload for Stream::operator << (PR #187462)
Felipe de Azevedo Piovezan via lldb-commits
lldb-commits at lists.llvm.org
Thu Mar 19 02:41:19 PDT 2026
https://github.com/felipepiovezan updated https://github.com/llvm/llvm-project/pull/187462
>From c895be71a44e1268868b610ba5cd5a9b90a7f8d1 Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 19 Mar 2026 08:35:27 +0000
Subject: [PATCH 1/2] [lldb] Implement llvm::formatv overload for
Stream::operator <<
This will allow us to more conveniently use llvm::formatv in the
codebase.
---
lldb/include/lldb/Utility/Stream.h | 12 +++++++++++-
lldb/source/Core/UserSettingsController.cpp | 2 +-
lldb/source/Interpreter/OptionValueProperties.cpp | 8 +++-----
lldb/source/Target/TraceDumper.cpp | 7 ++++---
lldb/source/Utility/Stream.cpp | 6 ++++++
lldb/unittests/Utility/StreamTest.cpp | 9 +++++++++
6 files changed, 34 insertions(+), 10 deletions(-)
diff --git a/lldb/include/lldb/Utility/Stream.h b/lldb/include/lldb/Utility/Stream.h
index 13455552131da..fc8d1775904ab 100644
--- a/lldb/include/lldb/Utility/Stream.h
+++ b/lldb/include/lldb/Utility/Stream.h
@@ -225,6 +225,16 @@ class Stream {
/// 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;
@@ -362,7 +372,7 @@ class Stream {
size_t PrintfVarArg(const char *format, va_list args);
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.
diff --git a/lldb/source/Core/UserSettingsController.cpp b/lldb/source/Core/UserSettingsController.cpp
index 5408d64b40647..206b2072ddaf2 100644
--- a/lldb/source/Core/UserSettingsController.cpp
+++ b/lldb/source/Core/UserSettingsController.cpp
@@ -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);
}
diff --git a/lldb/source/Interpreter/OptionValueProperties.cpp b/lldb/source/Interpreter/OptionValueProperties.cpp
index 521de3ddd5389..def6cc462f76a 100644
--- a/lldb/source/Interpreter/OptionValueProperties.cpp
+++ b/lldb/source/Interpreter/OptionValueProperties.cpp
@@ -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;
diff --git a/lldb/source/Target/TraceDumper.cpp b/lldb/source/Target/TraceDumper.cpp
index fa732fa87c529..5e87deb2ac9c1 100644
--- a/lldb/source/Target/TraceDumper.cpp
+++ b/lldb/source/Target/TraceDumper.cpp
@@ -156,9 +156,10 @@ class OutputWriterCLI : public TraceDumper::OutputWriter {
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) {
diff --git a/lldb/source/Utility/Stream.cpp b/lldb/source/Utility/Stream.cpp
index e9632c3e1fc1f..fbe7bdb6dd27c 100644
--- a/lldb/source/Utility/Stream.cpp
+++ b/lldb/source/Utility/Stream.cpp
@@ -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; }
diff --git a/lldb/unittests/Utility/StreamTest.cpp b/lldb/unittests/Utility/StreamTest.cpp
index c63dfda6947f3..7fb8bfd0ef3dd 100644
--- a/lldb/unittests/Utility/StreamTest.cpp
+++ b/lldb/unittests/Utility/StreamTest.cpp
@@ -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
>From 495b3d7b258eeefd0287d777446472dea9abc3dc Mon Sep 17 00:00:00 2001
From: Felipe de Azevedo Piovezan <fpiovezan at apple.com>
Date: Thu, 19 Mar 2026 09:41:05 +0000
Subject: [PATCH 2/2] fixup! add fixme comment
---
lldb/include/lldb/Utility/Stream.h | 2 ++
1 file changed, 2 insertions(+)
diff --git a/lldb/include/lldb/Utility/Stream.h b/lldb/include/lldb/Utility/Stream.h
index fc8d1775904ab..d0b60a4f5fe38 100644
--- a/lldb/include/lldb/Utility/Stream.h
+++ b/lldb/include/lldb/Utility/Stream.h
@@ -371,6 +371,8 @@ class Stream {
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) {
*this << llvm::formatv(format, std::forward<Args>(args)...);
}
More information about the lldb-commits
mailing list