Author: Ilia Kuklin
Date: 2026-08-27T19:12:53+05:00
New Revision: 1d282d29daf7da1be6aa4fa83a3b265fe25b90cf

URL: 
https://github.com/llvm/llvm-project/commit/1d282d29daf7da1be6aa4fa83a3b265fe25b90cf
DIFF: 
https://github.com/llvm/llvm-project/commit/1d282d29daf7da1be6aa4fa83a3b265fe25b90cf.diff

LOG: [lldb] Add error handling of failed casts in DIL (#217431)

This patch does 2 things:
1. If `ValueObject::CastToBasicType` or `ValueObject::CastToEnumType`
return an ValueObject with an error, retrieve the error message and
return it as `DILDiagnosticError`.
2. Fix a minor bug in error checking logic in
`ValueObject::CastToBasicType`.

Added: 
    

Modified: 
    lldb/source/ValueObject/DILEval.cpp
    lldb/source/ValueObject/ValueObject.cpp
    lldb/test/API/commands/frame/var-dil/expr/Casts/TestFrameVarDILCast.py

Removed: 
    


################################################################################
diff  --git a/lldb/source/ValueObject/DILEval.cpp 
b/lldb/source/ValueObject/DILEval.cpp
index 9be288173e8f3..fb98c99dbe360 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -88,10 +88,20 @@ Interpreter::UnaryConversion(lldb::ValueObjectSP valobj, 
uint32_t location) {
       if (!uint_bit_size)
         return uint_bit_size.takeError();
       if (bitfield_size < *int_bit_size ||
-          (in_type.IsSigned() && bitfield_size == *int_bit_size))
-        return valobj->CastToBasicType(int_type);
-      if (bitfield_size <= *uint_bit_size)
-        return valobj->CastToBasicType(uint_type);
+          (in_type.IsSigned() && bitfield_size == *int_bit_size)) {
+        auto result = valobj->CastToBasicType(int_type);
+        if (result->GetError().Fail())
+          return llvm::make_error<DILDiagnosticError>(
+              m_expr, result->GetError().AsCString(), location);
+        return result;
+      }
+      if (bitfield_size <= *uint_bit_size) {
+        auto result = valobj->CastToBasicType(uint_type);
+        if (result->GetError().Fail())
+          return llvm::make_error<DILDiagnosticError>(
+              m_expr, result->GetError().AsCString(), location);
+        return result;
+      }
       // Re-create as a const value with the same underlying type
       Scalar scalar;
       bool resolved = valobj->ResolveValue(scalar);
@@ -107,8 +117,13 @@ Interpreter::UnaryConversion(lldb::ValueObjectSP valobj, 
uint32_t location) {
 
   CompilerType promoted_type =
       valobj->GetCompilerType().GetPromotedIntegerType();
-  if (promoted_type)
-    return valobj->CastToBasicType(promoted_type);
+  if (promoted_type) {
+    auto result = valobj->CastToBasicType(promoted_type);
+    if (result->GetError().Fail())
+      return llvm::make_error<DILDiagnosticError>(
+          m_expr, result->GetError().AsCString(), location);
+    return result;
+  }
 
   return valobj;
 }
@@ -1933,18 +1948,19 @@ llvm::Expected<lldb::ValueObjectSP> 
Interpreter::Visit(const CastNode &node) {
                                                   node.GetLocation());
   }
 
+  lldb::ValueObjectSP result;
   switch (cast_kind) {
   case CastKind::eEnumeration: {
     // FIXME: is this correct for float vector types?
     if (op_type.GetTypeInfo() & lldb::eTypeIsFloat || op_type.IsInteger() ||
         op_type.IsEnumerationType())
-      return operand->CastToEnumType(target_type);
+      result = operand->CastToEnumType(target_type);
     break;
   }
   case CastKind::eArithmetic: {
     if (op_type.IsPointerType() || op_type.IsNullPtrType() ||
         op_type.IsScalarType() || op_type.IsEnumerationType())
-      return operand->CastToBasicType(target_type);
+      result = operand->CastToBasicType(target_type);
     break;
   }
   case CastKind::ePointer: {
@@ -1954,15 +1970,24 @@ llvm::Expected<lldb::ValueObjectSP> 
Interpreter::Visit(const CastNode &node) {
                                               : 
operand->GetValueAsUnsigned(0));
     llvm::StringRef name = "result";
     ExecutionContext exe_ctx(m_target.get(), false);
-    return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx,
-                                                     target_type,
-                                                     /* do_deref */ false);
+    result = ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx,
+                                                       target_type,
+                                                       /* do_deref */ false);
+    break;
   }
   case CastKind::eNone: {
     return lldb::ValueObjectSP();
   }
   } // switch
 
