[Lldb-commits] [lldb] 65f4e70 - [lldb] Add binary multiplication, division, remainder to DIL (#187281)
via lldb-commits
lldb-commits at lists.llvm.org
Mon Apr 13 04:29:34 PDT 2026
Author: Ilia Kuklin
Date: 2026-04-13T16:29:28+05:00
New Revision: 65f4e709e1e0edb650a5ff5263afcd5012d04228
URL: https://github.com/llvm/llvm-project/commit/65f4e709e1e0edb650a5ff5263afcd5012d04228
DIFF: https://github.com/llvm/llvm-project/commit/65f4e709e1e0edb650a5ff5263afcd5012d04228.diff
LOG: [lldb] Add binary multiplication, division, remainder to DIL (#187281)
Add binary arithmetic multiplication, division, remainder to DIL.
This patch also passes DILMode to the parser to check if binary
multiplication is allowed by the mode. This cannot be done in the lexer
alone, because it allows token `*` as a dereference operator for legacy
mode, but that token could also be a binary multiplication allowed only
in full mode.
Added:
Modified:
lldb/docs/dil-expr-lang.ebnf
lldb/include/lldb/ValueObject/DILAST.h
lldb/include/lldb/ValueObject/DILEval.h
lldb/include/lldb/ValueObject/DILLexer.h
lldb/include/lldb/ValueObject/DILParser.h
lldb/source/Target/StackFrame.cpp
lldb/source/ValueObject/DILAST.cpp
lldb/source/ValueObject/DILEval.cpp
lldb/source/ValueObject/DILLexer.cpp
lldb/source/ValueObject/DILParser.cpp
lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py
Removed:
################################################################################
diff --git a/lldb/docs/dil-expr-lang.ebnf b/lldb/docs/dil-expr-lang.ebnf
index cdf85d75fd8e2..b80533c015c95 100644
--- a/lldb/docs/dil-expr-lang.ebnf
+++ b/lldb/docs/dil-expr-lang.ebnf
@@ -5,8 +5,12 @@
expression = additive_expression ;
-additive_expression = cast_expression {"+" cast_expression}
- cast_expression {"-" cast_expression} ;
+additive_expression = multiplicative_expression {"+" multiplicative_expression}
+ multiplicative_expression {"-" multiplicative_expression} ;
+
+multiplicative_expression = cast_expression {"*" cast_expression}
+ | cast_expression {"/" cast_expression}
+ | cast_expression {"%" cast_expression} ;
cast_expression = unary_expression
| "(" type_id ")" cast_expression;
diff --git a/lldb/include/lldb/ValueObject/DILAST.h b/lldb/include/lldb/ValueObject/DILAST.h
index 350722fa6f22d..50530d687c41f 100644
--- a/lldb/include/lldb/ValueObject/DILAST.h
+++ b/lldb/include/lldb/ValueObject/DILAST.h
@@ -44,6 +44,9 @@ enum class UnaryOpKind {
enum class BinaryOpKind {
Add, // "+"
Sub, // "-"
+ Mul, // "*"
+ Div, // "/"
+ Rem, // "%"
};
/// Translates DIL tokens to BinaryOpKind.
diff --git a/lldb/include/lldb/ValueObject/DILEval.h b/lldb/include/lldb/ValueObject/DILEval.h
index 323ac5eace2ba..c5f41b5a0bc76 100644
--- a/lldb/include/lldb/ValueObject/DILEval.h
+++ b/lldb/include/lldb/ValueObject/DILEval.h
@@ -106,6 +106,15 @@ class Interpreter : Visitor {
llvm::Expected<lldb::ValueObjectSP>
EvaluateBinarySubtraction(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs,
uint32_t location);
+ llvm::Expected<lldb::ValueObjectSP>
+ EvaluateBinaryMultiplication(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs,
+ uint32_t location);
+ llvm::Expected<lldb::ValueObjectSP>
+ EvaluateBinaryDivision(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs,
+ uint32_t location);
+ llvm::Expected<lldb::ValueObjectSP>
+ EvaluateBinaryRemainder(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs,
+ uint32_t location);
llvm::Expected<CompilerType>
PickIntegerType(lldb::TypeSystemSP type_system,
std::shared_ptr<ExecutionContextScope> ctx,
diff --git a/lldb/include/lldb/ValueObject/DILLexer.h b/lldb/include/lldb/ValueObject/DILLexer.h
index a927aa236377e..1672e52b2adb0 100644
--- a/lldb/include/lldb/ValueObject/DILLexer.h
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -38,10 +38,12 @@ class Token {
l_paren,
l_square,
minus,
+ percent,
period,
plus,
r_paren,
r_square,
+ slash,
star,
};
diff --git a/lldb/include/lldb/ValueObject/DILParser.h b/lldb/include/lldb/ValueObject/DILParser.h
index 4afedb735af86..351eea6d0d268 100644
--- a/lldb/include/lldb/ValueObject/DILParser.h
+++ b/lldb/include/lldb/ValueObject/DILParser.h
@@ -71,7 +71,7 @@ class DILParser {
DILLexer lexer,
std::shared_ptr<StackFrame> frame_sp,
lldb::DynamicValueType use_dynamic,
- uint32_t options);
+ uint32_t options, lldb::DILMode mode);
~DILParser() = default;
@@ -88,12 +88,13 @@ class DILParser {
std::shared_ptr<StackFrame> frame_sp,
lldb::DynamicValueType use_dynamic, bool use_synthetic,
bool fragile_ivar, bool check_ptr_vs_member,
- llvm::Error &error);
+ llvm::Error &error, lldb::DILMode mode);
ASTNodeUP Run();
ASTNodeUP ParseExpression();
ASTNodeUP ParseAdditiveExpression();
+ ASTNodeUP ParseMultiplicativeExpression();
ASTNodeUP ParseUnaryExpression();
ASTNodeUP ParsePostfixExpression();
ASTNodeUP ParsePrimaryExpression();
@@ -146,6 +147,9 @@ class DILParser {
bool m_use_synthetic;
bool m_fragile_ivar;
bool m_check_ptr_vs_member;
+
+ // DIL Mode requested by the caller.
+ lldb::DILMode m_mode;
}; // class DILParser
} // namespace lldb_private::dil
diff --git a/lldb/source/Target/StackFrame.cpp b/lldb/source/Target/StackFrame.cpp
index a5d2d741c368f..4788533a2ede9 100644
--- a/lldb/source/Target/StackFrame.cpp
+++ b/lldb/source/Target/StackFrame.cpp
@@ -551,7 +551,7 @@ ValueObjectSP StackFrame::DILGetValueForVariableExpressionPath(
// Parse the expression.
auto tree_or_error =
dil::DILParser::Parse(var_expr, std::move(*lex_or_err),
- shared_from_this(), use_dynamic, options);
+ shared_from_this(), use_dynamic, options, mode);
if (!tree_or_error) {
error = Status::FromError(tree_or_error.takeError());
return ValueObjectConstResult::Create(nullptr, error.Clone());
diff --git a/lldb/source/ValueObject/DILAST.cpp b/lldb/source/ValueObject/DILAST.cpp
index dadd4cd365c7e..a454cacbf494f 100644
--- a/lldb/source/ValueObject/DILAST.cpp
+++ b/lldb/source/ValueObject/DILAST.cpp
@@ -17,6 +17,12 @@ BinaryOpKind GetBinaryOpKindFromToken(Token::Kind token_kind) {
return BinaryOpKind::Add;
case Token::minus:
return BinaryOpKind::Sub;
+ case Token::star:
+ return BinaryOpKind::Mul;
+ case Token::slash:
+ return BinaryOpKind::Div;
+ case Token::percent:
+ return BinaryOpKind::Rem;
default:
break;
}
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index 9983368065c0a..7801b9225f19e 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -587,11 +587,17 @@ Interpreter::EvaluateScalarOp(BinaryOpKind kind, lldb::ValueObjectSP lhs,
uint32_t location) {
Scalar l, r;
bool l_resolved = lhs->ResolveValue(l);
+ if (!l_resolved) {
+ std::string errMsg =
+ llvm::formatv("invalid lhs value: {0}", lhs->GetError().AsCString());
+ return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
+ }
bool r_resolved = rhs->ResolveValue(r);
-
- if (!l_resolved || !r_resolved)
- return llvm::make_error<DILDiagnosticError>(m_expr, "invalid scalar value",
- location);
+ if (!r_resolved) {
+ std::string errMsg =
+ llvm::formatv("invalid rhs value: {0}", rhs->GetError().AsCString());
+ return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
+ }
auto value_object = [this, result_type](Scalar scalar) {
return ValueObject::CreateValueObjectFromScalar(m_exe_ctx_scope, scalar,
@@ -603,6 +609,12 @@ Interpreter::EvaluateScalarOp(BinaryOpKind kind, lldb::ValueObjectSP lhs,
return value_object(l + r);
case BinaryOpKind::Sub:
return value_object(l - r);
+ case BinaryOpKind::Mul:
+ return value_object(l * r);
+ case BinaryOpKind::Div:
+ return value_object(l / r);
+ case BinaryOpKind::Rem:
+ return value_object(l % r);
}
return llvm::make_error<DILDiagnosticError>(
m_expr, "invalid arithmetic operation", location);
@@ -723,6 +735,83 @@ llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinarySubtraction(
location);
}
+llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryMultiplication(
+ lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
+ // Operation '*' works for:
+ // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
+ auto orig_lhs_type = lhs->GetCompilerType();
+ auto orig_rhs_type = rhs->GetCompilerType();
+ auto type_or_err = ArithmeticConversion(lhs, rhs, location);
+ if (!type_or_err)
+ return type_or_err.takeError();
+ CompilerType result_type = *type_or_err;
+
+ if (!result_type.IsScalarType()) {
+ std::string errMsg =
+ llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
+ orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
+ return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
+ location);
+ }
+
+ return EvaluateScalarOp(BinaryOpKind::Mul, lhs, rhs, result_type, location);
+}
+
+llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryDivision(
+ lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
+ // Operation '/' works for:
+ // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
+ auto orig_lhs_type = lhs->GetCompilerType();
+ auto orig_rhs_type = rhs->GetCompilerType();
+ auto type_or_err = ArithmeticConversion(lhs, rhs, location);
+ if (!type_or_err)
+ return type_or_err.takeError();
+ CompilerType result_type = *type_or_err;
+
+ if (!result_type.IsScalarType()) {
+ std::string errMsg =
+ llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
+ orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
+ return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
+ location);
+ }
+
+ // Check for zero only for integer division.
+ if (result_type.IsInteger() && rhs->GetValueAsSigned(-1) == 0) {
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, "division by zero is undefined", location);
+ }
+
+ return EvaluateScalarOp(BinaryOpKind::Div, lhs, rhs, result_type, location);
+}
+
+llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryRemainder(
+ lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
+ // Operation '%' works for:
+ // {integer,unscoped_enum} <-> {integer,unscoped_enum}
+ auto orig_lhs_type = lhs->GetCompilerType();
+ auto orig_rhs_type = rhs->GetCompilerType();
+ auto type_or_err = ArithmeticConversion(lhs, rhs, location);
+ if (!type_or_err)
+ return type_or_err.takeError();
+ CompilerType result_type = *type_or_err;
+
+ if (!result_type.IsInteger()) {
+ std::string errMsg =
+ llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
+ orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
+ return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
+ location);
+ }
+
+ if (rhs->GetValueAsSigned(-1) == 0) {
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, "division by zero is undefined", location);
+ }
+
+ return EvaluateScalarOp(BinaryOpKind::Rem, lhs, rhs, result_type, location);
+}
+
llvm::Expected<lldb::ValueObjectSP>
Interpreter::Visit(const BinaryOpNode &node) {
auto lhs_or_err = EvaluateAndDereference(node.GetLHS());
@@ -749,6 +838,12 @@ Interpreter::Visit(const BinaryOpNode &node) {
return EvaluateBinaryAddition(lhs, rhs, node.GetLocation());
case BinaryOpKind::Sub:
return EvaluateBinarySubtraction(lhs, rhs, node.GetLocation());
+ case BinaryOpKind::Mul:
+ return EvaluateBinaryMultiplication(lhs, rhs, node.GetLocation());
+ case BinaryOpKind::Div:
+ return EvaluateBinaryDivision(lhs, rhs, node.GetLocation());
+ case BinaryOpKind::Rem:
+ return EvaluateBinaryRemainder(lhs, rhs, node.GetLocation());
}
return llvm::make_error<DILDiagnosticError>(
diff --git a/lldb/source/ValueObject/DILLexer.cpp b/lldb/source/ValueObject/DILLexer.cpp
index c1ad354502438..c9848484851a7 100644
--- a/lldb/source/ValueObject/DILLexer.cpp
+++ b/lldb/source/ValueObject/DILLexer.cpp
@@ -46,6 +46,8 @@ llvm::StringRef Token::GetTokenName(Kind kind) {
return "l_square";
case Kind::minus:
return "minus";
+ case Token::percent:
+ return "percent";
case Kind::period:
return "period";
case Kind::plus:
@@ -54,6 +56,8 @@ llvm::StringRef Token::GetTokenName(Kind kind) {
return "r_paren";
case Kind::r_square:
return "r_square";
+ case Token::slash:
+ return "slash";
case Token::star:
return "star";
}
@@ -181,10 +185,11 @@ llvm::Expected<Token> DILLexer::Lex(llvm::StringRef expr,
}
constexpr std::pair<Token::Kind, const char *> operators[] = {
- {Token::amp, "&"}, {Token::arrow, "->"}, {Token::coloncolon, "::"},
- {Token::colon, ":"}, {Token::l_paren, "("}, {Token::l_square, "["},
- {Token::minus, "-"}, {Token::period, "."}, {Token::plus, "+"},
- {Token::r_paren, ")"}, {Token::r_square, "]"}, {Token::star, "*"},
+ {Token::amp, "&"}, {Token::arrow, "->"}, {Token::coloncolon, "::"},
+ {Token::colon, ":"}, {Token::l_paren, "("}, {Token::l_square, "["},
+ {Token::minus, "-"}, {Token::percent, "%"}, {Token::period, "."},
+ {Token::plus, "+"}, {Token::r_paren, ")"}, {Token::r_square, "]"},
+ {Token::slash, "/"}, {Token::star, "*"},
};
for (auto [kind, str] : operators) {
if (remainder.consume_front(str))
diff --git a/lldb/source/ValueObject/DILParser.cpp b/lldb/source/ValueObject/DILParser.cpp
index d226ba66ef889..51bdffd5087ca 100644
--- a/lldb/source/ValueObject/DILParser.cpp
+++ b/lldb/source/ValueObject/DILParser.cpp
@@ -103,9 +103,9 @@ CompilerType ResolveTypeByName(const std::string &name,
llvm::Expected<ASTNodeUP> DILParser::Parse(llvm::StringRef dil_input_expr,
DILLexer lexer,
std::shared_ptr<StackFrame> frame_sp,
-
lldb::DynamicValueType use_dynamic,
- uint32_t options) {
+ uint32_t options,
+ lldb::DILMode mode) {
const bool check_ptr_vs_member =
(options & StackFrame::eExpressionPathOptionCheckPtrVsMember) != 0;
const bool no_fragile_ivar =
@@ -116,7 +116,7 @@ llvm::Expected<ASTNodeUP> DILParser::Parse(llvm::StringRef dil_input_expr,
llvm::Error error = llvm::Error::success();
DILParser parser(dil_input_expr, lexer, frame_sp, use_dynamic,
!no_synth_child, !no_fragile_ivar, check_ptr_vs_member,
- error);
+ error, mode);
ASTNodeUP node_up = parser.Run();
assert(node_up && "ASTNodeUP must not contain a nullptr");
@@ -131,11 +131,11 @@ DILParser::DILParser(llvm::StringRef dil_input_expr, DILLexer lexer,
std::shared_ptr<StackFrame> frame_sp,
lldb::DynamicValueType use_dynamic, bool use_synthetic,
bool fragile_ivar, bool check_ptr_vs_member,
- llvm::Error &error)
+ llvm::Error &error, lldb::DILMode mode)
: m_ctx_scope(frame_sp), m_input_expr(dil_input_expr),
m_dil_lexer(std::move(lexer)), m_error(error), m_use_dynamic(use_dynamic),
m_use_synthetic(use_synthetic), m_fragile_ivar(fragile_ivar),
- m_check_ptr_vs_member(check_ptr_vs_member) {}
+ m_check_ptr_vs_member(check_ptr_vs_member), m_mode(mode) {}
ASTNodeUP DILParser::Run() {
ASTNodeUP expr = ParseExpression();
@@ -155,15 +155,43 @@ ASTNodeUP DILParser::ParseExpression() { return ParseAdditiveExpression(); }
// Parse an additive_expression.
//
// additive_expression:
-// cast_expression {"+" cast_expression}
+// multiplicative_expression {"+" multiplicative_expression}
//
ASTNodeUP DILParser::ParseAdditiveExpression() {
- auto lhs = ParseCastExpression();
+ auto lhs = ParseMultiplicativeExpression();
assert(lhs && "ASTNodeUP must not contain a nullptr");
while (CurToken().IsOneOf({Token::plus, Token::minus})) {
Token token = CurToken();
m_dil_lexer.Advance();
+ auto rhs = ParseMultiplicativeExpression();
+ assert(rhs && "ASTNodeUP must not contain a nullptr");
+ lhs = std::make_unique<BinaryOpNode>(
+ token.GetLocation(), GetBinaryOpKindFromToken(token.GetKind()),
+ std::move(lhs), std::move(rhs));
+ }
+
+ return lhs;
+}
+
+// Parse a multiplicative_expression.
+//
+// multiplicative_expression:
+// cast_expression {"*" cast_expression}
+// cast_expression {"/" cast_expression}
+// cast_expression {"%" cast_expression}
+//
+ASTNodeUP DILParser::ParseMultiplicativeExpression() {
+ auto lhs = ParseCastExpression();
+
+ while (CurToken().IsOneOf({Token::star, Token::slash, Token::percent})) {
+ Token token = CurToken();
+ if (token.Is(Token::star) && m_mode != lldb::eDILModeFull) {
+ BailOut("binary multiplication (*) is allowed only in DIL full mode",
+ token.GetLocation(), token.GetSpelling().length());
+ return std::make_unique<ErrorNode>();
+ }
+ m_dil_lexer.Advance();
auto rhs = ParseCastExpression();
assert(rhs && "ASTNodeUP must not contain a nullptr");
lhs = std::make_unique<BinaryOpNode>(
diff --git a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py
index fb3b877209d16..7729c1ce23d7d 100644
--- a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py
+++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py
@@ -65,6 +65,17 @@ def test_arithmetic(self):
self.expect_var_path("-2 + (+1)", value="-1", type="int")
self.expect_var_path("1 + (2 - 3)", value="0")
self.expect_var_path("s - x - 1", value="7")
+ self.expect_var_path("2 * 2", value="4", type="int")
+ self.expect_var_path("2 * 2.0", value="4", type="double")
+ self.expect_var_path("2 * 2.0f", value="4", type="float")
+ self.expect_var_path("4 / 2", value="2", type="int")
+ self.expect_var_path("4 / 2.0", value="2", type="double")
+ self.expect_var_path("4 / 2.0f", value="2", type="float")
+ self.expect_var_path("4 % 3", value="1", type="int")
+ self.expect_var_path("0.0 / 0", value="NaN")
+ self.expect_var_path("0 / 0.0", value="NaN")
+ self.expect_var_path("1 / +0.0", value="+Inf")
+ self.expect_var_path("1 / -0.0", value="-Inf")
# Check limits and overflows
frame = thread.GetFrameAtIndex(0)
@@ -98,7 +109,69 @@ def test_arithmetic(self):
# Check references and typedefs
self.expect_var_path("ref + 1", value="3")
self.expect_var_path("ref - 1l", value="1")
+ self.expect_var_path("ref * 2u", value="4")
+ self.expect_var_path("ref / 2ull", value="1")
+ self.expect_var_path("ref % 2", value="0")
self.expect_var_path("my_ref + 1", value="3")
self.expect_var_path("my_ref - 1", value="1")
+ self.expect_var_path("my_ref * 2", value="4")
+ self.expect_var_path("my_ref / 2", value="1")
+ self.expect_var_path("my_ref % 2", value="0")
self.expect_var_path("ref + my_ref", value="4")
self.expect_var_path("ref - my_ref", value="0")
+ self.expect_var_path("ref * my_ref", value="4")
+ self.expect_var_path("ref / my_ref", value="1")
+ self.expect_var_path("ref % my_ref", value="0")
+
+ # Check enums
+ self.expect_var_path("enum_one + 1", value="2")
+ self.expect_var_path("enum_one - 1", value="0")
+ self.expect_var_path("enum_one * 2", value="2")
+ self.expect_var_path("enum_one / 1", value="1")
+ self.expect_var_path("enum_one % 1", value="0")
+
+ # Check errors
+ self.expect(
+ "frame var -- '1 / 0'",
+ error=True,
+ substrs=["division by zero is undefined"],
+ )
+ self.expect(
+ "frame var -- '1 / uint_zero'",
+ error=True,
+ substrs=["division by zero is undefined"],
+ )
+ self.expect(
+ "frame var -- '1LL / 0 + 1'",
+ error=True,
+ substrs=["division by zero is undefined"],
+ )
+ self.expect(
+ "frame var -- '1 % 0'",
+ error=True,
+ substrs=["division by zero is undefined"],
+ )
+ self.expect(
+ "frame var -- '1 % uint_zero'",
+ error=True,
+ substrs=["division by zero is undefined"],
+ )
+ self.expect(
+ "frame var -- '*((int*) 0) + 1'",
+ error=True,
+ substrs=["invalid lhs value: parent is NULL"],
+ )
+ self.expect(
+ "frame var -- '1 / *((int*) 0)'",
+ error=True,
+ substrs=["invalid rhs value: parent is NULL"],
+ )
+
+ # Check that binary * is allowed only in full mode
+ frame = thread.GetFrameAtIndex(0)
+ simple = frame.GetValueForVariablePath("x * 2", lldb.eDILModeSimple)
+ legacy = frame.GetValueForVariablePath("x * 2", lldb.eDILModeLegacy)
+ full = frame.GetValueForVariablePath("x * 2", lldb.eDILModeFull)
+ self.assertFailure(simple.GetError())
+ self.assertFailure(legacy.GetError())
+ self.assertSuccess(full.GetError())
More information about the lldb-commits
mailing list