Author: Ilia Kuklin
Date: 2026-03-04T15:12:48+05:00
New Revision: 14af5be5da77a90acbc2d5d47488d9400d7cfed7

URL: 
https://github.com/llvm/llvm-project/commit/14af5be5da77a90acbc2d5d47488d9400d7cfed7
DIFF: 
https://github.com/llvm/llvm-project/commit/14af5be5da77a90acbc2d5d47488d9400d7cfed7.diff

LOG: [lldb] Add arithmetic binary subtraction to DIL (#184017)

Added: 
    

Modified: 
    lldb/docs/dil-expr-lang.ebnf
    lldb/include/lldb/ValueObject/DILAST.h
    lldb/include/lldb/ValueObject/DILEval.h
    lldb/source/ValueObject/DILAST.cpp
    lldb/source/ValueObject/DILEval.cpp
    lldb/source/ValueObject/DILParser.cpp
    
lldb/test/API/commands/frame/var-dil/basics/BitFieldExtraction/TestFrameVarDILBitFieldExtraction.py
    
lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py
    lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp

Removed: 
    


################################################################################
diff  --git a/lldb/docs/dil-expr-lang.ebnf b/lldb/docs/dil-expr-lang.ebnf
index 127c1d6337efa..cdf85d75fd8e2 100644
--- a/lldb/docs/dil-expr-lang.ebnf
+++ b/lldb/docs/dil-expr-lang.ebnf
@@ -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;

diff  --git a/lldb/include/lldb/ValueObject/DILAST.h 
b/lldb/include/lldb/ValueObject/DILAST.h
index 226f80ac70c5e..350722fa6f22d 100644
--- a/lldb/include/lldb/ValueObject/DILAST.h
+++ b/lldb/include/lldb/ValueObject/DILAST.h
@@ -43,6 +43,7 @@ enum class UnaryOpKind {
 /// The binary operators recognized by DIL.
 enum class BinaryOpKind {
   Add, // "+"
+  Sub, // "-"
 };
 
 /// Translates DIL tokens to BinaryOpKind.

diff  --git a/lldb/include/lldb/ValueObject/DILEval.h 
b/lldb/include/lldb/ValueObject/DILEval.h
index 54d33129908a3..a6223c4d998ab 100644
--- a/lldb/include/lldb/ValueObject/DILEval.h
+++ b/lldb/include/lldb/ValueObject/DILEval.h
@@ -97,6 +97,9 @@ class Interpreter : Visitor {
   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,

diff  --git a/lldb/source/ValueObject/DILAST.cpp 
b/lldb/source/ValueObject/DILAST.cpp
index 180708f79c269..dadd4cd365c7e 100644
--- a/lldb/source/ValueObject/DILAST.cpp
+++ b/lldb/source/ValueObject/DILAST.cpp
@@ -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;
   }

diff  --git a/lldb/source/ValueObject/DILEval.cpp 
b/lldb/source/ValueObject/DILEval.cpp
index acefb5dc6133b..1b841d39a034e 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -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>(

diff  --git a/lldb/source/ValueObject/DILParser.cpp 
b/lldb/source/ValueObject/DILParser.cpp
index f07607c93d927..bb5a86bc7168b 100644
--- a/lldb/source/ValueObject/DILParser.cpp
+++ b/lldb/source/ValueObject/DILParser.cpp
@@ -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();

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 0899083568125..026658c0cd25f 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
@@ -35,6 +35,9 @@ def test_bitfield_extraction(self):
         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 @@ def test_bitfield_extraction(self):
             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"],
-        )

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 bfa040b8cfb7b..03075314ab9b6 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
@@ -63,15 +63,25 @@ def test_arithmetic(self):
         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 
diff erent types have the same size
         uint = frame.GetValueForVariablePath("ui")
@@ -87,5 +97,20 @@ 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("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')"],
+        )

diff  --git a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp 
b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp
index f41b89beb2bde..1561ed6c8f655 100644
--- a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp
+++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp
@@ -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
 }


        
_______________________________________________
lldb-commits mailing list
[email protected]
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to