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
