Skip to content

[LLDB] Add array subscription and integer parsing to DIL #141102

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Merged
merged 2 commits into from
May 25, 2025

Conversation

kuilpd
Copy link
Contributor

@kuilpd kuilpd commented May 22, 2025

Reapply #138551 with an xfailed test on Windows

@kuilpd kuilpd requested a review from labath May 22, 2025 16:56
@kuilpd kuilpd added the lldb label May 22, 2025
@kuilpd kuilpd requested a review from JDevlieghere as a code owner May 22, 2025 16:56
@llvmbot
Copy link
Member

llvmbot commented May 22, 2025

@llvm/pr-subscribers-lldb

Author: Ilia Kuklin (kuilpd)

Changes

Patch is 21.53 KiB, truncated to 20.00 KiB below, full version: https://github.com/llvm/llvm-project/pull/141102.diff

13 Files Affected:

  • (modified) lldb/docs/dil-expr-lang.ebnf (+7-2)
  • (modified) lldb/include/lldb/ValueObject/DILAST.h (+26-2)
  • (modified) lldb/include/lldb/ValueObject/DILEval.h (+2)
  • (modified) lldb/include/lldb/ValueObject/DILLexer.h (+3)
  • (modified) lldb/include/lldb/ValueObject/DILParser.h (+2)
  • (modified) lldb/source/ValueObject/DILAST.cpp (+5)
  • (modified) lldb/source/ValueObject/DILEval.cpp (+49-2)
  • (modified) lldb/source/ValueObject/DILLexer.cpp (+27-3)
  • (modified) lldb/source/ValueObject/DILParser.cpp (+53-1)
  • (added) lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/Makefile (+3)
  • (added) lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py (+119)
  • (added) lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/main.cpp (+32)
  • (modified) lldb/unittests/ValueObject/DILLexerTests.cpp (+29-4)
diff --git a/lldb/docs/dil-expr-lang.ebnf b/lldb/docs/dil-expr-lang.ebnf
index c8bf4231b3e4a..d54f65df15865 100644
--- a/lldb/docs/dil-expr-lang.ebnf
+++ b/lldb/docs/dil-expr-lang.ebnf
@@ -6,16 +6,19 @@
 expression = unary_expression ;
 
 unary_expression = unary_operator expression
-                 | primary_expression ;
+                 | postfix_expression ;
 
 unary_operator = "*" | "&" ;
 
+postfix_expression = primary_expression
+                   | postfix_expression "[" integer_literal "]";
+
 primary_expression = id_expression
                    | "(" expression ")";
 
 id_expression = unqualified_id
               | qualified_id
-	      | register ;
+              | register ;
 
 unqualified_id = identifier ;
 
@@ -24,6 +27,8 @@ qualified_id = ["::"] [nested_name_specifier] unqualified_id
 
 identifier = ? C99 Identifier ? ;
 
+integer_literal = ? Integer constant: hexademical, decimal, octal, binary ? ;
+
 register = "$" ? Register name ? ;
 
 nested_name_specifier = type_name "::"