+  if (result) {
+    // If cast failed, retrieve the error message from the result.
+    if (result->GetError().Fail())
+      return llvm::make_error<DILDiagnosticError>(
+          m_expr, result->GetError().AsCString(), node.GetLocation());
+    return result;
+  }
+
   std::string errMsg =
       llvm::formatv("unable to cast from '{0}' to '{1}'",
                     op_type.TypeDescription(), target_type.TypeDescription());

diff  --git a/lldb/source/ValueObject/ValueObject.cpp 
b/lldb/source/ValueObject/ValueObject.cpp
index 2005885b584d6..bf4647456dbf0 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -3281,10 +3281,15 @@ lldb::ValueObjectSP 
ValueObject::CastToBasicType(CompilerType type) {
           return ValueObjectConstResult::Create(
               exe_ctx.GetBestExecutionContextScope(),
               Status::FromErrorStringWithFormat(
-                  "invalid type cast detected: %s",
-                  llvm::toString(float_value_or_err.takeError()).c_str()));
+                  "invalid cast from float to integer"));
         return ValueObject::CreateValueObjectFromAPInt(exe_ctx, integer, type,
                                                        "result");
+      } else {
+        return ValueObjectConstResult::Create(
+            exe_ctx.GetBestExecutionContextScope(),
+            Status::FromErrorStringWithFormat(
+                "cannot get value as APFloat: %s",
+                llvm::toString(float_value_or_err.takeError()).c_str()));
       }
     }
   }

diff  --git 
a/lldb/test/API/commands/frame/var-dil/expr/Casts/TestFrameVarDILCast.py 
b/lldb/test/API/commands/frame/var-dil/expr/Casts/TestFrameVarDILCast.py
index 56d3dc973b17e..7179a9acac441 100644
--- a/lldb/test/API/commands/frame/var-dil/expr/Casts/TestFrameVarDILCast.py
+++ b/lldb/test/API/commands/frame/var-dil/expr/Casts/TestFrameVarDILCast.py
@@ -322,3 +322,41 @@ def test_type_cast(self):
             error=True,
             substrs=["Cast from 'InnerFoo' to 'UnscopedEnum' is not allowed"],
         )
+
+        # Check that failed casts output errors with diagnostics
+        self.expect(
+            "script lldb.frame.GetValueForVariablePath('+(bool) *((float *) 
0)')",
+            substrs=["<user expression>:1:2: cannot get value as APFloat"],
+        )
+        self.expect(
+            "script lldb.frame.GetValueForVariablePath('+(int) *((int *) 0)')",
+            substrs=["<user expression>:1:2: cannot get value as APSInt"],
+        )
+        self.expect(
+            "script lldb.frame.GetValueForVariablePath('+(int) finf')",
+            substrs=["<user expression>:1:2: invalid cast from float to 
integer"],
+        )
+        self.expect(
+            "script lldb.frame.GetValueForVariablePath('+(int) *((float *) 
0)')",
+            substrs=["<user expression>:1:2: cannot get value as APFloat"],
+        )
+        self.expect(
+            "script lldb.frame.GetValueForVariablePath('+(float) *((int *) 
0)')",
+            substrs=["<user expression>:1:2: cannot get value as APSInt"],
+        )
+        self.expect(
+            "script lldb.frame.GetValueForVariablePath('+(float) *((float *) 
0)')",
+            substrs=["<user expression>:1:2: cannot get value as APFloat"],
+        )
+        self.expect(
+            "script lldb.frame.GetValueForVariablePath('+(UnscopedEnum) 
finf')",
+            substrs=["<user expression>:1:2: invalid cast from float to 
integer"],
+        )
+        self.expect(
+            "script lldb.frame.GetValueForVariablePath('+(UnscopedEnum) 
*((float *) 0)')",
+            substrs=["<user expression>:1:2: cannot get value as APFloat"],
+        )
+        self.expect(
+            "script lldb.frame.GetValueForVariablePath('+(UnscopedEnum) *((int 
*) 0)')",
+            substrs=["<user expression>:1:2: cannot get value as APSInt"],
+        )


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

Reply via email to