================
@@ -740,16 +763,209 @@ Interpreter::Visit(const BooleanLiteralNode *node) {
   return ValueObject::CreateValueObjectFromBool(m_target, value, "result");
 }
 
+llvm::Expected<CastKind>
+Interpreter::VerifyArithmeticCast(CompilerType source_type,
+                                  CompilerType target_type, int location) {
+  if (source_type.IsPointerType() || source_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",
+                                         source_type.TypeDescription(),
+                                         target_type.TypeDescription());
+      return llvm::make_error<DILDiagnosticError>(
+          m_expr, std::move(errMsg), location,
+          source_type.TypeDescription().length());
+    }
+
+    // Casting from pointer to bool is always valid.
+    if (target_type.IsBoolean())
+      return CastKind::eArithmetic;
+
+    // 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;
+    } else {
+      std::string errMsg = llvm::formatv("unable to get byte size for type 
{0}",
+                                         target_type.TypeDescription());
+      return llvm::make_error<DILDiagnosticError>(
+          m_expr, std::move(errMsg), location,
+          target_type.TypeDescription().length());
+    }
+
+    if (auto temp = source_type.GetByteSize(m_exe_ctx_scope.get())) {
+      rhs_type_byte_size = *temp;
+    } else {
+      std::string errMsg = llvm::formatv("unable to get byte size for type 
{0}",
+                                         source_type.TypeDescription());
+      return llvm::make_error<DILDiagnosticError>(
+          m_expr, std::move(errMsg), location,
+          source_type.TypeDescription().length());
+    }
+
+    if (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,
+          source_type.TypeDescription().length());
+    }
+  } else if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
+    // Otherwise accept only arithmetic types and enums.
+    std::string errMsg = llvm::formatv("cannot convert {0} to {1}",
+                                       source_type.TypeDescription(),
+                                       target_type.TypeDescription());
+
+    return llvm::make_error<DILDiagnosticError>(
+        m_expr, std::move(errMsg), location,
+        source_type.TypeDescription().length());
+  }
+  return CastKind::eArithmetic;
+}
+
+llvm::Expected<CastKind>
+Interpreter::VerifyCastType(lldb::ValueObjectSP operand,
+                            CompilerType source_type, CompilerType target_type,
+                            int location) {
+
+  if (target_type.IsScalarType())
+    return VerifyArithmeticCast(source_type, target_type, location);
+
+  if (target_type.IsEnumerationType()) {
+    // Cast to enum type.
+    if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
+      std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
+                                         source_type.TypeDescription(),
+                                         target_type.TypeDescription());
+
+      return llvm::make_error<DILDiagnosticError>(
+          m_expr, std::move(errMsg), location,
+          source_type.TypeDescription().length());
+    }
+    return CastKind::eEnumeration;
+  }
+
+  if (target_type.IsPointerType()) {
+    if (!source_type.IsInteger() && !source_type.IsEnumerationType() &&
+        !source_type.IsArrayType() && !source_type.IsPointerType() &&
+        !source_type.IsNullPtrType()) {
+      std::string errMsg = llvm::formatv(
+          "cannot cast from type {0} to pointer type {1}",
+          source_type.TypeDescription(), target_type.TypeDescription());
+
+      return llvm::make_error<DILDiagnosticError>(
+          m_expr, std::move(errMsg), location,
+          source_type.TypeDescription().length());
+    }
+    return CastKind::ePointer;
+  }
+
+  if (target_type.IsNullPtrType()) {
----------------
Michael137 wrote:

Do we have tests for the nullptr case? I'm tempted to suggest to not support 
casting to nullptr_t at all for now because it's not a cast the C++ allows 
(i.e., I'm pretty sure you can't cast *to* `std::nullptr_t`). What are the 
use-cases you had in mind?

I'd suggest removing this entire block.

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

Reply via email to