[Go to site: main page, start]

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 && node.GetName() == "nullptr") {
463 // If we got a "nullptr" identifier, and there is no defined variable with
464 // this name, resolve it as a null pointer.
465 llvm::Expected<lldb::TypeSystemSP> type_system =
467 if (!type_system)
468 return type_system.takeError();
469 type_system.get()->GetPointerByteSize();
470 llvm::APInt value(type_system.get()->GetPointerByteSize() * CHAR_BIT, 0);
471 Scalar scalar(value);
474 "result");
475 }
476
477 if (!identifier) {
478 std::string errMsg =
479 llvm::formatv("use of undeclared identifier '{0}'", node.GetName());
480 return llvm::make_error<DILDiagnosticError>(
481 m_expr, errMsg, node.GetLocation(), node.GetName().size());
482 }
483
484 return identifier;
485}
486
487llvm::Expected<lldb::ValueObjectSP>
490 auto op_or_err = Evaluate(node.GetOperand());
491 if (!op_or_err)
492 return op_or_err;
493
494 lldb::ValueObjectSP operand = *op_or_err;
495
496 switch (node.GetKind()) {
497 case UnaryOpKind::Deref: {
498 lldb::ValueObjectSP dynamic_op = operand->GetDynamicValue(m_use_dynamic);
499 if (dynamic_op)
500 operand = dynamic_op;
501
502 lldb::ValueObjectSP child_sp = operand->Dereference(error);
503 if (!child_sp && m_use_synthetic) {
504 if (lldb::ValueObjectSP synth_obj_sp = operand->GetSyntheticValue()) {
505 error.Clear();
506 child_sp = synth_obj_sp->Dereference(error);
507 }
508 }
509 if (error.Fail())
510 return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
511 node.GetLocation());
512
513 return child_sp;
514 }
515 case UnaryOpKind::AddrOf: {
517 lldb::ValueObjectSP value = operand->AddressOf(error);
518 if (error.Fail())
519 return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
520 node.GetLocation());
521
522 return value;
523 }
524 case UnaryOpKind::Minus: {
525 if (operand->GetCompilerType().IsReferenceType()) {
526 operand = operand->Dereference(error);
527 if (error.Fail())
528 return error.ToError();
529 }
530 llvm::Expected<lldb::ValueObjectSP> conv_op =
531 UnaryConversion(operand, node.GetOperand().GetLocation());
532 if (!conv_op)
533 return conv_op;
534 operand = *conv_op;
535 CompilerType operand_type = operand->GetCompilerType();
536 if (!operand_type.IsScalarType()) {
537 std::string errMsg =
538 llvm::formatv("invalid argument type '{0}' to unary expression",
539 operand_type.GetTypeName());
540 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
541 node.GetLocation());
542 }
543 Scalar scalar;
544 bool resolved = operand->ResolveValue(scalar);
545 if (!resolved)
546 break;
547
548 bool negated = scalar.UnaryNegate();
549 if (negated)
551 m_stack_frame, scalar, operand->GetCompilerType(), "result");
552 break;
553 }
554 case UnaryOpKind::Plus: {
555 if (operand->GetCompilerType().IsReferenceType()) {
556 operand = operand->Dereference(error);
557 if (error.Fail())
558 return error.ToError();
559 }
560 llvm::Expected<lldb::ValueObjectSP> conv_op =
561 UnaryConversion(operand, node.GetOperand().GetLocation());
562 if (!conv_op)
563 return conv_op;
564 operand = *conv_op;
565 CompilerType operand_type = operand->GetCompilerType();
566 if (!operand_type.IsScalarType() &&
567 // Unary plus is allowed for pointers.
568 !operand_type.IsPointerType()) {
569 std::string errMsg =
570 llvm::formatv("invalid argument type '{0}' to unary expression",
571 operand_type.GetTypeName());
572 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
573 node.GetLocation());
574 }
575 return operand;
576 }
577 case UnaryOpKind::Not: {
578 if (operand->GetCompilerType().IsReferenceType()) {
579 operand = operand->Dereference(error);
580 if (error.Fail())
581 return error.ToError();
582 }
583 llvm::Expected<lldb::ValueObjectSP> conv_op =
584 UnaryConversion(operand, node.GetLocation());
585 if (!conv_op)
586 return conv_op;
587 operand = *conv_op;
588 CompilerType operand_type = operand->GetCompilerType();
589 if (!operand_type.IsInteger()) {
590 std::string errMsg =
591 llvm::formatv("invalid argument type '{0}' to unary expression",
592 operand_type.GetTypeName());
593 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
594 node.GetLocation());
595 }
596 Scalar scalar;
597 bool resolved = operand->ResolveValue(scalar);
598 if (!resolved) {
599 std::string errMsg = llvm::formatv("invalid operand value: {0}",
600 operand->GetError().AsCString());
601 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
602 node.GetLocation());
603 }
604
605 bool flipped = scalar.OnesComplement();
606 if (flipped)
608 m_stack_frame, scalar, operand->GetCompilerType(), "result");
609 break;
610 }
611 case UnaryOpKind::LNot: {
612 if (operand->GetCompilerType().IsReferenceType()) {
613 operand = operand->Dereference(error);
614 if (error.Fail())
615 return error.ToError();
616 }
617 CompilerType operand_type = operand->GetCompilerType();
618 if (!operand_type.IsContextuallyConvertibleToBool()) {
619 std::string errMsg =
620 llvm::formatv("invalid argument type '{0}' to unary expression",
621 operand_type.GetTypeName());
622 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
623 node.GetLocation());
624 }
625 llvm::Expected<lldb::TypeSystemSP> type_system =
627 if (!type_system)
628 return type_system.takeError();
629 auto value_or_err = operand->GetValueAsBool();
630 if (!value_or_err)
631 return value_or_err.takeError();
633 !(*value_or_err), "result");
634 }
635 }
636 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid unary operation",
637 node.GetLocation());
638}
639
640llvm::Expected<lldb::ValueObjectSP>
642 BinaryOpKind operation, uint32_t location) {
643 assert(operation == BinaryOpKind::Add || operation == BinaryOpKind::Sub);
644 if (ptr->GetCompilerType().IsPointerToVoid())
645 return llvm::make_error<DILDiagnosticError>(
646 m_expr, "arithmetic on a pointer to void", location);
647 if (ptr->GetValueAsUnsigned(0) == 0 && offset != 0)
648 return llvm::make_error<DILDiagnosticError>(
649 m_expr, "arithmetic on a nullptr is undefined", location);
650
651 bool success;
652 int64_t offset_int = offset->GetValueAsSigned(0, &success);
653 if (!success) {
654 std::string errMsg = llvm::formatv("could not get the offset: {0}",
655 offset->GetError().AsCString());
656 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
657 location);
658 }
659
660 llvm::Expected<uint64_t> byte_size =
661 ptr->GetCompilerType().GetPointeeType().GetByteSize(&m_stack_frame);
662 if (!byte_size)
663 return byte_size.takeError();
664 uint64_t ptr_addr = ptr->GetValueAsUnsigned(0);
665 if (operation == BinaryOpKind::Sub)
666 ptr_addr -= offset_int * (*byte_size);
667 else
668 ptr_addr += offset_int * (*byte_size);
669
670 ExecutionContext exe_ctx(m_target.get(), false);
671 Scalar scalar(ptr_addr);
673 m_stack_frame, scalar, ptr->GetCompilerType(), "result");
674}
675
676llvm::Expected<lldb::ValueObjectSP>
678 lldb::ValueObjectSP rhs, CompilerType result_type,
679 uint32_t location) {
680 Scalar l, r;
681 bool l_resolved = lhs->ResolveValue(l);
682 if (!l_resolved) {
683 std::string errMsg =
684 llvm::formatv("invalid lhs value: {0}", lhs->GetError().AsCString());
685 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
686 }
687 bool r_resolved = rhs->ResolveValue(r);
688 if (!r_resolved) {
689 std::string errMsg =
690 llvm::formatv("invalid rhs value: {0}", rhs->GetError().AsCString());
691 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
692 }
693
694 auto value_object = [this, result_type](Scalar scalar) {
696 result_type, "result");
697 };
698
699 switch (kind) {
701 return value_object(l + r);
703 return value_object(l - r);
705 return value_object(l * r);
707 return value_object(l / r);
709 return value_object(l % r);
711 return value_object(l & r);
713 return value_object(l ^ r);
714 case BinaryOpKind::Or:
715 return value_object(l | r);
717 return value_object(l << r);
719 return value_object(l >> r);
720 default:
721 break;
722 }
723 return llvm::make_error<DILDiagnosticError>(
724 m_expr, "invalid arithmetic operation", location);
725}
726
727llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryAddition(
728 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
729 // Operation '+' works for:
730 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
731 // {integer,unscoped_enum} <-> pointer
732 // pointer <-> {integer,unscoped_enum}
733 auto orig_lhs_type = lhs->GetCompilerType();
734 auto orig_rhs_type = rhs->GetCompilerType();
735 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
736 if (!type_or_err)
737 return type_or_err.takeError();
738 CompilerType result_type = *type_or_err;
739
740 if (result_type.IsScalarType())
741 return EvaluateScalarOp(BinaryOpKind::Add, lhs, rhs, result_type, location);
742
743 // Check for pointer arithmetics.
744 // One of the operands must be a pointer and the other one an integer.
745 lldb::ValueObjectSP ptr, offset;
746 if (lhs->GetCompilerType().IsPointerType()) {
747 ptr = lhs;
748 offset = rhs;
749 } else if (rhs->GetCompilerType().IsPointerType()) {
750 ptr = rhs;
751 offset = lhs;
752 }
753
754 if (!ptr || !offset->GetCompilerType().IsInteger()) {
755 std::string errMsg =
756 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
757 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
758 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
759 location);
760 }
761
762 return PointerOffset(ptr, offset, BinaryOpKind::Add, location);
763}
764
765llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinarySubtraction(
766 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
767 // Operation '-' works for:
768 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
769 // pointer <-> {integer,unscoped_enum}
770 // pointer <-> pointer (if pointee types are compatible)
771 auto orig_lhs_type = lhs->GetCompilerType();
772 auto orig_rhs_type = rhs->GetCompilerType();
773 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
774 if (!type_or_err)
775 return type_or_err.takeError();
776 CompilerType result_type = *type_or_err;
777
778 if (result_type.IsScalarType())
779 return EvaluateScalarOp(BinaryOpKind::Sub, lhs, rhs, result_type, location);
780
781 auto lhs_type = lhs->GetCompilerType();
782 auto rhs_type = rhs->GetCompilerType();
783
784 // "pointer - integer" operation.
785 if (lhs_type.IsPointerType() && rhs_type.IsInteger())
786 return PointerOffset(lhs, rhs, BinaryOpKind::Sub, location);
787
788 // "pointer - pointer" operation.
789 if (lhs_type.IsPointerType() && rhs_type.IsPointerType()) {
790 if (lhs_type.IsPointerToVoid() && rhs_type.IsPointerToVoid()) {
791 return llvm::make_error<DILDiagnosticError>(
792 m_expr, "arithmetic on pointers to void", location);
793 }
794 // Compare canonical unqualified pointer types.
795 CompilerType lhs_unqualified_type = lhs_type.GetCanonicalType();
796 CompilerType rhs_unqualified_type = rhs_type.GetCanonicalType();
797 if (!lhs_unqualified_type.CompareTypes(rhs_unqualified_type)) {
798 std::string errMsg = llvm::formatv(
799 "'{0}' and '{1}' are not pointers to compatible types",
800 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
801 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
802 }
803
804 llvm::Expected<uint64_t> lhs_byte_size =
806 if (!lhs_byte_size)
807 return lhs_byte_size.takeError();
808 // Since pointers have compatible types, both have the same pointee size.
809 int64_t item_size = *lhs_byte_size;
810 int64_t diff = static_cast<int64_t>(lhs->GetValueAsUnsigned(0) -
811 rhs->GetValueAsUnsigned(0));
812 assert(item_size > 0 && "Pointee size cannot be 0");
813 if (diff % item_size != 0) {
814 // If address difference isn't divisible by pointee size then performing
815 // the operation is undefined behaviour.
816 return llvm::make_error<DILDiagnosticError>(
817 m_expr, "undefined pointer arithmetic", location);
818 }
819 diff /= item_size;
820
821 llvm::Expected<lldb::TypeSystemSP> type_system =
823 if (!type_system)
824 return type_system.takeError();
825 CompilerType ptrdiff_type = type_system.get()->GetPointerDiffType(true);
826 if (!ptrdiff_type)
827 return llvm::make_error<DILDiagnosticError>(
828 m_expr, "unable to determine pointer diff type", location);
829
830 Scalar scalar(diff);
832 ptrdiff_type, "result");
833 }
834
835 std::string errMsg =
836 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
837 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
838 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
839 location);
840}
841
842llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryMultiplication(
843 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
844 // Operation '*' works for:
845 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
846 auto orig_lhs_type = lhs->GetCompilerType();
847 auto orig_rhs_type = rhs->GetCompilerType();
848 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
849 if (!type_or_err)
850 return type_or_err.takeError();
851 CompilerType result_type = *type_or_err;
852
853 if (!result_type.IsScalarType()) {
854 std::string errMsg =
855 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
856 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
857 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
858 location);
859 }
860
861 return EvaluateScalarOp(BinaryOpKind::Mul, lhs, rhs, result_type, location);
862}
863
864llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryDivision(
865 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
866 // Operation '/' works for:
867 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
868 auto orig_lhs_type = lhs->GetCompilerType();
869 auto orig_rhs_type = rhs->GetCompilerType();
870 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
871 if (!type_or_err)
872 return type_or_err.takeError();
873 CompilerType result_type = *type_or_err;
874
875 if (!result_type.IsScalarType()) {
876 std::string errMsg =
877 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
878 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
879 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
880 location);
881 }
882
883 // Check for zero only for integer division.
884 if (result_type.IsInteger() && rhs->GetValueAsSigned(-1) == 0) {
885 return llvm::make_error<DILDiagnosticError>(
886 m_expr, "division by zero is undefined", location);
887 }
888
889 return EvaluateScalarOp(BinaryOpKind::Div, lhs, rhs, result_type, location);
890}
891
892llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryRemainder(
893 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
894 // Operation '%' works for:
895 // {integer,unscoped_enum} <-> {integer,unscoped_enum}
896 auto orig_lhs_type = lhs->GetCompilerType();
897 auto orig_rhs_type = rhs->GetCompilerType();
898 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
899 if (!type_or_err)
900 return type_or_err.takeError();
901 CompilerType result_type = *type_or_err;
902
903 if (!result_type.IsInteger()) {
904 std::string errMsg =
905 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
906 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
907 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
908 location);
909 }
910
911 if (rhs->GetValueAsSigned(-1) == 0) {
912 return llvm::make_error<DILDiagnosticError>(
913 m_expr, "division by zero is undefined", location);
914 }
915
916 return EvaluateScalarOp(BinaryOpKind::Rem, lhs, rhs, result_type, location);
917}
918
920 return ct.GetTypeInfo() & lldb::eTypeIsFloat;
921}
922
923static llvm::Expected<bool> VerifyAssignmentTypes(CompilerType lhs_type,
924 CompilerType rhs_type) {
925 // Make sure lhs is a legal type for DIL assignment.
926 if (!lhs_type.IsInteger() && !lhs_type.IsUnscopedEnumerationType() &&
927 !HasFloatingRepresentation(lhs_type) && !lhs_type.IsPointerType() &&
928 !lhs_type.IsScalarType())
929 return llvm::createStringError(
930 "Illegal type for lhs of assignment (not scalar numeric type)");
931
932 // Make sure rhs is a legal type for DIL assignment.
933 if (!rhs_type.IsInteger() && !rhs_type.IsUnscopedEnumerationType() &&
934 !HasFloatingRepresentation(rhs_type) && !rhs_type.IsPointerType())
935 return llvm::createStringError(
936 "Illegal type for rhs of assignment (not scalar numeric type)");
937
938 // Only allow assigning pointers to pointers.
939 if ((lhs_type.IsPointerType() && !rhs_type.IsPointerType()) ||
940 (!lhs_type.IsPointerType() && rhs_type.IsPointerType()))
941 return llvm::createStringError(
942 "Invalid assignment: Can only assign pointers to pointers");
943
944 // For "real numbers", the types must match exactly.
945 if ((HasFloatingRepresentation(rhs_type) ||
946 HasFloatingRepresentation(lhs_type)) &&
947 lhs_type != rhs_type) {
948 std::string err_msg =
949 llvm::formatv("Incompatible types for assignment: Cannot assign {0} "
950 "to {1}",
951 rhs_type.TypeDescription(), lhs_type.TypeDescription());
952 return llvm::createStringError(err_msg);
953 }
954
955 return true;
956}
957
958llvm::Expected<lldb::ValueObjectSP>
960 lldb::ValueObjectSP rhs, uint32_t location) {
961
962 auto all_ok =
963 VerifyAssignmentTypes(lhs->GetCompilerType(), rhs->GetCompilerType());
964 if (!all_ok)
965 return all_ok.takeError();
966
967 if (llvm::Error e = lhs->SetValueFromInteger(rhs, m_allow_var_updates))
968 return e;
969
970 return lhs;
971}
972
973llvm::Expected<lldb::ValueObjectSP>
975 lldb::ValueObjectSP rhs, uint32_t location) {
976 // Operations {'&', '|', '^'} work for:
977 // {integer,unscoped_enum} <-> {integer,unscoped_enum}
978 auto orig_lhs_type = lhs->GetCompilerType();
979 auto orig_rhs_type = rhs->GetCompilerType();
980 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
981 if (!type_or_err)
982 return type_or_err.takeError();
983 CompilerType result_type = *type_or_err;
984
985 if (!result_type.IsInteger()) {
986 std::string errMsg =
987 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
988 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
989 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
990 }
991
992 return EvaluateScalarOp(kind, lhs, rhs, result_type, location);
993}
994
995llvm::Expected<lldb::ValueObjectSP>
997 lldb::ValueObjectSP rhs, uint32_t location) {
998 // Operations {'>>', '<<'} work for:
999 // {integer,unscoped_enum} <-> {integer,unscoped_enum}
1000 CompilerType orig_lhs_type = lhs->GetCompilerType();
1001 CompilerType orig_rhs_type = rhs->GetCompilerType();
1002 auto lhs_or_err = UnaryConversion(lhs, location);
1003 if (!lhs_or_err)
1004 return lhs_or_err.takeError();
1005 lhs = *lhs_or_err;
1006 auto rhs_or_err = UnaryConversion(rhs, location);
1007 if (!rhs_or_err)
1008 return rhs_or_err.takeError();
1009 rhs = *rhs_or_err;
1010
1011 CompilerType lhs_type = lhs->GetCompilerType();
1012 CompilerType rhs_type = rhs->GetCompilerType();
1013 if (!lhs_type.IsInteger() || !rhs_type.IsInteger()) {
1014 std::string errMsg =
1015 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
1016 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
1017 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
1018 }
1019
1020 bool success;
1021 uint64_t amount = rhs->GetValueAsUnsigned(0, &success);
1022 if (!success)
1023 return llvm::make_error<DILDiagnosticError>(
1024 m_expr, "could not get the shift amount as an integer", location);
1025 llvm::Expected<uint64_t> lhs_size = lhs_type.GetBitSize(&m_stack_frame);
1026 if (!lhs_size)
1027 return lhs_size.takeError();
1028 if (amount >= *lhs_size)
1029 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid shift amount",
1030 location);
1031
1032 return EvaluateScalarOp(kind, lhs, rhs, lhs_type, location);
1033}
1034
1035llvm::Expected<lldb::ValueObjectSP>
1037 // Operations {'&&', '||'} work for:
1038 // {IsContextuallyConvertibleToBool} <-> {IsContextuallyConvertibleToBool}
1039 // Note: These operators will not evaluate or check the type of RHS
1040 // if the result is determined after evaluating LHS.
1041 auto lhs_or_err = EvaluateAndDereference(node.GetLHS());
1042 if (!lhs_or_err)
1043 return lhs_or_err;
1044 lldb::ValueObjectSP lhs = *lhs_or_err;
1045 auto lhs_type = lhs->GetCompilerType();
1046 if (!lhs_type.IsContextuallyConvertibleToBool()) {
1047 std::string errMsg = llvm::formatv(
1048 "value of type {0} is not contextually convertible to 'bool'",
1049 lhs_type.TypeDescription());
1050 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
1051 node.GetLocation());
1052 }
1053 llvm::Expected<lldb::TypeSystemSP> type_system =
1055 if (!type_system)
1056 return type_system.takeError();
1057
1058 // For "&&", exit early if LHS is "false"
1059 // For "||", exit early if LHS is "true".
1060 auto lvalue_or_err = lhs->GetValueAsBool();
1061 if (!lvalue_or_err)
1062 return lvalue_or_err.takeError();
1063 bool lhs_val = *lvalue_or_err;
1064 bool exit_early = node.GetKind() == BinaryOpKind::LAnd ? !lhs_val : lhs_val;
1065 if (exit_early)
1067 lhs_val, "result");
1068
1069 // If the result is to be determined, evaluate the RHS.
1070 auto rhs_or_err = EvaluateAndDereference(node.GetRHS());
1071 if (!rhs_or_err)
1072 return rhs_or_err;
1073 lldb::ValueObjectSP rhs = *rhs_or_err;
1074 auto rhs_type = rhs->GetCompilerType();
1075 if (!rhs_type.IsContextuallyConvertibleToBool()) {
1076 std::string errMsg = llvm::formatv(
1077 "value of type {0} is not contextually convertible to 'bool'",
1078 rhs_type.TypeDescription());
1079 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
1080 node.GetLocation());
1081 }
1082
1083 auto rvalue_or_err = rhs->GetValueAsBool();
1084 if (!rvalue_or_err)
1085 return rvalue_or_err.takeError();
1087 *rvalue_or_err, "result");
1088}
1089
1090llvm::Expected<lldb::ValueObjectSP>
1092 // Handle logical operators separately. They may or may not evaluate RHS.
1093 if (node.GetKind() == BinaryOpKind::LAnd ||
1094 node.GetKind() == BinaryOpKind::LOr)
1095 return EvaluateLogical(node);
1096
1097 auto lhs_or_err = EvaluateAndDereference(node.GetLHS());
1098 if (!lhs_or_err)
1099 return lhs_or_err;
1100 lldb::ValueObjectSP lhs = *lhs_or_err;
1101 auto rhs_or_err = EvaluateAndDereference(node.GetRHS());
1102 if (!rhs_or_err)
1103 return rhs_or_err;
1104 lldb::ValueObjectSP rhs = *rhs_or_err;
1105
1106 lldb::TypeSystemSP lhs_system =
1107 lhs->GetCompilerType().GetTypeSystem().GetSharedPointer();
1108 lldb::TypeSystemSP rhs_system =
1109 rhs->GetCompilerType().GetTypeSystem().GetSharedPointer();
1110 if (lhs_system->GetPluginName() != rhs_system->GetPluginName()) {
1111 // TODO: Attempt to convert values to current CU's type system
1112 return llvm::make_error<DILDiagnosticError>(
1113 m_expr, "operands have different type systems", node.GetLocation());
1114 }
1115
1116 switch (node.GetKind()) {
1117 case BinaryOpKind::Add:
1118 return EvaluateBinaryAddition(lhs, rhs, node.GetLocation());
1120 auto ret_or_err = EvaluateBinaryAddition(lhs, rhs, node.GetLocation());
1121 if (!ret_or_err)
1122 return ret_or_err;
1123 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1124 }
1126 return EvaluateAssignment(lhs, rhs, node.GetLocation());
1127 case BinaryOpKind::Sub:
1128 return EvaluateBinarySubtraction(lhs, rhs, node.GetLocation());
1130 auto ret_or_err = EvaluateBinarySubtraction(lhs, rhs, node.GetLocation());
1131 if (!ret_or_err)
1132 return ret_or_err;
1133 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1134 }
1135 case BinaryOpKind::Mul:
1136 return EvaluateBinaryMultiplication(lhs, rhs, node.GetLocation());
1137 case BinaryOpKind::Div:
1138 return EvaluateBinaryDivision(lhs, rhs, node.GetLocation());
1139 case BinaryOpKind::Rem:
1140 return EvaluateBinaryRemainder(lhs, rhs, node.GetLocation());
1141 case BinaryOpKind::And:
1142 case BinaryOpKind::Xor:
1143 case BinaryOpKind::Or:
1144 return EvaluateBinaryBitwise(node.GetKind(), lhs, rhs, node.GetLocation());
1145 case BinaryOpKind::Shl:
1146 case BinaryOpKind::Shr:
1147 return EvaluateBinaryShift(node.GetKind(), lhs, rhs, node.GetLocation());
1148 default:
1149 break;
1150 }
1151
1152 return llvm::make_error<DILDiagnosticError>(
1153 m_expr, "unimplemented binary operation", node.GetLocation());
1154}
1155
1156llvm::Expected<lldb::ValueObjectSP>
1158 auto base_or_err = Evaluate(node.GetBase());
1159 if (!base_or_err)
1160 return base_or_err;
1161 bool expr_is_ptr = node.GetIsArrow();
1162 lldb::ValueObjectSP base = *base_or_err;
1163
1164 // Perform some basic type & correctness checking.
1165 if (node.GetIsArrow()) {
1166 // If we have a non-pointer type with a synthetic value then lets check
1167 // if we have a synthetic dereference specified.
1168 if (!base->IsPointerType() && base->HasSyntheticValue()) {
1169 Status deref_error;
1170 if (lldb::ValueObjectSP synth_deref_sp =
1171 base->GetSyntheticValue()->Dereference(deref_error);
1172 synth_deref_sp && deref_error.Success()) {
1173 base = std::move(synth_deref_sp);
1174 }
1175 if (!base || deref_error.Fail()) {
1176 std::string errMsg = llvm::formatv(
1177 "Failed to dereference synthetic value: {0}", deref_error);
1178 return llvm::make_error<DILDiagnosticError>(
1179 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1180 }
1181
1182 // Some synthetic plug-ins fail to set the error in Dereference
1183 if (!base) {
1184 std::string errMsg = "Failed to dereference synthetic value";
1185 return llvm::make_error<DILDiagnosticError>(
1186 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1187 }
1188 expr_is_ptr = false;
1189 }
1190 }
1191
1193 bool base_is_ptr = base->IsPointerType();
1194
1195 if (expr_is_ptr != base_is_ptr) {
1196 if (base_is_ptr) {
1197 std::string errMsg =
1198 llvm::formatv("member reference type {0} is a pointer; "
1199 "did you mean to use '->'?",
1200 base->GetCompilerType().TypeDescription());
1201 return llvm::make_error<DILDiagnosticError>(
1202 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1203 } else {
1204 std::string errMsg =
1205 llvm::formatv("member reference type {0} is not a pointer; "
1206 "did you mean to use '.'?",
1207 base->GetCompilerType().TypeDescription());
1208 return llvm::make_error<DILDiagnosticError>(
1209 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1210 }
1211 }
1212 }
1213
1214 lldb::ValueObjectSP field_obj =
1215 base->GetChildMemberWithName(node.GetFieldName());
1216 if (!field_obj) {
1217 if (m_use_synthetic) {
1218 field_obj = base->GetSyntheticValue();
1219 if (field_obj)
1220 field_obj = field_obj->GetChildMemberWithName(node.GetFieldName());
1221 }
1222
1223 if (!m_use_synthetic || !field_obj) {
1224 std::string errMsg = llvm::formatv(
1225 "\"{0}\" is not a member of \"({1}) {2}\"", node.GetFieldName(),
1226 base->GetTypeName().AsCString("<invalid type>"), base->GetName());
1227 return llvm::make_error<DILDiagnosticError>(
1228 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1229 }
1230 }
1231
1232 if (field_obj) {
1234 lldb::ValueObjectSP dynamic_val_sp =
1235 field_obj->GetDynamicValue(m_use_dynamic);
1236 if (dynamic_val_sp)
1237 field_obj = dynamic_val_sp;
1238 }
1239 return field_obj;
1240 }
1241
1242 CompilerType base_type = base->GetCompilerType();
1243 if (node.GetIsArrow() && base->IsPointerType())
1244 base_type = base_type.GetPointeeType();
1245 std::string errMsg = llvm::formatv(
1246 "\"{0}\" is not a member of \"({1}) {2}\"", node.GetFieldName(),
1247 base->GetTypeName().AsCString("<invalid type>"), base->GetName());
1248 return llvm::make_error<DILDiagnosticError>(
1249 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1250}
1251
1252llvm::Expected<lldb::ValueObjectSP>
1254 auto idx_or_err = EvaluateAndDereference(node.GetIndex());
1255 if (!idx_or_err)
1256 return idx_or_err;
1257 lldb::ValueObjectSP idx = *idx_or_err;
1258
1259 if (!idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
1260 return llvm::make_error<DILDiagnosticError>(
1261 m_expr, "array subscript is not an integer", node.GetLocation());
1262 }
1263
1264 StreamString var_expr_path_strm;
1265 uint64_t child_idx = idx->GetValueAsUnsigned(0);
1266 lldb::ValueObjectSP child_valobj_sp;
1267
1268 auto base_or_err = Evaluate(node.GetBase());
1269 if (!base_or_err)
1270 return base_or_err;
1271 lldb::ValueObjectSP base = *base_or_err;
1272
1273 CompilerType base_type = base->GetCompilerType().GetNonReferenceType();
1274 base->GetExpressionPath(var_expr_path_strm);
1275 bool is_incomplete_array = false;
1276 if (base_type.IsPointerType()) {
1277 bool is_objc_pointer = true;
1278
1279 if (base->GetCompilerType().GetMinimumLanguage() != lldb::eLanguageTypeObjC)
1280 is_objc_pointer = false;
1281 else if (!base->GetCompilerType().IsPointerType())
1282 is_objc_pointer = false;
1283
1284 if (!m_use_synthetic && is_objc_pointer) {
1285 std::string err_msg = llvm::formatv(
1286 "\"({0}) {1}\" is an Objective-C pointer, and cannot be subscripted",
1287 base->GetTypeName().AsCString("<invalid type>"),
1288 var_expr_path_strm.GetData());
1289 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1290 node.GetLocation());
1291 }
1292 if (is_objc_pointer) {
1293 lldb::ValueObjectSP synthetic = base->GetSyntheticValue();
1294 if (!synthetic || synthetic == base) {
1295 std::string err_msg =
1296 llvm::formatv("\"({0}) {1}\" is not an array type",
1297 base->GetTypeName().AsCString("<invalid type>"),
1298 var_expr_path_strm.GetData());
1299 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1300 node.GetLocation());
1301 }
1302 if (static_cast<uint32_t>(child_idx) >=
1303 synthetic->GetNumChildrenIgnoringErrors()) {
1304 std::string err_msg = llvm::formatv(
1305 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1306 base->GetTypeName().AsCString("<invalid type>"),
1307 var_expr_path_strm.GetData());
1308 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1309 node.GetLocation());
1310 }
1311 child_valobj_sp = synthetic->GetChildAtIndex(child_idx);
1312 if (!child_valobj_sp) {
1313 std::string err_msg = llvm::formatv(
1314 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1315 base->GetTypeName().AsCString("<invalid type>"),
1316 var_expr_path_strm.GetData());
1317 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1318 node.GetLocation());
1319 }
1321 if (auto dynamic_sp = child_valobj_sp->GetDynamicValue(m_use_dynamic))
1322 child_valobj_sp = std::move(dynamic_sp);
1323 }
1324 return child_valobj_sp;
1325 }
1326
1327 child_valobj_sp = base->GetSyntheticArrayMember(child_idx, true);
1328 if (!child_valobj_sp) {
1329 std::string err_msg = llvm::formatv(
1330 "failed to use pointer as array for index {0} for "
1331 "\"({1}) {2}\"",
1332 child_idx, base->GetTypeName().AsCString("<invalid type>"),
1333 var_expr_path_strm.GetData());
1334 if (base_type.IsPointerToVoid())
1335 err_msg = "subscript of pointer to incomplete type 'void'";
1336 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1337 node.GetLocation());
1338 }
1339 } else if (base_type.IsArrayType(nullptr, nullptr, &is_incomplete_array)) {
1340 child_valobj_sp = base->GetChildAtIndex(child_idx);
1341 if (!child_valobj_sp && (is_incomplete_array || m_use_synthetic))
1342 child_valobj_sp = base->GetSyntheticArrayMember(child_idx, true);
1343 if (!child_valobj_sp) {
1344 std::string err_msg = llvm::formatv(
1345 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1346 base->GetTypeName().AsCString("<invalid type>"),
1347 var_expr_path_strm.GetData());
1348 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1349 node.GetLocation());
1350 }
1351 } else if (base_type.IsScalarType()) {
1352 child_valobj_sp =
1353 base->GetSyntheticBitFieldChild(child_idx, child_idx, true);
1354 if (!child_valobj_sp) {
1355 std::string err_msg = llvm::formatv(
1356 "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", child_idx,
1357 child_idx, base->GetTypeName().AsCString("<invalid type>"),
1358 var_expr_path_strm.GetData());
1359 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1360 node.GetLocation(), 1);
1361 }
1362 } else {
1363 lldb::ValueObjectSP synthetic = base->GetSyntheticValue();
1364 if (!m_use_synthetic || !synthetic || synthetic == base) {
1365 std::string err_msg =
1366 llvm::formatv("\"{0}\" is not an array type",
1367 base->GetTypeName().AsCString("<invalid type>"));
1368 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1369 node.GetLocation(), 1);
1370 }
1371 if (static_cast<uint32_t>(child_idx) >=
1372 synthetic->GetNumChildrenIgnoringErrors(child_idx + 1)) {
1373 std::string err_msg = llvm::formatv(
1374 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1375 base->GetTypeName().AsCString("<invalid type>"),
1376 var_expr_path_strm.GetData());
1377 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1378 node.GetLocation(), 1);
1379 }
1380 child_valobj_sp = synthetic->GetChildAtIndex(child_idx);
1381 if (!child_valobj_sp) {
1382 std::string err_msg = llvm::formatv(
1383 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1384 base->GetTypeName().AsCString("<invalid type>"),
1385 var_expr_path_strm.GetData());
1386 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1387 node.GetLocation(), 1);
1388 }
1389 }
1390
1391 if (child_valobj_sp) {
1393 if (auto dynamic_sp = child_valobj_sp->GetDynamicValue(m_use_dynamic))
1394 child_valobj_sp = std::move(dynamic_sp);
1395 }
1396 return child_valobj_sp;
1397 }
1398
1399 bool success;
1400 int64_t signed_child_idx = idx->GetValueAsSigned(0, &success);
1401 if (!success)
1402 return llvm::make_error<DILDiagnosticError>(
1403 m_expr, "could not get the index as an integer",
1404 node.GetIndex().GetLocation());
1405 return base->GetSyntheticArrayMember(signed_child_idx, true);
1406}
1407
1408llvm::Expected<lldb::ValueObjectSP>
1410 auto first_idx_or_err = EvaluateAndDereference(node.GetFirstIndex());
1411 if (!first_idx_or_err)
1412 return first_idx_or_err;
1413 lldb::ValueObjectSP first_idx = *first_idx_or_err;
1414 auto last_idx_or_err = EvaluateAndDereference(node.GetLastIndex());
1415 if (!last_idx_or_err)
1416 return last_idx_or_err;
1417 lldb::ValueObjectSP last_idx = *last_idx_or_err;
1418
1419 if (!first_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType() ||
1420 !last_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
1421 return llvm::make_error<DILDiagnosticError>(
1422 m_expr, "bit index is not an integer", node.GetLocation());
1423 }
1424
1425 bool success_first, success_last;
1426 int64_t first_index = first_idx->GetValueAsSigned(0, &success_first);
1427 int64_t last_index = last_idx->GetValueAsSigned(0, &success_last);
1428 if (!success_first || !success_last)
1429 return llvm::make_error<DILDiagnosticError>(
1430 m_expr, "could not get the index as an integer", node.GetLocation());
1431
1432 // Reject negative indices before the swap below, so the diagnostic reports
1433 // the range as the user wrote it. A negative index would also wrap to a huge
1434 // offset in the uint32_t GetSyntheticBitFieldChild call below.
1435 if (first_index < 0 || last_index < 0) {
1436 std::string message =
1437 llvm::formatv("bitfield range {0}:{1} is not valid (negative index)",
1438 first_index, last_index);
1439 return llvm::make_error<DILDiagnosticError>(m_expr, message,
1440 node.GetLocation());
1441 }
1442
1443 // if the format given is [high-low], swap range
1444 if (first_index > last_index)
1445 std::swap(first_index, last_index);
1446
1447 // GetMaxU64Bitfield in the data layer only supports up to 64 bits (it asserts
1448 // bitfield_bit_size <= 64 and otherwise shifts out of bounds), so reject a
1449 // wider range here.
1450 if (last_index - first_index >= 64) {
1451 std::string message =
1452 llvm::formatv("bitfield range {0}:{1} is not valid (more than 64 bits)",
1453 first_index, last_index);
1454 return llvm::make_error<DILDiagnosticError>(m_expr, message,
1455 node.GetLocation());
1456 }
1457
1458 auto base_or_err = EvaluateAndDereference(node.GetBase());
1459 if (!base_or_err)
1460 return base_or_err;
1461 lldb::ValueObjectSP base = *base_or_err;
1462
1463 // The high index must lie within the base object's storage; a bit index past
1464 // its bit size shifts out of bounds when the child is later read or formatted
1465 // (GetMaxU64Bitfield).
1466 llvm::Expected<uint64_t> base_bit_size =
1467 base->GetCompilerType().GetBitSize(&m_stack_frame);
1468 if (!base_bit_size)
1469 return base_bit_size.takeError();
1470 if (static_cast<uint64_t>(last_index) >= *base_bit_size) {
1471 std::string message = llvm::formatv(
1472 "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", first_index,
1473 last_index, base->GetTypeName().AsCString("<invalid type>"),
1474 base->GetName().GetStringRef());
1475 return llvm::make_error<DILDiagnosticError>(m_expr, message,
1476 node.GetLocation());
1477 }
1478
1479 lldb::ValueObjectSP child_valobj_sp =
1480 base->GetSyntheticBitFieldChild(first_index, last_index, true);
1481 if (!child_valobj_sp) {
1482 std::string message = llvm::formatv(
1483 "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", first_index,
1484 last_index, base->GetTypeName().AsCString("<invalid type>"),
1485 base->GetName().GetStringRef());
1486 return llvm::make_error<DILDiagnosticError>(m_expr, message,
1487 node.GetLocation());
1488 }
1489 return child_valobj_sp;
1490}
1491
1492llvm::Expected<CompilerType>
1495 const IntegerLiteralNode &literal) {
1496 // Binary, Octal, Hexadecimal and literals with a U suffix are allowed to be
1497 // an unsigned integer.
1498 bool unsigned_is_allowed = literal.IsUnsigned() || literal.GetRadix() != 10;
1499 llvm::APInt apint = literal.GetValue();
1500
1501 llvm::SmallVector<std::pair<lldb::BasicType, lldb::BasicType>, 3> candidates;
1502 if (literal.GetTypeSuffix() <= IntegerTypeSuffix::None)
1503 candidates.emplace_back(lldb::eBasicTypeInt,
1504 unsigned_is_allowed ? lldb::eBasicTypeUnsignedInt
1506 if (literal.GetTypeSuffix() <= IntegerTypeSuffix::Long)
1507 candidates.emplace_back(lldb::eBasicTypeLong,
1508 unsigned_is_allowed ? lldb::eBasicTypeUnsignedLong
1510 candidates.emplace_back(lldb::eBasicTypeLongLong,
1512 for (auto [signed_, unsigned_] : candidates) {
1513 CompilerType signed_type = type_system->GetBasicTypeFromAST(signed_);
1514 if (!signed_type)
1515 continue;
1516 llvm::Expected<uint64_t> size = signed_type.GetBitSize(&ctx);
1517 if (!size)
1518 return size.takeError();
1519 if (!literal.IsUnsigned() && apint.isIntN(*size - 1))
1520 return signed_type;
1521 if (unsigned_ != lldb::eBasicTypeInvalid && apint.isIntN(*size))
1522 return type_system->GetBasicTypeFromAST(unsigned_);
1523 }
1524
1525 return llvm::make_error<DILDiagnosticError>(
1526 m_expr,
1527 "integer literal is too large to be represented in any integer type",
1528 literal.GetLocation());
1529}
1530
1531llvm::Expected<lldb::ValueObjectSP>
1533 llvm::Expected<lldb::TypeSystemSP> type_system =
1535 if (!type_system)
1536 return type_system.takeError();
1537
1538 llvm::Expected<CompilerType> type =
1539 PickIntegerType(*type_system, m_stack_frame, node);
1540 if (!type)
1541 return type.takeError();
1542
1543 Scalar scalar = node.GetValue();
1544 // APInt from StringRef::getAsInteger comes with just enough bitwidth to
1545 // hold the value. This adjusts APInt bitwidth to match the compiler type.
1546 llvm::Expected<uint64_t> type_bitsize = type->GetBitSize(&m_stack_frame);
1547 if (!type_bitsize)
1548 return type_bitsize.takeError();
1549 // Literal itself cannot be a negative value, so we do an unsigned extension.
1550 scalar.TruncOrExtendTo(*type_bitsize, false);
1551 // If the picked compiler type is signed, make the scalar signed as well.
1552 if (type->IsSigned())
1553 scalar.MakeSigned();
1555 "result");
1556}
1557
1558llvm::Expected<lldb::ValueObjectSP>
1560 llvm::Expected<lldb::TypeSystemSP> type_system =
1562 if (!type_system)
1563 return type_system.takeError();
1564
1565 bool isFloat =
1566 &node.GetValue().getSemantics() == &llvm::APFloat::IEEEsingle();
1567 lldb::BasicType basic_type =
1569 CompilerType type = GetBasicType(*type_system, basic_type);
1570
1571 if (!type)
1572 return llvm::make_error<DILDiagnosticError>(
1573 m_expr, "unable to create a const literal", node.GetLocation());
1574
1575 Scalar scalar = node.GetValue();
1577 "result");
1578}
1579
1580llvm::Expected<lldb::ValueObjectSP>
1582 bool value = node.GetValue();
1583 llvm::Expected<lldb::TypeSystemSP> type_system =
1585 if (!type_system)
1586 return type_system.takeError();
1588 value, "result");
1589}
1590
1591llvm::Expected<CastKind>
1593 CompilerType target_type, int location) {
1594 if (source_type.IsPointerType() || source_type.IsNullPtrType()) {
1595 // Cast from pointer to float/double is not allowed.
1596 if (target_type.GetTypeInfo() & lldb::eTypeIsFloat) {
1597 std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
1598 source_type.TypeDescription(),
1599 target_type.TypeDescription());
1600 return llvm::make_error<DILDiagnosticError>(
1601 m_expr, std::move(errMsg), location,
1602 source_type.TypeDescription().length());
1603 }
1604
1605 // Casting from pointer to bool is always valid.
1606 if (target_type.IsBoolean())
1607 return CastKind::eArithmetic;
1608
1609 // Otherwise check if the result type is at least as big as the pointer
1610 // size.
1611 uint64_t type_byte_size = 0;
1612 uint64_t rhs_type_byte_size = 0;
1613 if (auto temp = target_type.GetByteSize(&m_stack_frame)) {
1614 type_byte_size = *temp;
1615 } else {
1616 std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
1617 target_type.TypeDescription());
1618 LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), temp.takeError(),
1619 "GetByteSize failed: {0}");
1620 return llvm::make_error<DILDiagnosticError>(
1621 m_expr, std::move(errMsg), location,
1622 target_type.TypeDescription().length());
1623 }
1624
1625 if (auto temp = source_type.GetByteSize(&m_stack_frame)) {
1626 rhs_type_byte_size = *temp;
1627 } else {
1628 std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
1629 source_type.TypeDescription());
1630 LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), temp.takeError(),
1631 "GetByteSize failed: {0}");
1632 return llvm::make_error<DILDiagnosticError>(
1633 m_expr, std::move(errMsg), location,
1634 source_type.TypeDescription().length());
1635 }
1636
1637 if (type_byte_size < rhs_type_byte_size) {
1638 std::string errMsg = llvm::formatv(
1639 "cast from pointer to smaller type {0} loses information",
1640 target_type.TypeDescription());
1641 return llvm::make_error<DILDiagnosticError>(
1642 m_expr, std::move(errMsg), location,
1643 source_type.TypeDescription().length());
1644 }
1645 } else if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
1646 // Otherwise accept only arithmetic types and enums.
1647 std::string errMsg = llvm::formatv("cannot convert {0} to {1}",
1648 source_type.TypeDescription(),
1649 target_type.TypeDescription());
1650
1651 return llvm::make_error<DILDiagnosticError>(
1652 m_expr, std::move(errMsg), location,
1653 source_type.TypeDescription().length());
1654 }
1655 return CastKind::eArithmetic;
1656}
1657
1658llvm::Expected<CastKind>
1660 CompilerType source_type, CompilerType target_type,
1661 int location) {
1662
1663 if (target_type.IsScalarType())
1664 return VerifyArithmeticCast(source_type, target_type, location);
1665
1666 if (target_type.IsEnumerationType()) {
1667 // Cast to enum type.
1668 if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
1669 std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
1670 source_type.TypeDescription(),
1671 target_type.TypeDescription());
1672
1673 return llvm::make_error<DILDiagnosticError>(
1674 m_expr, std::move(errMsg), location,
1675 source_type.TypeDescription().length());
1676 }
1678 }
1679
1680 if (target_type.IsPointerType()) {
1681 if (!source_type.IsInteger() && !source_type.IsEnumerationType() &&
1682 !source_type.IsArrayType() && !source_type.IsPointerType() &&
1683 !source_type.IsNullPtrType()) {
1684 std::string errMsg = llvm::formatv(
1685 "cannot cast from type {0} to pointer type {1}",
1686 source_type.TypeDescription(), target_type.TypeDescription());
1687
1688 return llvm::make_error<DILDiagnosticError>(
1689 m_expr, std::move(errMsg), location,
1690 source_type.TypeDescription().length());
1691 }
1692 return CastKind::ePointer;
1693 }
1694
1695 // Unsupported cast.
1696 std::string errMsg = llvm::formatv(
1697 "casting of {0} to {1} is not implemented yet",
1698 source_type.TypeDescription(), target_type.TypeDescription());
1699 return llvm::make_error<DILDiagnosticError>(
1700 m_expr, std::move(errMsg), location,
1701 source_type.TypeDescription().length());
1702}
1703
1704llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const CastNode &node) {
1705 auto operand_or_err = Evaluate(node.GetOperand());
1706
1707 if (!operand_or_err)
1708 return operand_or_err;
1709
1710 lldb::ValueObjectSP operand = *operand_or_err;
1711 CompilerType op_type = operand->GetCompilerType();
1712 CompilerType target_type = node.GetType();
1713
1714 if (op_type.IsReferenceType())
1715 op_type = op_type.GetNonReferenceType();
1716 if (target_type.IsScalarType() && op_type.IsArrayType()) {
1717 operand = ArrayToPointerConversion(*operand, m_stack_frame,
1718 operand->GetName().GetStringRef());
1719 op_type = operand->GetCompilerType();
1720 }
1721 auto type_or_err =
1722 VerifyCastType(operand, op_type, target_type, node.GetLocation());
1723 if (!type_or_err)
1724 return type_or_err.takeError();
1725
1726 CastKind cast_kind = *type_or_err;
1727 if (operand->GetCompilerType().IsReferenceType()) {
1728 Status error;
1729 operand = operand->Dereference(error);
1730 if (error.Fail())
1731 return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
1732 node.GetLocation());
1733 }
1734
1735 switch (cast_kind) {
1737 // FIXME: is this correct for float vector types?
1738 if (op_type.GetTypeInfo() & lldb::eTypeIsFloat || op_type.IsInteger() ||
1739 op_type.IsEnumerationType())
1740 return operand->CastToEnumType(target_type);
1741 break;
1742 }
1743 case CastKind::eArithmetic: {
1744 if (op_type.IsPointerType() || op_type.IsNullPtrType() ||
1745 op_type.IsScalarType() || op_type.IsEnumerationType())
1746 return operand->CastToBasicType(target_type);
1747 break;
1748 }
1749 case CastKind::ePointer: {
1750 uint64_t addr = op_type.IsArrayType()
1751 ? operand->GetLoadAddress()
1752 : (op_type.IsSigned() ? operand->GetValueAsSigned(0)
1753 : operand->GetValueAsUnsigned(0));
1754 llvm::StringRef name = "result";
1755 ExecutionContext exe_ctx(m_target.get(), false);
1756 return ValueObject::CreateValueObjectFromAddress(name, addr, exe_ctx,
1757 target_type,
1758 /* do_deref */ false);
1759 }
1760 case CastKind::eNone: {
1761 return lldb::ValueObjectSP();
1762 }
1763 } // switch
1764
1765 std::string errMsg =
1766 llvm::formatv("unable to cast from '{0}' to '{1}'",
1767 op_type.TypeDescription(), target_type.TypeDescription());
1768 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
1769 node.GetLocation());
1770}
1771
1772llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const SizeOfNode &node) {
1773 CompilerType typearg = node.GetTypeArg();
1774 Scalar size;
1775 if (typearg.IsValid()) {
1776 if (typearg.IsReferenceType())
1777 typearg = typearg.GetNonReferenceType();
1778 llvm::Expected<uint64_t> byte_size = typearg.GetByteSize(m_target.get());
1779 if (!byte_size)
1780 return byte_size.takeError();
1781 size = *byte_size;
1782 } else {
1783 auto arg_or_err = EvaluateAndDereference(node.GetNodeArg());
1784 if (!arg_or_err)
1785 return arg_or_err;
1786 lldb::ValueObjectSP arg = *arg_or_err;
1787
1788 if (arg->IsBitfield())
1789 return llvm::make_error<DILDiagnosticError>(
1790 m_expr, "invalid application of 'sizeof' to bit-field",
1791 node.GetLocation());
1792
1793 llvm::Expected<uint64_t> byte_size = arg->GetByteSize();
1794 if (!byte_size)
1795 return byte_size.takeError();
1796 size = *byte_size;
1797 }
1798
1799 llvm::Expected<lldb::TypeSystemSP> type_system =
1801 if (!type_system)
1802 return type_system.takeError();
1803 CompilerType size_type = type_system.get()->GetSizeType();
1804 if (!size_type)
1805 return llvm::make_error<DILDiagnosticError>(
1806 m_expr, "unable to determine size type", node.GetLocation());
1807
1809 size_type, "result");
1810}
1811
1812} // namespace lldb_private::dil
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:405
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.
bool IsContextuallyConvertibleToBool() const
This may only be defined in TypeSystemClang.
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:90
uint32_t GetLocation() const
Definition DILAST.h:98
virtual llvm::Expected< lldb::ValueObjectSP > Accept(Visitor *v) const =0
ASTNode & GetLHS() const
Definition DILAST.h:188
BinaryOpKind GetKind() const
Definition DILAST.h:187
ASTNode & GetRHS() const
Definition DILAST.h:189
ASTNode & GetOperand() const
Definition DILAST.h:318
CompilerType GetType() const
Definition DILAST.h:317
const llvm::APFloat & GetValue() const
Definition DILAST.h:281
std::string GetName() const
Definition DILAST.h:125
IntegerTypeSuffix GetTypeSuffix() const
Definition DILAST.h:260
const llvm::APInt & GetValue() const
Definition DILAST.h:257
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryRemainder(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:892
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:727
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:641
llvm::Expected< lldb::ValueObjectSP > EvaluateScalarOp(BinaryOpKind kind, lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, CompilerType result_type, uint32_t location)
Definition DILEval.cpp:677
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:996
llvm::Expected< lldb::ValueObjectSP > EvaluateLogical(const BinaryOpNode &node)
Definition DILEval.cpp:1036
llvm::Expected< lldb::ValueObjectSP > EvaluateBinarySubtraction(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:765
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:864
lldb::DynamicValueType m_use_dynamic
Definition DILEval.h:163
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:842
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:1659
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:1493
llvm::Expected< lldb::ValueObjectSP > EvaluateAssignment(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:959
llvm::Expected< CastKind > VerifyArithmeticCast(CompilerType source_type, CompilerType target_type, int location)
A helper function for VerifyCastType (below).
Definition DILEval.cpp:1592
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryBitwise(BinaryOpKind kind, lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:974
llvm::StringRef GetFieldName() const
Definition DILAST.h:146
ASTNode & GetBase() const
Definition DILAST.h:144
ASTNode & GetNodeArg() const
Definition DILAST.h:341
CompilerType GetTypeArg() const
Definition DILAST.h:342
UnaryOpKind GetKind() const
Definition DILAST.h:166
ASTNode & GetOperand() const
Definition DILAST.h:167
CastKind
The type casts allowed by DIL.
Definition DILAST.h:69
@ eEnumeration
Casting from a scalar to an enumeration type.
Definition DILAST.h:71
@ ePointer
Casting to a pointer type.
Definition DILAST.h:72
@ eNone
Invalid promotion type (results in error).
Definition DILAST.h:73
@ eArithmetic
Casting to a scalar.
Definition DILAST.h:70
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:47
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:923
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:919
Log * GetLog(Cat mask)
Retrieve the Log object for the channel associated with the given log enum.
Definition Log.h:338
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),...