diff --git a/lldb/include/lldb/ValueObject/DILAST.h b/lldb/include/lldb/ValueObject/DILAST.h
index fe3827ef0516a..c53fafefe2a0a 100644
--- a/lldb/include/lldb/ValueObject/DILAST.h
+++ b/lldb/include/lldb/ValueObject/DILAST.h
@@ -18,8 +18,10 @@ namespace lldb_private::dil {
 
 /// The various types DIL AST nodes (used by the DIL parser).
 enum class NodeKind {
+  eArraySubscriptNode,
   eErrorNode,
   eIdentifierNode,
+  eScalarLiteralNode,
   eUnaryOpNode,
 };
 
@@ -96,8 +98,8 @@ class UnaryOpNode : public ASTNode {
 
   llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override;
 
-  UnaryOpKind kind() const { return m_kind; }
-  ASTNode *operand() const { return m_operand.get(); }
+  UnaryOpKind GetKind() const { return m_kind; }
+  ASTNode *GetOperand() const { return m_operand.get(); }
 
   static bool classof(const ASTNode *node) {
     return node->GetKind() == NodeKind::eUnaryOpNode;
@@ -108,6 +110,26 @@ class UnaryOpNode : public ASTNode {
   ASTNodeUP m_operand;
 };
 
+class ArraySubscriptNode : public ASTNode {
+public:
+  ArraySubscriptNode(uint32_t location, ASTNodeUP base, int64_t index)
+      : ASTNode(location, NodeKind::eArraySubscriptNode),
+        m_base(std::move(base)), m_index(index) {}
+
+  llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override;
+
+  ASTNode *GetBase() const { return m_base.get(); }
+  int64_t GetIndex() const { return m_index; }
+
+  static bool classof(const ASTNode *node) {
+    return node->GetKind() == NodeKind::eArraySubscriptNode;
+  }
+
+private:
+  ASTNodeUP m_base;
+  int64_t m_index;
+};
+
 /// This class contains one Visit method for each specialized type of
 /// DIL AST node. The Visit methods are used to dispatch a DIL AST node to
 /// the correct function in the DIL expression evaluator for evaluating that
@@ -119,6 +141,8 @@ class Visitor {
   Visit(const IdentifierNode *node) = 0;
   virtual llvm::Expected<lldb::ValueObjectSP>
   Visit(const UnaryOpNode *node) = 0;
+  virtual llvm::Expected<lldb::ValueObjectSP>
+  Visit(const ArraySubscriptNode *node) = 0;
 };
 
 } // namespace lldb_private::dil
diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h
index b1dd3fdb49739..03f869297c18f 100644
--- a/lldb/include/lldb/ValueObject/DILEval.h
+++ b/lldb/include/lldb/ValueObject/DILEval.h
@@ -50,6 +50,8 @@ class Interpreter : Visitor {
   llvm::Expected<lldb::ValueObjectSP>
   Visit(const IdentifierNode *node) override;
   llvm::Expected<lldb::ValueObjectSP> Visit(const UnaryOpNode *node) override;
+  llvm::Expected<lldb::ValueObjectSP>
+  Visit(const ArraySubscriptNode *node) override;
 
   // Used by the interpreter to create objects, perform casts, etc.
   lldb::TargetSP m_target;
diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
index 3508b8b7a85c6..0176db73835e9 100644
--- a/lldb/include/lldb/ValueObject/DILLexer.h
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -29,7 +29,10 @@ class Token {
     eof,
     identifier,
     l_paren,
+    l_square,
+    numeric_constant,
     r_paren,
+    r_square,
     star,
   };
 
diff --git a/lldb/include/lldb/ValueObject/DILParser.h b/lldb/include/lldb/ValueObject/DILParser.h
index f5c00b1040ef4..2df9678173870 100644
--- a/lldb/include/lldb/ValueObject/DILParser.h
+++ b/lldb/include/lldb/ValueObject/DILParser.h
@@ -84,12 +84,14 @@ class DILParser {
 
   ASTNodeUP ParseExpression();
   ASTNodeUP ParseUnaryExpression();
+  ASTNodeUP ParsePostfixExpression();
   ASTNodeUP ParsePrimaryExpression();
 
   std::string ParseNestedNameSpecifier();
 
   std::string ParseIdExpression();
   std::string ParseUnqualifiedId();
+  std::optional<int64_t> ParseIntegerConstant();
 
   void BailOut(const std::string &error, uint32_t loc, uint16_t err_len);
 
diff --git a/lldb/source/ValueObject/DILAST.cpp b/lldb/source/ValueObject/DILAST.cpp
index ea847587501ee..330b5a3f3c586 100644
--- a/lldb/source/ValueObject/DILAST.cpp
+++ b/lldb/source/ValueObject/DILAST.cpp
@@ -23,4 +23,9 @@ llvm::Expected<lldb::ValueObjectSP> UnaryOpNode::Accept(Visitor *v) const {
   return v->Visit(this);
 }
 
+llvm::Expected<lldb::ValueObjectSP>
+ArraySubscriptNode::Accept(Visitor *v) const {
+  return v->Visit(this);
+}
+
 } // namespace lldb_private::dil
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index 15a66d4866305..da3f9969fce2b 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -237,13 +237,13 @@ Interpreter::Visit(const IdentifierNode *node) {
 llvm::Expected<lldb::ValueObjectSP>
 Interpreter::Visit(const UnaryOpNode *node) {
   Status error;
-  auto rhs_or_err = Evaluate(node->operand());
+  auto rhs_or_err = Evaluate(node->GetOperand());
   if (!rhs_or_err)
     return rhs_or_err;
 
   lldb::ValueObjectSP rhs = *rhs_or_err;
 
-  switch (node->kind()) {
+  switch (node->GetKind()) {
   case UnaryOpKind::Deref: {
     lldb::ValueObjectSP dynamic_rhs = rhs->GetDynamicValue(m_default_dynamic);
     if (dynamic_rhs)
@@ -272,4 +272,51 @@ Interpreter::Visit(const UnaryOpNode *node) {
       m_expr, "invalid ast: unexpected binary operator", node->GetLocation());
 }
 
+llvm::Expected<lldb::ValueObjectSP>
+Interpreter::Visit(const ArraySubscriptNode *node) {
+  auto lhs_or_err = Evaluate(node->GetBase());
+  if (!lhs_or_err)
+    return lhs_or_err;
+  lldb::ValueObjectSP base = *lhs_or_err;
+
+  // Check to see if 'base' has a synthetic value; if so, try using that.
+  uint64_t child_idx = node->GetIndex();
+  if (lldb::ValueObjectSP synthetic = base->GetSyntheticValue()) {
+    llvm::Expected<uint32_t> num_children =
+        synthetic->GetNumChildren(child_idx + 1);
+    if (!num_children)
+      return llvm::make_error<DILDiagnosticError>(
+          m_expr, toString(num_children.takeError()), node->GetLocation());
+    if (child_idx >= *num_children) {
+      std::string message = llvm::formatv(
+          "array index {0} is not valid for \"({1}) {2}\"", child_idx,
+          base->GetTypeName().AsCString("<invalid type>"),
+          base->GetName().AsCString());
+      return llvm::make_error<DILDiagnosticError>(m_expr, message,
+                                                  node->GetLocation());
+    }
+    if (lldb::ValueObjectSP child_valobj_sp =
+            synthetic->GetChildAtIndex(child_idx))
+      return child_valobj_sp;
+  }
+
+  auto base_type = base->GetCompilerType().GetNonReferenceType();
+  if (!base_type.IsPointerType() && !base_type.IsArrayType())
+    return llvm::make_error<DILDiagnosticError>(
+        m_expr, "subscripted value is not an array or pointer",
+        node->GetLocation());
+  if (base_type.IsPointerToVoid())
+    return llvm::make_error<DILDiagnosticError>(
+        m_expr, "subscript of pointer to incomplete type 'void'",
+        node->GetLocation());
+
+  if (base_type.IsArrayType()) {
+    if (lldb::ValueObjectSP child_valobj_sp = base->GetChildAtIndex(child_idx))
+      return child_valobj_sp;
+  }
+
+  int64_t signed_child_idx = node->GetIndex();
+  return base->GetSyntheticArrayMember(signed_child_idx, true);
+}
+
 } // namespace lldb_private::dil
diff --git a/lldb/source/ValueObject/DILLexer.cpp b/lldb/source/ValueObject/DILLexer.cpp
index b9c2e7971e3b4..449feb7dee55b 100644
--- a/lldb/source/ValueObject/DILLexer.cpp
+++ b/lldb/source/ValueObject/DILLexer.cpp
@@ -13,6 +13,7 @@
 
 #include "lldb/ValueObject/DILLexer.h"
 #include "lldb/Utility/Status.h"
+#include "lldb/ValueObject/DILParser.h"
 #include "llvm/ADT/StringSwitch.h"
 
 namespace lldb_private::dil {
@@ -29,8 +30,14 @@ llvm::StringRef Token::GetTokenName(Kind kind) {
     return "identifier";
   case Kind::l_paren:
     return "l_paren";
+  case Kind::l_square:
+    return "l_square";
+  case Kind::numeric_constant:
+    return "numeric_constant";
   case Kind::r_paren:
     return "r_paren";
+  case Kind::r_square:
+    return "r_square";
   case Token::star:
     return "star";
   }
@@ -57,6 +64,18 @@ static std::optional<llvm::StringRef> IsWord(llvm::StringRef expr,
   return candidate;
 }
 
+static bool IsNumberBodyChar(char ch) { return IsDigit(ch) || IsLetter(ch); }
+
+static std::optional<llvm::StringRef> IsNumber(llvm::StringRef expr,
+                                               llvm::StringRef &remainder) {
+  if (IsDigit(remainder[0])) {
+    llvm::StringRef number = remainder.take_while(IsNumberBodyChar);
+    remainder = remainder.drop_front(number.size());
+    return number;
+  }
+  return std::nullopt;
+}
+
 llvm::Expected<DILLexer> DILLexer::Create(llvm::StringRef expr) {
   std::vector<Token> tokens;
   llvm::StringRef remainder = expr;
@@ -81,13 +100,17 @@ llvm::Expected<Token> DILLexer::Lex(llvm::StringRef expr,
     return Token(Token::eof, "", (uint32_t)expr.size());
 
   uint32_t position = cur_pos - expr.begin();
+  std::optional<llvm::StringRef> maybe_number = IsNumber(expr, remainder);
+  if (maybe_number)
+    return Token(Token::numeric_constant, maybe_number->str(), position);
   std::optional<llvm::StringRef> maybe_word = IsWord(expr, remainder);
   if (maybe_word)
     return Token(Token::identifier, maybe_word->str(), position);
 
   constexpr std::pair<Token::Kind, const char *> operators[] = {
-      {Token::amp, "&"},     {Token::coloncolon, "::"}, {Token::l_paren, "("},
-      {Token::r_paren, ")"}, {Token::star, "*"},
+      {Token::amp, "&"},      {Token::coloncolon, "::"}, {Token::l_paren, "("},
+      {Token::l_square, "["}, {Token::r_paren, ")"},     {Token::r_square, "]"},
+      {Token::star, "*"},
   };
   for (auto [kind, str] : operators) {
     if (remainder.consume_front(str))
@@ -95,7 +118,8 @@ llvm::Expected<Token> DILLexer::Lex(llvm::StringRef expr,
   }
 
   // Unrecognized character(s) in string; unable to lex it.
-  return llvm::createStringError("Unable to lex input string");
+  return llvm::make_error<DILDiagnosticError>(expr, "unrecognized token",
+                                              position);
 }
 
 } // namespace lldb_private::dil
diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp
index 2c78eae8cf6bf..f310538617589 100644
--- a/lldb/source/ValueObject/DILParser.cpp
+++ b/lldb/source/ValueObject/DILParser.cpp
@@ -111,7 +111,42 @@ ASTNodeUP DILParser::ParseUnaryExpression() {
       llvm_unreachable("invalid token kind");
     }
   }
-  return ParsePrimaryExpression();
+  return ParsePostfixExpression();
+}
+
+// Parse a postfix_expression.
+//
+//  postfix_expression:
+//    primary_expression
+//    postfix_expression "[" integer_literal "]"
+//
+ASTNodeUP DILParser::ParsePostfixExpression() {
+  ASTNodeUP lhs = ParsePrimaryExpression();
+  while (CurToken().Is(Token::l_square)) {
+    uint32_t loc = CurToken().GetLocation();
+    Token token = CurToken();
+    switch (token.GetKind()) {
+    case Token::l_square: {
+      m_dil_lexer.Advance();
+      std::optional<int64_t> rhs = ParseIntegerConstant();
+      if (!rhs) {
+        BailOut(
+            llvm::formatv("failed to parse integer constant: {0}", CurToken()),
+            CurToken().GetLocation(), CurToken().GetSpelling().length());
+        return std::make_unique<ErrorNode>();
+      }
+      Expect(Token::r_square);
+      m_dil_lexer.Advance();
+      lhs = std::make_unique<ArraySubscriptNode>(loc, std::move(lhs),
+                                                 std::move(*rhs));
+      break;
+    }
+    default:
+      llvm_unreachable("invalid token");
+    }
+  }
+
+  return lhs;
 }
 
 // Parse a primary_expression.
@@ -280,6 +315,23 @@ void DILParser::BailOut(const std::string &error, uint32_t loc,
   m_dil_lexer.ResetTokenIdx(m_dil_lexer.NumLexedTokens() - 1);
 }
 
+// Parse a integer_literal.
+//
+//  integer_literal:
+//    ? Integer constant ?
+//
+std::optional<int64_t> DILParser::ParseIntegerConstant() {
+  auto spelling = CurToken().GetSpelling();
+  llvm::StringRef spelling_ref = spelling;
+  int64_t raw_value;
+  if (!spelling_ref.getAsInteger<int64_t>(0, raw_value)) {
+    m_dil_lexer.Advance();
+    return raw_value;
+  }
+
+  return std::nullopt;
+}
+
 void DILParser::Expect(Token::Kind kind) {
   if (CurToken().IsNot(kind)) {
     BailOut(llvm::formatv("expected {0}, got: {1}", kind, CurToken()),
diff --git a/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/Makefile b/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
diff --git a/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py b/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py
new file mode 100644
index 0000000000000..88de5965184fd
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py
@@ -0,0 +1,119 @@
+"""
+Test DIL array subscript.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test import lldbutil
+
+
+class TestFrameVarDILArraySubscript(TestBase):
+    NO_DEBUG_INFO_TESTCASE = True
+
+    def expect_var_path(self, expr, compare_to_framevar=False, value=None, type=None):
+        value_dil = super().expect_var_path(expr, value=value, type=type)
+        if compare_to_framevar:
+            self.runCmd("settings set target.experimental.use-DIL false")
+            value_frv = super().expect_var_path(expr, value=value, type=type)
+            self.runCmd("settings set target.experimental.use-DIL true")
+            self.assertEqual(value_dil.GetValue(), value_frv.GetValue())
+
+    def test_subscript(self):
+        self.build()
+        lldbutil.run_to_source_breakpoint(
+            self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
+        )
+
+        self.runCmd("settings set target.experimental.use-DIL true")
+
+        # Test int[] and int*
+        self.expect_var_path("int_arr[0]", True, value="1")
+        self.expect_var_path("int_ptr[1]", True, value="2")
+        self.expect("frame var 'int_arr[enum_one]'", error=True)
+
+        # Test when base and index are references.
+        self.expect_var_path("int_arr[0]", True, value="1")
+        self.expect("frame var 'int_arr[idx_1_ref]'", error=True)
+        self.expect("frame var 'int_arr[enum_ref]'", error=True)
+        self.expect_var_path("int_arr_ref[0]", value="1")
+        self.expect("frame var 'int_arr_ref[idx_1_ref]'", error=True)
+        self.expect("frame var 'int_arr_ref[enum_ref]'", error=True)
+
+        # Test when base and index are typedefs.
+        self.expect_var_path("td_int_arr[0]", True, value="1")
+        self.expect("frame var 'td_int_arr[td_int_idx_1]'", error=True)
+        self.expect("frame var 'td_int_arr[td_td_int_idx_2]'", error=True)
+        self.expect_var_path("td_int_ptr[0]", True, value="1")
+        self.expect("frame var 'td_int_ptr[td_int_idx_1]'", error=True)
+        self.expect("frame var 'td_int_ptr[td_td_int_idx_2]'", error=True)
+
+        # Both typedefs and refs
+        self.expect("frame var 'td_int_arr_ref[td_int_idx_1_ref]'", error=True)
+
+        # Test for index out of bounds.
+        self.expect_var_path("int_arr[42]", True, type="int")
+        self.expect_var_path("int_arr[100]", True, type="int")
+
+        # Test address-of of the subscripted value.
+        self.expect_var_path("*(&int_arr[1])", value="2")
+
+        # Test for negative index.
+        self.expect(
+            "frame var 'int_arr[-1]'",
+            error=True,
+            substrs=["unrecognized token"],
+        )
+
+        # Test for floating point index
+        self.expect(
+            "frame var 'int_arr[1.0]'",
+            error=True,
+            substrs=["unrecognized token"],
+        )
+
+        # Base should be a "pointer to T" and index should be of an integral type.
+        self.expect(
+            "frame var 'idx_1[0]'",
+            error=True,
+            substrs=["subscripted value is not an array or pointer"],
+        )
+        self.expect(
+            "frame var 'idx_1_ref[0]'",
+            error=True,
+            substrs=["subscripted value is not an array or pointer"],
+        )
+        self.expect(
+            "frame var 'int_arr[int_ptr]'",
+            error=True,
+            substrs=["failed to parse integer constant"],
+        )
+        self.expect(
+            "frame var '1[2]'",
+            error=True,
+            substrs=["Unexpected token"],
+        )
+
+        # Base should not be a pointer to void
+        self.expect(
+            "frame var 'p_void[0]'",
+            error=True,
+            substrs=["subscript of pointer to incomplete type 'void'"],
+        )
+
+    @skipIf(oslist=["windows"], archs=["aarch64"])
+    def test_subscript_synthetic(self):
+        self.build()
+        lldbutil.run_to_source_breakpoint(
+            self, "Set a breakpoint here", lldb.SBFileSpec("main.cpp")
+        )
+
+        self.runCmd("settings set target.experimental.use-DIL true")
+
+        # Test synthetic value subscription
+        self.expect_var_path("vector[1]", value="2")
+        self.expect(
+            "frame var 'vector[100]'",
+            error=True,
+            substrs=["array index 100 is not valid"],
+        )
diff --git a/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/main.cpp b/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/main.cpp
new file mode 100644
index 0000000000000..485666ae46c20
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/main.cpp
@@ -0,0 +1,32 @@
+#include <vector>
+
+int main(int argc, char **argv) {
+  int int_arr[] = {1, 2, 3};
+  int *int_ptr = int_arr;
+  int(&int_arr_ref)[3] = int_arr;
+  void *p_void = (void *)int_arr;
+
+  int idx_1 = 1;
+  const int &idx_1_ref = idx_1;
+
+  typedef int td_int_t;
+  typedef td_int_t td_td_int_t;
+  typedef int *td_int_ptr_t;
+  typedef int &td_int_ref_t;
+
+  td_int_t td_int_idx_1 = 1;
+  td_td_int_t td_td_int_idx_2 = 2;
+
+  td_int_t td_int_arr[3] = {1, 2, 3};
+  td_int_ptr_t td_int_ptr = td_int_arr;
+
+  td_int_ref_t td_int_idx_1_ref = td_int_idx_1;
+  td_int_t(&td_int_arr_ref)[3] = td_int_arr;
+
+  enum Enum { kZero, kOne } enum_one = kOne;
+  Enum &enum_ref = enum_one;
+
+  std::vector<int> vector = {1, 2, 3};
+
+  return 0; // Set a breakpoint here
+}
diff --git a/lldb/unittests/ValueObject/DILLexerTests.cpp b/lldb/unittests/ValueObject/DILLexerTests.cpp
index 9afa957901ae7..f65034c1dbea3 100644
--- a/lldb/unittests/ValueObject/DILLexerTests.cpp
+++ b/lldb/unittests/ValueObject/DILLexerTests.cpp
@@ -121,11 +121,11 @@ TEST(DILLexerTests, IdentifiersTest) {
       "a_b",       "this", "self", "a", "MyName", "namespace"};
 
   // The lexer can lex these strings, but they should not be identifiers.
-  std::vector<std::string> invalid_identifiers = {"", "::", "(", ")"};
+  std::vector<std::string> invalid_identifiers = {"", "::", "(", ")", "0abc"};
 
   // The lexer is expected to fail attempting to lex these strings (it cannot
   // create valid tokens out of them).
-  std::vector<std::string> invalid_tok_strings = {"234", "2a", "2", "1MyName"};
+  std::vector<std::string> invalid_tok_strings = {"#include", "a@a"};
 
   // Verify that all of the valid identifiers c...
[truncated]

@kuilpd
Copy link
Contributor Author

kuilpd commented May 22, 2025

@labath
This code

    llvm::Expected<uint32_t> num_children = synthetic->GetNumChildren(child_idx + 1);

didn't work for std::vector on Windows on AArch64, got a buildbot error there: https://lab.llvm.org/buildbot/#/builders/141/builds/8906

AssertionError: '<user expression 0>:1:7: array index 1 is not valid for "(vector<int, std::allocator<int> >) vector"
   1 | vector[1]
     | ^' is not success

It returned some value, but probably zero, so the child_idx >= *num_children failed.
I don't know how to even approach this, can we just skip the test for now as I did in the second commit?

Copy link
Collaborator

@labath labath left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it's fine. the std::vector formatter tests are not running currently on windows, so it's likely that formatter is just broken there. Since this is test for the DIL and not std::vector, we could write our own formatter to test this functionality, but I think that would be overkill. We can keep the test here, and once the new implementation is enabled, we can move the relevant part to the test for std::vector.

substrs=["subscript of pointer to incomplete type 'void'"],
)

@skipIf(oslist=["windows"], archs=["aarch64"])
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Suggested change
@skipIf(oslist=["windows"], archs=["aarch64"])
@expectedFailureAll(oslist=["windows"])

I doubt this is specific to aarch64. It just happens we have no other bot around. And lets use xfail so we know to re-enable this when it gets fixed.

@kuilpd kuilpd force-pushed the DIL-upstream-add-subscript-fix-test branch from 928fb6f to 37fbebf Compare May 25, 2025 15:16
@kuilpd kuilpd merged commit fe51d8a into llvm:main May 25, 2025
11 checks passed
@llvm-ci
Copy link
Collaborator

llvm-ci commented May 25, 2025

LLVM Buildbot has detected a new failure on builder lldb-remote-linux-ubuntu running on as-builder-9 while building lldb at step 16 "test-check-lldb-api".

Full details are available at: https://lab.llvm.org/buildbot/#/builders/195/builds/9534

Here is the relevant piece of the build log for the reference
Step 16 (test-check-lldb-api) failure: Test just built components: check-lldb-api completed (failure)
******************** TEST 'lldb-api :: functionalities/thread/exit_during_step/TestExitDuringStep.py' FAILED ********************
Script:
--
/usr/bin/python3.12 /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/llvm-project/lldb/test/API/dotest.py -u CXXFLAGS -u CFLAGS --env LLVM_LIBS_DIR=/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./lib --env LLVM_INCLUDE_DIR=/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/include --env LLVM_TOOLS_DIR=/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./bin --libcxx-include-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/include/c++/v1 --libcxx-include-target-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/include/aarch64-unknown-linux-gnu/c++/v1 --libcxx-library-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./lib/aarch64-unknown-linux-gnu --arch aarch64 --build-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/lldb-test-build.noindex --lldb-module-cache-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/lldb-test-build.noindex/module-cache-lldb/lldb-api --clang-module-cache-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/lldb-test-build.noindex/module-cache-clang/lldb-api --executable /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./bin/lldb --compiler /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/bin/clang --dsymutil /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./bin/dsymutil --make /usr/bin/gmake --llvm-tools-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./bin --lldb-obj-root /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/tools/lldb --lldb-libs-dir /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/./lib --cmake-build-type Release --platform-url connect://jetson-agx-2198.lab.llvm.org:1234 --platform-working-dir /home/ubuntu/lldb-tests --sysroot /mnt/fs/jetson-agx-ubuntu --env ARCH_CFLAGS=-mcpu=cortex-a78 --platform-name remote-linux --skip-category=lldb-server /home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/llvm-project/lldb/test/API/functionalities/thread/exit_during_step -p TestExitDuringStep.py
--
Exit Code: 1

Command Output (stdout):
--
lldb version 21.0.0git (https://github.com/llvm/llvm-project.git revision fe51d8ae5772626ef8237c33e0911695cf4f07db)
  clang revision fe51d8ae5772626ef8237c33e0911695cf4f07db
  llvm revision fe51d8ae5772626ef8237c33e0911695cf4f07db
Setting up remote platform 'remote-linux'
Connecting to remote platform 'remote-linux' at 'connect://jetson-agx-2198.lab.llvm.org:1234'...
Connected.
Setting remote platform working directory to '/home/ubuntu/lldb-tests'...
Skipping the following test categories: ['lldb-server', 'dsym', 'gmodules', 'debugserver', 'objc', 'lldb-dap']

--
Command Output (stderr):
--
WARNING:root:Custom libc++ is not supported for remote runs: ignoring --libcxx arguments
UNSUPPORTED: LLDB (/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/bin/clang-aarch64) :: test_dsym (TestExitDuringStep.ExitDuringStepTestCase.test_dsym) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/bin/clang-aarch64) :: test_dwarf (TestExitDuringStep.ExitDuringStepTestCase.test_dwarf)
PASS: LLDB (/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/bin/clang-aarch64) :: test_dwo (TestExitDuringStep.ExitDuringStepTestCase.test_dwo)
UNSUPPORTED: LLDB (/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/bin/clang-aarch64) :: test_step_in_dsym (TestExitDuringStep.ExitDuringStepTestCase.test_step_in_dsym) (test case does not fall in any category of interest for this run) 
FAIL: LLDB (/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/bin/clang-aarch64) :: test_step_in_dwarf (TestExitDuringStep.ExitDuringStepTestCase.test_step_in_dwarf)
PASS: LLDB (/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/bin/clang-aarch64) :: test_step_in_dwo (TestExitDuringStep.ExitDuringStepTestCase.test_step_in_dwo)
UNSUPPORTED: LLDB (/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/bin/clang-aarch64) :: test_step_over_dsym (TestExitDuringStep.ExitDuringStepTestCase.test_step_over_dsym) (test case does not fall in any category of interest for this run) 
PASS: LLDB (/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/bin/clang-aarch64) :: test_step_over_dwarf (TestExitDuringStep.ExitDuringStepTestCase.test_step_over_dwarf)
PASS: LLDB (/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/bin/clang-aarch64) :: test_step_over_dwo (TestExitDuringStep.ExitDuringStepTestCase.test_step_over_dwo)
======================================================================
FAIL: test_step_in_dwarf (TestExitDuringStep.ExitDuringStepTestCase.test_step_in_dwarf)
   Test thread exit during step-in handling.
----------------------------------------------------------------------
Traceback (most recent call last):
  File "/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/llvm-project/lldb/packages/Python/lldbsuite/test/lldbtest.py", line 1804, in test_method
    return attrvalue(self)
           ^^^^^^^^^^^^^^^
  File "/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/llvm-project/lldb/test/API/functionalities/thread/exit_during_step/TestExitDuringStep.py", line 33, in test_step_in
    self.exit_during_step_base(
  File "/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/llvm-project/lldb/test/API/functionalities/thread/exit_during_step/TestExitDuringStep.py", line 118, in exit_during_step_base
    self.assertGreaterEqual(
AssertionError: 0 not greater than or equal to 22 : Stepped to unexpected line, 0
Config=aarch64-/home/buildbot/worker/as-builder-9/lldb-remote-linux-ubuntu/build/bin/clang
----------------------------------------------------------------------
Ran 9 tests in 11.522s

FAILED (failures=1, skipped=3)

...

sivan-shani pushed a commit to sivan-shani/llvm-project that referenced this pull request Jun 3, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants