[Lldb-commits] [lldb] [lldb] Use AST nodes as Subscript and BitField arguments in DIL (PR #169363)
Ilia Kuklin via lldb-commits
lldb-commits at lists.llvm.org
Tue Dec 9 08:13:09 PST 2025
https://github.com/kuilpd updated https://github.com/llvm/llvm-project/pull/169363
>From 04720a744587cccd827b9c2bb23bcc0c3c4a1836 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Mon, 24 Nov 2025 19:43:04 +0500
Subject: [PATCH 1/4] [LLDB] Use AST nodes as Subscript and BitField arguments
in DIL
---
lldb/docs/dil-expr-lang.ebnf | 5 +-
lldb/include/lldb/ValueObject/DILAST.h | 24 +++----
lldb/include/lldb/ValueObject/DILEval.h | 2 +
lldb/include/lldb/ValueObject/DILParser.h | 1 -
lldb/source/ValueObject/DILEval.cpp | 70 ++++++++++++++-----
lldb/source/ValueObject/DILParser.cpp | 49 ++-----------
.../TestFrameVarDILArraySubscript.py | 48 ++++++-------
.../var-dil/basics/ArraySubscript/main.cpp | 5 +-
.../TestFrameVarDILBitFieldExtraction.py | 28 ++++----
.../basics/BitFieldExtraction/main.cpp | 10 ++-
10 files changed, 123 insertions(+), 119 deletions(-)
diff --git a/lldb/docs/dil-expr-lang.ebnf b/lldb/docs/dil-expr-lang.ebnf
index ccd2b00223910..554b107c117e0 100644
--- a/lldb/docs/dil-expr-lang.ebnf
+++ b/lldb/docs/dil-expr-lang.ebnf
@@ -11,7 +11,8 @@ unary_expression = postfix_expression
unary_operator = "*" | "&" | "+" | "-";
postfix_expression = primary_expression
- | postfix_expression "[" integer_literal "]"
+ | postfix_expression "[" expression "]"
+ | postfix_expression "[" expression "-" expression "]"
| postfix_expression "." id_expression
| postfix_expression "->" id_expression ;
@@ -31,8 +32,6 @@ qualified_id = ["::"] [nested_name_specifier] unqualified_id
identifier = ? C99 Identifier ? ;
-integer_literal = ? Integer constant: hexademical, decimal, octal, binary ? ;
-
numeric_literal = ? Integer constant: hexademical, decimal, octal, binary ?
| ? Floating constant ? ;
diff --git a/lldb/include/lldb/ValueObject/DILAST.h b/lldb/include/lldb/ValueObject/DILAST.h
index 91f8d93c09622..31de575f25fb0 100644
--- a/lldb/include/lldb/ValueObject/DILAST.h
+++ b/lldb/include/lldb/ValueObject/DILAST.h
@@ -141,14 +141,14 @@ class UnaryOpNode : public ASTNode {
class ArraySubscriptNode : public ASTNode {
public:
- ArraySubscriptNode(uint32_t location, ASTNodeUP base, int64_t index)
+ ArraySubscriptNode(uint32_t location, ASTNodeUP base, ASTNodeUP index)
: ASTNode(location, NodeKind::eArraySubscriptNode),
- m_base(std::move(base)), m_index(index) {}
+ m_base(std::move(base)), m_index(std::move(index)) {}
llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override;
ASTNode *GetBase() const { return m_base.get(); }
- int64_t GetIndex() const { return m_index; }
+ ASTNode *GetIndex() const { return m_index.get(); }
static bool classof(const ASTNode *node) {
return node->GetKind() == NodeKind::eArraySubscriptNode;
@@ -156,22 +156,22 @@ class ArraySubscriptNode : public ASTNode {
private:
ASTNodeUP m_base;
- int64_t m_index;
+ ASTNodeUP m_index;
};
class BitFieldExtractionNode : public ASTNode {
public:
- BitFieldExtractionNode(uint32_t location, ASTNodeUP base, int64_t first_index,
- int64_t last_index)
+ BitFieldExtractionNode(uint32_t location, ASTNodeUP base,
+ ASTNodeUP first_index, ASTNodeUP last_index)
: ASTNode(location, NodeKind::eBitExtractionNode),
- m_base(std::move(base)), m_first_index(first_index),
- m_last_index(last_index) {}
+ m_base(std::move(base)), m_first_index(std::move(first_index)),
+ m_last_index(std::move(last_index)) {}
llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override;
ASTNode *GetBase() const { return m_base.get(); }
- int64_t GetFirstIndex() const { return m_first_index; }
- int64_t GetLastIndex() const { return m_last_index; }
+ ASTNode *GetFirstIndex() const { return m_first_index.get(); }
+ ASTNode *GetLastIndex() const { return m_last_index.get(); }
static bool classof(const ASTNode *node) {
return node->GetKind() == NodeKind::eBitExtractionNode;
@@ -179,8 +179,8 @@ class BitFieldExtractionNode : public ASTNode {
private:
ASTNodeUP m_base;
- int64_t m_first_index;
- int64_t m_last_index;
+ ASTNodeUP m_first_index;
+ ASTNodeUP m_last_index;
};
enum class IntegerTypeSuffix { None, Long, LongLong };
diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h
index a65edc58cc4e7..b88177a269ab5 100644
--- a/lldb/include/lldb/ValueObject/DILEval.h
+++ b/lldb/include/lldb/ValueObject/DILEval.h
@@ -46,6 +46,8 @@ class Interpreter : Visitor {
llvm::Expected<lldb::ValueObjectSP> Evaluate(const ASTNode *node);
private:
+ llvm::Expected<lldb::ValueObjectSP>
+ EvaluateAndDereference(const ASTNode *node);
llvm::Expected<lldb::ValueObjectSP>
Visit(const IdentifierNode *node) override;
llvm::Expected<lldb::ValueObjectSP> Visit(const MemberOfNode *node) override;
diff --git a/lldb/include/lldb/ValueObject/DILParser.h b/lldb/include/lldb/ValueObject/DILParser.h
index c9d28333ffed1..0633ab08e849b 100644
--- a/lldb/include/lldb/ValueObject/DILParser.h
+++ b/lldb/include/lldb/ValueObject/DILParser.h
@@ -95,7 +95,6 @@ class DILParser {
std::string ParseIdExpression();
std::string ParseUnqualifiedId();
- std::optional<int64_t> ParseIntegerConstant();
ASTNodeUP ParseNumericLiteral();
ASTNodeUP ParseIntegerLiteral();
ASTNodeUP ParseFloatingPointLiteral();
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index 40a05a467f883..46d949a52f880 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -251,6 +251,22 @@ llvm::Expected<lldb::ValueObjectSP> Interpreter::Evaluate(const ASTNode *node) {
return value_or_error;
}
+llvm::Expected<lldb::ValueObjectSP>
+Interpreter::EvaluateAndDereference(const ASTNode *node) {
+ auto valobj_or_err = Evaluate(node);
+ if (!valobj_or_err)
+ return valobj_or_err;
+ lldb::ValueObjectSP valobj = *valobj_or_err;
+
+ Status error;
+ if (valobj->GetCompilerType().IsReferenceType()) {
+ valobj = valobj->Dereference(error);
+ if (error.Fail())
+ return error.ToError();
+ }
+ return valobj;
+}
+
llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const IdentifierNode *node) {
lldb::DynamicValueType use_dynamic = m_use_dynamic;
@@ -477,13 +493,22 @@ Interpreter::Visit(const MemberOfNode *node) {
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;
+ auto base_or_err = Evaluate(node->GetBase());
+ if (!base_or_err)
+ return base_or_err;
+ lldb::ValueObjectSP base = *base_or_err;
+ auto idx_or_err = EvaluateAndDereference(node->GetIndex());
+ if (!idx_or_err)
+ return idx_or_err;
+ lldb::ValueObjectSP idx = *idx_or_err;
+
+ if (!idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, "array subscript is not an integer", node->GetLocation());
+ }
StreamString var_expr_path_strm;
- uint64_t child_idx = node->GetIndex();
+ uint64_t child_idx = idx->GetValueAsUnsigned(0);
lldb::ValueObjectSP child_valobj_sp;
bool is_incomplete_array = false;
@@ -613,29 +638,38 @@ Interpreter::Visit(const ArraySubscriptNode *node) {
return child_valobj_sp;
}
- int64_t signed_child_idx = node->GetIndex();
+ int64_t signed_child_idx = idx->GetValueAsSigned(0);
return base->GetSyntheticArrayMember(signed_child_idx, true);
}
llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const BitFieldExtractionNode *node) {
- auto lhs_or_err = Evaluate(node->GetBase());
- if (!lhs_or_err)
- return lhs_or_err;
- lldb::ValueObjectSP base = *lhs_or_err;
- int64_t first_index = node->GetFirstIndex();
- int64_t last_index = node->GetLastIndex();
+ auto base_or_err = EvaluateAndDereference(node->GetBase());
+ if (!base_or_err)
+ return base_or_err;
+ lldb::ValueObjectSP base = *base_or_err;
+ auto first_idx_or_err = EvaluateAndDereference(node->GetFirstIndex());
+ if (!first_idx_or_err)
+ return first_idx_or_err;
+ lldb::ValueObjectSP first_idx = *first_idx_or_err;
+ auto last_idx_or_err = EvaluateAndDereference(node->GetLastIndex());
+ if (!last_idx_or_err)
+ return last_idx_or_err;
+ lldb::ValueObjectSP last_idx = *last_idx_or_err;
+
+ if (!first_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType() ||
+ !last_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, "bit index is not an integer", node->GetLocation());
+ }
+
+ int64_t first_index = first_idx->GetValueAsSigned(0);
+ int64_t last_index = last_idx->GetValueAsSigned(0);
// if the format given is [high-low], swap range
if (first_index > last_index)
std::swap(first_index, last_index);
- Status error;
- if (base->GetCompilerType().IsReferenceType()) {
- base = base->Dereference(error);
- if (error.Fail())
- return error.ToError();
- }
lldb::ValueObjectSP child_valobj_sp =
base->GetSyntheticBitFieldChild(first_index, last_index, true);
if (!child_valobj_sp) {
diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp
index 072ddff1e28d2..b23c667e883d8 100644
--- a/lldb/source/ValueObject/DILParser.cpp
+++ b/lldb/source/ValueObject/DILParser.cpp
@@ -127,8 +127,8 @@ ASTNodeUP DILParser::ParseUnaryExpression() {
//
// postfix_expression:
// primary_expression
-// postfix_expression "[" integer_literal "]"
-// postfix_expression "[" integer_literal "-" integer_literal "]"
+// postfix_expression "[" expression "]"
+// postfix_expression "[" expression "-" expression "]"
// postfix_expression "." id_expression
// postfix_expression "->" id_expression
//
@@ -140,27 +140,15 @@ ASTNodeUP DILParser::ParsePostfixExpression() {
switch (token.GetKind()) {
case Token::l_square: {
m_dil_lexer.Advance();
- std::optional<int64_t> index = ParseIntegerConstant();
- if (!index) {
- BailOut(
- llvm::formatv("failed to parse integer constant: {0}", CurToken()),
- CurToken().GetLocation(), CurToken().GetSpelling().length());
- return std::make_unique<ErrorNode>();
- }
+ ASTNodeUP index = ParseExpression();
if (CurToken().GetKind() == Token::minus) {
m_dil_lexer.Advance();
- std::optional<int64_t> last_index = ParseIntegerConstant();
- if (!last_index) {
- BailOut(llvm::formatv("failed to parse integer constant: {0}",
- CurToken()),
- CurToken().GetLocation(), CurToken().GetSpelling().length());
- return std::make_unique<ErrorNode>();
- }
+ ASTNodeUP last_index = ParseExpression();
lhs = std::make_unique<BitFieldExtractionNode>(
- loc, std::move(lhs), std::move(*index), std::move(*last_index));
+ loc, std::move(lhs), std::move(index), std::move(last_index));
} else {
lhs = std::make_unique<ArraySubscriptNode>(loc, std::move(lhs),
- std::move(*index));
+ std::move(index));
}
Expect(Token::r_square);
m_dil_lexer.Advance();
@@ -374,31 +362,6 @@ void DILParser::BailOut(const std::string &error, uint32_t loc,
m_dil_lexer.ResetTokenIdx(m_dil_lexer.NumLexedTokens() - 1);
}
-// FIXME: Remove this once subscript operator uses ScalarLiteralNode.
-// Parse a integer_literal.
-//
-// integer_literal:
-// ? Integer constant ?
-//
-std::optional<int64_t> DILParser::ParseIntegerConstant() {
- std::string number_spelling;
- if (CurToken().GetKind() == Token::minus) {
- // StringRef::getAsInteger<>() can parse negative numbers.
- // FIXME: Remove this once unary minus operator is added.
- number_spelling = "-";
- m_dil_lexer.Advance();
- }
- number_spelling.append(CurToken().GetSpelling());
- llvm::StringRef spelling_ref = number_spelling;
- int64_t raw_value;
- if (!spelling_ref.getAsInteger<int64_t>(0, raw_value)) {
- m_dil_lexer.Advance();
- return raw_value;
- }
-
- return std::nullopt;
-}
-
// Parse a numeric_literal.
//
// numeric_literal:
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
index f47e86266f474..33d2e3c4fc2b2 100644
--- a/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py
+++ b/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/TestFrameVarDILArraySubscript.py
@@ -11,14 +11,6 @@
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(
@@ -28,45 +20,45 @@ def test_subscript(self):
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)
+ self.expect_var_path("int_arr[0]", value="1")
+ self.expect_var_path("int_ptr[1]", value="2")
+ self.expect_var_path("int_ptr[enum_one]", value="2")
# 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[0]", value="1")
+ self.expect_var_path("int_arr[idx_1_ref]", value="2")
+ self.expect_var_path("int_arr[enum_ref]", value="2")
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)
+ self.expect_var_path("int_arr_ref[idx_1_ref]", value="2")
+ self.expect_var_path("int_arr_ref[enum_ref]", value="2")
# 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)
+ self.expect_var_path("td_int_arr[0]", value="1")
+ self.expect_var_path("td_int_arr[td_int_idx_1]", value="2")
+ self.expect_var_path("td_int_arr[td_td_int_idx_2]", value="3")
+ self.expect_var_path("td_int_ptr[0]", value="1")
+ self.expect_var_path("td_int_ptr[td_int_idx_1]", value="2")
+ self.expect_var_path("td_int_ptr[td_td_int_idx_2]", value="3")
# Both typedefs and refs
- self.expect("frame var 'td_int_arr_ref[td_int_idx_1_ref]'", error=True)
+ self.expect_var_path("td_int_arr_ref[td_int_idx_1_ref]", value="2")
# Test for index out of bounds. 1 beyond the end.
- self.expect_var_path("int_arr[3]", True, type="int")
+ self.expect_var_path("int_arr[3]", type="int")
# Far beyond the end (but not far enough to be off the top of the stack).
- self.expect_var_path("int_arr[10]", True, type="int")
+ self.expect_var_path("int_arr[10]", type="int")
# Test address-of of the subscripted value.
self.expect_var_path("*(&int_arr[1])", value="2")
# Test for negative index.
- self.expect_var_path("int_ptr_1[-1]", True, value="1")
+ self.expect_var_path("int_ptr_1[-1]", value="1")
# Test for floating point index
self.expect(
"frame var 'int_arr[1.0]'",
error=True,
- substrs=["failed to parse integer constant: <'1.0' (float_constant)>"],
+ substrs=["array subscript is not an integer"],
)
# Test accessing bits in scalar types.
@@ -85,7 +77,7 @@ def test_subscript(self):
self.expect(
"frame var 'int_arr[int_ptr]'",
error=True,
- substrs=["failed to parse integer constant"],
+ substrs=["array subscript is not an integer"],
)
# Base should not be a pointer to void
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
index 03ad3e872ca76..241e93a0240cb 100644
--- a/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/main.cpp
+++ b/lldb/test/API/commands/frame/var-dil/basics/ArraySubscript/main.cpp
@@ -6,6 +6,8 @@ class myArray {
int m_arr_size = 4;
};
+void stop() {}
+
int main(int argc, char **argv) {
int int_arr[] = {1, 2, 3};
int *int_ptr = int_arr;
@@ -38,5 +40,6 @@ int main(int argc, char **argv) {
myArray ma;
myArray *ma_ptr = &ma;
- return 0; // Set a breakpoint here
+ stop(); // Set a breakpoint here
+ return 0;
}
diff --git a/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py b/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py
index 7b5ef0650b6e1..476c072b1cdc8 100644
--- a/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py
+++ b/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py
@@ -11,14 +11,6 @@
class TestFrameVarDILBitFieldExtraction(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_bitfield_extraction(self):
self.build()
lldbutil.run_to_source_breakpoint(
@@ -28,14 +20,21 @@ def test_bitfield_extraction(self):
self.runCmd("settings set target.experimental.use-DIL true")
# Test ranges and type
- self.expect_var_path("value[0-1]", True, value="3", type="int:2")
- self.expect_var_path("value[4-7]", True, value="7", type="int:4")
- self.expect_var_path("value[7-0]", True, value="115", type="int:8")
+ self.expect_var_path("value[0-1]", value="3", type="int:2")
+ self.expect_var_path("value[4-7]", value="7", type="int:4")
+ self.expect_var_path("value[7-0]", value="115", type="int:8")
# Test reference and dereferenced pointer
self.expect_var_path("value_ref[0-1]", value="3", type="int:2")
self.expect_var_path("(*value_ptr)[0-1]", value="3", type="int:2")
+ # Test ranges as variable, reference, enum
+ self.expect_var_path("value[idx_0-idx_1]", value="3", type="int:2")
+ self.expect_var_path("value[0-idx_1_ref]", value="3", type="int:2")
+ self.expect_var_path("value[idx_1_ref-0]", value="3", type="int:2")
+ self.expect_var_path("value[0-enum_one]", value="3", type="int:2")
+ self.expect_var_path("value[enum_one-0]", value="3", type="int:2")
+
# Test array and pointer
self.expect(
"frame var 'int_arr[0-2]'",
@@ -52,5 +51,10 @@ def test_bitfield_extraction(self):
self.expect(
"frame var 'value[1-]'",
error=True,
- substrs=["failed to parse integer constant"],
+ substrs=["Unexpected token: <']' (r_square)>"],
+ )
+ self.expect(
+ "frame var 'value[1-2.0]'",
+ error=True,
+ substrs=["bit index is not an integer"],
)
diff --git a/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/main.cpp b/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/main.cpp
index a35f68a9e30a8..122ea4e1acded 100644
--- a/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/main.cpp
+++ b/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/main.cpp
@@ -1,9 +1,17 @@
+void stop() {}
+
int main(int argc, char **argv) {
int value = 0b01110011;
int &value_ref = value;
int *value_ptr = &value;
+ int idx_0 = 0;
+ int idx_1 = 1;
+ const int &idx_1_ref = idx_1;
+ enum Enum { kZero, kOne } enum_one = kOne;
+
int int_arr[] = {7, 3, 1};
- return 0; // Set a breakpoint here
+ stop(); // Set a breakpoint here
+ return 0;
}
>From 5b8694045d9a6001baa0d3aa2fbe52556578fdf6 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Tue, 9 Dec 2025 20:24:59 +0500
Subject: [PATCH 2/4] Check GetValueAsSigned for success
---
lldb/source/ValueObject/DILEval.cpp | 15 ++++++++++++---
1 file changed, 12 insertions(+), 3 deletions(-)
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index 46d949a52f880..937c33fdf1c0e 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -638,7 +638,12 @@ Interpreter::Visit(const ArraySubscriptNode *node) {
return child_valobj_sp;
}
- int64_t signed_child_idx = idx->GetValueAsSigned(0);
+ bool success;
+ int64_t signed_child_idx = idx->GetValueAsSigned(0, &success);
+ if (!success)
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, "could not get the index as an integer",
+ node->GetIndex()->GetLocation());
return base->GetSyntheticArrayMember(signed_child_idx, true);
}
@@ -663,8 +668,12 @@ Interpreter::Visit(const BitFieldExtractionNode *node) {
m_expr, "bit index is not an integer", node->GetLocation());
}
- int64_t first_index = first_idx->GetValueAsSigned(0);
- int64_t last_index = last_idx->GetValueAsSigned(0);
+ bool success_first, success_last;
+ int64_t first_index = first_idx->GetValueAsSigned(0, &success_first);
+ int64_t last_index = last_idx->GetValueAsSigned(0, &success_last);
+ if (!success_first || !success_last)
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, "could not get the index as an integer", node->GetLocation());
// if the format given is [high-low], swap range
if (first_index > last_index)
>From 5f2d38021907ea41d497c029ecf773babd83d3ae Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Tue, 9 Dec 2025 20:25:19 +0500
Subject: [PATCH 3/4] Add a test
---
.../BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py b/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py
index 476c072b1cdc8..3f2107d965013 100644
--- a/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py
+++ b/lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py
@@ -58,3 +58,8 @@ def test_bitfield_extraction(self):
error=True,
substrs=["bit index is not an integer"],
)
+ self.expect(
+ "frame var 'value[2.0-1]'",
+ error=True,
+ substrs=["bit index is not an integer"],
+ )
>From 6beba5c3ef52a2bf48c3709eb46084ef276a7edb Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Tue, 9 Dec 2025 20:49:54 +0500
Subject: [PATCH 4/4] Move node evaluation closer to usage
---
lldb/source/ValueObject/DILEval.cpp | 20 ++++++++++----------
1 file changed, 10 insertions(+), 10 deletions(-)
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index 937c33fdf1c0e..0e59a9103433f 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -493,10 +493,6 @@ Interpreter::Visit(const MemberOfNode *node) {
llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const ArraySubscriptNode *node) {
- auto base_or_err = Evaluate(node->GetBase());
- if (!base_or_err)
- return base_or_err;
- lldb::ValueObjectSP base = *base_or_err;
auto idx_or_err = EvaluateAndDereference(node->GetIndex());
if (!idx_or_err)
return idx_or_err;
@@ -511,10 +507,14 @@ Interpreter::Visit(const ArraySubscriptNode *node) {
uint64_t child_idx = idx->GetValueAsUnsigned(0);
lldb::ValueObjectSP child_valobj_sp;
- bool is_incomplete_array = false;
+ auto base_or_err = Evaluate(node->GetBase());
+ if (!base_or_err)
+ return base_or_err;
+ lldb::ValueObjectSP base = *base_or_err;
+
CompilerType base_type = base->GetCompilerType().GetNonReferenceType();
base->GetExpressionPath(var_expr_path_strm);
-
+ bool is_incomplete_array = false;
if (base_type.IsPointerType()) {
bool is_objc_pointer = true;
@@ -649,10 +649,6 @@ Interpreter::Visit(const ArraySubscriptNode *node) {
llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const BitFieldExtractionNode *node) {
- auto base_or_err = EvaluateAndDereference(node->GetBase());
- if (!base_or_err)
- return base_or_err;
- lldb::ValueObjectSP base = *base_or_err;
auto first_idx_or_err = EvaluateAndDereference(node->GetFirstIndex());
if (!first_idx_or_err)
return first_idx_or_err;
@@ -679,6 +675,10 @@ Interpreter::Visit(const BitFieldExtractionNode *node) {
if (first_index > last_index)
std::swap(first_index, last_index);
+ auto base_or_err = EvaluateAndDereference(node->GetBase());
+ if (!base_or_err)
+ return base_or_err;
+ lldb::ValueObjectSP base = *base_or_err;
lldb::ValueObjectSP child_valobj_sp =
base->GetSyntheticBitFieldChild(first_index, last_index, true);
if (!child_valobj_sp) {
More information about the lldb-commits
mailing list