[Lldb-commits] [lldb] [lldb] Fix alias parsing with joined options (PR #190301)

Dave Lee via lldb-commits lldb-commits at lists.llvm.org
Sat Apr 4 07:22:04 PDT 2026


https://github.com/kastiglione updated https://github.com/llvm/llvm-project/pull/190301

>From 3873abae5ceb98fd5c56dfed85745f8ba195235d Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Thu, 2 Apr 2026 18:57:43 -0700
Subject: [PATCH 1/2] [lldb] Fix alias parsing with joined options

---
 lldb/source/Interpreter/Options.cpp           | 40 ++++++++++++-------
 .../Commands/command-alias-joined-arg.test    |  7 ++++
 2 files changed, 32 insertions(+), 15 deletions(-)
 create mode 100644 lldb/test/Shell/Commands/command-alias-joined-arg.test

diff --git a/lldb/source/Interpreter/Options.cpp b/lldb/source/Interpreter/Options.cpp
index 283c9cc0105a1..54b8edfee4842 100644
--- a/lldb/source/Interpreter/Options.cpp
+++ b/lldb/source/Interpreter/Options.cpp
@@ -21,8 +21,10 @@
 #include "lldb/Interpreter/CommandReturnObject.h"
 #include "lldb/Target/Target.h"
 #include "lldb/Utility/AnsiTerminal.h"
+#include "lldb/Utility/OptionDefinition.h"
 #include "lldb/Utility/StreamString.h"
 #include "llvm/ADT/STLExtras.h"
+#include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ErrorExtras.h"
 
 using namespace lldb;
@@ -887,18 +889,28 @@ static Args ReconstituteArgsAfterParsing(llvm::ArrayRef<char *> parsed,
   return result;
 }
 
-static size_t FindArgumentIndexForOption(const Args &args,
-                                         const Option &long_option) {
+/// Find the index of the given option in the arguments. If the option takes an
+/// argument, the second index is the index of the value in args. Otherwise, the
+/// second index is -1.
+static std::pair<size_t, size_t>
+FindArgumentIndexForOption(const Args &args, const Option &long_option) {
   std::string short_opt = llvm::formatv("-{0}", char(long_option.val)).str();
   std::string long_opt =
-      std::string(llvm::formatv("--{0}", long_option.definition->long_option));
+      llvm::formatv("--{0}", long_option.definition->long_option).str();
   for (const auto &entry : llvm::enumerate(args)) {
-    if (entry.value().ref().starts_with(short_opt) ||
-        entry.value().ref().starts_with(long_opt))
-      return entry.index();
+    llvm::StringRef arg = entry.value().ref();
+    size_t idx = entry.index();
+    if (long_option.definition->option_has_arg == OptionParser::eNoArgument)
+      return {idx, -1};
+    size_t val_idx;
+    if (arg == short_opt || arg.starts_with(long_opt))
+      val_idx = idx + 1;
+    else if (arg.starts_with(short_opt))
+      val_idx = idx;
+    return {idx, val_idx};
   }
 
-  return size_t(-1);
+  return {-1, -1};
 }
 
 static std::string BuildShortOptions(const Option *long_options) {
@@ -987,10 +999,9 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args,
 
     StreamString option_str;
     option_str.Printf("-%c", val);
-    const OptionDefinition *def = long_options[long_options_index].definition;
-    int has_arg =
-        (def == nullptr) ? OptionParser::eNoArgument : def->option_has_arg;
-
+    const Option &opt = long_options[long_options_index];
+    int has_arg = opt.definition ? opt.definition->option_has_arg
+                                 : OptionParser::eNoArgument;
     const char *option_arg = nullptr;
     switch (has_arg) {
     case OptionParser::eRequiredArgument:
@@ -1020,12 +1031,11 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args,
     // Note: We also need to preserve any option argument values that were
     // surrounded by backticks, as we lose track of them in the
     // option_args_vector.
-    size_t idx =
-        FindArgumentIndexForOption(args_copy, long_options[long_options_index]);
+    auto [idx, val_idx] = FindArgumentIndexForOption(args_copy, opt);
     std::string option_to_insert;
     if (option_arg) {
-      if (idx != size_t(-1) && has_arg) {
-        bool arg_has_backtick = args_copy[idx + 1].GetQuoteChar() == '`';
+      if (val_idx != size_t(-1) && val_idx < args_copy.size() && has_arg) {
+        bool arg_has_backtick = args_copy[val_idx].GetQuoteChar() == '`';
         if (arg_has_backtick)
           option_to_insert = "`";
         option_to_insert += option_arg;
diff --git a/lldb/test/Shell/Commands/command-alias-joined-arg.test b/lldb/test/Shell/Commands/command-alias-joined-arg.test
new file mode 100644
index 0000000000000..c95672a2cc54a
--- /dev/null
+++ b/lldb/test/Shell/Commands/command-alias-joined-arg.test
@@ -0,0 +1,7 @@
+# Test that command alias with a joined argument (`-P1` in this test) is
+# properly parsed (does not crash).
+
+# RUN: %lldb < %s | FileCheck %s
+command alias vptr frame variable -P1
+help
+# CHECK: {{^ *}}vptr{{ +}}--

>From 4368b23b18adae6ab4f1e8f3b447293304a06ddb Mon Sep 17 00:00:00 2001
From: Dave Lee <davelee.com at gmail.com>
Date: Sat, 4 Apr 2026 07:18:24 -0700
Subject: [PATCH 2/2] Add and use LLDB_INVALID_INDEX64

---
 lldb/include/lldb/lldb-defines.h    |  1 +
 lldb/source/Interpreter/Options.cpp | 11 ++++++-----
 2 files changed, 7 insertions(+), 5 deletions(-)

diff --git a/lldb/include/lldb/lldb-defines.h b/lldb/include/lldb/lldb-defines.h
index 8e1029387d2da..515f7cff58d8a 100644
--- a/lldb/include/lldb/lldb-defines.h
+++ b/lldb/include/lldb/lldb-defines.h
@@ -81,6 +81,7 @@
 #define LLDB_INVALID_STOP_ID 0
 #define LLDB_INVALID_ADDRESS UINT64_MAX
 #define LLDB_INVALID_INDEX32 UINT32_MAX
+#define LLDB_INVALID_INDEX64 UINT64_MAX
 #define LLDB_INVALID_IVAR_OFFSET UINT32_MAX
 #define LLDB_INVALID_IMAGE_TOKEN UINT32_MAX
 #define LLDB_INVALID_MODULE_VERSION UINT32_MAX
diff --git a/lldb/source/Interpreter/Options.cpp b/lldb/source/Interpreter/Options.cpp
index 54b8edfee4842..cc9f3ebd706fd 100644
--- a/lldb/source/Interpreter/Options.cpp
+++ b/lldb/source/Interpreter/Options.cpp
@@ -23,6 +23,7 @@
 #include "lldb/Utility/AnsiTerminal.h"
 #include "lldb/Utility/OptionDefinition.h"
 #include "lldb/Utility/StreamString.h"
+#include "lldb/lldb-defines.h"
 #include "llvm/ADT/STLExtras.h"
 #include "llvm/ADT/StringRef.h"
 #include "llvm/Support/ErrorExtras.h"
@@ -891,7 +892,7 @@ static Args ReconstituteArgsAfterParsing(llvm::ArrayRef<char *> parsed,
 
 /// Find the index of the given option in the arguments. If the option takes an
 /// argument, the second index is the index of the value in args. Otherwise, the
-/// second index is -1.
+/// second index is LLDB_INVALID_INDEX64.
 static std::pair<size_t, size_t>
 FindArgumentIndexForOption(const Args &args, const Option &long_option) {
   std::string short_opt = llvm::formatv("-{0}", char(long_option.val)).str();
@@ -901,7 +902,7 @@ FindArgumentIndexForOption(const Args &args, const Option &long_option) {
     llvm::StringRef arg = entry.value().ref();
     size_t idx = entry.index();
     if (long_option.definition->option_has_arg == OptionParser::eNoArgument)
-      return {idx, -1};
+      return {idx, LLDB_INVALID_INDEX64};
     size_t val_idx;
     if (arg == short_opt || arg.starts_with(long_opt))
       val_idx = idx + 1;
@@ -910,7 +911,7 @@ FindArgumentIndexForOption(const Args &args, const Option &long_option) {
     return {idx, val_idx};
   }
 
-  return {-1, -1};
+  return {LLDB_INVALID_INDEX64, LLDB_INVALID_INDEX64};
 }
 
 static std::string BuildShortOptions(const Option *long_options) {
@@ -1034,7 +1035,7 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args,
     auto [idx, val_idx] = FindArgumentIndexForOption(args_copy, opt);
     std::string option_to_insert;
     if (option_arg) {
-      if (val_idx != size_t(-1) && val_idx < args_copy.size() && has_arg) {
+      if (val_idx != LLDB_INVALID_INDEX64 && val_idx < args_copy.size()) {
         bool arg_has_backtick = args_copy[val_idx].GetQuoteChar() == '`';
         if (arg_has_backtick)
           option_to_insert = "`";
@@ -1049,7 +1050,7 @@ llvm::Expected<Args> Options::ParseAlias(const Args &args,
     option_arg_vector->emplace_back(std::string(option_str.GetString()),
                                     has_arg, option_to_insert);
 
-    if (idx == size_t(-1))
+    if (idx == LLDB_INVALID_INDEX64)
       continue;
 
     if (!input_line.empty()) {



More information about the lldb-commits mailing list