[lldb] Add arithmetic binary subtraction to DIL (#184017)
This commit is contained in:
parent
b6761b287f
commit
14af5be5da
@ -5,7 +5,8 @@
|
||||
|
||||
expression = additive_expression ;
|
||||
|
||||
additive_expression = cast_expression {"+" cast_expression} ;
|
||||
additive_expression = cast_expression {"+" cast_expression}
|
||||
cast_expression {"-" cast_expression} ;
|
||||
|
||||
cast_expression = unary_expression
|
||||
| "(" type_id ")" cast_expression;
|
||||
|
||||
@ -43,6 +43,7 @@ enum class UnaryOpKind {
|
||||
/// The binary operators recognized by DIL.
|
||||
enum class BinaryOpKind {
|
||||
Add, // "+"
|
||||
Sub, // "-"
|
||||
};
|
||||
|
||||
/// Translates DIL tokens to BinaryOpKind.
|
||||
|
||||
@ -97,6 +97,9 @@ private:
|
||||
llvm::Expected<lldb::ValueObjectSP>
|
||||
EvaluateBinaryAddition(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs,
|
||||
uint32_t location);
|
||||
llvm::Expected<lldb::ValueObjectSP>
|
||||
EvaluateBinarySubtraction(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs,
|
||||
uint32_t location);
|
||||
llvm::Expected<CompilerType>
|
||||
PickIntegerType(lldb::TypeSystemSP type_system,
|
||||
std::shared_ptr<ExecutionContextScope> ctx,
|
||||
|
||||
@ -15,6 +15,8 @@ BinaryOpKind GetBinaryOpKindFromToken(Token::Kind token_kind) {
|
||||
switch (token_kind) {
|
||||
case Token::plus:
|
||||
return BinaryOpKind::Add;
|
||||
case Token::minus:
|
||||
return BinaryOpKind::Sub;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
@ -558,6 +558,8 @@ Interpreter::EvaluateScalarOp(BinaryOpKind kind, lldb::ValueObjectSP lhs,
|
||||
switch (kind) {
|
||||
case BinaryOpKind::Add:
|
||||
return value_object(l + r);
|
||||
case BinaryOpKind::Sub:
|
||||
return value_object(l - r);
|
||||
}
|
||||
return llvm::make_error<DILDiagnosticError>(
|
||||
m_expr, "invalid arithmetic operation", location);
|
||||
@ -585,6 +587,28 @@ llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryAddition(
|
||||
location);
|
||||
}
|
||||
|
||||
llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinarySubtraction(
|
||||
lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
|
||||
// Operation '-' works for:
|
||||
// {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
|
||||
// TODO: Pointer arithmetics
|
||||
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())
|
||||
return EvaluateScalarOp(BinaryOpKind::Sub, lhs, rhs, result_type, location);
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
llvm::Expected<lldb::ValueObjectSP>
|
||||
Interpreter::Visit(const BinaryOpNode &node) {
|
||||
auto lhs_or_err = EvaluateAndDereference(node.GetLHS());
|
||||
@ -609,6 +633,8 @@ Interpreter::Visit(const BinaryOpNode &node) {
|
||||
switch (node.GetKind()) {
|
||||
case BinaryOpKind::Add:
|
||||
return EvaluateBinaryAddition(lhs, rhs, node.GetLocation());
|
||||
case BinaryOpKind::Sub:
|
||||
return EvaluateBinarySubtraction(lhs, rhs, node.GetLocation());
|
||||
}
|
||||
|
||||
return llvm::make_error<DILDiagnosticError>(
|
||||
|
||||
@ -138,7 +138,7 @@ ASTNodeUP DILParser::ParseAdditiveExpression() {
|
||||
auto lhs = ParseCastExpression();
|
||||
assert(lhs && "ASTNodeUP must not contain a nullptr");
|
||||
|
||||
while (CurToken().Is(Token::plus)) {
|
||||
while (CurToken().IsOneOf({Token::plus, Token::minus})) {
|
||||
Token token = CurToken();
|
||||
m_dil_lexer.Advance();
|
||||
auto rhs = ParseCastExpression();
|
||||
|
||||
@ -35,6 +35,9 @@ class TestFrameVarDILBitFieldExtraction(TestBase):
|
||||
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 that old range syntax is now a binary subtraction
|
||||
self.expect_var_path("value[6-1]", value="1", type="int:1")
|
||||
|
||||
# Test array and pointer
|
||||
self.expect(
|
||||
"frame var 'int_arr[0:2]'",
|
||||
@ -63,8 +66,3 @@ class TestFrameVarDILBitFieldExtraction(TestBase):
|
||||
error=True,
|
||||
substrs=["bit index is not an integer"],
|
||||
)
|
||||
self.expect(
|
||||
"frame var 'value[0-2]'",
|
||||
error=True,
|
||||
substrs=["use of '-' for bitfield range is deprecated; use ':' instead"],
|
||||
)
|
||||
|
||||
@ -63,15 +63,25 @@ class TestFrameVarDILArithmetic(TestBase):
|
||||
self.expect_var_path("1 + s + (x + l)", value="18", type="long")
|
||||
self.expect_var_path("+2 + (-1)", value="1", type="int")
|
||||
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")
|
||||
|
||||
# Check limits and overflows
|
||||
frame = thread.GetFrameAtIndex(0)
|
||||
int_min = frame.GetValueForVariablePath("int_min").GetValue()
|
||||
int_max = frame.GetValueForVariablePath("int_max").GetValue()
|
||||
uint_max = frame.GetValueForVariablePath("uint_max").GetValue()
|
||||
ll_min = frame.GetValueForVariablePath("ll_min").GetValue()
|
||||
ll_max = frame.GetValueForVariablePath("ll_max").GetValue()
|
||||
ull_max = frame.GetValueForVariablePath("ull_max").GetValue()
|
||||
self.expect_var_path("int_max + 1", value=int_min)
|
||||
self.expect_var_path("int_min - 1", value=int_max)
|
||||
self.expect_var_path("uint_max + 1", value="0")
|
||||
self.expect_var_path("uint_zero - 1", value=uint_max)
|
||||
self.expect_var_path("ll_max + 1", value=ll_min)
|
||||
self.expect_var_path("ll_min - 1", value=ll_max)
|
||||
self.expect_var_path("ull_max + 1", value="0")
|
||||
self.expect_var_path("ull_zero - 1", value=ull_max)
|
||||
|
||||
# Check signed integer promotion when different types have the same size
|
||||
uint = frame.GetValueForVariablePath("ui")
|
||||
@ -87,5 +97,20 @@ class TestFrameVarDILArithmetic(TestBase):
|
||||
|
||||
# Check references and typedefs
|
||||
self.expect_var_path("ref + 1", value="3")
|
||||
self.expect_var_path("ref - 1l", value="1")
|
||||
self.expect_var_path("my_ref + 1", value="3")
|
||||
self.expect_var_path("my_ref - 1", value="1")
|
||||
self.expect_var_path("ref + my_ref", value="4")
|
||||
self.expect_var_path("ref - my_ref", value="0")
|
||||
|
||||
# TODO: Pointer arithmetics
|
||||
self.expect(
|
||||
"frame var -- 'p + 1'",
|
||||
error=True,
|
||||
substrs=["invalid operands to binary expression ('int *' and 'int')"],
|
||||
)
|
||||
self.expect(
|
||||
"frame var -- 'p - 1'",
|
||||
error=True,
|
||||
substrs=["invalid operands to binary expression ('int *' and 'int')"],
|
||||
)
|
||||
|
||||
@ -33,9 +33,11 @@ int main(int argc, char **argv) {
|
||||
int int_max = std::numeric_limits<int>::max();
|
||||
int int_min = std::numeric_limits<int>::min();
|
||||
unsigned int uint_max = std::numeric_limits<unsigned int>::max();
|
||||
unsigned int uint_zero = 0;
|
||||
long long ll_max = std::numeric_limits<long long>::max();
|
||||
long long ll_min = std::numeric_limits<long long>::min();
|
||||
unsigned long long ull_max = std::numeric_limits<unsigned long long>::max();
|
||||
unsigned long long ull_zero = 0;
|
||||
|
||||
return 0; // Set a breakpoint here
|
||||
}
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user