Author: Felipe de Azevedo Piovezan Date: 2026-03-20T08:08:48Z New Revision: 4df296733da97e368dd81bc0c366ed9781f92fe7
URL: https://github.com/llvm/llvm-project/commit/4df296733da97e368dd81bc0c366ed9781f92fe7 DIFF: https://github.com/llvm/llvm-project/commit/4df296733da97e368dd81bc0c366ed9781f92fe7.diff LOG: [lldb] Implement llvm::formatv overload for Stream::operator << (#187462) This will allow us to more conveniently use llvm::formatv in the codebase. Added: Modified: lldb/include/lldb/Utility/Stream.h lldb/source/Core/UserSettingsController.cpp lldb/source/Interpreter/OptionValueProperties.cpp lldb/source/Target/TraceDumper.cpp lldb/source/Utility/Stream.cpp lldb/unittests/Utility/StreamTest.cpp Removed: ################################################################################ diff --git a/lldb/include/lldb/Utility/Stream.h b/lldb/include/lldb/Utility/Stream.h index 13455552131da..d0b60a4f5fe38 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; @@ -361,8 +371,10 @@ 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) { - 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 _______________________________________________ lldb-commits mailing list [email protected] https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits
