[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-12 Thread John Harrison via lldb-commits

https://github.com/ashgti approved this pull request.


https://github.com/llvm/llvm-project/pull/175048
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-12 Thread Sergei Druzhkov via lldb-commits


@@ -288,8 +288,8 @@ static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg 
&target_arg,
   if (!stdio.empty()) {
 llvm::SmallVector files;

DrSergei wrote:

I mean using `llvm::SmallVector stdio_files;` to 
avoid constant duplication

https://github.com/llvm/llvm-project/pull/175048
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-12 Thread Ebuka Ezike via lldb-commits


@@ -288,8 +288,8 @@ static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg 
&target_arg,
   if (!stdio.empty()) {
 llvm::SmallVector files;

da-viper wrote:

I changed it to stdio_files instead as num_of_stdio indicates it is a number. 

https://github.com/llvm/llvm-project/pull/175048
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-12 Thread Ebuka Ezike via lldb-commits

https://github.com/da-viper updated 
https://github.com/llvm/llvm-project/pull/175048

>From e6988e729f084a2775d18c68bb4dbc749133db67 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike 
Date: Mon, 29 Dec 2025 01:51:47 +
Subject: [PATCH 1/8] [lldb-dap] fix redirection with program args

---
 .../tools/lldb-dap/Handler/RequestHandler.cpp | 24 +--
 lldb/tools/lldb-dap/JSONUtils.cpp | 20 +---
 .../lldb-dap/Protocol/ProtocolRequests.cpp|  9 ++-
 lldb/tools/lldb-dap/tool/lldb-dap.cpp |  4 ++--
 4 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
index b06a43d7421c1..8be83fac2c117 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
@@ -61,25 +61,25 @@ static uint32_t SetLaunchFlag(uint32_t flags, bool flag,
 static void
 SetupIORedirection(const std::vector> &stdio,
lldb::SBLaunchInfo &launch_info) {
-  size_t n = std::max(stdio.size(), static_cast(3));
-  for (size_t i = 0; i < n; i++) {
-std::optional path;
-if (stdio.size() <= i)
-  path = stdio.back();
-else
-  path = stdio[i];
-if (!path)
+  for (const auto &[idx, value_opt] : llvm::enumerate(stdio)) {
+if (!value_opt)
   continue;
-switch (i) {
+const std::string &path = value_opt.value();
+assert(!path.empty() && "paths should not be empty");
+
+const int fd = static_cast(idx);
+switch (fd) {
 case 0:
-  launch_info.AddOpenFileAction(i, path->c_str(), true, false);
+  launch_info.AddOpenFileAction(STDIN_FILENO, path.c_str(), true, false);
   break;
 case 1:
+  launch_info.AddOpenFileAction(STDOUT_FILENO, path.c_str(), false, true);
+  break;
 case 2:
-  launch_info.AddOpenFileAction(i, path->c_str(), false, true);
+  launch_info.AddOpenFileAction(STDERR_FILENO, path.c_str(), false, true);
   break;
 default:
-  launch_info.AddOpenFileAction(i, path->c_str(), true, true);
+  launch_info.AddOpenFileAction(fd, path.c_str(), true, true);
   break;
 }
   }
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp 
b/lldb/tools/lldb-dap/JSONUtils.cpp
index 9a2142cd847ab..4bf9d6e19ad80 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -720,20 +720,24 @@ llvm::json::Object CreateRunInTerminalReverseRequest(
 req_args.push_back("--debugger-pid");
 req_args.push_back(std::to_string(debugger_pid));
   }
-  req_args.push_back("--launch-target");
-  req_args.push_back(program.str());
+
   if (!stdio.empty()) {
-req_args.push_back("--stdio");
+req_args.emplace_back("--stdio");
+
 std::stringstream ss;
+std::string_view delimiter;
 for (const std::optional &file : stdio) {
+  ss << std::exchange(delimiter, ":");
   if (file)
-ss << *file;
-  ss << ":";
+ss << file.value();
 }
-std::string files = ss.str();
-files.pop_back();
-req_args.push_back(std::move(files));
+req_args.push_back(ss.str());
   }
+
+  // WARNING: Any argument added after `launch-target` is passed to to the
+  // target.
+  req_args.emplace_back("--launch-target");
+  req_args.push_back(program.str());
   req_args.insert(req_args.end(), args.begin(), args.end());
   run_in_terminal_args.try_emplace("args", req_args);
 
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp 
b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
index c3225f6ba0e35..1f8283eba86fa 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
@@ -296,7 +296,7 @@ bool fromJSON(const json::Value &Params, Console &C, 
json::Path P) {
 bool fromJSON(const json::Value &Params, LaunchRequestArguments &LRA,
   json::Path P) {
   json::ObjectMapper O(Params, P);
-  bool success =
+  const bool success =
   O && fromJSON(Params, LRA.configuration, P) &&
   O.mapOptional("noDebug", LRA.noDebug) &&
   O.mapOptional("launchCommands", LRA.launchCommands) &&
@@ -310,6 +310,13 @@ bool fromJSON(const json::Value &Params, 
LaunchRequestArguments &LRA,
   O.mapOptional("stdio", LRA.stdio) && parseEnv(Params, LRA.env, P);
   if (!success)
 return false;
+
+  for (std::optional &io_path : LRA.stdio) {
+// set empty paths to null.
+if (io_path && llvm::StringRef(*io_path).trim().empty())
+  io_path.reset();
+  }
+
   // Validate that we have a well formed launch request.
   if (!LRA.launchCommands.empty() &&
   LRA.console != protocol::eConsoleInternal) {
diff --git a/lldb/tools/lldb-dap/tool/lldb-dap.cpp 
b/lldb/tools/lldb-dap/tool/lldb-dap.cpp
index e3b9d57e7d3a1..90168dec699b7 100644
--- a/lldb/tools/lldb-dap/tool/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/tool/lldb-dap.cpp
@@ -288,8 +288,8 @@ static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg 
&target_arg,
   if (!stdio.

[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-12 Thread Ebuka Ezike via lldb-commits

https://github.com/da-viper updated 
https://github.com/llvm/llvm-project/pull/175048

>From e6988e729f084a2775d18c68bb4dbc749133db67 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike 
Date: Mon, 29 Dec 2025 01:51:47 +
Subject: [PATCH 1/7] [lldb-dap] fix redirection with program args

---
 .../tools/lldb-dap/Handler/RequestHandler.cpp | 24 +--
 lldb/tools/lldb-dap/JSONUtils.cpp | 20 +---
 .../lldb-dap/Protocol/ProtocolRequests.cpp|  9 ++-
 lldb/tools/lldb-dap/tool/lldb-dap.cpp |  4 ++--
 4 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
index b06a43d7421c1..8be83fac2c117 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
@@ -61,25 +61,25 @@ static uint32_t SetLaunchFlag(uint32_t flags, bool flag,
 static void
 SetupIORedirection(const std::vector> &stdio,
lldb::SBLaunchInfo &launch_info) {
-  size_t n = std::max(stdio.size(), static_cast(3));
-  for (size_t i = 0; i < n; i++) {
-std::optional path;
-if (stdio.size() <= i)
-  path = stdio.back();
-else
-  path = stdio[i];
-if (!path)
+  for (const auto &[idx, value_opt] : llvm::enumerate(stdio)) {
+if (!value_opt)
   continue;
-switch (i) {
+const std::string &path = value_opt.value();
+assert(!path.empty() && "paths should not be empty");
+
+const int fd = static_cast(idx);
+switch (fd) {
 case 0:
-  launch_info.AddOpenFileAction(i, path->c_str(), true, false);
+  launch_info.AddOpenFileAction(STDIN_FILENO, path.c_str(), true, false);
   break;
 case 1:
+  launch_info.AddOpenFileAction(STDOUT_FILENO, path.c_str(), false, true);
+  break;
 case 2:
-  launch_info.AddOpenFileAction(i, path->c_str(), false, true);
+  launch_info.AddOpenFileAction(STDERR_FILENO, path.c_str(), false, true);
   break;
 default:
-  launch_info.AddOpenFileAction(i, path->c_str(), true, true);
+  launch_info.AddOpenFileAction(fd, path.c_str(), true, true);
   break;
 }
   }
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp 
b/lldb/tools/lldb-dap/JSONUtils.cpp
index 9a2142cd847ab..4bf9d6e19ad80 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -720,20 +720,24 @@ llvm::json::Object CreateRunInTerminalReverseRequest(
 req_args.push_back("--debugger-pid");
 req_args.push_back(std::to_string(debugger_pid));
   }
-  req_args.push_back("--launch-target");
-  req_args.push_back(program.str());
+
   if (!stdio.empty()) {
-req_args.push_back("--stdio");
+req_args.emplace_back("--stdio");
+
 std::stringstream ss;
+std::string_view delimiter;
 for (const std::optional &file : stdio) {
+  ss << std::exchange(delimiter, ":");
   if (file)
-ss << *file;
-  ss << ":";
+ss << file.value();
 }
-std::string files = ss.str();
-files.pop_back();
-req_args.push_back(std::move(files));
+req_args.push_back(ss.str());
   }
+
+  // WARNING: Any argument added after `launch-target` is passed to to the
+  // target.
+  req_args.emplace_back("--launch-target");
+  req_args.push_back(program.str());
   req_args.insert(req_args.end(), args.begin(), args.end());
   run_in_terminal_args.try_emplace("args", req_args);
 
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp 
b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
index c3225f6ba0e35..1f8283eba86fa 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
@@ -296,7 +296,7 @@ bool fromJSON(const json::Value &Params, Console &C, 
json::Path P) {
 bool fromJSON(const json::Value &Params, LaunchRequestArguments &LRA,
   json::Path P) {
   json::ObjectMapper O(Params, P);
-  bool success =
+  const bool success =
   O && fromJSON(Params, LRA.configuration, P) &&
   O.mapOptional("noDebug", LRA.noDebug) &&
   O.mapOptional("launchCommands", LRA.launchCommands) &&
@@ -310,6 +310,13 @@ bool fromJSON(const json::Value &Params, 
LaunchRequestArguments &LRA,
   O.mapOptional("stdio", LRA.stdio) && parseEnv(Params, LRA.env, P);
   if (!success)
 return false;
+
+  for (std::optional &io_path : LRA.stdio) {
+// set empty paths to null.
+if (io_path && llvm::StringRef(*io_path).trim().empty())
+  io_path.reset();
+  }
+
   // Validate that we have a well formed launch request.
   if (!LRA.launchCommands.empty() &&
   LRA.console != protocol::eConsoleInternal) {
diff --git a/lldb/tools/lldb-dap/tool/lldb-dap.cpp 
b/lldb/tools/lldb-dap/tool/lldb-dap.cpp
index e3b9d57e7d3a1..90168dec699b7 100644
--- a/lldb/tools/lldb-dap/tool/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/tool/lldb-dap.cpp
@@ -288,8 +288,8 @@ static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg 
&target_arg,
   if (!stdio.

[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-08 Thread Sergei Druzhkov via lldb-commits


@@ -288,8 +288,8 @@ static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg 
&target_arg,
   if (!stdio.empty()) {
 llvm::SmallVector files;

DrSergei wrote:

nit: can we use `num_of_stdio` in `SmallVector`

https://github.com/llvm/llvm-project/pull/175048
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-08 Thread Sergei Druzhkov via lldb-commits

https://github.com/DrSergei approved this pull request.

Thank you, LGTM

https://github.com/llvm/llvm-project/pull/175048
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-08 Thread Sergei Druzhkov via lldb-commits


@@ -720,20 +720,24 @@ llvm::json::Object CreateRunInTerminalReverseRequest(
 req_args.push_back("--debugger-pid");
 req_args.push_back(std::to_string(debugger_pid));
   }
-  req_args.push_back("--launch-target");
-  req_args.push_back(program.str());
+
   if (!stdio.empty()) {
-req_args.push_back("--stdio");
+req_args.emplace_back("--stdio");
+
 std::stringstream ss;
+std::string_view delimiter;
 for (const std::optional &file : stdio) {
+  ss << std::exchange(delimiter, ":");
   if (file)
-ss << *file;
-  ss << ":";
+ss << file.value();

DrSergei wrote:

nit: I think we can keep `*file`, because `value()` performs checks that 
optional contains value. Maybe this check is skipped when we use build wihtout 
exceptions, but it looks like that we use `*` more often than `value()`

https://github.com/llvm/llvm-project/pull/175048
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-08 Thread Sergei Druzhkov via lldb-commits


@@ -406,14 +406,25 @@ def terminate(self):
 
 class _LocalProcess(_BaseProcess):
 def __init__(self, trace_on):
-self._proc = None
+self._proc: Popen | None = None

DrSergei wrote:

nit: maybe use `Optional` like in `reverse_process` below

https://github.com/llvm/llvm-project/pull/175048
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-08 Thread Sergei Druzhkov via lldb-commits

https://github.com/DrSergei edited 
https://github.com/llvm/llvm-project/pull/175048
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-08 Thread Sergei Druzhkov via lldb-commits


@@ -0,0 +1,24 @@
+#include 
+#include 
+
+int main(int argc, char *argv[]) {
+  const bool use_stdin = argc <= 1;
+  const char *use_env = std::getenv("FROM_ENV");
+
+  if (use_env != nullptr) { // from environment variable
+std::cout << "[STDOUT][FROM_ENV]: " << use_env;
+std::cerr << "[STDERR][FROM_ENV]: " << use_env;
+
+  } else if (use_stdin) { // from standard in
+std::string line;
+std::getline(std::cin, line);
+std::cout << "[STDOUT][FROM_STDIN]: " << line;
+std::cerr << "[STDERR][FROM_STDIN]: " << line;
+
+  } else { // from argv
+const char *first_arg = argv[1];
+std::cout << "[STDOUT][FROM_ARGV]: " << first_arg;
+std::cerr << "[STDERR][FROM_ARGV]: " << first_arg;
+  }
+  return 0;
+}

DrSergei wrote:

nit: add empty line at the end of file

https://github.com/llvm/llvm-project/pull/175048
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-08 Thread Sergei Druzhkov via lldb-commits


@@ -25,6 +25,9 @@
 #if !defined(_WIN32)
 #include 
 #endif
+#ifdef _WIN32

DrSergei wrote:

nit: maybe use `#else`

https://github.com/llvm/llvm-project/pull/175048
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-08 Thread Ebuka Ezike via lldb-commits

https://github.com/da-viper updated 
https://github.com/llvm/llvm-project/pull/175048

>From e6988e729f084a2775d18c68bb4dbc749133db67 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike 
Date: Mon, 29 Dec 2025 01:51:47 +
Subject: [PATCH 1/6] [lldb-dap] fix redirection with program args

---
 .../tools/lldb-dap/Handler/RequestHandler.cpp | 24 +--
 lldb/tools/lldb-dap/JSONUtils.cpp | 20 +---
 .../lldb-dap/Protocol/ProtocolRequests.cpp|  9 ++-
 lldb/tools/lldb-dap/tool/lldb-dap.cpp |  4 ++--
 4 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
index b06a43d7421c1..8be83fac2c117 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
@@ -61,25 +61,25 @@ static uint32_t SetLaunchFlag(uint32_t flags, bool flag,
 static void
 SetupIORedirection(const std::vector> &stdio,
lldb::SBLaunchInfo &launch_info) {
-  size_t n = std::max(stdio.size(), static_cast(3));
-  for (size_t i = 0; i < n; i++) {
-std::optional path;
-if (stdio.size() <= i)
-  path = stdio.back();
-else
-  path = stdio[i];
-if (!path)
+  for (const auto &[idx, value_opt] : llvm::enumerate(stdio)) {
+if (!value_opt)
   continue;
-switch (i) {
+const std::string &path = value_opt.value();
+assert(!path.empty() && "paths should not be empty");
+
+const int fd = static_cast(idx);
+switch (fd) {
 case 0:
-  launch_info.AddOpenFileAction(i, path->c_str(), true, false);
+  launch_info.AddOpenFileAction(STDIN_FILENO, path.c_str(), true, false);
   break;
 case 1:
+  launch_info.AddOpenFileAction(STDOUT_FILENO, path.c_str(), false, true);
+  break;
 case 2:
-  launch_info.AddOpenFileAction(i, path->c_str(), false, true);
+  launch_info.AddOpenFileAction(STDERR_FILENO, path.c_str(), false, true);
   break;
 default:
-  launch_info.AddOpenFileAction(i, path->c_str(), true, true);
+  launch_info.AddOpenFileAction(fd, path.c_str(), true, true);
   break;
 }
   }
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp 
b/lldb/tools/lldb-dap/JSONUtils.cpp
index 9a2142cd847ab..4bf9d6e19ad80 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -720,20 +720,24 @@ llvm::json::Object CreateRunInTerminalReverseRequest(
 req_args.push_back("--debugger-pid");
 req_args.push_back(std::to_string(debugger_pid));
   }
-  req_args.push_back("--launch-target");
-  req_args.push_back(program.str());
+
   if (!stdio.empty()) {
-req_args.push_back("--stdio");
+req_args.emplace_back("--stdio");
+
 std::stringstream ss;
+std::string_view delimiter;
 for (const std::optional &file : stdio) {
+  ss << std::exchange(delimiter, ":");
   if (file)
-ss << *file;
-  ss << ":";
+ss << file.value();
 }
-std::string files = ss.str();
-files.pop_back();
-req_args.push_back(std::move(files));
+req_args.push_back(ss.str());
   }
+
+  // WARNING: Any argument added after `launch-target` is passed to to the
+  // target.
+  req_args.emplace_back("--launch-target");
+  req_args.push_back(program.str());
   req_args.insert(req_args.end(), args.begin(), args.end());
   run_in_terminal_args.try_emplace("args", req_args);
 
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp 
b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
index c3225f6ba0e35..1f8283eba86fa 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
@@ -296,7 +296,7 @@ bool fromJSON(const json::Value &Params, Console &C, 
json::Path P) {
 bool fromJSON(const json::Value &Params, LaunchRequestArguments &LRA,
   json::Path P) {
   json::ObjectMapper O(Params, P);
-  bool success =
+  const bool success =
   O && fromJSON(Params, LRA.configuration, P) &&
   O.mapOptional("noDebug", LRA.noDebug) &&
   O.mapOptional("launchCommands", LRA.launchCommands) &&
@@ -310,6 +310,13 @@ bool fromJSON(const json::Value &Params, 
LaunchRequestArguments &LRA,
   O.mapOptional("stdio", LRA.stdio) && parseEnv(Params, LRA.env, P);
   if (!success)
 return false;
+
+  for (std::optional &io_path : LRA.stdio) {
+// set empty paths to null.
+if (io_path && llvm::StringRef(*io_path).trim().empty())
+  io_path.reset();
+  }
+
   // Validate that we have a well formed launch request.
   if (!LRA.launchCommands.empty() &&
   LRA.console != protocol::eConsoleInternal) {
diff --git a/lldb/tools/lldb-dap/tool/lldb-dap.cpp 
b/lldb/tools/lldb-dap/tool/lldb-dap.cpp
index e3b9d57e7d3a1..90168dec699b7 100644
--- a/lldb/tools/lldb-dap/tool/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/tool/lldb-dap.cpp
@@ -288,8 +288,8 @@ static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg 
&target_arg,
   if (!stdio.

[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-08 Thread Ebuka Ezike via lldb-commits

da-viper wrote:

darker recommended format style differs from the one in CI.

https://github.com/llvm/llvm-project/pull/175048
___
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits


[Lldb-commits] [lldb] [lldb-dap] Add testcases for stdio redirection on different console types. (PR #175048)

2026-01-08 Thread Ebuka Ezike via lldb-commits

https://github.com/da-viper updated 
https://github.com/llvm/llvm-project/pull/175048

>From e6988e729f084a2775d18c68bb4dbc749133db67 Mon Sep 17 00:00:00 2001
From: Ebuka Ezike 
Date: Mon, 29 Dec 2025 01:51:47 +
Subject: [PATCH 1/5] [lldb-dap] fix redirection with program args

---
 .../tools/lldb-dap/Handler/RequestHandler.cpp | 24 +--
 lldb/tools/lldb-dap/JSONUtils.cpp | 20 +---
 .../lldb-dap/Protocol/ProtocolRequests.cpp|  9 ++-
 lldb/tools/lldb-dap/tool/lldb-dap.cpp |  4 ++--
 4 files changed, 34 insertions(+), 23 deletions(-)

diff --git a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp 
b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
index b06a43d7421c1..8be83fac2c117 100644
--- a/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
+++ b/lldb/tools/lldb-dap/Handler/RequestHandler.cpp
@@ -61,25 +61,25 @@ static uint32_t SetLaunchFlag(uint32_t flags, bool flag,
 static void
 SetupIORedirection(const std::vector> &stdio,
lldb::SBLaunchInfo &launch_info) {
-  size_t n = std::max(stdio.size(), static_cast(3));
-  for (size_t i = 0; i < n; i++) {
-std::optional path;
-if (stdio.size() <= i)
-  path = stdio.back();
-else
-  path = stdio[i];
-if (!path)
+  for (const auto &[idx, value_opt] : llvm::enumerate(stdio)) {
+if (!value_opt)
   continue;
-switch (i) {
+const std::string &path = value_opt.value();
+assert(!path.empty() && "paths should not be empty");
+
+const int fd = static_cast(idx);
+switch (fd) {
 case 0:
-  launch_info.AddOpenFileAction(i, path->c_str(), true, false);
+  launch_info.AddOpenFileAction(STDIN_FILENO, path.c_str(), true, false);
   break;
 case 1:
+  launch_info.AddOpenFileAction(STDOUT_FILENO, path.c_str(), false, true);
+  break;
 case 2:
-  launch_info.AddOpenFileAction(i, path->c_str(), false, true);
+  launch_info.AddOpenFileAction(STDERR_FILENO, path.c_str(), false, true);
   break;
 default:
-  launch_info.AddOpenFileAction(i, path->c_str(), true, true);
+  launch_info.AddOpenFileAction(fd, path.c_str(), true, true);
   break;
 }
   }
diff --git a/lldb/tools/lldb-dap/JSONUtils.cpp 
b/lldb/tools/lldb-dap/JSONUtils.cpp
index 9a2142cd847ab..4bf9d6e19ad80 100644
--- a/lldb/tools/lldb-dap/JSONUtils.cpp
+++ b/lldb/tools/lldb-dap/JSONUtils.cpp
@@ -720,20 +720,24 @@ llvm::json::Object CreateRunInTerminalReverseRequest(
 req_args.push_back("--debugger-pid");
 req_args.push_back(std::to_string(debugger_pid));
   }
-  req_args.push_back("--launch-target");
-  req_args.push_back(program.str());
+
   if (!stdio.empty()) {
-req_args.push_back("--stdio");
+req_args.emplace_back("--stdio");
+
 std::stringstream ss;
+std::string_view delimiter;
 for (const std::optional &file : stdio) {
+  ss << std::exchange(delimiter, ":");
   if (file)
-ss << *file;
-  ss << ":";
+ss << file.value();
 }
-std::string files = ss.str();
-files.pop_back();
-req_args.push_back(std::move(files));
+req_args.push_back(ss.str());
   }
+
+  // WARNING: Any argument added after `launch-target` is passed to to the
+  // target.
+  req_args.emplace_back("--launch-target");
+  req_args.push_back(program.str());
   req_args.insert(req_args.end(), args.begin(), args.end());
   run_in_terminal_args.try_emplace("args", req_args);
 
diff --git a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp 
b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
index c3225f6ba0e35..1f8283eba86fa 100644
--- a/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
+++ b/lldb/tools/lldb-dap/Protocol/ProtocolRequests.cpp
@@ -296,7 +296,7 @@ bool fromJSON(const json::Value &Params, Console &C, 
json::Path P) {
 bool fromJSON(const json::Value &Params, LaunchRequestArguments &LRA,
   json::Path P) {
   json::ObjectMapper O(Params, P);
-  bool success =
+  const bool success =
   O && fromJSON(Params, LRA.configuration, P) &&
   O.mapOptional("noDebug", LRA.noDebug) &&
   O.mapOptional("launchCommands", LRA.launchCommands) &&
@@ -310,6 +310,13 @@ bool fromJSON(const json::Value &Params, 
LaunchRequestArguments &LRA,
   O.mapOptional("stdio", LRA.stdio) && parseEnv(Params, LRA.env, P);
   if (!success)
 return false;
+
+  for (std::optional &io_path : LRA.stdio) {
+// set empty paths to null.
+if (io_path && llvm::StringRef(*io_path).trim().empty())
+  io_path.reset();
+  }
+
   // Validate that we have a well formed launch request.
   if (!LRA.launchCommands.empty() &&
   LRA.console != protocol::eConsoleInternal) {
diff --git a/lldb/tools/lldb-dap/tool/lldb-dap.cpp 
b/lldb/tools/lldb-dap/tool/lldb-dap.cpp
index e3b9d57e7d3a1..90168dec699b7 100644
--- a/lldb/tools/lldb-dap/tool/lldb-dap.cpp
+++ b/lldb/tools/lldb-dap/tool/lldb-dap.cpp
@@ -288,8 +288,8 @@ static llvm::Error LaunchRunInTerminalTarget(llvm::opt::Arg 
&target_arg,
   if (!stdio.