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