2121
2222namespace lldb_private ::dil {
2323
24+ lldb::ValueObjectSP
25+ GetDynamicOrSyntheticValue (lldb::ValueObjectSP value_sp,
26+ lldb::DynamicValueType use_dynamic,
27+ bool use_synthetic) {
28+ if (!value_sp)
29+ return nullptr ;
30+
31+ if (use_dynamic != lldb::eNoDynamicValues) {
32+ lldb::ValueObjectSP dynamic_sp = value_sp->GetDynamicValue (use_dynamic);
33+ if (dynamic_sp)
34+ value_sp = dynamic_sp;
35+ }
36+
37+ if (use_synthetic) {
38+ lldb::ValueObjectSP synthetic_sp = value_sp->GetSyntheticValue ();
39+ if (synthetic_sp)
40+ value_sp = synthetic_sp;
41+ }
42+
43+ return value_sp;
44+ }
45+
2446static llvm::Expected<lldb::TypeSystemSP>
2547GetTypeSystemFromCU (std::shared_ptr<ExecutionContextScope> ctx) {
2648 auto stack_frame = ctx->CalculateStackFrame ();
@@ -42,13 +64,14 @@ static CompilerType GetBasicType(lldb::TypeSystemSP type_system,
4264 return CompilerType ();
4365}
4466
45- static lldb::ValueObjectSP
46- ArrayToPointerConversion (ValueObject &valobj, ExecutionContextScope &ctx) {
67+ static lldb::ValueObjectSP ArrayToPointerConversion (ValueObject &valobj,
68+ ExecutionContextScope &ctx,
69+ llvm::StringRef name) {
4770 uint64_t addr = valobj.GetLoadAddress ();
4871 ExecutionContext exe_ctx;
4972 ctx.CalculateExecutionContext (exe_ctx);
5073 return ValueObject::CreateValueObjectFromAddress (
51- " result " , addr, exe_ctx,
74+ name , addr, exe_ctx,
5275 valobj.GetCompilerType ().GetArrayElementType (&ctx).GetPointerType (),
5376 /* do_deref */ false );
5477}
@@ -100,7 +123,7 @@ Interpreter::UnaryConversion(lldb::ValueObjectSP valobj, uint32_t location) {
100123 }
101124
102125 if (in_type.IsArrayType ())
103- valobj = ArrayToPointerConversion (*valobj, *m_exe_ctx_scope);
126+ valobj = ArrayToPointerConversion (*valobj, *m_exe_ctx_scope, " result " );
104127
105128 if (valobj->GetCompilerType ().IsInteger () ||
106129 valobj->GetCompilerType ().IsUnscopedEnumerationType ()) {
@@ -783,16 +806,179 @@ Interpreter::Visit(const BooleanLiteralNode &node) {
783806 return ValueObject::CreateValueObjectFromBool (m_target, value, " result" );
784807}
785808
809+ llvm::Expected<CastKind>
810+ Interpreter::VerifyArithmeticCast (CompilerType source_type,
811+ CompilerType target_type, int location) {
812+ if (source_type.IsPointerType () || source_type.IsNullPtrType ()) {
813+ // Cast from pointer to float/double is not allowed.
814+ if (target_type.IsFloat ()) {
815+ std::string errMsg = llvm::formatv (" Cast from {0} to {1} is not allowed" ,
816+ source_type.TypeDescription (),
817+ target_type.TypeDescription ());
818+ return llvm::make_error<DILDiagnosticError>(
819+ m_expr, std::move (errMsg), location,
820+ source_type.TypeDescription ().length ());
821+ }
822+
823+ // Casting from pointer to bool is always valid.
824+ if (target_type.IsBoolean ())
825+ return CastKind::eArithmetic;
826+
827+ // Otherwise check if the result type is at least as big as the pointer
828+ // size.
829+ uint64_t type_byte_size = 0 ;
830+ uint64_t rhs_type_byte_size = 0 ;
831+ if (auto temp = target_type.GetByteSize (m_exe_ctx_scope.get ())) {
832+ type_byte_size = *temp;
833+ } else {
834+ std::string errMsg = llvm::formatv (" unable to get byte size for type {0}" ,
835+ target_type.TypeDescription ());
836+ return llvm::make_error<DILDiagnosticError>(
837+ m_expr, std::move (errMsg), location,
838+ target_type.TypeDescription ().length ());
839+ }
840+
841+ if (auto temp = source_type.GetByteSize (m_exe_ctx_scope.get ())) {
842+ rhs_type_byte_size = *temp;
843+ } else {
844+ std::string errMsg = llvm::formatv (" unable to get byte size for type {0}" ,
845+ source_type.TypeDescription ());
846+ return llvm::make_error<DILDiagnosticError>(
847+ m_expr, std::move (errMsg), location,
848+ source_type.TypeDescription ().length ());
849+ }
850+
851+ if (type_byte_size < rhs_type_byte_size) {
852+ std::string errMsg = llvm::formatv (
853+ " cast from pointer to smaller type {0} loses information" ,
854+ target_type.TypeDescription ());
855+ return llvm::make_error<DILDiagnosticError>(
856+ m_expr, std::move (errMsg), location,
857+ source_type.TypeDescription ().length ());
858+ }
859+ } else if (!source_type.IsScalarType () && !source_type.IsEnumerationType ()) {
860+ // Otherwise accept only arithmetic types and enums.
861+ std::string errMsg = llvm::formatv (" cannot convert {0} to {1}" ,
862+ source_type.TypeDescription (),
863+ target_type.TypeDescription ());
864+
865+ return llvm::make_error<DILDiagnosticError>(
866+ m_expr, std::move (errMsg), location,
867+ source_type.TypeDescription ().length ());
868+ }
869+ return CastKind::eArithmetic;
870+ }
871+
872+ llvm::Expected<CastKind>
873+ Interpreter::VerifyCastType (lldb::ValueObjectSP operand,
874+ CompilerType source_type, CompilerType target_type,
875+ int location) {
876+
877+ if (target_type.IsScalarType ())
878+ return VerifyArithmeticCast (source_type, target_type, location);
879+
880+ if (target_type.IsEnumerationType ()) {
881+ // Cast to enum type.
882+ if (!source_type.IsScalarType () && !source_type.IsEnumerationType ()) {
883+ std::string errMsg = llvm::formatv (" Cast from {0} to {1} is not allowed" ,
884+ source_type.TypeDescription (),
885+ target_type.TypeDescription ());
886+
887+ return llvm::make_error<DILDiagnosticError>(
888+ m_expr, std::move (errMsg), location,
889+ source_type.TypeDescription ().length ());
890+ }
891+ return CastKind::eEnumeration;
892+ }
893+
894+ if (target_type.IsPointerType ()) {
895+ if (!source_type.IsInteger () && !source_type.IsEnumerationType () &&
896+ !source_type.IsArrayType () && !source_type.IsPointerType () &&
897+ !source_type.IsNullPtrType ()) {
898+ std::string errMsg = llvm::formatv (
899+ " cannot cast from type {0} to pointer type {1}" ,
900+ source_type.TypeDescription (), target_type.TypeDescription ());
901+
902+ return llvm::make_error<DILDiagnosticError>(
903+ m_expr, std::move (errMsg), location,
904+ source_type.TypeDescription ().length ());
905+ }
906+ return CastKind::ePointer;
907+ }
908+
909+ // Unsupported cast.
910+ std::string errMsg = llvm::formatv (
911+ " casting of {0} to {1} is not implemented yet" ,
912+ source_type.TypeDescription (), target_type.TypeDescription ());
913+ return llvm::make_error<DILDiagnosticError>(
914+ m_expr, std::move (errMsg), location,
915+ source_type.TypeDescription ().length ());
916+ }
917+
786918llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit (const CastNode &node) {
787919 auto operand_or_err = Evaluate (node.GetOperand ());
920+
788921 if (!operand_or_err)
789922 return operand_or_err;
790923
791924 lldb::ValueObjectSP operand = *operand_or_err;
792- // Don't actually do the cast for now -- that code will be added later.
793- // For now just return an error message.
794- return llvm::make_error<DILDiagnosticError>(
795- m_expr, " Type casting is not supported here." , node.GetLocation ());
925+ CompilerType op_type = operand->GetCompilerType ();
926+ CompilerType target_type = node.GetType ();
927+
928+ if (op_type.IsReferenceType ())
929+ op_type = op_type.GetNonReferenceType ();
930+ if (target_type.IsScalarType () && op_type.IsArrayType ()) {
931+ operand = ArrayToPointerConversion (*operand, *m_exe_ctx_scope,
932+ operand->GetName ().GetStringRef ());
933+ op_type = operand->GetCompilerType ();
934+ }
935+ auto type_or_err =
936+ VerifyCastType (operand, op_type, target_type, node.GetLocation ());
937+ if (!type_or_err)
938+ return type_or_err.takeError ();
939+
940+ CastKind cast_kind = *type_or_err;
941+ if (operand->GetCompilerType ().IsReferenceType ()) {
942+ Status error;
943+ operand = operand->Dereference (error);
944+ if (error.Fail ())
945+ return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString (),
946+ node.GetLocation ());
947+ }
948+
949+ switch (cast_kind) {
950+ case CastKind::eEnumeration: {
951+ if (op_type.IsFloat () || op_type.IsInteger () || op_type.IsEnumerationType ())
952+ return operand->CastToEnumType (target_type);
953+ break ;
954+ }
955+ case CastKind::eArithmetic: {
956+ if (op_type.IsPointerType () || op_type.IsNullPtrType () ||
957+ op_type.IsScalarType () || op_type.IsEnumerationType ())
958+ return operand->CastToBasicType (target_type);
959+ break ;
960+ }
961+ case CastKind::ePointer: {
962+ uint64_t addr = op_type.IsArrayType ()
963+ ? operand->GetLoadAddress ()
964+ : (op_type.IsSigned () ? operand->GetValueAsSigned (0 )
965+ : operand->GetValueAsUnsigned (0 ));
966+ llvm::StringRef name = " result" ;
967+ ExecutionContext exe_ctx (m_target.get (), false );
968+ return ValueObject::CreateValueObjectFromAddress (name, addr, exe_ctx,
969+ target_type,
970+ /* do_deref */ false );
971+ }
972+ case CastKind::eNone: {
973+ return lldb::ValueObjectSP ();
974+ }
975+ } // switch
976+
977+ std::string errMsg =
978+ llvm::formatv (" unable to cast from '{0}' to '{1}'" ,
979+ op_type.TypeDescription (), target_type.TypeDescription ());
980+ return llvm::make_error<DILDiagnosticError>(m_expr, std::move (errMsg),
981+ node.GetLocation ());
796982}
797983
798984} // namespace lldb_private::dil
0 commit comments