[Lldb-commits] [lldb] [LLDB] Add type casting to DIL, part 2 or 3 (PR #170332)
Michael Buch via lldb-commits
lldb-commits at lists.llvm.org
Tue Dec 9 03:27:00 PST 2025
================
@@ -740,16 +771,242 @@ Interpreter::Visit(const BooleanLiteralNode *node) {
return ValueObject::CreateValueObjectFromBool(m_target, value, "result");
}
+llvm::Expected<CompilerType>
+Interpreter::VerifyCastType(lldb::ValueObjectSP &operand, CompilerType &op_type,
+ CompilerType target_type,
+ CastPromotionKind &promo_kind, CastKind &cast_kind,
+ int location) {
+
+ promo_kind = CastPromotionKind::eNone;
+ if (op_type.IsReferenceType())
+ op_type = op_type.GetNonReferenceType();
+ if (target_type.IsScalarType()) {
+ if (op_type.IsArrayType()) {
+ // Do array-to-pointer conversion.
+ CompilerType deref_type =
+ op_type.IsReferenceType() ? op_type.GetNonReferenceType() : op_type;
+ CompilerType result_type =
+ deref_type.GetArrayElementType(nullptr).GetPointerType();
+ uint64_t addr = operand->GetLoadAddress();
+ llvm::StringRef name = operand->GetName().GetStringRef();
+ operand = ValueObject::CreateValueObjectFromAddress(
+ name, addr, m_exe_ctx_scope, result_type, /*do_deref=*/false);
+ op_type = result_type;
+ }
+
+ if (op_type.IsPointerType() || op_type.IsNullPtrType()) {
+ // Cast from pointer to float/double is not allowed.
+ if (target_type.IsFloat()) {
+ std::string errMsg = llvm::formatv(
+ "Cast from {0} to {1} is not allowed", op_type.TypeDescription(),
+ target_type.TypeDescription());
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, std::move(errMsg), location,
+ op_type.TypeDescription().length());
+ }
+ // Casting pointer to bool is valid. Otherwise check if the result type
+ // is at least as big as the pointer size.
+ uint64_t type_byte_size = 0;
+ uint64_t rhs_type_byte_size = 0;
+ if (auto temp = target_type.GetByteSize(m_exe_ctx_scope.get()))
+ type_byte_size = *temp;
+ if (auto temp = op_type.GetByteSize(m_exe_ctx_scope.get()))
+ rhs_type_byte_size = *temp;
+ if (!target_type.IsBoolean() && type_byte_size < rhs_type_byte_size) {
+ std::string errMsg = llvm::formatv(
+ "cast from pointer to smaller type {0} loses information",
+ target_type.TypeDescription());
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, std::move(errMsg), location,
+ op_type.TypeDescription().length());
+ }
+ } else if (!op_type.IsScalarType() && !op_type.IsEnumerationType()) {
+ // Otherwise accept only arithmetic types and enums.
+ std::string errMsg = llvm::formatv(
+ "cannot convert {0} to {1} without a conversion operator",
+ op_type.TypeDescription(), target_type.TypeDescription());
+
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, std::move(errMsg), location,
+ op_type.TypeDescription().length());
+ }
+ promo_kind = CastPromotionKind::eArithmetic;
+ return target_type;
+ }
+
+ if (target_type.IsEnumerationType()) {
+ // Cast to enum type.
+ if (!op_type.IsScalarType() && !op_type.IsEnumerationType()) {
+ std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
+ op_type.TypeDescription(),
+ target_type.TypeDescription());
+
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, std::move(errMsg), location,
+ op_type.TypeDescription().length());
+ }
+ cast_kind = CastKind::eEnumeration;
+ return target_type;
+ }
+
+ if (target_type.IsPointerType()) {
+ if (!op_type.IsInteger() && !op_type.IsEnumerationType() &&
+ !op_type.IsArrayType() && !op_type.IsPointerType() &&
+ !op_type.IsNullPtrType()) {
+ std::string errMsg = llvm::formatv(
+ "cannot cast from type {0} to pointer type {1}",
+ op_type.TypeDescription(), target_type.TypeDescription());
+
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, std::move(errMsg), location,
+ op_type.TypeDescription().length());
+ }
+ promo_kind = CastPromotionKind::ePointer;
+ return target_type;
+ }
+
+ if (target_type.IsNullPtrType()) {
+ // Cast to nullptr type.
+ bool is_signed;
+ if (!target_type.IsNullPtrType() &&
+ (!operand->IsIntegerType(is_signed) ||
+ (is_signed && operand->GetValueAsSigned(0) != 0) ||
+ (!is_signed && operand->GetValueAsUnsigned(0) != 0))) {
+ std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
+ op_type.TypeDescription(),
+ target_type.TypeDescription());
+
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, std::move(errMsg), location,
+ op_type.TypeDescription().length());
+ }
+ cast_kind = CastKind::eNullptr;
+ return target_type;
+ }
+
+ if (target_type.IsReferenceType()) {
+ // Cast to a reference type.
+ cast_kind = CastKind::eReference;
+ return target_type;
+ }
+
+ // Unsupported cast.
+ std::string errMsg =
+ llvm::formatv("casting of {0} to {1} is not implemented yet",
+ op_type.TypeDescription(), target_type.TypeDescription());
+ return llvm::make_error<DILDiagnosticError>(
+ m_expr, std::move(errMsg), location, op_type.TypeDescription().length());
+}
+
llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const CastNode *node) {
auto operand_or_err = Evaluate(node->GetOperand());
if (!operand_or_err)
return operand_or_err;
lldb::ValueObjectSP operand = *operand_or_err;
- // Don't actually do the cast for now -- that code will be added later.
- // For now just return an error message.
- return llvm::make_error<DILDiagnosticError>(
- m_expr, "Type casting is not supported here.", node->GetLocation());
+ CompilerType op_type = operand->GetCompilerType();
+ CastKind cast_kind = CastKind::eNone;
+ CastPromotionKind promo_kind = CastPromotionKind::eNone;
+
+ auto type_or_err = VerifyCastType(operand, op_type, node->GetType(),
+ promo_kind, cast_kind, node->GetLocation());
+ if (!type_or_err)
+ return type_or_err.takeError();
+
+ CompilerType target_type = *type_or_err;
+ if (op_type.IsReferenceType()) {
+ Status error;
+ operand = operand->Dereference(error);
+ if (error.Fail())
+ return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
+ node->GetLocation());
+ }
+
+ switch (cast_kind) {
+ case CastKind::eEnumeration: {
+ if (!target_type.IsEnumerationType()) {
+ std::string errMsg = "invalid ast: target type should be an enumeration.";
+ return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
+ node->GetLocation());
+ }
+ if (op_type.IsFloat())
+ return operand->CastToEnumType(target_type);
+
+ if (op_type.IsInteger() || op_type.IsEnumerationType())
----------------
Michael137 wrote:
Can we fold these two if-conditions together?
https://github.com/llvm/llvm-project/pull/170332
More information about the lldb-commits
mailing list