https://github.com/kuilpd updated 
https://github.com/llvm/llvm-project/pull/155617

>From 4d14bbb31d0411c45b95778d1659ccc416165be1 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuk...@accesssoftek.com>
Date: Mon, 4 Aug 2025 19:11:55 +0500
Subject: [PATCH 1/6] [LLDB] Add unary plus and minus to DIL

---
 lldb/include/lldb/ValueObject/DILAST.h        |   2 +
 lldb/source/ValueObject/DILEval.cpp           | 155 ++++++++++++++++--
 lldb/source/ValueObject/DILLexer.cpp          |   1 -
 lldb/source/ValueObject/DILParser.cpp         |  10 +-
 .../frame/var-dil/expr/Arithmetic/Makefile    |   3 +
 .../Arithmetic/TestFrameVarDILArithmetic.py   |  40 +++++
 .../frame/var-dil/expr/Arithmetic/main.cpp    |   9 +
 7 files changed, 203 insertions(+), 17 deletions(-)
 create mode 100644 
lldb/test/API/commands/frame/var-dil/expr/Arithmetic/Makefile
 create mode 100644 
lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py
 create mode 100644 
lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp

diff --git a/lldb/include/lldb/ValueObject/DILAST.h 
b/lldb/include/lldb/ValueObject/DILAST.h
index 1d10755c46e39..900eb8a792a1e 100644
--- a/lldb/include/lldb/ValueObject/DILAST.h
+++ b/lldb/include/lldb/ValueObject/DILAST.h
@@ -32,6 +32,8 @@ enum class NodeKind {
 enum class UnaryOpKind {
   AddrOf, // "&"
   Deref,  // "*"
+  Minus,  // "-"
+  Plus,   // "+"
 };
 
 /// Forward declaration, for use in DIL AST nodes. Definition is at the very
diff --git a/lldb/source/ValueObject/DILEval.cpp 
b/lldb/source/ValueObject/DILEval.cpp
index c6cf41ee9e9ee..595c25085bfed 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -21,6 +21,73 @@
 
 namespace lldb_private::dil {
 
+static CompilerType GetBasicTypeFromCU(std::shared_ptr<StackFrame> ctx,
+                                       lldb::BasicType basic_type) {
+  SymbolContext symbol_context =
+      ctx->GetSymbolContext(lldb::eSymbolContextCompUnit);
+  auto language = symbol_context.comp_unit->GetLanguage();
+
+  symbol_context = ctx->GetSymbolContext(lldb::eSymbolContextModule);
+  auto type_system =
+      symbol_context.module_sp->GetTypeSystemForLanguage(language);
+
+  if (type_system)
+    if (auto compiler_type = 
type_system.get()->GetBasicTypeFromAST(basic_type))
+      return compiler_type;
+
+  return CompilerType();
+}
+
+static CompilerType GetIntCompilerTypeForSize(uint32_t size, bool is_signed,
+                                              lldb::TypeSystemSP type_system,
+                                              std::shared_ptr<StackFrame> ctx) 
{
+  lldb::BasicType promote_types[] = {
+      // lldb::eBasicTypeChar,     lldb::eBasicTypeUnsignedChar,
+      // lldb::eBasicTypeShort,    lldb::eBasicTypeUnsignedShort,
+      lldb::eBasicTypeInt,      lldb::eBasicTypeUnsignedInt,
+      lldb::eBasicTypeLong,     lldb::eBasicTypeUnsignedLong,
+      lldb::eBasicTypeLongLong, lldb::eBasicTypeUnsignedLongLong,
+  };
+  for (auto &basic_type : promote_types) {
+    uint64_t byte_size = 0;
+    CompilerType type = GetBasicType(type_system, basic_type);
+    if (auto temp = type.GetByteSize(ctx.get()))
+      byte_size = *temp;
+    if (size < byte_size ||
+        (size == byte_size &&
+         is_signed == (bool)(type.GetTypeInfo() & lldb::eTypeIsSigned))) {
+      return type;
+    }
+  }
+
+  llvm_unreachable("size could not fit into long long");
+  return CompilerType();
+}
+
+static llvm::Expected<Scalar>
+GetScalarFromValueObject(lldb::ValueObjectSP valobj,
+                         std::shared_ptr<StackFrame> ctx) {
+  auto type = valobj->GetCompilerType();
+  Scalar scalar;
+  bool resolved = valobj->ResolveValue(scalar);
+  if (resolved) {
+    if (scalar.GetType() == scalar.e_int) {
+      auto apsint = scalar.GetAPSInt();
+      auto type_bitsize = type.GetBitSize(ctx.get());
+      if (type_bitsize) {
+        llvm::APSInt adjusted;
+        if (type.IsSigned())
+          adjusted = apsint.sextOrTrunc(*type_bitsize);
+        else
+          adjusted = apsint.zextOrTrunc(*type_bitsize);
+        return Scalar(adjusted);
+      }
+    } else
+      return scalar;
+  }
+  return Scalar();
+}
+
 static lldb::VariableSP DILFindVariable(ConstString name,
                                         VariableList &variable_list) {
   lldb::VariableSP exact_match;
@@ -175,21 +242,21 @@ Interpreter::Visit(const IdentifierNode *node) {
 llvm::Expected<lldb::ValueObjectSP>
 Interpreter::Visit(const UnaryOpNode *node) {
   Status error;
-  auto rhs_or_err = Evaluate(node->GetOperand());
-  if (!rhs_or_err)
-    return rhs_or_err;
+  auto op_or_err = Evaluate(node->GetOperand());
+  if (!op_or_err)
+    return op_or_err;
 
-  lldb::ValueObjectSP rhs = *rhs_or_err;
+  lldb::ValueObjectSP operand = *op_or_err;
 
   switch (node->GetKind()) {
   case UnaryOpKind::Deref: {
-    lldb::ValueObjectSP dynamic_rhs = rhs->GetDynamicValue(m_use_dynamic);
-    if (dynamic_rhs)
-      rhs = dynamic_rhs;
+    lldb::ValueObjectSP dynamic_op = operand->GetDynamicValue(m_use_dynamic);
+    if (dynamic_op)
+      operand = dynamic_op;
 
-    lldb::ValueObjectSP child_sp = rhs->Dereference(error);
+    lldb::ValueObjectSP child_sp = operand->Dereference(error);
     if (!child_sp && m_use_synthetic) {
-      if (lldb::ValueObjectSP synth_obj_sp = rhs->GetSyntheticValue()) {
+      if (lldb::ValueObjectSP synth_obj_sp = operand->GetSyntheticValue()) {
         error.Clear();
         child_sp = synth_obj_sp->Dereference(error);
       }
@@ -202,18 +269,78 @@ Interpreter::Visit(const UnaryOpNode *node) {
   }
   case UnaryOpKind::AddrOf: {
     Status error;
-    lldb::ValueObjectSP value = rhs->AddressOf(error);
+    lldb::ValueObjectSP value = operand->AddressOf(error);
     if (error.Fail())
       return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
                                                   node->GetLocation());
 
     return value;
   }
+  case UnaryOpKind::Minus: {
+    auto operand_type = operand->GetCompilerType();
+    if (!operand_type.IsScalarType()) {
+      std::string errMsg =
+          llvm::formatv("invalid argument type '{0}' to unary expression",
+                        operand_type.GetTypeName());
+      return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
+                                                  node->GetLocation());
+    }
+    auto scalar = GetScalarFromValueObject(operand, m_exe_ctx_scope);
+    if (!scalar)
+      break;
+
+    bool negated = scalar->UnaryNegate();
+    if (scalar->GetType() == Scalar::e_int) {
+      auto promo_type = GetIntCompilerTypeForSize(
+          scalar->GetByteSize(), scalar->IsSigned(),
+          operand_type.GetTypeSystem().GetSharedPointer(), m_exe_ctx_scope);
+      auto type_bitsize = promo_type.GetBitSize(m_exe_ctx_scope.get());
+
+      if (type_bitsize && negated) {
+        scalar->IntegralPromote(*type_bitsize, promo_type.IsSigned());
+        return ValueObject::CreateValueObjectFromScalar(m_target, *scalar,
+                                                        promo_type, "result");
+      }
+    } else
+      return ValueObject::CreateValueObjectFromScalar(m_target, *scalar,
+                                                      operand_type, "result");
+    break;
   }
-
-  // Unsupported/invalid operation.
-  return llvm::make_error<DILDiagnosticError>(
-      m_expr, "invalid ast: unexpected binary operator", node->GetLocation());
+  case UnaryOpKind::Plus: {
+    auto operand_type = operand->GetCompilerType();
+    // Unary plus is allowed for pointers.
+    if (operand_type.IsPointerType())
+      return operand;
+    if (!operand_type.IsScalarType()) {
+      std::string errMsg =
+          llvm::formatv("invalid argument type '{0}' to unary expression",
+                        operand_type.GetTypeName());
+      return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
+                                                  node->GetLocation());
+    }
+    auto scalar = GetScalarFromValueObject(operand, m_exe_ctx_scope);
+    if (!scalar)
+      break;
+
+    if (scalar->GetType() == Scalar::e_int) {
+      auto promo_type = GetIntCompilerTypeForSize(
+          scalar->GetByteSize(), scalar->IsSigned(),
+          operand_type.GetTypeSystem().GetSharedPointer(), m_exe_ctx_scope);
+      auto type_bitsize = promo_type.GetBitSize(m_exe_ctx_scope.get());
+
+      if (type_bitsize) {
+        scalar->IntegralPromote(*type_bitsize, promo_type.IsSigned());
+        return ValueObject::CreateValueObjectFromScalar(m_target, *scalar,
+                                                        promo_type, "result");
+      }
+    } else
+      return ValueObject::CreateValueObjectFromScalar(m_target, *scalar,
+                                                      operand_type, "result");
+    break;
+  }
+  }
+  return llvm::make_error<DILDiagnosticError>(m_expr, "invalid unary 
operation",
+                                              node->GetLocation());
 }
 
 llvm::Expected<lldb::ValueObjectSP>
diff --git a/lldb/source/ValueObject/DILLexer.cpp 
b/lldb/source/ValueObject/DILLexer.cpp
index 0b2288a9d9230..77879f50cc9ad 100644
--- a/lldb/source/ValueObject/DILLexer.cpp
+++ b/lldb/source/ValueObject/DILLexer.cpp
@@ -42,7 +42,6 @@ llvm::StringRef Token::GetTokenName(Kind kind) {
     return "minus";
   case Kind::period:
     return "period";
-    return "l_square";
   case Kind::plus:
     return "plus";
   case Kind::r_paren:
diff --git a/lldb/source/ValueObject/DILParser.cpp 
b/lldb/source/ValueObject/DILParser.cpp
index 8c4f7fdb25bea..b88345d18a6d4 100644
--- a/lldb/source/ValueObject/DILParser.cpp
+++ b/lldb/source/ValueObject/DILParser.cpp
@@ -95,7 +95,8 @@ ASTNodeUP DILParser::ParseExpression() { return 
ParseUnaryExpression(); }
 //    "*"
 //
 ASTNodeUP DILParser::ParseUnaryExpression() {
-  if (CurToken().IsOneOf({Token::amp, Token::star})) {
+  if (CurToken().IsOneOf(
+          {Token::amp, Token::star, Token::minus, Token::plus})) {
     Token token = CurToken();
     uint32_t loc = token.GetLocation();
     m_dil_lexer.Advance();
@@ -107,7 +108,12 @@ ASTNodeUP DILParser::ParseUnaryExpression() {
     case Token::amp:
       return std::make_unique<UnaryOpNode>(loc, UnaryOpKind::AddrOf,
                                            std::move(rhs));
-
+    case Token::minus:
+      return std::make_unique<UnaryOpNode>(loc, UnaryOpKind::Minus,
+                                           std::move(rhs));
+    case Token::plus:
+      return std::make_unique<UnaryOpNode>(loc, UnaryOpKind::Plus,
+                                           std::move(rhs));
     default:
       llvm_unreachable("invalid token kind");
     }
diff --git a/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/Makefile 
b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/Makefile
new file mode 100644
index 0000000000000..99998b20bcb05
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/Makefile
@@ -0,0 +1,3 @@
+CXX_SOURCES := main.cpp
+
+include Makefile.rules
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
new file mode 100644
index 0000000000000..d10622738cc6f
--- /dev/null
+++ 
b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/TestFrameVarDILArithmetic.py
@@ -0,0 +1,40 @@
+"""
+Test DIL arithmetic.
+"""
+
+import lldb
+from lldbsuite.test.lldbtest import *
+from lldbsuite.test.decorators import *
+from lldbsuite.test import lldbutil
+
+
+class TestFrameVarDILArithmetic(TestBase):
+    NO_DEBUG_INFO_TESTCASE = True
+
+    def test_arithmetic(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")
+
+        # Check unary
+        self.expect_var_path("+0", value="0")
+        self.expect_var_path("-0", value="0")
+        self.expect_var_path("+1", value="1")
+        self.expect_var_path("-1", value="-1")
+        self.expect_var_path("s", value="10")
+        self.expect_var_path("+s", value="10")
+        self.expect_var_path("-s", value="-10")
+        self.expect_var_path("us", value="1")
+        self.expect_var_path("-us", value="-1")
+        self.expect_var_path("+0.0", value="0")
+        self.expect_var_path("-0.0", value="-0")
+        self.expect_var_path("-9223372036854775808", 
value="9223372036854775808")
+        self.expect_var_path("+p", type="int *")
+        self.expect(
+            "frame var -- '-p'",
+            error=True,
+            substrs=["invalid argument type 'int *' to unary expression"],
+        )
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
new file mode 100644
index 0000000000000..2567453cc293d
--- /dev/null
+++ b/lldb/test/API/commands/frame/var-dil/expr/Arithmetic/main.cpp
@@ -0,0 +1,9 @@
+int main(int argc, char **argv) {
+  short s = 10;
+  unsigned short us = 1;
+
+  int x = 2;
+  int &r = x;
+  int *p = &x;
+  return 0; // Set a breakpoint here
+}

>From 424159def9255980463e654a032a628ed30bc0cb Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuk...@accesssoftek.com>
Date: Thu, 7 Aug 2025 19:42:22 +0500
Subject: [PATCH 2/6] Type promotion

---
 lldb/source/ValueObject/DILEval.cpp           | 261 ++++++++++--------
 .../Arithmetic/TestFrameVarDILArithmetic.py   |   4 +
 .../frame/var-dil/expr/Arithmetic/main.cpp    |  10 +
 3 files changed, 167 insertions(+), 108 deletions(-)

diff --git a/lldb/source/ValueObject/DILEval.cpp 
b/lldb/source/ValueObject/DILEval.cpp
index 595c25085bfed..05ce5b4b8f7af 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -21,71 +21,153 @@
 
 namespace lldb_private::dil {
 
-static CompilerType GetBasicTypeFromCU(std::shared_ptr<StackFrame> ctx,
-                                       lldb::BasicType basic_type) {
+static llvm::Expected<lldb::TypeSystemSP>
+GetTypeSystemFromCU(std::shared_ptr<StackFrame> ctx) {
   SymbolContext symbol_context =
       ctx->GetSymbolContext(lldb::eSymbolContextCompUnit);
-  auto language = symbol_context.comp_unit->GetLanguage();
+  lldb::LanguageType language = symbol_context.comp_unit->GetLanguage();
 
   symbol_context = ctx->GetSymbolContext(lldb::eSymbolContextModule);
-  auto type_system =
-      symbol_context.module_sp->GetTypeSystemForLanguage(language);
+  return symbol_context.module_sp->GetTypeSystemForLanguage(language);
+}
 
+static CompilerType GetBasicType(lldb::TypeSystemSP type_system,
+                                 lldb::BasicType basic_type) {
   if (type_system)
-    if (auto compiler_type = 
type_system.get()->GetBasicTypeFromAST(basic_type))
-      return compiler_type;
+    return type_system.get()->GetBasicTypeFromAST(basic_type);
 
   return CompilerType();
 }
 
-static CompilerType GetIntCompilerTypeForSize(uint32_t size, bool is_signed,
-                                              lldb::TypeSystemSP type_system,
-                                              std::shared_ptr<StackFrame> ctx) 
{
-  lldb::BasicType promote_types[] = {
-      // lldb::eBasicTypeChar,     lldb::eBasicTypeUnsignedChar,
-      // lldb::eBasicTypeShort,    lldb::eBasicTypeUnsignedShort,
-      lldb::eBasicTypeInt,      lldb::eBasicTypeUnsignedInt,
-      lldb::eBasicTypeLong,     lldb::eBasicTypeUnsignedLong,
-      lldb::eBasicTypeLongLong, lldb::eBasicTypeUnsignedLongLong,
-  };
-  for (auto &basic_type : promote_types) {
-    uint64_t byte_size = 0;
-    CompilerType type = GetBasicType(type_system, basic_type);
-    if (auto temp = type.GetByteSize(ctx.get()))
-      byte_size = *temp;
-    if (size < byte_size ||
-        (size == byte_size &&
-         is_signed == (bool)(type.GetTypeInfo() & lldb::eTypeIsSigned))) {
-      return type;
+static llvm::Expected<CompilerType>
+DoIntegralPromotion(CompilerType from, lldb::TypeSystemSP type_system,
+                    std::shared_ptr<StackFrame> ctx) {
+  if (!from.IsInteger() && !from.IsUnscopedEnumerationType())
+    return from;
+
+  if (!from.IsPromotableIntegerType())
+    return from;
+
+  if (from.IsUnscopedEnumerationType())
+    // TODO: fix this by creating CompilerType::GetEnumerationPromotionType()
+    return DoIntegralPromotion(from.GetEnumerationIntegerType(), type_system,
+                               ctx);
+  lldb::BasicType builtin_type =
+      from.GetCanonicalType().GetBasicTypeEnumeration();
+
+  uint64_t from_size = 0;
+  if (builtin_type == lldb::eBasicTypeWChar ||
+      builtin_type == lldb::eBasicTypeSignedWChar ||
+      builtin_type == lldb::eBasicTypeUnsignedWChar ||
+      builtin_type == lldb::eBasicTypeChar16 ||
+      builtin_type == lldb::eBasicTypeChar32) {
+    // Find the type that can hold the entire range of values for our type.
+    bool is_signed = from.IsSigned();
+    llvm::Expected<uint64_t> from_size = from.GetByteSize(ctx.get());
+    if (!from_size)
+      return from_size.takeError();
+
+    CompilerType promote_types[] = {
+        GetBasicType(type_system, lldb::eBasicTypeInt),
+        GetBasicType(type_system, lldb::eBasicTypeUnsignedInt),
+        GetBasicType(type_system, lldb::eBasicTypeLong),
+        GetBasicType(type_system, lldb::eBasicTypeUnsignedLong),
+        GetBasicType(type_system, lldb::eBasicTypeLongLong),
+        GetBasicType(type_system, lldb::eBasicTypeUnsignedLongLong),
+    };
+    for (CompilerType &type : promote_types) {
+      llvm::Expected<uint64_t> byte_size = type.GetByteSize(ctx.get());
+      if (!byte_size)
+        return byte_size.takeError();
+      if (*from_size < *byte_size ||
+          (*from_size == *byte_size && is_signed == type.IsSigned())) {
+        return type;
+      }
     }
+    llvm_unreachable("char type should fit into long long");
   }
 
-  llvm_unreachable("size could not fit into long long");
-  return CompilerType();
+  // Here we can promote only to "int" or "unsigned int".
+  CompilerType int_type = GetBasicType(type_system, lldb::eBasicTypeInt);
+  llvm::Expected<uint64_t> int_byte_size = int_type.GetByteSize(ctx.get());
+  if (!int_byte_size)
+    return int_byte_size.takeError();
+
+  // Signed integer types can be safely promoted to "int".
+  if (from.IsSigned()) {
+    return int_type;
+  }
+  // Unsigned integer types are promoted to "unsigned int" if "int" cannot hold
+  // their entire value range.
+  return (from_size == *int_byte_size)
+             ? GetBasicType(type_system, lldb::eBasicTypeUnsignedInt)
+             : int_type;
 }
 
-static llvm::Expected<Scalar>
-GetScalarFromValueObject(lldb::ValueObjectSP valobj,
+static lldb::ValueObjectSP
+ArrayToPointerConversion(lldb::ValueObjectSP valobj,
                          std::shared_ptr<StackFrame> ctx) {
-  auto type = valobj->GetCompilerType();
-  Scalar scalar;
-  bool resolved = valobj->ResolveValue(scalar);
-  if (resolved) {
-    if (scalar.GetType() == scalar.e_int) {
-      auto apsint = scalar.GetAPSInt();
-      auto type_bitsize = type.GetBitSize(ctx.get());
-      if (type_bitsize) {
-        llvm::APSInt adjusted;
-        if (type.IsSigned())
-          adjusted = apsint.sextOrTrunc(*type_bitsize);
-        else
-          adjusted = apsint.zextOrTrunc(*type_bitsize);
-        return Scalar(adjusted);
-      }
-    } else
-      return scalar;
+  assert(valobj->IsArrayType() &&
+         "an argument to array-to-pointer conversion must be an array");
+
+  uint64_t addr = valobj->GetLoadAddress();
+  ExecutionContext exe_ctx;
+  ctx->CalculateExecutionContext(exe_ctx);
+  return ValueObject::CreateValueObjectFromAddress(
+      "result", addr, exe_ctx,
+      
valobj->GetCompilerType().GetArrayElementType(ctx.get()).GetPointerType(),
+      /* do_deref */ false);
+}
+
+static llvm::Expected<lldb::ValueObjectSP>
+UnaryConversion(lldb::ValueObjectSP valobj, std::shared_ptr<StackFrame> ctx) {
+  // Perform usual conversions for unary operators. At the moment this includes
+  // array-to-pointer and the integral promotion for eligible types.
+  llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU(ctx);
+  if (!type_system)
+    return type_system.takeError();
+  CompilerType in_type = valobj->GetCompilerType();
+  CompilerType result_type;
+  if (valobj->IsBitfield()) {
+    // Promote bitfields. If `int` can represent the bitfield value, it is
+    // converted to `int`. Otherwise, if `unsigned int` can represent it, it
+    // is converted to `unsigned int`. Otherwise, it is treated as its
+    // underlying type.
+    uint32_t bitfield_size = valobj->GetBitfieldBitSize();
+    // Some bitfields have undefined size (e.g. result of ternary operation).
+    // The AST's `bitfield_size` of those is 0, and no promotion takes place.
+    if (bitfield_size > 0 && in_type.IsInteger()) {
+      CompilerType int_type = GetBasicType(*type_system, lldb::eBasicTypeInt);
+      CompilerType uint_type =
+          GetBasicType(*type_system, lldb::eBasicTypeUnsignedInt);
+      llvm::Expected<uint64_t> int_bit_size = int_type.GetBitSize(ctx.get());
+      if (!int_bit_size)
+        return int_bit_size.takeError();
+      llvm::Expected<uint64_t> uint_bit_size = uint_type.GetBitSize(ctx.get());
+      if (!uint_bit_size)
+        return int_bit_size.takeError();
+      if (bitfield_size < *int_bit_size ||
+          (in_type.IsSigned() && bitfield_size == *int_bit_size))
+        valobj = valobj->CastToBasicType(int_type);
+      else if (bitfield_size <= *uint_bit_size)
+        valobj = valobj->CastToBasicType(uint_type);
+    }
   }
-  return Scalar();
+
+  if (in_type.IsArrayType())
+    valobj = ArrayToPointerConversion(valobj, ctx);
+
+  if (valobj->GetCompilerType().IsInteger() ||
+      valobj->GetCompilerType().IsUnscopedEnumerationType()) {
+    llvm::Expected<CompilerType> promoted_type =
+        DoIntegralPromotion(valobj->GetCompilerType(), *type_system, ctx);
+    if (!promoted_type)
+      return promoted_type.takeError();
+    if (!promoted_type->CompareTypes(valobj->GetCompilerType()))
+      return valobj->CastToBasicType(*promoted_type);
+  }
+
+  return valobj;
 }
 
 static lldb::VariableSP DILFindVariable(ConstString name,
@@ -277,7 +359,12 @@ Interpreter::Visit(const UnaryOpNode *node) {
     return value;
   }
   case UnaryOpKind::Minus: {
-    auto operand_type = operand->GetCompilerType();
+    llvm::Expected<lldb::ValueObjectSP> conv_op =
+        UnaryConversion(operand, m_exe_ctx_scope);
+    if (!conv_op)
+      return conv_op;
+    operand = *conv_op;
+    CompilerType operand_type = operand->GetCompilerType();
     if (!operand_type.IsScalarType()) {
       std::string errMsg =
           llvm::formatv("invalid argument type '{0}' to unary expression",
@@ -285,58 +372,34 @@ Interpreter::Visit(const UnaryOpNode *node) {
       return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
                                                   node->GetLocation());
     }
-    auto scalar = GetScalarFromValueObject(operand, m_exe_ctx_scope);
-    if (!scalar)
+    Scalar scalar;
+    bool resolved = operand->ResolveValue(scalar);
+    if (!resolved)
       break;
 
-    bool negated = scalar->UnaryNegate();
-    if (scalar->GetType() == Scalar::e_int) {
-      auto promo_type = GetIntCompilerTypeForSize(
-          scalar->GetByteSize(), scalar->IsSigned(),
-          operand_type.GetTypeSystem().GetSharedPointer(), m_exe_ctx_scope);
-      auto type_bitsize = promo_type.GetBitSize(m_exe_ctx_scope.get());
-
-      if (type_bitsize && negated) {
-        scalar->IntegralPromote(*type_bitsize, promo_type.IsSigned());
-        return ValueObject::CreateValueObjectFromScalar(m_target, *scalar,
-                                                        promo_type, "result");
-      }
-    } else
-      return ValueObject::CreateValueObjectFromScalar(m_target, *scalar,
-                                                      operand_type, "result");
+    bool negated = scalar.UnaryNegate();
+    if (negated)
+      return ValueObject::CreateValueObjectFromScalar(
+          m_target, scalar, operand->GetCompilerType(), "result");
     break;
   }
   case UnaryOpKind::Plus: {
-    auto operand_type = operand->GetCompilerType();
-    // Unary plus is allowed for pointers.
-    if (operand_type.IsPointerType())
-      return operand;
-    if (!operand_type.IsScalarType()) {
+    llvm::Expected<lldb::ValueObjectSP> conv_op =
+        UnaryConversion(operand, m_exe_ctx_scope);
+    if (!conv_op)
+      return conv_op;
+    operand = *conv_op;
+    CompilerType operand_type = operand->GetCompilerType();
+    if (!operand_type.IsScalarType() &&
+        // Unary plus is allowed for pointers.
+        !operand_type.IsPointerType()) {
       std::string errMsg =
           llvm::formatv("invalid argument type '{0}' to unary expression",
                         operand_type.GetTypeName());
       return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
                                                   node->GetLocation());
     }
-    auto scalar = GetScalarFromValueObject(operand, m_exe_ctx_scope);
-    if (!scalar)
-      break;
-
-    if (scalar->GetType() == Scalar::e_int) {
-      auto promo_type = GetIntCompilerTypeForSize(
-          scalar->GetByteSize(), scalar->IsSigned(),
-          operand_type.GetTypeSystem().GetSharedPointer(), m_exe_ctx_scope);
-      auto type_bitsize = promo_type.GetBitSize(m_exe_ctx_scope.get());
-
-      if (type_bitsize) {
-        scalar->IntegralPromote(*type_bitsize, promo_type.IsSigned());
-        return ValueObject::CreateValueObjectFromScalar(m_target, *scalar,
-                                                        promo_type, "result");
-      }
-    } else
-      return ValueObject::CreateValueObjectFromScalar(m_target, *scalar,
-                                                      operand_type, "result");
-    break;
+    return operand;
   }
   }
   return llvm::make_error<DILDiagnosticError>(m_expr, "invalid unary 
operation",
@@ -626,24 +689,6 @@ Interpreter::Visit(const BitFieldExtractionNode *node) {
   return child_valobj_sp;
 }
 
-static llvm::Expected<lldb::TypeSystemSP>
-GetTypeSystemFromCU(std::shared_ptr<StackFrame> ctx) {
-  SymbolContext symbol_context =
-      ctx->GetSymbolContext(lldb::eSymbolContextCompUnit);
-  lldb::LanguageType language = symbol_context.comp_unit->GetLanguage();
-
-  symbol_context = ctx->GetSymbolContext(lldb::eSymbolContextModule);
-  return symbol_context.module_sp->GetTypeSystemForLanguage(language);
-}
-
-static CompilerType GetBasicType(lldb::TypeSystemSP type_system,
-                                 lldb::BasicType basic_type) {
-  if (type_system)
-    return type_system.get()->GetBasicTypeFromAST(basic_type);
-
-  return CompilerType();
-}
-
 llvm::Expected<CompilerType>
 Interpreter::PickIntegerType(lldb::TypeSystemSP type_system,
                              std::shared_ptr<ExecutionContextScope> ctx,
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 d10622738cc6f..fc53b656d7591 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
@@ -32,6 +32,10 @@ def test_arithmetic(self):
         self.expect_var_path("+0.0", value="0")
         self.expect_var_path("-0.0", value="-0")
         self.expect_var_path("-9223372036854775808", 
value="9223372036854775808")
+        self.expect_var_path("+array", type="int *")
+        self.expect_var_path("+enum_one", value="1")
+        self.expect_var_path("-enum_one", value="4294967295") # TODO: fix
+        self.expect_var_path("+bf.a", value="7")
         self.expect_var_path("+p", type="int *")
         self.expect(
             "frame var -- '-p'",
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 2567453cc293d..125a64d7b7109 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
@@ -1,3 +1,5 @@
+#include <cstdint>
+
 int main(int argc, char **argv) {
   short s = 10;
   unsigned short us = 1;
@@ -5,5 +7,13 @@ int main(int argc, char **argv) {
   int x = 2;
   int &r = x;
   int *p = &x;
+  int array[] = {1};
+  enum Enum { kZero, kOne } enum_one = kOne;
+
+  struct BitFieldStruct {
+    uint16_t a : 10;
+  };
+  BitFieldStruct bf = {7};
+
   return 0; // Set a breakpoint here
 }

>From 05eec8b50f3f6aa93ffaa66ff9810bdcf0eb5546 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuk...@accesssoftek.com>
Date: Tue, 19 Aug 2025 20:22:51 +0500
Subject: [PATCH 3/6] Move DoIntegralPromotion and IsPromotableIntegerType to
 TypeSystem

---
 lldb/include/lldb/Symbol/TypeSystem.h         |  7 ++
 .../TypeSystem/Clang/TypeSystemClang.cpp      | 96 +++++++++++++++++++
 .../TypeSystem/Clang/TypeSystemClang.h        |  8 ++
 lldb/source/Symbol/CompilerType.cpp           | 28 +-----
 lldb/source/Symbol/TypeSystem.cpp             | 10 ++
 lldb/source/ValueObject/DILEval.cpp           | 82 +++-------------
 .../Arithmetic/TestFrameVarDILArithmetic.py   |  2 +-
 7 files changed, 137 insertions(+), 96 deletions(-)

diff --git a/lldb/include/lldb/Symbol/TypeSystem.h 
b/lldb/include/lldb/Symbol/TypeSystem.h
index 16a2e0b5a52fb..d74e6a0e05625 100644
--- a/lldb/include/lldb/Symbol/TypeSystem.h
+++ b/lldb/include/lldb/Symbol/TypeSystem.h
@@ -412,6 +412,13 @@ class TypeSystem : public PluginInterface,
   GetIntegralTemplateArgument(lldb::opaque_compiler_type_t type, size_t idx,
                               bool expand_pack);
 
+  // DIL
+
+  virtual bool IsPromotableIntegerType(lldb::opaque_compiler_type_t type);
+
+  virtual llvm::Expected<CompilerType>
+  DoIntegralPromotion(CompilerType from, ExecutionContextScope *exe_scope);
+
   // Dumping types
 
 #ifndef NDEBUG
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
index 39aacdb58e694..4d4ca522e052a 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.cpp
@@ -7320,6 +7320,102 @@ CompilerType TypeSystemClang::GetTypeForFormatters(void 
*type) {
   return CompilerType();
 }
 
+bool TypeSystemClang::IsPromotableIntegerType(
+    lldb::opaque_compiler_type_t type) {
+  // Unscoped enums are always considered as promotable, even if their
+  // underlying type does not need to be promoted (e.g. "int").
+  bool is_signed = false;
+  bool isUnscopedEnumerationType =
+      IsEnumerationType(type, is_signed) && !IsScopedEnumerationType(type);
+  if (isUnscopedEnumerationType)
+    return true;
+
+  switch (GetBasicTypeEnumeration(type)) {
+  case lldb::eBasicTypeBool:
+  case lldb::eBasicTypeChar:
+  case lldb::eBasicTypeSignedChar:
+  case lldb::eBasicTypeUnsignedChar:
+  case lldb::eBasicTypeShort:
+  case lldb::eBasicTypeUnsignedShort:
+  case lldb::eBasicTypeWChar:
+  case lldb::eBasicTypeSignedWChar:
+  case lldb::eBasicTypeUnsignedWChar:
+  case lldb::eBasicTypeChar16:
+  case lldb::eBasicTypeChar32:
+    return true;
+
+  default:
+    return false;
+  }
+
+  llvm_unreachable("All cases handled above.");
+}
+
+llvm::Expected<CompilerType>
+TypeSystemClang::DoIntegralPromotion(CompilerType from,
+                                     ExecutionContextScope *exe_scope) {
+  if (!from.IsInteger() && !from.IsUnscopedEnumerationType())
+    return from;
+
+  if (!from.IsPromotableIntegerType())
+    return from;
+
+  if (from.IsUnscopedEnumerationType()) {
+    EnumDecl *enum_decl = GetAsEnumDecl(from);
+    CompilerType promotion_type = GetType(enum_decl->getPromotionType());
+    return DoIntegralPromotion(promotion_type, exe_scope);
+  }
+
+  lldb::BasicType builtin_type =
+      from.GetCanonicalType().GetBasicTypeEnumeration();
+  uint64_t from_size = 0;
+  if (builtin_type == lldb::eBasicTypeWChar ||
+      builtin_type == lldb::eBasicTypeSignedWChar ||
+      builtin_type == lldb::eBasicTypeUnsignedWChar ||
+      builtin_type == lldb::eBasicTypeChar16 ||
+      builtin_type == lldb::eBasicTypeChar32) {
+    // Find the type that can hold the entire range of values for our type.
+    bool is_signed = from.IsSigned();
+    llvm::Expected<uint64_t> from_size = from.GetByteSize(exe_scope);
+    if (!from_size)
+      return from_size.takeError();
+    CompilerType promote_types[] = {
+        GetBasicTypeFromAST(lldb::eBasicTypeInt),
+        GetBasicTypeFromAST(lldb::eBasicTypeUnsignedInt),
+        GetBasicTypeFromAST(lldb::eBasicTypeLong),
+        GetBasicTypeFromAST(lldb::eBasicTypeUnsignedLong),
+        GetBasicTypeFromAST(lldb::eBasicTypeLongLong),
+        GetBasicTypeFromAST(lldb::eBasicTypeUnsignedLongLong),
+    };
+    for (CompilerType &type : promote_types) {
+      llvm::Expected<uint64_t> byte_size = type.GetByteSize(exe_scope);
+      if (!byte_size)
+        return byte_size.takeError();
+      if (*from_size < *byte_size ||
+          (*from_size == *byte_size && is_signed == type.IsSigned())) {
+        return type;
+      }
+    }
+    llvm_unreachable("char type should fit into long long");
+  }
+
+  // Here we can promote only to "int" or "unsigned int".
+  CompilerType int_type = GetBasicTypeFromAST(lldb::eBasicTypeInt);
+  llvm::Expected<uint64_t> int_byte_size = int_type.GetByteSize(exe_scope);
+  if (!int_byte_size)
+    return int_byte_size.takeError();
+
+  // Signed integer types can be safely promoted to "int".
+  if (from.IsSigned()) {
+    return int_type;
+  }
+  // Unsigned integer types are promoted to "unsigned int" if "int" cannot hold
+  // their entire value range.
+  return (from_size == *int_byte_size)
+             ? GetBasicTypeFromAST(lldb::eBasicTypeUnsignedInt)
+             : int_type;
+}
+
 clang::EnumDecl *TypeSystemClang::GetAsEnumDecl(const CompilerType &type) {
   const clang::EnumType *enutype =
       llvm::dyn_cast<clang::EnumType>(ClangUtil::GetCanonicalQualType(type));
diff --git a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h 
b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
index 709f89590ba3b..0ca1a1e2578b3 100644
--- a/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
+++ b/lldb/source/Plugins/TypeSystem/Clang/TypeSystemClang.h
@@ -939,6 +939,14 @@ class TypeSystemClang : public TypeSystem {
 
   CompilerType GetTypeForFormatters(void *type) override;
 
+  // DIL
+
+  bool IsPromotableIntegerType(lldb::opaque_compiler_type_t type) override;
+
+  llvm::Expected<CompilerType>
+  DoIntegralPromotion(CompilerType from,
+                      ExecutionContextScope *exe_scope) override;
+
 #define LLDB_INVALID_DECL_LEVEL UINT32_MAX
   // LLDB_INVALID_DECL_LEVEL is returned by CountDeclLevels if child_decl_ctx
   // could not be found in decl_ctx.
diff --git a/lldb/source/Symbol/CompilerType.cpp 
b/lldb/source/Symbol/CompilerType.cpp
index 62c0ddf51c012..a22e817f818ce 100644
--- a/lldb/source/Symbol/CompilerType.cpp
+++ b/lldb/source/Symbol/CompilerType.cpp
@@ -373,30 +373,10 @@ bool CompilerType::IsScalarOrUnscopedEnumerationType() 
const {
 }
 
 bool CompilerType::IsPromotableIntegerType() const {
-  // Unscoped enums are always considered as promotable, even if their
-  // underlying type does not need to be promoted (e.g. "int").
-  if (IsUnscopedEnumerationType())
-    return true;
-
-  switch (GetBasicTypeEnumeration()) {
-  case lldb::eBasicTypeBool:
-  case lldb::eBasicTypeChar:
-  case lldb::eBasicTypeSignedChar:
-  case lldb::eBasicTypeUnsignedChar:
-  case lldb::eBasicTypeShort:
-  case lldb::eBasicTypeUnsignedShort:
-  case lldb::eBasicTypeWChar:
-  case lldb::eBasicTypeSignedWChar:
-  case lldb::eBasicTypeUnsignedWChar:
-  case lldb::eBasicTypeChar16:
-  case lldb::eBasicTypeChar32:
-    return true;
-
-  default:
-    return false;
-  }
-
-  llvm_unreachable("All cases handled above.");
+  if (IsValid())
+    if (auto type_system_sp = GetTypeSystem())
+      return type_system_sp->IsPromotableIntegerType(m_type);
+  return false;
 }
 
 bool CompilerType::IsPointerToVoid() const {
diff --git a/lldb/source/Symbol/TypeSystem.cpp 
b/lldb/source/Symbol/TypeSystem.cpp
index f7d634ffa2dec..7df049084e6fb 100644
--- a/lldb/source/Symbol/TypeSystem.cpp
+++ b/lldb/source/Symbol/TypeSystem.cpp
@@ -123,6 +123,16 @@ CompilerType TypeSystem::GetTypeForFormatters(void *type) {
   return CompilerType(weak_from_this(), type);
 }
 
+bool TypeSystem::IsPromotableIntegerType(lldb::opaque_compiler_type_t type) {
+  return false;
+}
+
+llvm::Expected<CompilerType>
+TypeSystem::DoIntegralPromotion(CompilerType from,
+                                ExecutionContextScope *exe_scope) {
+  return CompilerType();
+}
+
 bool TypeSystem::IsTemplateType(lldb::opaque_compiler_type_t type) {
   return false;
 }
diff --git a/lldb/source/ValueObject/DILEval.cpp 
b/lldb/source/ValueObject/DILEval.cpp
index 05ce5b4b8f7af..ff757f34772ef 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -22,12 +22,15 @@
 namespace lldb_private::dil {
 
 static llvm::Expected<lldb::TypeSystemSP>
-GetTypeSystemFromCU(std::shared_ptr<StackFrame> ctx) {
+GetTypeSystemFromCU(std::shared_ptr<ExecutionContextScope> ctx) {
+  auto stack_frame = ctx->CalculateStackFrame();
+  if (!stack_frame)
+    return llvm::createStringError("no stack frame in this context");
   SymbolContext symbol_context =
-      ctx->GetSymbolContext(lldb::eSymbolContextCompUnit);
+      stack_frame->GetSymbolContext(lldb::eSymbolContextCompUnit);
   lldb::LanguageType language = symbol_context.comp_unit->GetLanguage();
 
-  symbol_context = ctx->GetSymbolContext(lldb::eSymbolContextModule);
+  symbol_context = stack_frame->GetSymbolContext(lldb::eSymbolContextModule);
   return symbol_context.module_sp->GetTypeSystemForLanguage(language);
 }
 
@@ -39,74 +42,9 @@ static CompilerType GetBasicType(lldb::TypeSystemSP 
type_system,
   return CompilerType();
 }
 
-static llvm::Expected<CompilerType>
-DoIntegralPromotion(CompilerType from, lldb::TypeSystemSP type_system,
-                    std::shared_ptr<StackFrame> ctx) {
-  if (!from.IsInteger() && !from.IsUnscopedEnumerationType())
-    return from;
-
-  if (!from.IsPromotableIntegerType())
-    return from;
-
-  if (from.IsUnscopedEnumerationType())
-    // TODO: fix this by creating CompilerType::GetEnumerationPromotionType()
-    return DoIntegralPromotion(from.GetEnumerationIntegerType(), type_system,
-                               ctx);
-  lldb::BasicType builtin_type =
-      from.GetCanonicalType().GetBasicTypeEnumeration();
-
-  uint64_t from_size = 0;
-  if (builtin_type == lldb::eBasicTypeWChar ||
-      builtin_type == lldb::eBasicTypeSignedWChar ||
-      builtin_type == lldb::eBasicTypeUnsignedWChar ||
-      builtin_type == lldb::eBasicTypeChar16 ||
-      builtin_type == lldb::eBasicTypeChar32) {
-    // Find the type that can hold the entire range of values for our type.
-    bool is_signed = from.IsSigned();
-    llvm::Expected<uint64_t> from_size = from.GetByteSize(ctx.get());
-    if (!from_size)
-      return from_size.takeError();
-
-    CompilerType promote_types[] = {
-        GetBasicType(type_system, lldb::eBasicTypeInt),
-        GetBasicType(type_system, lldb::eBasicTypeUnsignedInt),
-        GetBasicType(type_system, lldb::eBasicTypeLong),
-        GetBasicType(type_system, lldb::eBasicTypeUnsignedLong),
-        GetBasicType(type_system, lldb::eBasicTypeLongLong),
-        GetBasicType(type_system, lldb::eBasicTypeUnsignedLongLong),
-    };
-    for (CompilerType &type : promote_types) {
-      llvm::Expected<uint64_t> byte_size = type.GetByteSize(ctx.get());
-      if (!byte_size)
-        return byte_size.takeError();
-      if (*from_size < *byte_size ||
-          (*from_size == *byte_size && is_signed == type.IsSigned())) {
-        return type;
-      }
-    }
-    llvm_unreachable("char type should fit into long long");
-  }
-
-  // Here we can promote only to "int" or "unsigned int".
-  CompilerType int_type = GetBasicType(type_system, lldb::eBasicTypeInt);
-  llvm::Expected<uint64_t> int_byte_size = int_type.GetByteSize(ctx.get());
-  if (!int_byte_size)
-    return int_byte_size.takeError();
-
-  // Signed integer types can be safely promoted to "int".
-  if (from.IsSigned()) {
-    return int_type;
-  }
-  // Unsigned integer types are promoted to "unsigned int" if "int" cannot hold
-  // their entire value range.
-  return (from_size == *int_byte_size)
-             ? GetBasicType(type_system, lldb::eBasicTypeUnsignedInt)
-             : int_type;
-}
-
 static lldb::ValueObjectSP
 ArrayToPointerConversion(lldb::ValueObjectSP valobj,
-                         std::shared_ptr<StackFrame> ctx) {
+                         std::shared_ptr<ExecutionContextScope> ctx) {
   assert(valobj->IsArrayType() &&
          "an argument to array-to-pointer conversion must be an array");
 
@@ -120,7 +58,8 @@ ArrayToPointerConversion(lldb::ValueObjectSP valobj,
 }
 
 static llvm::Expected<lldb::ValueObjectSP>
-UnaryConversion(lldb::ValueObjectSP valobj, std::shared_ptr<StackFrame> ctx) {
+UnaryConversion(lldb::ValueObjectSP valobj,
+                std::shared_ptr<ExecutionContextScope> ctx) {
   // Perform usual conversions for unary operators. At the moment this includes
   // array-to-pointer and the integral promotion for eligible types.
   llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU(ctx);
@@ -160,7 +99,8 @@ UnaryConversion(lldb::ValueObjectSP valobj, 
std::shared_ptr<StackFrame> ctx) {
   if (valobj->GetCompilerType().IsInteger() ||
       valobj->GetCompilerType().IsUnscopedEnumerationType()) {
     llvm::Expected<CompilerType> promoted_type =
-        DoIntegralPromotion(valobj->GetCompilerType(), *type_system, ctx);
+        type_system.get()->DoIntegralPromotion(valobj->GetCompilerType(),
+                                               ctx.get());
     if (!promoted_type)
       return promoted_type.takeError();
     if (!promoted_type->CompareTypes(valobj->GetCompilerType()))
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 fc53b656d7591..c6a97e6f52089 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
@@ -34,7 +34,7 @@ def test_arithmetic(self):
         self.expect_var_path("-9223372036854775808", 
value="9223372036854775808")
         self.expect_var_path("+array", type="int *")
         self.expect_var_path("+enum_one", value="1")
-        self.expect_var_path("-enum_one", value="4294967295") # TODO: fix
+        self.expect_var_path("-enum_one", value="-1")
         self.expect_var_path("+bf.a", value="7")
         self.expect_var_path("+p", type="int *")
         self.expect(

>From 86c86fc7accdde1b8914c1351ebb9a0044157469 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuk...@accesssoftek.com>
Date: Tue, 19 Aug 2025 22:47:24 +0500
Subject: [PATCH 4/6] Adjust bitfield promotion

---
 lldb/include/lldb/ValueObject/DILEval.h       |  2 +
 lldb/source/ValueObject/DILEval.cpp           | 37 +++++++++++--------
 .../Arithmetic/TestFrameVarDILArithmetic.py   |  6 ++-
 .../frame/var-dil/expr/Arithmetic/main.cpp    |  7 +++-
 4 files changed, 34 insertions(+), 18 deletions(-)

diff --git a/lldb/include/lldb/ValueObject/DILEval.h 
b/lldb/include/lldb/ValueObject/DILEval.h
index 5a48c2c989f4d..11f44336cbf55 100644
--- a/lldb/include/lldb/ValueObject/DILEval.h
+++ b/lldb/include/lldb/ValueObject/DILEval.h
@@ -59,6 +59,8 @@ class Interpreter : Visitor {
   llvm::Expected<lldb::ValueObjectSP>
   Visit(const FloatLiteralNode *node) override;
 
+  llvm::Expected<lldb::ValueObjectSP>
+  UnaryConversion(lldb::ValueObjectSP valobj);
   llvm::Expected<CompilerType>
   PickIntegerType(lldb::TypeSystemSP type_system,
                   std::shared_ptr<ExecutionContextScope> ctx,
diff --git a/lldb/source/ValueObject/DILEval.cpp 
b/lldb/source/ValueObject/DILEval.cpp
index ff757f34772ef..c31b90ce83663 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -57,12 +57,12 @@ ArrayToPointerConversion(lldb::ValueObjectSP valobj,
       /* do_deref */ false);
 }
 
-static llvm::Expected<lldb::ValueObjectSP>
-UnaryConversion(lldb::ValueObjectSP valobj,
-                std::shared_ptr<ExecutionContextScope> ctx) {
+llvm::Expected<lldb::ValueObjectSP>
+Interpreter::UnaryConversion(lldb::ValueObjectSP valobj) {
   // Perform usual conversions for unary operators. At the moment this includes
   // array-to-pointer and the integral promotion for eligible types.
-  llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU(ctx);
+  llvm::Expected<lldb::TypeSystemSP> type_system =
+      GetTypeSystemFromCU(m_exe_ctx_scope);
   if (!type_system)
     return type_system.takeError();
   CompilerType in_type = valobj->GetCompilerType();
@@ -79,28 +79,37 @@ UnaryConversion(lldb::ValueObjectSP valobj,
       CompilerType int_type = GetBasicType(*type_system, lldb::eBasicTypeInt);
       CompilerType uint_type =
           GetBasicType(*type_system, lldb::eBasicTypeUnsignedInt);
-      llvm::Expected<uint64_t> int_bit_size = int_type.GetBitSize(ctx.get());
+      llvm::Expected<uint64_t> int_bit_size =
+          int_type.GetBitSize(m_exe_ctx_scope.get());
       if (!int_bit_size)
         return int_bit_size.takeError();
-      llvm::Expected<uint64_t> uint_bit_size = uint_type.GetBitSize(ctx.get());
+      llvm::Expected<uint64_t> uint_bit_size =
+          uint_type.GetBitSize(m_exe_ctx_scope.get());
       if (!uint_bit_size)
         return int_bit_size.takeError();
       if (bitfield_size < *int_bit_size ||
           (in_type.IsSigned() && bitfield_size == *int_bit_size))
-        valobj = valobj->CastToBasicType(int_type);
-      else if (bitfield_size <= *uint_bit_size)
-        valobj = valobj->CastToBasicType(uint_type);
+        return valobj->CastToBasicType(int_type);
+      if (bitfield_size <= *uint_bit_size)
+        return valobj->CastToBasicType(uint_type);
+      // Re-create as a const value with the same underlying type
+      Scalar scalar;
+      bool resolved = valobj->ResolveValue(scalar);
+      if (!resolved)
+        return llvm::createStringError("invalid scalar value");
+      return ValueObject::CreateValueObjectFromScalar(m_target, scalar, 
in_type,
+                                                      "result");
     }
   }
 
   if (in_type.IsArrayType())
-    valobj = ArrayToPointerConversion(valobj, ctx);
+    valobj = ArrayToPointerConversion(valobj, m_exe_ctx_scope);
 
   if (valobj->GetCompilerType().IsInteger() ||
       valobj->GetCompilerType().IsUnscopedEnumerationType()) {
     llvm::Expected<CompilerType> promoted_type =
         type_system.get()->DoIntegralPromotion(valobj->GetCompilerType(),
-                                               ctx.get());
+                                               m_exe_ctx_scope.get());
     if (!promoted_type)
       return promoted_type.takeError();
     if (!promoted_type->CompareTypes(valobj->GetCompilerType()))
@@ -299,8 +308,7 @@ Interpreter::Visit(const UnaryOpNode *node) {
     return value;
   }
   case UnaryOpKind::Minus: {
-    llvm::Expected<lldb::ValueObjectSP> conv_op =
-        UnaryConversion(operand, m_exe_ctx_scope);
+    llvm::Expected<lldb::ValueObjectSP> conv_op = UnaryConversion(operand);
     if (!conv_op)
       return conv_op;
     operand = *conv_op;
@@ -324,8 +332,7 @@ Interpreter::Visit(const UnaryOpNode *node) {
     break;
   }
   case UnaryOpKind::Plus: {
-    llvm::Expected<lldb::ValueObjectSP> conv_op =
-        UnaryConversion(operand, m_exe_ctx_scope);
+    llvm::Expected<lldb::ValueObjectSP> conv_op = UnaryConversion(operand);
     if (!conv_op)
       return conv_op;
     operand = *conv_op;
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 c6a97e6f52089..d2b0ecd75966e 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
@@ -35,7 +35,11 @@ def test_arithmetic(self):
         self.expect_var_path("+array", type="int *")
         self.expect_var_path("+enum_one", value="1")
         self.expect_var_path("-enum_one", value="-1")
-        self.expect_var_path("+bf.a", value="7")
+        self.expect_var_path("-bitfield.a", value="-1", type="int")
+        self.expect_var_path("+bitfield.a", value="1", type="int")
+        self.expect_var_path("+bitfield.b", value="2", type="int")
+        self.expect_var_path("+bitfield.c", value="3", type="unsigned int")
+        self.expect_var_path("+bitfield.d", value="4", type="uint64_t")
         self.expect_var_path("+p", type="int *")
         self.expect(
             "frame var -- '-p'",
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 125a64d7b7109..fdeb6cf49ccfd 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
@@ -11,9 +11,12 @@ int main(int argc, char **argv) {
   enum Enum { kZero, kOne } enum_one = kOne;
 
   struct BitFieldStruct {
-    uint16_t a : 10;
+    char a : 4;
+    int b : 32;
+    unsigned int c : 32;
+    uint64_t d : 48;
   };
-  BitFieldStruct bf = {7};
+  BitFieldStruct bitfield = {1, 2, 3, 4};
 
   return 0; // Set a breakpoint here
 }

>From 80b5f94f4b70dd9dfee584bfa0c42fada5c6ef39 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuk...@accesssoftek.com>
Date: Fri, 22 Aug 2025 17:18:33 +0500
Subject: [PATCH 5/6] Expand the test

---
 .../Arithmetic/TestFrameVarDILArithmetic.py   | 19 +++++++++++--------
 .../frame/var-dil/expr/Arithmetic/main.cpp    |  3 +++
 2 files changed, 14 insertions(+), 8 deletions(-)

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 d2b0ecd75966e..76edc5837cf2b 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
@@ -19,27 +19,30 @@ def test_arithmetic(self):
 
         self.runCmd("settings set target.experimental.use-DIL true")
 
-        # Check unary
+        # Check unary results and integral promotion
         self.expect_var_path("+0", value="0")
         self.expect_var_path("-0", value="0")
         self.expect_var_path("+1", value="1")
         self.expect_var_path("-1", value="-1")
-        self.expect_var_path("s", value="10")
-        self.expect_var_path("+s", value="10")
-        self.expect_var_path("-s", value="-10")
-        self.expect_var_path("us", value="1")
-        self.expect_var_path("-us", value="-1")
+        self.expect_var_path("-9223372036854775808", 
value="9223372036854775808")
+        self.expect_var_path("s", value="10", type="short")
+        self.expect_var_path("+s", value="10", type="int")
+        self.expect_var_path("-s", value="-10", type="int")
+        self.expect_var_path("+us", value="1", type="int")
+        self.expect_var_path("-us", value="-1", type="int")
         self.expect_var_path("+0.0", value="0")
         self.expect_var_path("-0.0", value="-0")
-        self.expect_var_path("-9223372036854775808", 
value="9223372036854775808")
-        self.expect_var_path("+array", type="int *")
         self.expect_var_path("+enum_one", value="1")
         self.expect_var_path("-enum_one", value="-1")
+        self.expect_var_path("+wchar", value="1")
+        self.expect_var_path("+char16", value="2")
+        self.expect_var_path("+char32", value="3")
         self.expect_var_path("-bitfield.a", value="-1", type="int")
         self.expect_var_path("+bitfield.a", value="1", type="int")
         self.expect_var_path("+bitfield.b", value="2", type="int")
         self.expect_var_path("+bitfield.c", value="3", type="unsigned int")
         self.expect_var_path("+bitfield.d", value="4", type="uint64_t")
+        self.expect_var_path("+array", type="int *")
         self.expect_var_path("+p", type="int *")
         self.expect(
             "frame var -- '-p'",
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 fdeb6cf49ccfd..5090ce8e34e3d 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
@@ -9,6 +9,9 @@ int main(int argc, char **argv) {
   int *p = &x;
   int array[] = {1};
   enum Enum { kZero, kOne } enum_one = kOne;
+  wchar_t wchar = 1;
+  char16_t char16 = 2;
+  char32_t char32 = 3;
 
   struct BitFieldStruct {
     char a : 4;

>From 72b4fbc46c9e91fea5fb80bc97b045f8af9294ef Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuk...@accesssoftek.com>
Date: Thu, 28 Aug 2025 22:05:57 +0500
Subject: [PATCH 6/6] Expand grammar

---
 lldb/docs/dil-expr-lang.ebnf          | 2 +-
 lldb/source/ValueObject/DILParser.cpp | 2 ++
 2 files changed, 3 insertions(+), 1 deletion(-)

diff --git a/lldb/docs/dil-expr-lang.ebnf b/lldb/docs/dil-expr-lang.ebnf
index 67328939ba420..20804935bf356 100644
--- a/lldb/docs/dil-expr-lang.ebnf
+++ b/lldb/docs/dil-expr-lang.ebnf
@@ -8,7 +8,7 @@ expression = unary_expression ;
 unary_expression = postfix_expression
                  | unary_operator expression ;
 
-unary_operator = "*" | "&" ;
+unary_operator = "*" | "&" | "+" | "-";
 
 postfix_expression = primary_expression
                    | postfix_expression "[" integer_literal "]"
diff --git a/lldb/source/ValueObject/DILParser.cpp 
b/lldb/source/ValueObject/DILParser.cpp
index b88345d18a6d4..b1ba25213c803 100644
--- a/lldb/source/ValueObject/DILParser.cpp
+++ b/lldb/source/ValueObject/DILParser.cpp
@@ -93,6 +93,8 @@ ASTNodeUP DILParser::ParseExpression() { return 
ParseUnaryExpression(); }
 //  unary_operator:
 //    "&"
 //    "*"
+//    "+"
+//    "-"
 //
 ASTNodeUP DILParser::ParseUnaryExpression() {
   if (CurToken().IsOneOf(

_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to