https://github.com/DavidSpickett created 
https://github.com/llvm/llvm-project/pull/209468

Expected<string> is equivalent to bool+stream, but harder to misuse.

>From aaf1498fd49ed7b06ced48442032fdfac75fdd3c Mon Sep 17 00:00:00 2001
From: David Spickett <[email protected]>
Date: Mon, 29 Jun 2026 12:53:54 +0000
Subject: [PATCH] [lldb] Return llvm::Expected from ListChannelCategories

Expected<string> is equivalent to bool+stream, but harder
to misuse.
---
 lldb/include/lldb/Utility/Log.h           |  4 ++--
 lldb/source/Commands/CommandObjectLog.cpp | 11 ++++++++---
 lldb/source/Utility/Log.cpp               | 17 +++++++++--------
 lldb/unittests/Utility/LogTest.cpp        | 21 +++++++--------------
 4 files changed, 26 insertions(+), 27 deletions(-)

diff --git a/lldb/include/lldb/Utility/Log.h b/lldb/include/lldb/Utility/Log.h
index 636584dac3cce..1cd3e23381ff3 100644
--- a/lldb/include/lldb/Utility/Log.h
+++ b/lldb/include/lldb/Utility/Log.h
@@ -210,8 +210,8 @@ class Log final {
                              llvm::raw_ostream &output_stream,
                              llvm::raw_ostream &error_stream);
 
-  static bool ListChannelCategories(llvm::StringRef channel,
-                                    llvm::raw_ostream &stream);
+  static llvm::Expected<std::string>
+  ListChannelCategories(llvm::StringRef channel);
 
   /// Returns the list of log channels.
   static std::vector<llvm::StringRef> ListChannels();
diff --git a/lldb/source/Commands/CommandObjectLog.cpp 
b/lldb/source/Commands/CommandObjectLog.cpp
index 07abbbc919c7d..b2743611d3525 100644
--- a/lldb/source/Commands/CommandObjectLog.cpp
+++ b/lldb/source/Commands/CommandObjectLog.cpp
@@ -309,9 +309,14 @@ class CommandObjectLogList : public CommandObjectParsed {
       result.SetStatus(eReturnStatusSuccessFinishResult);
     } else {
       bool success = true;
-      for (const auto &entry : args.entries())
-        success =
-            success && Log::ListChannelCategories(entry.ref(), output_stream);
+      for (const auto &entry : args.entries()) {
+        auto err_or_list = Log::ListChannelCategories(entry.ref());
+        if (!err_or_list) {
+          success = false;
+          output_stream << toString(err_or_list.takeError());
+        } else
+          output_stream << *err_or_list;
+      }
       if (success)
         result.SetStatus(eReturnStatusSuccessFinishResult);
     }
diff --git a/lldb/source/Utility/Log.cpp b/lldb/source/Utility/Log.cpp
index 2ed1444fbb5e6..dd813efb90f90 100644
--- a/lldb/source/Utility/Log.cpp
+++ b/lldb/source/Utility/Log.cpp
@@ -282,15 +282,16 @@ bool Log::DumpLogChannel(llvm::StringRef channel,
   return true;
 }
 
-bool Log::ListChannelCategories(llvm::StringRef channel,
-                                llvm::raw_ostream &stream) {
+llvm::Expected<std::string>
+Log::ListChannelCategories(llvm::StringRef channel) {
   auto ch = g_channel_map->find(channel);
-  if (ch == g_channel_map->end()) {
-    stream << llvm::formatv("Invalid log channel '{0}'.\n", channel);
-    return false;
-  }
-  ListCategories(stream, *ch);
-  return true;
+  if (ch == g_channel_map->end())
+    return llvm::createStringErrorV("Invalid log channel '{0}'.\n", channel);
+
+  std::string categories;
+  llvm::raw_string_ostream strm(categories);
+  ListCategories(strm, *ch);
+  return categories;
 }
 
 void Log::DisableAllLogChannels() {
diff --git a/lldb/unittests/Utility/LogTest.cpp 
b/lldb/unittests/Utility/LogTest.cpp
index f8514930eac2b..6eaa318dfe34c 100644
--- a/lldb/unittests/Utility/LogTest.cpp
+++ b/lldb/unittests/Utility/LogTest.cpp
@@ -40,13 +40,6 @@ namespace lldb_private {
 template <> Log::Channel &LogChannelFor<TestChannel>() { return test_channel; }
 } // namespace lldb_private
 
-// Wrap list function to make it easier to test.
-static bool ListCategories(llvm::StringRef channel, std::string &result) {
-  result.clear();
-  llvm::raw_string_ostream result_stream(result);
-  return Log::ListChannelCategories(channel, result_stream);
-}
-
 namespace {
 // A test fixture which provides tests with a pre-registered channel.
 struct LogChannelTest : public ::testing::Test {
@@ -276,18 +269,18 @@ TEST_F(LogChannelTest, Disable) {
 
 TEST_F(LogChannelTest, List) {
   std::string list;
-  EXPECT_TRUE(ListCategories("chan", list));
-  std::string expected =
-      R"(Logging categories for 'chan':
+  EXPECT_THAT_EXPECTED(Log::ListChannelCategories("chan"),
+                       llvm::HasValue(
+                           R"(Logging categories for 'chan':
   all - all available logging categories
   default - default set of logging categories
   foo - log foo
   bar - log bar
-)";
-  EXPECT_EQ(expected, list);
+)"));
 
-  EXPECT_FALSE(ListCategories("chanchan", list));
-  EXPECT_EQ("Invalid log channel 'chanchan'.\n", list);
+  EXPECT_THAT_EXPECTED(
+      Log::ListChannelCategories("chanchan"),
+      llvm::FailedWithMessage("Invalid log channel 'chanchan'.\n"));
 }
 
 TEST_F(LogChannelEnabledTest, log_options) {

_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to