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