LLDB mainline
DILEval.cpp
Go to the documentation of this file.
1//===-- DILEval.cpp -------------------------------------------------------===//
2//
3// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
4// See https://llvm.org/LICENSE.txt for license information.
5// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
6//
7//===----------------------------------------------------------------------===//
8
10#include "lldb/Core/Module.h"
20#include "llvm/Support/FormatAdapters.h"
21#include <memory>
22
23namespace lldb_private::dil {
24
27 lldb::DynamicValueType use_dynamic,
28 bool use_synthetic) {
29 if (!value_sp)
30 return nullptr;
31
32 if (use_dynamic != lldb::eNoDynamicValues) {
33 lldb::ValueObjectSP dynamic_sp = value_sp->GetDynamicValue(use_dynamic);
34 if (dynamic_sp)
35 value_sp = dynamic_sp;
36 }
37
38 if (use_synthetic) {
39 lldb::ValueObjectSP synthetic_sp = value_sp->GetSyntheticValue();
40 if (synthetic_sp)
41 value_sp = synthetic_sp;
42 }
43
44 return value_sp;
45}
46
48 lldb::BasicType basic_type) {
49 if (type_system)
50 return type_system.get()->GetBasicTypeFromAST(basic_type);
51
52 return CompilerType();
53}
54
57 llvm::StringRef name) {
58 uint64_t addr = valobj.GetLoadAddress();
59 ExecutionContext exe_ctx;
60 ctx.CalculateExecutionContext(exe_ctx);
62 name, addr, exe_ctx,
64 /* do_deref */ false);
65}
66
67llvm::Expected<lldb::ValueObjectSP>
69 if (!valobj)
70 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid value object",
71 location);
72 llvm::Expected<lldb::TypeSystemSP> type_system =
74 if (!type_system)
75 return type_system.takeError();
76
77 CompilerType in_type = valobj->GetCompilerType();
78 if (valobj->IsBitfield()) {
79 // Promote bitfields. If `int` can represent the bitfield value, it is
80 // converted to `int`. Otherwise, if `unsigned int` can represent it, it
81 // is converted to `unsigned int`. Otherwise, it is treated as its
82 // underlying type.
83 uint32_t bitfield_size = valobj->GetBitfieldBitSize();
84 // Some bitfields have undefined size (e.g. result of ternary operation).
85 // The AST's `bitfield_size` of those is 0, and no promotion takes place.
86 if (bitfield_size > 0 && in_type.IsInteger()) {
87 CompilerType int_type = GetBasicType(*type_system, lldb::eBasicTypeInt);
88 CompilerType uint_type =
90 llvm::Expected<uint64_t> int_bit_size =
91 int_type.GetBitSize(m_exe_ctx_scope.get());
92 if (!int_bit_size)
93 return int_bit_size.takeError();
94 llvm::Expected<uint64_t> uint_bit_size =
95 uint_type.GetBitSize(m_exe_ctx_scope.get());
96 if (!uint_bit_size)
97 return int_bit_size.takeError();
98 if (bitfield_size < *int_bit_size ||
99 (in_type.IsSigned() && bitfield_size == *int_bit_size))
100 return valobj->CastToBasicType(int_type);
101 if (bitfield_size <= *uint_bit_size)
102 return valobj->CastToBasicType(uint_type);
103 // Re-create as a const value with the same underlying type
104 Scalar scalar;
105 bool resolved = valobj->ResolveValue(scalar);
106 if (!resolved)
107 return llvm::createStringError("invalid scalar value");
109 in_type, "result");
110 }
111 }
112
113 if (in_type.IsArrayType())
114 valobj = ArrayToPointerConversion(*valobj, *m_exe_ctx_scope, "result");
115
116 if (valobj->GetCompilerType().IsInteger() ||
117 valobj->GetCompilerType().IsUnscopedEnumerationType()) {
118 llvm::Expected<CompilerType> promoted_type =
119 type_system.get()->DoIntegralPromotion(valobj->GetCompilerType(),
120 m_exe_ctx_scope.get());
121 if (!promoted_type)
122 return promoted_type.takeError();
123 if (!promoted_type->CompareTypes(valobj->GetCompilerType()))
124 return valobj->CastToBasicType(*promoted_type);
125 }
126
127 return valobj;
128}
129
130/// Basic types with a lower rank are converted to the basic type
131/// with a higher rank.
132static size_t ConversionRank(CompilerType type) {
133 switch (type.GetCanonicalType().GetBasicTypeEnumeration()) {
135 return 1;
139 return 2;
142 return 3;
145 return 4;
148 return 5;
151 return 6;
154 return 7;
156 return 8;
158 return 9;
160 return 10;
162 return 11;
163 default:
164 break;
165 }
166 return 0;
167}
168
188
189llvm::Expected<CompilerType>
191 CompilerType &rhs_type) {
192 assert(lhs_type.IsInteger() && rhs_type.IsInteger());
193 if (!lhs_type.IsSigned() && rhs_type.IsSigned()) {
194 llvm::Expected<uint64_t> lhs_size =
195 lhs_type.GetBitSize(m_exe_ctx_scope.get());
196 if (!lhs_size)
197 return lhs_size.takeError();
198 llvm::Expected<uint64_t> rhs_size =
199 rhs_type.GetBitSize(m_exe_ctx_scope.get());
200 if (!rhs_size)
201 return rhs_size.takeError();
202
203 if (*rhs_size == *lhs_size) {
204 llvm::Expected<lldb::TypeSystemSP> type_system =
206 if (!type_system)
207 return type_system.takeError();
208 CompilerType r_type_unsigned = GetBasicType(
209 *type_system,
212 return r_type_unsigned;
213 }
214 }
215 return rhs_type;
216}
217
218llvm::Expected<CompilerType>
220 lldb::ValueObjectSP &rhs, uint32_t location) {
221 // Apply unary conversion for both operands.
222 auto lhs_or_err = UnaryConversion(lhs, location);
223 if (!lhs_or_err)
224 return lhs_or_err.takeError();
225 lhs = *lhs_or_err;
226 auto rhs_or_err = UnaryConversion(rhs, location);
227 if (!rhs_or_err)
228 return rhs_or_err.takeError();
229 rhs = *rhs_or_err;
230
231 CompilerType lhs_type = lhs->GetCompilerType();
232 CompilerType rhs_type = rhs->GetCompilerType();
233
234 // If types already match, no need for further conversions.
235 if (lhs_type.CompareTypes(rhs_type))
236 return lhs_type;
237
238 // If either of the operands is not arithmetic (e.g. pointer), we're done.
239 if (!lhs_type.IsScalarType() || !rhs_type.IsScalarType())
240 return CompilerType();
241
242 size_t l_rank = ConversionRank(lhs_type);
243 size_t r_rank = ConversionRank(rhs_type);
244 if (l_rank == 0 || r_rank == 0)
245 return llvm::make_error<DILDiagnosticError>(
246 m_expr, "unexpected basic type in arithmetic operation", location);
247
248 // If both operands are integer, check if we need to promote
249 // the higher ranked signed type.
250 if (lhs_type.IsInteger() && rhs_type.IsInteger()) {
251 using Rank = std::tuple<size_t, bool>;
252 Rank int_l_rank = {l_rank, !lhs_type.IsSigned()};
253 Rank int_r_rank = {r_rank, !rhs_type.IsSigned()};
254 if (int_l_rank < int_r_rank) {
255 auto type_or_err = PromoteSignedInteger(lhs_type, rhs_type);
256 if (!type_or_err)
257 return type_or_err.takeError();
258 return *type_or_err;
259 }
260 if (int_l_rank > int_r_rank) {
261 auto type_or_err = PromoteSignedInteger(rhs_type, lhs_type);
262 if (!type_or_err)
263 return type_or_err.takeError();
264 return *type_or_err;
265 }
266 return lhs_type;
267 }
268
269 // Handle other combinations of integer and floating point operands.
270 if (l_rank < r_rank)
271 return rhs_type;
272 return lhs_type;
273}
274
276 VariableList &variable_list) {
277 lldb::VariableSP exact_match;
278 std::vector<lldb::VariableSP> possible_matches;
279
280 for (lldb::VariableSP var_sp : variable_list) {
281 llvm::StringRef str_ref_name = var_sp->GetName().GetStringRef();
282
283 str_ref_name.consume_front("::");
284 // Check for the exact same match
285 if (str_ref_name == name.GetStringRef())
286 return var_sp;
287
288 // Check for possible matches by base name
289 if (var_sp->NameMatches(name))
290 possible_matches.push_back(var_sp);
291 }
292
293 // If there's a non-exact match, take it.
294 if (possible_matches.size() > 0)
295 return possible_matches[0];
296
297 return nullptr;
298}
299
301 llvm::StringRef name_ref, std::shared_ptr<StackFrame> stack_frame,
302 lldb::TargetSP target_sp, lldb::DynamicValueType use_dynamic) {
303 // Get a global variables list without the locals from the current frame
304 SymbolContext symbol_context =
305 stack_frame->GetSymbolContext(lldb::eSymbolContextCompUnit);
306 lldb::VariableListSP variable_list;
307 if (symbol_context.comp_unit)
308 variable_list = symbol_context.comp_unit->GetVariableList(true);
309
310 name_ref.consume_front("::");
311 lldb::ValueObjectSP value_sp;
312 if (variable_list) {
313 lldb::VariableSP var_sp =
314 DILFindVariable(ConstString(name_ref), *variable_list);
315 if (var_sp)
316 value_sp =
317 stack_frame->GetValueObjectForFrameVariable(var_sp, use_dynamic);
318 }
319
320 if (value_sp)
321 return value_sp;
322
323 // Check for match in modules global variables.
324 VariableList modules_var_list;
325 target_sp->GetImages().FindGlobalVariables(
326 ConstString(name_ref), std::numeric_limits<uint32_t>::max(),
327 modules_var_list);
328
329 if (!modules_var_list.Empty()) {
330 lldb::VariableSP var_sp =
331 DILFindVariable(ConstString(name_ref), modules_var_list);
332 if (var_sp)
333 value_sp = ValueObjectVariable::Create(stack_frame.get(), var_sp);
334
335 if (value_sp)
336 return value_sp;
337 }
338 return nullptr;
339}
340
341lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
342 std::shared_ptr<StackFrame> stack_frame,
343 lldb::DynamicValueType use_dynamic) {
344 // Support $rax as a special syntax for accessing registers.
345 // Will return an invalid value in case the requested register doesn't exist.
346 if (name_ref.consume_front("$")) {
347 lldb::RegisterContextSP reg_ctx(stack_frame->GetRegisterContext());
348 if (!reg_ctx)
349 return nullptr;
350
351 if (const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name_ref))
352 return ValueObjectRegister::Create(stack_frame.get(), reg_ctx, reg_info);
353
354 return nullptr;
355 }
356
357 if (!name_ref.contains("::")) {
358 // Lookup in the current frame.
359 // Try looking for a local variable in current scope.
360 lldb::VariableListSP variable_list(
361 stack_frame->GetInScopeVariableList(false));
362
363 lldb::ValueObjectSP value_sp;
364 if (variable_list) {
365 lldb::VariableSP var_sp =
366 variable_list->FindVariable(ConstString(name_ref));
367 if (var_sp)
368 value_sp =
369 stack_frame->GetValueObjectForFrameVariable(var_sp, use_dynamic);
370 }
371
372 if (value_sp)
373 return value_sp;
374
375 // Try looking for an instance variable (class member).
376 SymbolContext sc = stack_frame->GetSymbolContext(
377 lldb::eSymbolContextFunction | lldb::eSymbolContextBlock);
378 llvm::StringRef ivar_name = sc.GetInstanceVariableName();
379 value_sp = stack_frame->FindVariable(ConstString(ivar_name));
380 if (value_sp)
381 value_sp = value_sp->GetChildMemberWithName(name_ref);
382
383 if (value_sp)
384 return value_sp;
385 }
386 return nullptr;
387}
388
389Interpreter::Interpreter(lldb::TargetSP target, llvm::StringRef expr,
390 std::shared_ptr<StackFrame> frame_sp,
391 lldb::DynamicValueType use_dynamic, uint32_t options)
392 : m_target(std::move(target)), m_expr(expr), m_exe_ctx_scope(frame_sp),
393 m_use_dynamic(use_dynamic) {
394
395 const bool check_ptr_vs_member =
397 const bool no_fragile_ivar =
399 const bool no_synth_child =
401 const bool allow_var_updates =
403
404 m_use_synthetic = !no_synth_child;
405 m_fragile_ivar = !no_fragile_ivar;
406 m_check_ptr_vs_member = check_ptr_vs_member;
407 m_allow_var_updates = allow_var_updates;
408}
409
410llvm::Expected<lldb::ValueObjectSP> Interpreter::Evaluate(const ASTNode &node) {
411 // Evaluate an AST.
412 auto value_or_error = node.Accept(this);
413 // Convert SP with a nullptr to an error.
414 if (value_or_error && !*value_or_error)
415 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid value object",
416 node.GetLocation());
417 // Return the computed value-or-error. The caller is responsible for
418 // checking if an error occurred during the evaluation.
419 return value_or_error;
420}
421
422llvm::Expected<lldb::ValueObjectSP>
424 auto valobj_or_err = Evaluate(node);
425 if (!valobj_or_err)
426 return valobj_or_err;
427 lldb::ValueObjectSP valobj = *valobj_or_err;
428
430 if (valobj->GetCompilerType().IsReferenceType()) {
431 valobj = valobj->Dereference(error);
432 if (error.Fail())
433 return error.ToError();
434 }
435 return valobj;
436}
437
438llvm::Expected<lldb::ValueObjectSP>
441
442 lldb::ValueObjectSP identifier =
443 LookupIdentifier(node.GetName(), m_exe_ctx_scope, use_dynamic);
444
445 if (!identifier)
447 m_target, use_dynamic);
448 if (!identifier) {
449 std::string errMsg =
450 llvm::formatv("use of undeclared identifier '{0}'", node.GetName());
451 return llvm::make_error<DILDiagnosticError>(
452 m_expr, errMsg, node.GetLocation(), node.GetName().size());
453 }
454
455 return identifier;
456}
457
458llvm::Expected<lldb::ValueObjectSP>
461 auto op_or_err = Evaluate(node.GetOperand());
462 if (!op_or_err)
463 return op_or_err;
464
465 lldb::ValueObjectSP operand = *op_or_err;
466
467 switch (node.GetKind()) {
468 case UnaryOpKind::Deref: {
469 lldb::ValueObjectSP dynamic_op = operand->GetDynamicValue(m_use_dynamic);
470 if (dynamic_op)
471 operand = dynamic_op;
472
473 lldb::ValueObjectSP child_sp = operand->Dereference(error);
474 if (!child_sp && m_use_synthetic) {
475 if (lldb::ValueObjectSP synth_obj_sp = operand->GetSyntheticValue()) {
476 error.Clear();
477 child_sp = synth_obj_sp->Dereference(error);
478 }
479 }
480 if (error.Fail())
481 return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
482 node.GetLocation());
483
484 return child_sp;
485 }
486 case UnaryOpKind::AddrOf: {
488 lldb::ValueObjectSP value = operand->AddressOf(error);
489 if (error.Fail())
490 return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
491 node.GetLocation());
492
493 return value;
494 }
495 case UnaryOpKind::Minus: {
496 if (operand->GetCompilerType().IsReferenceType()) {
497 operand = operand->Dereference(error);
498 if (error.Fail())
499 return error.ToError();
500 }
501 llvm::Expected<lldb::ValueObjectSP> conv_op =
502 UnaryConversion(operand, node.GetOperand().GetLocation());
503 if (!conv_op)
504 return conv_op;
505 operand = *conv_op;
506 CompilerType operand_type = operand->GetCompilerType();
507 if (!operand_type.IsScalarType()) {
508 std::string errMsg =
509 llvm::formatv("invalid argument type '{0}' to unary expression",
510 operand_type.GetTypeName());
511 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
512 node.GetLocation());
513 }
514 Scalar scalar;
515 bool resolved = operand->ResolveValue(scalar);
516 if (!resolved)
517 break;
518
519 bool negated = scalar.UnaryNegate();
520 if (negated)
522 m_exe_ctx_scope, scalar, operand->GetCompilerType(), "result");
523 break;
524 }
525 case UnaryOpKind::Plus: {
526 if (operand->GetCompilerType().IsReferenceType()) {
527 operand = operand->Dereference(error);
528 if (error.Fail())
529 return error.ToError();
530 }
531 llvm::Expected<lldb::ValueObjectSP> conv_op =
532 UnaryConversion(operand, node.GetOperand().GetLocation());
533 if (!conv_op)
534 return conv_op;
535 operand = *conv_op;
536 CompilerType operand_type = operand->GetCompilerType();
537 if (!operand_type.IsScalarType() &&
538 // Unary plus is allowed for pointers.
539 !operand_type.IsPointerType()) {
540 std::string errMsg =
541 llvm::formatv("invalid argument type '{0}' to unary expression",
542 operand_type.GetTypeName());
543 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
544 node.GetLocation());
545 }
546 return operand;
547 }
548 }
549 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid unary operation",
550 node.GetLocation());
551}
552
553llvm::Expected<lldb::ValueObjectSP>
555 BinaryOpKind operation, uint32_t location) {
556 assert(operation == BinaryOpKind::Add || operation == BinaryOpKind::Sub);
557 if (ptr->GetCompilerType().IsPointerToVoid())
558 return llvm::make_error<DILDiagnosticError>(
559 m_expr, "arithmetic on a pointer to void", location);
560 if (ptr->GetValueAsUnsigned(0) == 0 && offset != 0)
561 return llvm::make_error<DILDiagnosticError>(
562 m_expr, "arithmetic on a nullptr is undefined", location);
563
564 bool success;
565 int64_t offset_int = offset->GetValueAsSigned(0, &success);
566 if (!success) {
567 std::string errMsg = llvm::formatv("could not get the offset: {0}",
568 offset->GetError().AsCString());
569 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
570 location);
571 }
572
573 llvm::Expected<uint64_t> byte_size =
574 ptr->GetCompilerType().GetPointeeType().GetByteSize(
575 m_exe_ctx_scope.get());
576 if (!byte_size)
577 return byte_size.takeError();
578 uint64_t ptr_addr = ptr->GetValueAsUnsigned(0);
579 if (operation == BinaryOpKind::Sub)
580 ptr_addr -= offset_int * (*byte_size);
581 else
582 ptr_addr += offset_int * (*byte_size);
583
584 ExecutionContext exe_ctx(m_target.get(), false);
585 Scalar scalar(ptr_addr);
587 m_exe_ctx_scope, scalar, ptr->GetCompilerType(), "result");
588}
589
590llvm::Expected<lldb::ValueObjectSP>
592 lldb::ValueObjectSP rhs, CompilerType result_type,
593 uint32_t location) {
594 Scalar l, r;
595 bool l_resolved = lhs->ResolveValue(l);
596 bool r_resolved = rhs->ResolveValue(r);
597
598 if (!l_resolved || !r_resolved)
599 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid scalar value",
600 location);
601
602 auto value_object = [this, result_type](Scalar scalar) {
604 result_type, "result");
605 };
606
607 switch (kind) {
609 return value_object(l + r);
611 return value_object(l - r);
612 }
613 return llvm::make_error<DILDiagnosticError>(
614 m_expr, "invalid arithmetic operation", location);
615}
616
617llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryAddition(
618 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
619 // Operation '+' works for:
620 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
621 // {integer,unscoped_enum} <-> pointer
622 // pointer <-> {integer,unscoped_enum}
623 auto orig_lhs_type = lhs->GetCompilerType();
624 auto orig_rhs_type = rhs->GetCompilerType();
625 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
626 if (!type_or_err)
627 return type_or_err.takeError();
628 CompilerType result_type = *type_or_err;
629
630 if (result_type.IsScalarType())
631 return EvaluateScalarOp(BinaryOpKind::Add, lhs, rhs, result_type, location);
632
633 // Check for pointer arithmetics.
634 // One of the operands must be a pointer and the other one an integer.
635 lldb::ValueObjectSP ptr, offset;
636 if (lhs->GetCompilerType().IsPointerType()) {
637 ptr = lhs;
638 offset = rhs;
639 } else if (rhs->GetCompilerType().IsPointerType()) {
640 ptr = rhs;
641 offset = lhs;
642 }
643
644 if (!ptr || !offset->GetCompilerType().IsInteger()) {
645 std::string errMsg =
646 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
647 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
648 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
649 location);
650 }
651
652 return PointerOffset(ptr, offset, BinaryOpKind::Add, location);
653}
654
655llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinarySubtraction(
656 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
657 // Operation '-' works for:
658 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
659 // pointer <-> {integer,unscoped_enum}
660 // pointer <-> pointer (if pointee types are compatible)
661 auto orig_lhs_type = lhs->GetCompilerType();
662 auto orig_rhs_type = rhs->GetCompilerType();
663 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
664 if (!type_or_err)
665 return type_or_err.takeError();
666 CompilerType result_type = *type_or_err;
667
668 if (result_type.IsScalarType())
669 return EvaluateScalarOp(BinaryOpKind::Sub, lhs, rhs, result_type, location);
670
671 auto lhs_type = lhs->GetCompilerType();
672 auto rhs_type = rhs->GetCompilerType();
673
674 // "pointer - integer" operation.
675 if (lhs_type.IsPointerType() && rhs_type.IsInteger())
676 return PointerOffset(lhs, rhs, BinaryOpKind::Sub, location);
677
678 // "pointer - pointer" operation.
679 if (lhs_type.IsPointerType() && rhs_type.IsPointerType()) {
680 if (lhs_type.IsPointerToVoid() && rhs_type.IsPointerToVoid()) {
681 return llvm::make_error<DILDiagnosticError>(
682 m_expr, "arithmetic on pointers to void", location);
683 }
684 // Compare canonical unqualified pointer types.
685 CompilerType lhs_unqualified_type = lhs_type.GetCanonicalType();
686 CompilerType rhs_unqualified_type = rhs_type.GetCanonicalType();
687 if (!lhs_unqualified_type.CompareTypes(rhs_unqualified_type)) {
688 std::string errMsg = llvm::formatv(
689 "'{0}' and '{1}' are not pointers to compatible types",
690 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
691 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
692 }
693
694 llvm::Expected<uint64_t> lhs_byte_size =
696 if (!lhs_byte_size)
697 return lhs_byte_size.takeError();
698 // Since pointers have compatible types, both have the same pointee size.
699 int64_t item_size = *lhs_byte_size;
700 int64_t diff = static_cast<int64_t>(lhs->GetValueAsUnsigned(0) -
701 rhs->GetValueAsUnsigned(0));
702 assert(item_size > 0 && "Pointee size cannot be 0");
703 if (diff % item_size != 0) {
704 // If address difference isn't divisible by pointee size then performing
705 // the operation is undefined behaviour.
706 return llvm::make_error<DILDiagnosticError>(
707 m_expr, "undefined pointer arithmetic", location);
708 }
709 diff /= item_size;
710
711 llvm::Expected<lldb::TypeSystemSP> type_system =
713 if (!type_system)
714 return type_system.takeError();
715 CompilerType ptrdiff_type = type_system.get()->GetPointerDiffType(true);
716 if (!ptrdiff_type)
717 return llvm::make_error<DILDiagnosticError>(
718 m_expr, "unable to determine pointer diff type", location);
719
720 Scalar scalar(diff);
722 ptrdiff_type, "result");
723 }
724
725 std::string errMsg =
726 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
727 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
728 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
729 location);
730}
731
732llvm::Expected<lldb::ValueObjectSP>
734 auto lhs_or_err = EvaluateAndDereference(node.GetLHS());
735 if (!lhs_or_err)
736 return lhs_or_err;
737 lldb::ValueObjectSP lhs = *lhs_or_err;
738 auto rhs_or_err = EvaluateAndDereference(node.GetRHS());
739 if (!rhs_or_err)
740 return rhs_or_err;
741 lldb::ValueObjectSP rhs = *rhs_or_err;
742
743 lldb::TypeSystemSP lhs_system =
744 lhs->GetCompilerType().GetTypeSystem().GetSharedPointer();
745 lldb::TypeSystemSP rhs_system =
746 rhs->GetCompilerType().GetTypeSystem().GetSharedPointer();
747 if (lhs_system->GetPluginName() != rhs_system->GetPluginName()) {
748 // TODO: Attempt to convert values to current CU's type system
749 return llvm::make_error<DILDiagnosticError>(
750 m_expr, "operands have different type systems", node.GetLocation());
751 }
752
753 switch (node.GetKind()) {
755 return EvaluateBinaryAddition(lhs, rhs, node.GetLocation());
757 return EvaluateBinarySubtraction(lhs, rhs, node.GetLocation());
758 }
759
760 return llvm::make_error<DILDiagnosticError>(
761 m_expr, "unimplemented binary operation", node.GetLocation());
762}
763
764llvm::Expected<lldb::ValueObjectSP>
766 auto base_or_err = Evaluate(node.GetBase());
767 if (!base_or_err)
768 return base_or_err;
769 bool expr_is_ptr = node.GetIsArrow();
770 lldb::ValueObjectSP base = *base_or_err;
771
772 // Perform some basic type & correctness checking.
773 if (node.GetIsArrow()) {
774 if (!m_fragile_ivar) {
775 // Make sure we aren't trying to deref an objective
776 // C ivar if this is not allowed
777 const uint32_t pointer_type_flags =
778 base->GetCompilerType().GetTypeInfo(nullptr);
779 if ((pointer_type_flags & lldb::eTypeIsObjC) &&
780 (pointer_type_flags & lldb::eTypeIsPointer)) {
781 // This was an objective C object pointer and it was requested we
782 // skip any fragile ivars so return nothing here
783 return lldb::ValueObjectSP();
784 }
785 }
786
787 // If we have a non-pointer type with a synthetic value then lets check
788 // if we have a synthetic dereference specified.
789 if (!base->IsPointerType() && base->HasSyntheticValue()) {
790 Status deref_error;
791 if (lldb::ValueObjectSP synth_deref_sp =
792 base->GetSyntheticValue()->Dereference(deref_error);
793 synth_deref_sp && deref_error.Success()) {
794 base = std::move(synth_deref_sp);
795 }
796 if (!base || deref_error.Fail()) {
797 std::string errMsg = llvm::formatv(
798 "Failed to dereference synthetic value: {0}", deref_error);
799 return llvm::make_error<DILDiagnosticError>(
800 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
801 }
802
803 // Some synthetic plug-ins fail to set the error in Dereference
804 if (!base) {
805 std::string errMsg = "Failed to dereference synthetic value";
806 return llvm::make_error<DILDiagnosticError>(
807 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
808 }
809 expr_is_ptr = false;
810 }
811 }
812
814 bool base_is_ptr = base->IsPointerType();
815
816 if (expr_is_ptr != base_is_ptr) {
817 if (base_is_ptr) {
818 std::string errMsg =
819 llvm::formatv("member reference type {0} is a pointer; "
820 "did you mean to use '->'?",
821 base->GetCompilerType().TypeDescription());
822 return llvm::make_error<DILDiagnosticError>(
823 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
824 } else {
825 std::string errMsg =
826 llvm::formatv("member reference type {0} is not a pointer; "
827 "did you mean to use '.'?",
828 base->GetCompilerType().TypeDescription());
829 return llvm::make_error<DILDiagnosticError>(
830 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
831 }
832 }
833 }
834
835 lldb::ValueObjectSP field_obj =
836 base->GetChildMemberWithName(node.GetFieldName());
837 if (!field_obj) {
838 if (m_use_synthetic) {
839 field_obj = base->GetSyntheticValue();
840 if (field_obj)
841 field_obj = field_obj->GetChildMemberWithName(node.GetFieldName());
842 }
843
844 if (!m_use_synthetic || !field_obj) {
845 std::string errMsg = llvm::formatv(
846 "\"{0}\" is not a member of \"({1}) {2}\"", node.GetFieldName(),
847 base->GetTypeName().AsCString("<invalid type>"), base->GetName());
848 return llvm::make_error<DILDiagnosticError>(
849 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
850 }
851 }
852
853 if (field_obj) {
855 lldb::ValueObjectSP dynamic_val_sp =
856 field_obj->GetDynamicValue(m_use_dynamic);
857 if (dynamic_val_sp)
858 field_obj = dynamic_val_sp;
859 }
860 return field_obj;
861 }
862
863 CompilerType base_type = base->GetCompilerType();
864 if (node.GetIsArrow() && base->IsPointerType())
865 base_type = base_type.GetPointeeType();
866 std::string errMsg = llvm::formatv(
867 "\"{0}\" is not a member of \"({1}) {2}\"", node.GetFieldName(),
868 base->GetTypeName().AsCString("<invalid type>"), base->GetName());
869 return llvm::make_error<DILDiagnosticError>(
870 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
871}
872
873llvm::Expected<lldb::ValueObjectSP>
875 auto idx_or_err = EvaluateAndDereference(node.GetIndex());
876 if (!idx_or_err)
877 return idx_or_err;
878 lldb::ValueObjectSP idx = *idx_or_err;
879
880 if (!idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
881 return llvm::make_error<DILDiagnosticError>(
882 m_expr, "array subscript is not an integer", node.GetLocation());
883 }
884
885 StreamString var_expr_path_strm;
886 uint64_t child_idx = idx->GetValueAsUnsigned(0);
887 lldb::ValueObjectSP child_valobj_sp;
888
889 auto base_or_err = Evaluate(node.GetBase());
890 if (!base_or_err)
891 return base_or_err;
892 lldb::ValueObjectSP base = *base_or_err;
893
894 CompilerType base_type = base->GetCompilerType().GetNonReferenceType();
895 base->GetExpressionPath(var_expr_path_strm);
896 bool is_incomplete_array = false;
897 if (base_type.IsPointerType()) {
898 bool is_objc_pointer = true;
899
900 if (base->GetCompilerType().GetMinimumLanguage() != lldb::eLanguageTypeObjC)
901 is_objc_pointer = false;
902 else if (!base->GetCompilerType().IsPointerType())
903 is_objc_pointer = false;
904
905 if (!m_use_synthetic && is_objc_pointer) {
906 std::string err_msg = llvm::formatv(
907 "\"({0}) {1}\" is an Objective-C pointer, and cannot be subscripted",
908 base->GetTypeName().AsCString("<invalid type>"),
909 var_expr_path_strm.GetData());
910 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
911 node.GetLocation());
912 }
913 if (is_objc_pointer) {
914 lldb::ValueObjectSP synthetic = base->GetSyntheticValue();
915 if (!synthetic || synthetic == base) {
916 std::string err_msg =
917 llvm::formatv("\"({0}) {1}\" is not an array type",
918 base->GetTypeName().AsCString("<invalid type>"),
919 var_expr_path_strm.GetData());
920 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
921 node.GetLocation());
922 }
923 if (static_cast<uint32_t>(child_idx) >=
924 synthetic->GetNumChildrenIgnoringErrors()) {
925 std::string err_msg = llvm::formatv(
926 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
927 base->GetTypeName().AsCString("<invalid type>"),
928 var_expr_path_strm.GetData());
929 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
930 node.GetLocation());
931 }
932 child_valobj_sp = synthetic->GetChildAtIndex(child_idx);
933 if (!child_valobj_sp) {
934 std::string err_msg = llvm::formatv(
935 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
936 base->GetTypeName().AsCString("<invalid type>"),
937 var_expr_path_strm.GetData());
938 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
939 node.GetLocation());
940 }
942 if (auto dynamic_sp = child_valobj_sp->GetDynamicValue(m_use_dynamic))
943 child_valobj_sp = std::move(dynamic_sp);
944 }
945 return child_valobj_sp;
946 }
947
948 child_valobj_sp = base->GetSyntheticArrayMember(child_idx, true);
949 if (!child_valobj_sp) {
950 std::string err_msg = llvm::formatv(
951 "failed to use pointer as array for index {0} for "
952 "\"({1}) {2}\"",
953 child_idx, base->GetTypeName().AsCString("<invalid type>"),
954 var_expr_path_strm.GetData());
955 if (base_type.IsPointerToVoid())
956 err_msg = "subscript of pointer to incomplete type 'void'";
957 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
958 node.GetLocation());
959 }
960 } else if (base_type.IsArrayType(nullptr, nullptr, &is_incomplete_array)) {
961 child_valobj_sp = base->GetChildAtIndex(child_idx);
962 if (!child_valobj_sp && (is_incomplete_array || m_use_synthetic))
963 child_valobj_sp = base->GetSyntheticArrayMember(child_idx, true);
964 if (!child_valobj_sp) {
965 std::string err_msg = llvm::formatv(
966 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
967 base->GetTypeName().AsCString("<invalid type>"),
968 var_expr_path_strm.GetData());
969 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
970 node.GetLocation());
971 }
972 } else if (base_type.IsScalarType()) {
973 child_valobj_sp =
974 base->GetSyntheticBitFieldChild(child_idx, child_idx, true);
975 if (!child_valobj_sp) {
976 std::string err_msg = llvm::formatv(
977 "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", child_idx,
978 child_idx, base->GetTypeName().AsCString("<invalid type>"),
979 var_expr_path_strm.GetData());
980 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
981 node.GetLocation(), 1);
982 }
983 } else {
984 lldb::ValueObjectSP synthetic = base->GetSyntheticValue();
985 if (!m_use_synthetic || !synthetic || synthetic == base) {
986 std::string err_msg =
987 llvm::formatv("\"{0}\" is not an array type",
988 base->GetTypeName().AsCString("<invalid type>"));
989 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
990 node.GetLocation(), 1);
991 }
992 if (static_cast<uint32_t>(child_idx) >=
993 synthetic->GetNumChildrenIgnoringErrors(child_idx + 1)) {
994 std::string err_msg = llvm::formatv(
995 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
996 base->GetTypeName().AsCString("<invalid type>"),
997 var_expr_path_strm.GetData());
998 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
999 node.GetLocation(), 1);
1000 }
1001 child_valobj_sp = synthetic->GetChildAtIndex(child_idx);
1002 if (!child_valobj_sp) {
1003 std::string err_msg = llvm::formatv(
1004 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1005 base->GetTypeName().AsCString("<invalid type>"),
1006 var_expr_path_strm.GetData());
1007 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1008 node.GetLocation(), 1);
1009 }
1010 }
1011
1012 if (child_valobj_sp) {
1014 if (auto dynamic_sp = child_valobj_sp->GetDynamicValue(m_use_dynamic))
1015 child_valobj_sp = std::move(dynamic_sp);
1016 }
1017 return child_valobj_sp;
1018 }
1019
1020 bool success;
1021 int64_t signed_child_idx = idx->GetValueAsSigned(0, &success);
1022 if (!success)
1023 return llvm::make_error<DILDiagnosticError>(
1024 m_expr, "could not get the index as an integer",
1025 node.GetIndex().GetLocation());
1026 return base->GetSyntheticArrayMember(signed_child_idx, true);
1027}
1028
1029llvm::Expected<lldb::ValueObjectSP>
1031 auto first_idx_or_err = EvaluateAndDereference(node.GetFirstIndex());
1032 if (!first_idx_or_err)
1033 return first_idx_or_err;
1034 lldb::ValueObjectSP first_idx = *first_idx_or_err;
1035 auto last_idx_or_err = EvaluateAndDereference(node.GetLastIndex());
1036 if (!last_idx_or_err)
1037 return last_idx_or_err;
1038 lldb::ValueObjectSP last_idx = *last_idx_or_err;
1039
1040 if (!first_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType() ||
1041 !last_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
1042 return llvm::make_error<DILDiagnosticError>(
1043 m_expr, "bit index is not an integer", node.GetLocation());
1044 }
1045
1046 bool success_first, success_last;
1047 int64_t first_index = first_idx->GetValueAsSigned(0, &success_first);
1048 int64_t last_index = last_idx->GetValueAsSigned(0, &success_last);
1049 if (!success_first || !success_last)
1050 return llvm::make_error<DILDiagnosticError>(
1051 m_expr, "could not get the index as an integer", node.GetLocation());
1052
1053 // if the format given is [high-low], swap range
1054 if (first_index > last_index)
1055 std::swap(first_index, last_index);
1056
1057 auto base_or_err = EvaluateAndDereference(node.GetBase());
1058 if (!base_or_err)
1059 return base_or_err;
1060 lldb::ValueObjectSP base = *base_or_err;
1061 lldb::ValueObjectSP child_valobj_sp =
1062 base->GetSyntheticBitFieldChild(first_index, last_index, true);
1063 if (!child_valobj_sp) {
1064 std::string message = llvm::formatv(
1065 "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", first_index,
1066 last_index, base->GetTypeName().AsCString("<invalid type>"),
1067 base->GetName().AsCString());
1068 return llvm::make_error<DILDiagnosticError>(m_expr, message,
1069 node.GetLocation());
1070 }
1071 return child_valobj_sp;
1072}
1073
1074llvm::Expected<CompilerType>
1076 std::shared_ptr<ExecutionContextScope> ctx,
1077 const IntegerLiteralNode &literal) {
1078 // Binary, Octal, Hexadecimal and literals with a U suffix are allowed to be
1079 // an unsigned integer.
1080 bool unsigned_is_allowed = literal.IsUnsigned() || literal.GetRadix() != 10;
1081 llvm::APInt apint = literal.GetValue();
1082
1083 llvm::SmallVector<std::pair<lldb::BasicType, lldb::BasicType>, 3> candidates;
1084 if (literal.GetTypeSuffix() <= IntegerTypeSuffix::None)
1085 candidates.emplace_back(lldb::eBasicTypeInt,
1086 unsigned_is_allowed ? lldb::eBasicTypeUnsignedInt
1088 if (literal.GetTypeSuffix() <= IntegerTypeSuffix::Long)
1089 candidates.emplace_back(lldb::eBasicTypeLong,
1090 unsigned_is_allowed ? lldb::eBasicTypeUnsignedLong
1092 candidates.emplace_back(lldb::eBasicTypeLongLong,
1094 for (auto [signed_, unsigned_] : candidates) {
1095 CompilerType signed_type = type_system->GetBasicTypeFromAST(signed_);
1096 if (!signed_type)
1097 continue;
1098 llvm::Expected<uint64_t> size = signed_type.GetBitSize(ctx.get());
1099 if (!size)
1100 return size.takeError();
1101 if (!literal.IsUnsigned() && apint.isIntN(*size - 1))
1102 return signed_type;
1103 if (unsigned_ != lldb::eBasicTypeInvalid && apint.isIntN(*size))
1104 return type_system->GetBasicTypeFromAST(unsigned_);
1105 }
1106
1107 return llvm::make_error<DILDiagnosticError>(
1108 m_expr,
1109 "integer literal is too large to be represented in any integer type",
1110 literal.GetLocation());
1111}
1112
1113llvm::Expected<lldb::ValueObjectSP>
1115 llvm::Expected<lldb::TypeSystemSP> type_system =
1117 if (!type_system)
1118 return type_system.takeError();
1119
1120 llvm::Expected<CompilerType> type =
1121 PickIntegerType(*type_system, m_exe_ctx_scope, node);
1122 if (!type)
1123 return type.takeError();
1124
1125 Scalar scalar = node.GetValue();
1126 // APInt from StringRef::getAsInteger comes with just enough bitwidth to
1127 // hold the value. This adjusts APInt bitwidth to match the compiler type.
1128 llvm::Expected<uint64_t> type_bitsize =
1129 type->GetBitSize(m_exe_ctx_scope.get());
1130 if (!type_bitsize)
1131 return type_bitsize.takeError();
1132 scalar.TruncOrExtendTo(*type_bitsize, false);
1134 *type, "result");
1135}
1136
1137llvm::Expected<lldb::ValueObjectSP>
1139 llvm::Expected<lldb::TypeSystemSP> type_system =
1141 if (!type_system)
1142 return type_system.takeError();
1143
1144 bool isFloat =
1145 &node.GetValue().getSemantics() == &llvm::APFloat::IEEEsingle();
1146 lldb::BasicType basic_type =
1148 CompilerType type = GetBasicType(*type_system, basic_type);
1149
1150 if (!type)
1151 return llvm::make_error<DILDiagnosticError>(
1152 m_expr, "unable to create a const literal", node.GetLocation());
1153
1154 Scalar scalar = node.GetValue();
1156 "result");
1157}
1158
1159llvm::Expected<lldb::ValueObjectSP>
1161 bool value = node.GetValue();
1162 llvm::Expected<lldb::TypeSystemSP> type_system =
1164 if (!type_system)
1165 return type_system.takeError();
1167 value, "result");
1168}
1169
1170llvm::Expected<CastKind>
1172 CompilerType target_type, int location) {
1173 if (source_type.IsPointerType() || source_type.IsNullPtrType()) {
1174 // Cast from pointer to float/double is not allowed.
1175 if (target_type.GetTypeInfo() & lldb::eTypeIsFloat) {
1176 std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
1177 source_type.TypeDescription(),
1178 target_type.TypeDescription());
1179 return llvm::make_error<DILDiagnosticError>(
1180 m_expr, std::move(errMsg), location,
1181 source_type.TypeDescription().length());
1182 }
1183
1184 // Casting from pointer to bool is always valid.
1185 if (target_type.IsBoolean())
1186 return CastKind::eArithmetic;
1187
1188 // Otherwise check if the result type is at least as big as the pointer
1189 // size.
1190 uint64_t type_byte_size = 0;
1191 uint64_t rhs_type_byte_size = 0;
1192 if (auto temp = target_type.GetByteSize(m_exe_ctx_scope.get())) {
1193 type_byte_size = *temp;
1194 } else {
1195 std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
1196 target_type.TypeDescription());
1197 return llvm::make_error<DILDiagnosticError>(
1198 m_expr, std::move(errMsg), location,
1199 target_type.TypeDescription().length());
1200 }
1201
1202 if (auto temp = source_type.GetByteSize(m_exe_ctx_scope.get())) {
1203 rhs_type_byte_size = *temp;
1204 } else {
1205 std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
1206 source_type.TypeDescription());
1207 return llvm::make_error<DILDiagnosticError>(
1208 m_expr, std::move(errMsg), location,
1209 source_type.TypeDescription().length());
1210 }
1211
1212 if (type_byte_size < rhs_type_byte_size) {
1213 std::string errMsg = llvm::formatv(
1214 "cast from pointer to smaller type {0} loses information",
1215 target_type.TypeDescription());
1216 return llvm::make_error<DILDiagnosticError>(
1217 m_expr, std::move(errMsg), location,
1218 source_type.TypeDescription().length());
1219 }
1220 } else if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
1221 // Otherwise accept only arithmetic types and enums.
1222 std::string errMsg = llvm::formatv("cannot convert {0} to {1}",
1223 source_type.TypeDescription(),
1224 target_type.TypeDescription());
1225
1226 return llvm::make_error<DILDiagnosticError>(
1227 m_expr, std::move(errMsg), location,
1228 source_type.TypeDescription().length());
1229 }
1230 return CastKind::eArithmetic;
1231}
1232
1233llvm::Expected<CastKind>
1235 CompilerType source_type, CompilerType target_type,
1236 int location) {
1237
1238 if (target_type.IsScalarType())
1239 return VerifyArithmeticCast(source_type, target_type, location);
1240
1241 if (target_type.IsEnumerationType()) {
1242 // Cast to enum type.
1243 if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
1244 std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
1245 source_type.TypeDescription(),
1246 target_type.TypeDescription());
1247
1248 return llvm::make_error<DILDiagnosticError>(
1249 m_expr, std::move(errMsg), location,
1250 source_type.TypeDescription().length());
1251 }
1253 }
1254
1255 if (target_type.IsPointerType()) {
1256 if (!source_type.IsInteger() && !source_type.IsEnumerationType() &&
1257 !source_type.IsArrayType() && !source_type.IsPointerType() &&
1258 !source_type.IsNullPtrType()) {
1259 std::string errMsg = llvm::formatv(
1260 "cannot cast from type {0} to pointer type {1}",
1261 source_type.TypeDescription(), target_type.TypeDescription());
1262
1263 return llvm::make_error<DILDiagnosticError>(
1264 m_expr, std::move(errMsg), location,
1265 source_type.TypeDescription().length());
1266 }
1267 return CastKind::ePointer;
1268 }
1269
1270 // Unsupported cast.
1271 std::string errMsg = llvm::formatv(
1272 "casting of {0} to {1} is not implemented yet",
1273 source_type.TypeDescription(), target_type.TypeDescription());
1274 return llvm::make_error<DILDiagnosticError>(
1275 m_expr, std::move(errMsg), location,
1276 source_type.TypeDescription().length());
1277}
1278
1279llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const CastNode &node) {
1280 auto operand_or_err = Evaluate(node.GetOperand());
1281
1282 if (!operand_or_err)
1283 return operand_or_err;
1284
1285 lldb::ValueObjectSP operand = *operand_or_err;
1286 CompilerType op_type = operand->GetCompilerType();
1287 CompilerType target_type = node.GetType();
1288
1289 if (op_type.IsReferenceType())
1290 op_type = op_type.GetNonReferenceType();
1291 if (target_type.IsScalarType() && op_type.IsArrayType()) {
1292 operand = ArrayToPointerConversion(*operand, *m_exe_ctx_scope,
1293 operand->GetName().GetStringRef());
1294 op_type = operand->GetCompilerType();
1295 }
1296 auto type_or_err =
1297 VerifyCastType(operand, op_type, target_type, node.GetLocation());
1298 if (!type_or_err)
1299 return type_or_err.takeError();
1300
1301 CastKind cast_kind = *type_or_err;
1302 if (operand->GetCompilerType().IsReferenceType()) {
1303 Status error;
1304 operand = operand->Dereference(error);
1305 if (error.Fail())
1306 return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
1307 node.GetLocation());
1308 }
1309
1310 switch (cast_kind) {
1312 // FIXME: is this correct for float vector types?
1313 if (op_type.GetTypeInfo() & lldb::eTypeIsFloat || op_type.IsInteger() ||
1314 op_type.IsEnumerationType())
1315 return operand->CastToEnumType(target_type);
1316 break;
1317 }
1318 case CastKind::eArithmetic: {
1319 if (op_type.IsPointerType() || op_type.IsNullPtrType() ||
1320 op_type.IsScalarType() || op_type.IsEnumerationType())
1321 return operand->CastToBasicType(target_type);
1322 break;
1323 }
1324 case CastKind::ePointer: {
1325 uint64_t addr = op_type.IsArrayType()
1326 ? operand->GetLoadAddress()
1327 : (op_type.IsSigned() ? operand->GetValueAsSigned(0)
1328 : operand->GetValueAsUnsigned(0));
1329 llvm::StringRef name = "result";
1330 ExecutionContext exe_ctx(m_target.get(), false);
1331 return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx,
1332 target_type,
1333 /* do_deref */ false);
1334 }
1335 case CastKind::eNone: {
1336 return lldb::ValueObjectSP();
1337 }
1338 } // switch
1339
1340 std::string errMsg =
1341 llvm::formatv("unable to cast from '{0}' to '{1}'",
1342 op_type.TypeDescription(), target_type.TypeDescription());
1343 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
1344 node.GetLocation());
1345}
1346
1347} // namespace lldb_private::dil
static llvm::raw_ostream & error(Stream &strm)
lldb::VariableListSP GetVariableList(bool can_create)
Get the variable list for a compile unit.
Generic representation of a type in a programming language.
bool IsEnumerationType(bool &is_signed) const
lldb::BasicType GetBasicTypeEnumeration() const
bool IsArrayType(CompilerType *element_type=nullptr, uint64_t *size=nullptr, bool *is_incomplete=nullptr) const
CompilerType GetPointerType() const
Return a new CompilerType that is a pointer to this type.
llvm::Expected< uint64_t > GetByteSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bytes.
CompilerType GetNonReferenceType() const
If this type is a reference to a type (L value or R value reference), return a new type with the refe...
ConstString GetTypeName(bool BaseOnly=false) const
bool IsReferenceType(CompilerType *pointee_type=nullptr, bool *is_rvalue=nullptr) const
CompilerType GetArrayElementType(ExecutionContextScope *exe_scope) const
Creating related types.
bool IsInteger() const
This is used when you don't care about the signedness of the integer.
CompilerType GetPointeeType() const
If this type is a pointer type, return the type that the pointer points to, else return an invalid ty...
uint32_t GetTypeInfo(CompilerType *pointee_or_element_compiler_type=nullptr) const
bool CompareTypes(CompilerType rhs) const
llvm::Expected< uint64_t > GetBitSize(ExecutionContextScope *exe_scope) const
Return the size of the type in bits.
CompilerType GetCanonicalType() const
bool IsPointerType(CompilerType *pointee_type=nullptr) const
A uniqued constant string class.
Definition ConstString.h:40
llvm::StringRef GetStringRef() const
Get the string value as a llvm::StringRef.
"lldb/Target/ExecutionContextScope.h" Inherit from this if your object can reconstruct its execution ...
virtual void CalculateExecutionContext(ExecutionContext &exe_ctx)=0
Reconstruct the object's execution context into sc.
"lldb/Target/ExecutionContext.h" A class that contains an execution context.
void TruncOrExtendTo(uint16_t bits, bool sign)
Convert to an integer with bits and the given signedness.
Definition Scalar.cpp:204
An error handling class.
Definition Status.h:118
bool Fail() const
Test for error condition.
Definition Status.cpp:293
bool Success() const
Test for success condition.
Definition Status.cpp:303
const char * GetData() const
Defines a symbol context baton that can be handed other debug core functions.
llvm::StringRef GetInstanceVariableName()
Determines the name of the instance variable for the this decl context.
CompileUnit * comp_unit
The CompileUnit for a given query.
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, lldb::RegisterContextSP &reg_ctx_sp, const RegisterInfo *reg_info)
static lldb::ValueObjectSP Create(ExecutionContextScope *exe_scope, const lldb::VariableSP &var_sp)
static lldb::ValueObjectSP CreateValueObjectFromAddress(llvm::StringRef name, uint64_t address, const ExecutionContext &exe_ctx, CompilerType type, bool do_deref=true)
Given an address either create a value object containing the value at that address,...
static lldb::ValueObjectSP CreateValueObjectFromScalar(const ExecutionContext &exe_ctx, Scalar &s, CompilerType type, llvm::StringRef name)
Create a value object containing the given Scalar value.
lldb::addr_t GetLoadAddress()
Return the target load address associated with this value object.
CompilerType GetCompilerType()
static lldb::ValueObjectSP CreateValueObjectFromBool(const ExecutionContext &exe_ctx, lldb::TypeSystemSP typesystem, bool value, llvm::StringRef name)
Create a value object containing the given boolean value.
The rest of the classes in this file, except for the Visitor class at the very end,...
Definition DILAST.h:74
uint32_t GetLocation() const
Definition DILAST.h:82
virtual llvm::Expected< lldb::ValueObjectSP > Accept(Visitor *v) const =0
ASTNode & GetLHS() const
Definition DILAST.h:172
BinaryOpKind GetKind() const
Definition DILAST.h:171
ASTNode & GetRHS() const
Definition DILAST.h:173
ASTNode & GetOperand() const
Definition DILAST.h:302
CompilerType GetType() const
Definition DILAST.h:301
const llvm::APFloat & GetValue() const
Definition DILAST.h:265
std::string GetName() const
Definition DILAST.h:109
IntegerTypeSuffix GetTypeSuffix() const
Definition DILAST.h:244
const llvm::APInt & GetValue() const
Definition DILAST.h:241
std::shared_ptr< StackFrame > m_exe_ctx_scope
Definition DILEval.h:134
llvm::Expected< lldb::ValueObjectSP > Evaluate(const ASTNode &node)
Evaluate an ASTNode.
Definition DILEval.cpp:410
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryAddition(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:617
llvm::Expected< lldb::ValueObjectSP > EvaluateAndDereference(const ASTNode &node)
Evaluate an ASTNode.
Definition DILEval.cpp:423
llvm::Expected< lldb::ValueObjectSP > PointerOffset(lldb::ValueObjectSP ptr, lldb::ValueObjectSP offset, BinaryOpKind operation, uint32_t location)
Add or subtract the offset to the pointer according to the pointee type byte size.
Definition DILEval.cpp:554
llvm::Expected< lldb::ValueObjectSP > EvaluateScalarOp(BinaryOpKind kind, lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, CompilerType result_type, uint32_t location)
Definition DILEval.cpp:591
llvm::Expected< CompilerType > PromoteSignedInteger(CompilerType &lhs_type, CompilerType &rhs_type)
If lhs_type is unsigned and rhs_type is signed, check whether it can represent all of the values of l...
Definition DILEval.cpp:190
llvm::Expected< lldb::ValueObjectSP > EvaluateBinarySubtraction(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:655
llvm::Expected< lldb::ValueObjectSP > UnaryConversion(lldb::ValueObjectSP valobj, uint32_t location)
Perform usual unary conversions on a value.
Definition DILEval.cpp:68
llvm::Expected< lldb::ValueObjectSP > Visit(const IdentifierNode &node) override
Definition DILEval.cpp:439
llvm::Expected< CompilerType > PickIntegerType(lldb::TypeSystemSP type_system, std::shared_ptr< ExecutionContextScope > ctx, const IntegerLiteralNode &literal)
Definition DILEval.cpp:1075
Interpreter(lldb::TargetSP target, llvm::StringRef expr, std::shared_ptr< StackFrame > frame_sp, lldb::DynamicValueType use_dynamic, uint32_t options)
Definition DILEval.cpp:389
lldb::DynamicValueType m_use_dynamic
Definition DILEval.h:135
llvm::Expected< CompilerType > ArithmeticConversion(lldb::ValueObjectSP &lhs, lldb::ValueObjectSP &rhs, uint32_t location)
Perform an arithmetic conversion on two values from an arithmetic operation.
Definition DILEval.cpp:219
llvm::Expected< CastKind > VerifyCastType(lldb::ValueObjectSP operand, CompilerType source_type, CompilerType target_type, int location)
As a preparation for type casting, compare the requested 'target' type of the cast with the type of t...
Definition DILEval.cpp:1234
llvm::Expected< CastKind > VerifyArithmeticCast(CompilerType source_type, CompilerType target_type, int location)
A helper function for VerifyCastType (below).
Definition DILEval.cpp:1171
llvm::StringRef GetFieldName() const
Definition DILAST.h:130
ASTNode & GetBase() const
Definition DILAST.h:128
UnaryOpKind GetKind() const
Definition DILAST.h:150
ASTNode & GetOperand() const
Definition DILAST.h:151
CastKind
The type casts allowed by DIL.
Definition DILAST.h:53
@ eEnumeration
Casting from a scalar to an enumeration type.
Definition DILAST.h:55
@ ePointer
Casting to a pointer type.
Definition DILAST.h:56
@ eNone
Invalid promotion type (results in error).
Definition DILAST.h:57
@ eArithmetic
Casting to a scalar.
Definition DILAST.h:54
static lldb::BasicType BasicTypeToUnsigned(lldb::BasicType basic_type)
Definition DILEval.cpp:169
llvm::Expected< lldb::TypeSystemSP > GetTypeSystemFromCU(std::shared_ptr< StackFrame > ctx)
Definition DILParser.cpp:49
lldb::ValueObjectSP GetDynamicOrSyntheticValue(lldb::ValueObjectSP value_sp, lldb::DynamicValueType use_dynamic, bool use_synthetic)
Definition DILEval.cpp:26
static CompilerType GetBasicType(lldb::TypeSystemSP type_system, lldb::BasicType basic_type)
Definition DILEval.cpp:47
static lldb::ValueObjectSP ArrayToPointerConversion(ValueObject &valobj, ExecutionContextScope &ctx, llvm::StringRef name)
Definition DILEval.cpp:55
BinaryOpKind
The binary operators recognized by DIL.
Definition DILAST.h:44
static size_t ConversionRank(CompilerType type)
Basic types with a lower rank are converted to the basic type with a higher rank.
Definition DILEval.cpp:132
static lldb::VariableSP DILFindVariable(ConstString name, VariableList &variable_list)
Definition DILEval.cpp:275
lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref, std::shared_ptr< StackFrame > frame_sp, lldb::TargetSP target_sp, lldb::DynamicValueType use_dynamic)
Given the name of an identifier, check to see if it matches the name of a global variable.
Definition DILEval.cpp:300
lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref, std::shared_ptr< StackFrame > frame_sp, lldb::DynamicValueType use_dynamic)
Given the name of an identifier (variable name, member name, type name, etc.), find the ValueObject f...
Definition DILEval.cpp:341
std::shared_ptr< lldb_private::TypeSystem > TypeSystemSP
BasicType
Basic types enumeration for the public API SBType::GetBasicType().
@ eBasicTypeUnsignedShort
@ eBasicTypeSignedChar
@ eBasicTypeUnsignedInt128
@ eBasicTypeUnsignedLong
@ eBasicTypeUnsignedChar
@ eBasicTypeUnsignedLongLong
@ eBasicTypeLongDouble
@ eBasicTypeUnsignedInt
std::shared_ptr< lldb_private::ValueObject > ValueObjectSP
@ eLanguageTypeObjC
Objective-C.
std::shared_ptr< lldb_private::VariableList > VariableListSP
std::shared_ptr< lldb_private::Variable > VariableSP
std::shared_ptr< lldb_private::Target > TargetSP
std::shared_ptr< lldb_private::RegisterContext > RegisterContextSP
Every register is described in detail including its name, alternate name (optional),...