[Lldb-commits] [lldb] [lldb] Redo error handling of ValueObject's CastToBasicType and CastToEnumType (PR #217431)
Ilia Kuklin via lldb-commits
lldb-commits at lists.llvm.org
Fri Aug 21 10:36:37 PDT 2026
https://github.com/kuilpd updated https://github.com/llvm/llvm-project/pull/217431
>From 2ad48088a09b26ae8fc0bad1313a6674d3ca92d6 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Wed, 19 Aug 2026 21:34:00 +0500
Subject: [PATCH 1/3] [lldb] Redo error handling in ValueObject's
CastToBasicType and CastToEnumType
---
lldb/include/lldb/ValueObject/ValueObject.h | 4 +-
lldb/source/ValueObject/DILEval.cpp | 47 ++++++--
lldb/source/ValueObject/ValueObject.cpp | 112 +++++++-----------
.../var-dil/expr/Casts/TestFrameVarDILCast.py | 14 +++
4 files changed, 94 insertions(+), 83 deletions(-)
diff --git a/lldb/include/lldb/ValueObject/ValueObject.h b/lldb/include/lldb/ValueObject/ValueObject.h
index c370993d372b7..5d35c30bcf262 100644
--- a/lldb/include/lldb/ValueObject/ValueObject.h
+++ b/lldb/include/lldb/ValueObject/ValueObject.h
@@ -667,11 +667,11 @@ class ValueObject {
// Take a ValueObject that contains a scalar, enum or pointer type, and
// cast it to a "basic" type (integer, float or boolean).
- lldb::ValueObjectSP CastToBasicType(CompilerType type);
+ llvm::Expected<lldb::ValueObjectSP> CastToBasicType(CompilerType type);
// Take a ValueObject that contain an integer, float or enum, and cast it
// to an enum.
- lldb::ValueObjectSP CastToEnumType(CompilerType type);
+ llvm::Expected<lldb::ValueObjectSP> CastToEnumType(CompilerType type);
/// If this object represents a C++ class with a vtable, return an object
/// that represents the virtual function table. If the object isn't a class
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index d448444b43eba..c196509850a6a 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 value_or_err = valobj->CastToBasicType(int_type);
+ if (!value_or_err)
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, llvm::toString(value_or_err.takeError()), location);
+ return *value_or_err;
+ }
+ if (bitfield_size <= *uint_bit_size) {
+ auto value_or_err = valobj->CastToBasicType(uint_type);
+ if (!value_or_err)
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, llvm::toString(value_or_err.takeError()), location);
+ return *value_or_err;
+ }
// 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 value_or_err = valobj->CastToBasicType(promoted_type);
+ if (!value_or_err)
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, llvm::toString(value_or_err.takeError()), location);
+ return *value_or_err;
+ }
return valobj;
}
@@ -1933,14 +1948,26 @@ llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const CastNode &node) {
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);
+ op_type.IsEnumerationType()) {
+ auto value_or_err = operand->CastToEnumType(target_type);
+ if (!value_or_err)
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, llvm::toString(value_or_err.takeError()),
+ node.GetLocation());
+ return *value_or_err;
+ }
break;
}
case CastKind::eArithmetic: {
if (op_type.IsPointerType() || op_type.IsNullPtrType() ||
- op_type.IsScalarType() || op_type.IsEnumerationType())
- return operand->CastToBasicType(target_type);
+ op_type.IsScalarType() || op_type.IsEnumerationType()) {
+ auto value_or_err = operand->CastToBasicType(target_type);
+ if (!value_or_err)
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, llvm::toString(value_or_err.takeError()),
+ node.GetLocation());
+ return *value_or_err;
+ }
break;
}
case CastKind::ePointer: {
diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp
index 5571507a7d545..39516d3359b1a 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -3190,7 +3190,8 @@ ValueObject::CastBaseToDerivedType(CompilerType type, uint64_t offset) {
return value->Dereference(error);
}
-lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
+llvm::Expected<lldb::ValueObjectSP>
+ValueObject::CastToBasicType(CompilerType type) {
bool is_scalar = GetCompilerType().IsScalarType();
bool is_enum = GetCompilerType().IsEnumerationType();
bool is_pointer =
@@ -3200,14 +3201,11 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
ExecutionContext exe_ctx(GetExecutionContextRef());
if (!type.IsScalarType())
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorString("target type must be a scalar"));
+ return llvm::createStringError("target type must be a scalar");
if (!is_scalar && !is_enum && !is_pointer)
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorString("argument must be a scalar, enum, or pointer"));
+ return llvm::createStringError(
+ "argument must be a scalar, enum, or pointer");
lldb::TargetSP target = GetTargetSP();
uint64_t type_byte_size = 0;
@@ -3220,14 +3218,11 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
if (is_pointer) {
if (!type.IsInteger() && !type.IsBoolean())
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorString("target type must be an integer or boolean"));
+ return llvm::createStringError(
+ "target type must be an integer or boolean");
if (!type.IsBoolean() && type_byte_size < val_byte_size)
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorString(
- "target type cannot be smaller than the pointer type"));
+ return llvm::createStringError(
+ "target type cannot be smaller than the pointer type");
}
if (type.IsBoolean()) {
@@ -3242,11 +3237,9 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
exe_ctx, type.GetTypeSystem().GetSharedPointer(),
!float_value_or_err->isZero(), "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()));
+ return llvm::createStringErrorV(
+ "cannot get value as APFloat: {0}",
+ llvm::toString(float_value_or_err.takeError()));
}
}
@@ -3261,11 +3254,9 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
return ValueObject::CreateValueObjectFromAPInt(exe_ctx, ext, type,
"result");
} else
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorStringWithFormat(
- "cannot get value as APSInt: %s",
- llvm::toString(int_value_or_err.takeError()).c_str()));
+ return llvm::createStringErrorV(
+ "cannot get value as APSInt: {0}",
+ llvm::toString(int_value_or_err.takeError()));
} else if (is_scalar && is_float) {
llvm::APSInt integer(type_byte_size * CHAR_BIT, !type.IsSigned());
bool is_exact;
@@ -3278,13 +3269,13 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
// Casting floating point values that are out of bounds of the target
// type is undefined behaviour.
if (status & llvm::APFloatBase::opInvalidOp)
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorStringWithFormat(
- "invalid type cast detected: %s",
- llvm::toString(float_value_or_err.takeError()).c_str()));
+ return llvm::createStringError("invalid cast from float to integer");
return ValueObject::CreateValueObjectFromAPInt(exe_ctx, integer, type,
"result");
+ } else {
+ return llvm::createStringErrorV(
+ "cannot get value as APFloat: {0}",
+ llvm::toString(float_value_or_err.takeError()));
}
}
}
@@ -3301,11 +3292,9 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
return ValueObject::CreateValueObjectFromAPFloat(exe_ctx, f, type,
"result");
} else {
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorStringWithFormat(
- "cannot get value as APSInt: %s",
- llvm::toString(int_value_or_err.takeError()).c_str()));
+ return llvm::createStringErrorV(
+ "cannot get value as APSInt: {0}",
+ llvm::toString(int_value_or_err.takeError()));
}
} else {
if (is_integer) {
@@ -3317,11 +3306,9 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
return ValueObject::CreateValueObjectFromAPFloat(exe_ctx, f, type,
"result");
} else {
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorStringWithFormat(
- "cannot get value as APSInt: %s",
- llvm::toString(int_value_or_err.takeError()).c_str()));
+ return llvm::createStringErrorV(
+ "cannot get value as APSInt: {0}",
+ llvm::toString(int_value_or_err.takeError()));
}
}
if (is_float) {
@@ -3333,37 +3320,30 @@ lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
return ValueObject::CreateValueObjectFromAPFloat(exe_ctx, f, 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()));
+ return llvm::createStringErrorV(
+ "cannot get value as APFloat: {0}",
+ llvm::toString(float_value_or_err.takeError()));
}
}
}
}
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorString("Unable to perform requested cast"));
+ return llvm::createStringError("Unable to perform requested cast");
}
-lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {
+llvm::Expected<lldb::ValueObjectSP>
+ValueObject::CastToEnumType(CompilerType type) {
bool is_enum = GetCompilerType().IsEnumerationType();
bool is_integer = GetCompilerType().IsInteger();
bool is_float = HasFloatingRepresentation(GetCompilerType());
ExecutionContext exe_ctx(GetExecutionContextRef());
if (!is_enum && !is_integer && !is_float)
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorString(
- "argument must be an integer, a float, or an enum"));
+ return llvm::createStringError(
+ "argument must be an integer, a float, or an enum");
if (!type.IsEnumerationType())
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorString("target type must be an enum"));
+ return llvm::createStringError("target type must be an enum");
lldb::TargetSP target = GetTargetSP();
uint64_t byte_size = 0;
@@ -3382,17 +3362,12 @@ lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {
// Casting floating point values that are out of bounds of the target
// type is undefined behaviour.
if (status & llvm::APFloatBase::opInvalidOp)
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorString("invalid cast from float to integer"));
+ return llvm::createStringError("invalid cast from float to integer");
return ValueObject::CreateValueObjectFromAPInt(exe_ctx, integer, type,
"result");
} else
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorStringWithFormatv(
- "cannot get value as APFloat: {0}",
- llvm::toString(value_or_err.takeError())));
+ return llvm::createStringErrorV("cannot get value as APFloat: {0}",
+ llvm::toString(value_or_err.takeError()));
} else {
// Get the value as APSInt and extend or truncate it to the requested size.
auto value_or_err = GetValueAsAPSInt();
@@ -3401,15 +3376,10 @@ lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {
return ValueObject::CreateValueObjectFromAPInt(exe_ctx, ext, type,
"result");
} else
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorStringWithFormat(
- "cannot get value as APSInt: %s",
- llvm::toString(value_or_err.takeError()).c_str()));
+ return llvm::createStringErrorV("cannot get value as APSInt: {0}",
+ llvm::toString(value_or_err.takeError()));
}
- return ValueObjectConstResult::Create(
- exe_ctx.GetBestExecutionContextScope(),
- Status::FromErrorString("Cannot perform requested cast"));
+ return llvm::createStringError("Cannot perform requested cast");
}
ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}
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 567981cd670e9..7bde0e91cada8 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,17 @@ 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('+(int) finf')",
+ substrs=["<user expression>:1:2: invalid cast from float to integer"],
+ )
+ 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('+(UnscopedEnum) *((float *) 0)')",
+ substrs=["<user expression>:1:2: cannot get value as APFloat"],
+ )
>From 594b4cc35a82418d103e98ae0598d10addd7dc1a Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Fri, 21 Aug 2026 17:34:29 +0500
Subject: [PATCH 2/3] Revert "[lldb] Redo error handling in ValueObject's
CastToBasicType and CastToEnumType"
This reverts commit 2ad48088a09b26ae8fc0bad1313a6674d3ca92d6.
---
lldb/include/lldb/ValueObject/ValueObject.h | 4 +-
lldb/source/ValueObject/DILEval.cpp | 47 ++------
lldb/source/ValueObject/ValueObject.cpp | 112 +++++++++++-------
.../var-dil/expr/Casts/TestFrameVarDILCast.py | 14 ---
4 files changed, 83 insertions(+), 94 deletions(-)
diff --git a/lldb/include/lldb/ValueObject/ValueObject.h b/lldb/include/lldb/ValueObject/ValueObject.h
index 5d35c30bcf262..c370993d372b7 100644
--- a/lldb/include/lldb/ValueObject/ValueObject.h
+++ b/lldb/include/lldb/ValueObject/ValueObject.h
@@ -667,11 +667,11 @@ class ValueObject {
// Take a ValueObject that contains a scalar, enum or pointer type, and
// cast it to a "basic" type (integer, float or boolean).
- llvm::Expected<lldb::ValueObjectSP> CastToBasicType(CompilerType type);
+ lldb::ValueObjectSP CastToBasicType(CompilerType type);
// Take a ValueObject that contain an integer, float or enum, and cast it
// to an enum.
- llvm::Expected<lldb::ValueObjectSP> CastToEnumType(CompilerType type);
+ lldb::ValueObjectSP CastToEnumType(CompilerType type);
/// If this object represents a C++ class with a vtable, return an object
/// that represents the virtual function table. If the object isn't a class
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index c196509850a6a..d448444b43eba 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -88,20 +88,10 @@ 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)) {
- auto value_or_err = valobj->CastToBasicType(int_type);
- if (!value_or_err)
- return llvm::make_error<DILDiagnosticError>(
- m_expr, llvm::toString(value_or_err.takeError()), location);
- return *value_or_err;
- }
- if (bitfield_size <= *uint_bit_size) {
- auto value_or_err = valobj->CastToBasicType(uint_type);
- if (!value_or_err)
- return llvm::make_error<DILDiagnosticError>(
- m_expr, llvm::toString(value_or_err.takeError()), location);
- return *value_or_err;
- }
+ (in_type.IsSigned() && bitfield_size == *int_bit_size))
+ 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);
@@ -117,13 +107,8 @@ Interpreter::UnaryConversion(lldb::ValueObjectSP valobj, uint32_t location) {
CompilerType promoted_type =
valobj->GetCompilerType().GetPromotedIntegerType();
- if (promoted_type) {
- auto value_or_err = valobj->CastToBasicType(promoted_type);
- if (!value_or_err)
- return llvm::make_error<DILDiagnosticError>(
- m_expr, llvm::toString(value_or_err.takeError()), location);
- return *value_or_err;
- }
+ if (promoted_type)
+ return valobj->CastToBasicType(promoted_type);
return valobj;
}
@@ -1948,26 +1933,14 @@ llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const CastNode &node) {
case CastKind::eEnumeration: {
// FIXME: is this correct for float vector types?
if (op_type.GetTypeInfo() & lldb::eTypeIsFloat || op_type.IsInteger() ||
- op_type.IsEnumerationType()) {
- auto value_or_err = operand->CastToEnumType(target_type);
- if (!value_or_err)
- return llvm::make_error<DILDiagnosticError>(
- m_expr, llvm::toString(value_or_err.takeError()),
- node.GetLocation());
- return *value_or_err;
- }
+ op_type.IsEnumerationType())
+ return operand->CastToEnumType(target_type);
break;
}
case CastKind::eArithmetic: {
if (op_type.IsPointerType() || op_type.IsNullPtrType() ||
- op_type.IsScalarType() || op_type.IsEnumerationType()) {
- auto value_or_err = operand->CastToBasicType(target_type);
- if (!value_or_err)
- return llvm::make_error<DILDiagnosticError>(
- m_expr, llvm::toString(value_or_err.takeError()),
- node.GetLocation());
- return *value_or_err;
- }
+ op_type.IsScalarType() || op_type.IsEnumerationType())
+ return operand->CastToBasicType(target_type);
break;
}
case CastKind::ePointer: {
diff --git a/lldb/source/ValueObject/ValueObject.cpp b/lldb/source/ValueObject/ValueObject.cpp
index 39516d3359b1a..5571507a7d545 100644
--- a/lldb/source/ValueObject/ValueObject.cpp
+++ b/lldb/source/ValueObject/ValueObject.cpp
@@ -3190,8 +3190,7 @@ ValueObject::CastBaseToDerivedType(CompilerType type, uint64_t offset) {
return value->Dereference(error);
}
-llvm::Expected<lldb::ValueObjectSP>
-ValueObject::CastToBasicType(CompilerType type) {
+lldb::ValueObjectSP ValueObject::CastToBasicType(CompilerType type) {
bool is_scalar = GetCompilerType().IsScalarType();
bool is_enum = GetCompilerType().IsEnumerationType();
bool is_pointer =
@@ -3201,11 +3200,14 @@ ValueObject::CastToBasicType(CompilerType type) {
ExecutionContext exe_ctx(GetExecutionContextRef());
if (!type.IsScalarType())
- return llvm::createStringError("target type must be a scalar");
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorString("target type must be a scalar"));
if (!is_scalar && !is_enum && !is_pointer)
- return llvm::createStringError(
- "argument must be a scalar, enum, or pointer");
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorString("argument must be a scalar, enum, or pointer"));
lldb::TargetSP target = GetTargetSP();
uint64_t type_byte_size = 0;
@@ -3218,11 +3220,14 @@ ValueObject::CastToBasicType(CompilerType type) {
if (is_pointer) {
if (!type.IsInteger() && !type.IsBoolean())
- return llvm::createStringError(
- "target type must be an integer or boolean");
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorString("target type must be an integer or boolean"));
if (!type.IsBoolean() && type_byte_size < val_byte_size)
- return llvm::createStringError(
- "target type cannot be smaller than the pointer type");
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorString(
+ "target type cannot be smaller than the pointer type"));
}
if (type.IsBoolean()) {
@@ -3237,9 +3242,11 @@ ValueObject::CastToBasicType(CompilerType type) {
exe_ctx, type.GetTypeSystem().GetSharedPointer(),
!float_value_or_err->isZero(), "result");
else
- return llvm::createStringErrorV(
- "cannot get value as APFloat: {0}",
- llvm::toString(float_value_or_err.takeError()));
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorStringWithFormat(
+ "cannot get value as APFloat: %s",
+ llvm::toString(float_value_or_err.takeError()).c_str()));
}
}
@@ -3254,9 +3261,11 @@ ValueObject::CastToBasicType(CompilerType type) {
return ValueObject::CreateValueObjectFromAPInt(exe_ctx, ext, type,
"result");
} else
- return llvm::createStringErrorV(
- "cannot get value as APSInt: {0}",
- llvm::toString(int_value_or_err.takeError()));
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorStringWithFormat(
+ "cannot get value as APSInt: %s",
+ llvm::toString(int_value_or_err.takeError()).c_str()));
} else if (is_scalar && is_float) {
llvm::APSInt integer(type_byte_size * CHAR_BIT, !type.IsSigned());
bool is_exact;
@@ -3269,13 +3278,13 @@ ValueObject::CastToBasicType(CompilerType type) {
// Casting floating point values that are out of bounds of the target
// type is undefined behaviour.
if (status & llvm::APFloatBase::opInvalidOp)
- return llvm::createStringError("invalid cast from float to integer");
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorStringWithFormat(
+ "invalid type cast detected: %s",
+ llvm::toString(float_value_or_err.takeError()).c_str()));
return ValueObject::CreateValueObjectFromAPInt(exe_ctx, integer, type,
"result");
- } else {
- return llvm::createStringErrorV(
- "cannot get value as APFloat: {0}",
- llvm::toString(float_value_or_err.takeError()));
}
}
}
@@ -3292,9 +3301,11 @@ ValueObject::CastToBasicType(CompilerType type) {
return ValueObject::CreateValueObjectFromAPFloat(exe_ctx, f, type,
"result");
} else {
- return llvm::createStringErrorV(
- "cannot get value as APSInt: {0}",
- llvm::toString(int_value_or_err.takeError()));
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorStringWithFormat(
+ "cannot get value as APSInt: %s",
+ llvm::toString(int_value_or_err.takeError()).c_str()));
}
} else {
if (is_integer) {
@@ -3306,9 +3317,11 @@ ValueObject::CastToBasicType(CompilerType type) {
return ValueObject::CreateValueObjectFromAPFloat(exe_ctx, f, type,
"result");
} else {
- return llvm::createStringErrorV(
- "cannot get value as APSInt: {0}",
- llvm::toString(int_value_or_err.takeError()));
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorStringWithFormat(
+ "cannot get value as APSInt: %s",
+ llvm::toString(int_value_or_err.takeError()).c_str()));
}
}
if (is_float) {
@@ -3320,30 +3333,37 @@ ValueObject::CastToBasicType(CompilerType type) {
return ValueObject::CreateValueObjectFromAPFloat(exe_ctx, f, type,
"result");
} else {
- return llvm::createStringErrorV(
- "cannot get value as APFloat: {0}",
- llvm::toString(float_value_or_err.takeError()));
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorStringWithFormat(
+ "cannot get value as APFloat: %s",
+ llvm::toString(float_value_or_err.takeError()).c_str()));
}
}
}
}
- return llvm::createStringError("Unable to perform requested cast");
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorString("Unable to perform requested cast"));
}
-llvm::Expected<lldb::ValueObjectSP>
-ValueObject::CastToEnumType(CompilerType type) {
+lldb::ValueObjectSP ValueObject::CastToEnumType(CompilerType type) {
bool is_enum = GetCompilerType().IsEnumerationType();
bool is_integer = GetCompilerType().IsInteger();
bool is_float = HasFloatingRepresentation(GetCompilerType());
ExecutionContext exe_ctx(GetExecutionContextRef());
if (!is_enum && !is_integer && !is_float)
- return llvm::createStringError(
- "argument must be an integer, a float, or an enum");
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorString(
+ "argument must be an integer, a float, or an enum"));
if (!type.IsEnumerationType())
- return llvm::createStringError("target type must be an enum");
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorString("target type must be an enum"));
lldb::TargetSP target = GetTargetSP();
uint64_t byte_size = 0;
@@ -3362,12 +3382,17 @@ ValueObject::CastToEnumType(CompilerType type) {
// Casting floating point values that are out of bounds of the target
// type is undefined behaviour.
if (status & llvm::APFloatBase::opInvalidOp)
- return llvm::createStringError("invalid cast from float to integer");
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorString("invalid cast from float to integer"));
return ValueObject::CreateValueObjectFromAPInt(exe_ctx, integer, type,
"result");
} else
- return llvm::createStringErrorV("cannot get value as APFloat: {0}",
- llvm::toString(value_or_err.takeError()));
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorStringWithFormatv(
+ "cannot get value as APFloat: {0}",
+ llvm::toString(value_or_err.takeError())));
} else {
// Get the value as APSInt and extend or truncate it to the requested size.
auto value_or_err = GetValueAsAPSInt();
@@ -3376,10 +3401,15 @@ ValueObject::CastToEnumType(CompilerType type) {
return ValueObject::CreateValueObjectFromAPInt(exe_ctx, ext, type,
"result");
} else
- return llvm::createStringErrorV("cannot get value as APSInt: {0}",
- llvm::toString(value_or_err.takeError()));
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorStringWithFormat(
+ "cannot get value as APSInt: %s",
+ llvm::toString(value_or_err.takeError()).c_str()));
}
- return llvm::createStringError("Cannot perform requested cast");
+ return ValueObjectConstResult::Create(
+ exe_ctx.GetBestExecutionContextScope(),
+ Status::FromErrorString("Cannot perform requested cast"));
}
ValueObject::EvaluationPoint::EvaluationPoint() : m_mod_id(), m_exe_ctx_ref() {}
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 7bde0e91cada8..567981cd670e9 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,17 +322,3 @@ 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('+(int) finf')",
- substrs=["<user expression>:1:2: invalid cast from float to integer"],
- )
- 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('+(UnscopedEnum) *((float *) 0)')",
- substrs=["<user expression>:1:2: cannot get value as APFloat"],
- )
>From 15909773d9e30ca4d6a9f92fcbc8d263395e74d0 Mon Sep 17 00:00:00 2001
From: Ilia Kuklin <ikuklin at accesssoftek.com>
Date: Fri, 21 Aug 2026 18:04:12 +0500
Subject: [PATCH 3/3] [lldb] Handle errors of failed casts in DIL
---
lldb/source/ValueObject/DILEval.cpp | 47 ++++++++++++++-----
lldb/source/ValueObject/ValueObject.cpp | 9 +++-
.../var-dil/expr/Casts/TestFrameVarDILCast.py | 38 +++++++++++++++
3 files changed, 81 insertions(+), 13 deletions(-)
diff --git a/lldb/source/ValueObject/DILEval.cpp b/lldb/source/ValueObject/DILEval.cpp
index d448444b43eba..2995abb1bec2b 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;
}
@@ -1929,18 +1944,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: {
@@ -1950,15 +1966,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 5571507a7d545..b55ef2dd3b0d1 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 567981cd670e9..9f56149d94456 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"],
+ )
More information about the lldb-commits
mailing list