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

Reply via email to