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