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