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"
17#include "lldb/Target/Target.h"
24#include "llvm/Support/ErrorExtras.h"
25#include "llvm/Support/FormatAdapters.h"
26#include <memory>
27#include <optional>
28
29namespace lldb_private::dil {
30
32 lldb::BasicType basic_type) {
33 if (type_system)
34 return type_system.get()->GetBasicTypeFromAST(basic_type);
35
36 return CompilerType();
37}
38
40 ExecutionContext &exe_ctx,
41 llvm::StringRef name) {
42 uint64_t addr = valobj.GetLoadAddress();
44 name, addr, exe_ctx,
45 valobj.GetCompilerType()
48 /* do_deref */ false);
49}
50
51static llvm::Expected<SymbolContext>
53 auto frame_sp = exe_ctx.GetFrameSP();
54 if (!frame_sp)
55 return llvm::createStringError("no stack frame in execution context");
56
57 SymbolContext symbol_context = frame_sp->GetSymbolContext(
58 lldb::eSymbolContextCompUnit | lldb::eSymbolContextModule);
59 if (!symbol_context.comp_unit)
60 return llvm::createStringErrorV("no compile unit for frame: {0}",
61 frame_sp->GetFunctionName());
62 if (!symbol_context.module_sp)
63 return llvm::createStringErrorV("no module for frame: {0}",
64 frame_sp->GetFunctionName());
65 return symbol_context;
66}
67
68llvm::Expected<lldb::LanguageType> Interpreter::GetSourceLanguageFromCU() {
69 llvm::Expected<SymbolContext> symbol_context =
71 if (!symbol_context)
72 return symbol_context.takeError();
73
74 return symbol_context->comp_unit->GetLanguage();
75}
76
77llvm::Expected<lldb::TypeSystemSP> Interpreter::GetTypeSystemFromCU() {
79 if (auto frame_sp = m_exe_ctx.GetFrameSP()) {
80 SymbolContext symbol_context =
81 frame_sp->GetSymbolContext(lldb::eSymbolContextCompUnit);
82 if (symbol_context.comp_unit) {
83 language = symbol_context.comp_unit->GetLanguage();
84 symbol_context = frame_sp->GetSymbolContext(lldb::eSymbolContextModule);
85 if (symbol_context.module_sp)
86 return symbol_context.module_sp->GetTypeSystemForLanguage(language);
87 }
88 }
89
90 lldb::TargetSP target_sp = m_exe_ctx.GetTargetSP();
91 if (!target_sp)
92 return llvm::createStringError("no target for frame");
93 if (language == lldb::eLanguageTypeUnknown)
94 language = target_sp->GetLanguage().AsLanguageType();
95 return target_sp->GetScratchTypeSystemForLanguage(language);
96}
97
98// DIL normally treats '.' as member access, but register names may contain
99// periods. Reconstruct the candidate so an exact register name takes
100// precedence.
101static std::optional<std::string> GetRegisterPathName(const ASTNode &node) {
102 if (node.GetKind() == NodeKind::eIdentifierNode) {
103 std::string name_storage =
104 static_cast<const IdentifierNode &>(node).GetName();
105 llvm::StringRef name = name_storage;
106 if (name.consume_front("$"))
107 return name.str();
108 return std::nullopt;
109 }
110
111 if (node.GetKind() != NodeKind::eMemberOfNode)
112 return std::nullopt;
113 const auto &member = static_cast<const MemberOfNode &>(node);
114 if (member.GetIsArrow())
115 return std::nullopt;
116 std::optional<std::string> base_name = GetRegisterPathName(member.GetBase());
117 if (!base_name)
118 return std::nullopt;
119 return *base_name + "." + member.GetFieldName().str();
120}
121
122llvm::Expected<lldb::ValueObjectSP>
124 if (!valobj)
125 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid value object",
126 location);
127 llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
128 if (!type_system)
129 return type_system.takeError();
130
131 CompilerType in_type = valobj->GetCompilerType();
132 if (valobj->IsBitfield()) {
133 // Promote bitfields. If `int` can represent the bitfield value, it is
134 // converted to `int`. Otherwise, if `unsigned int` can represent it, it
135 // is converted to `unsigned int`. Otherwise, it is treated as its
136 // underlying type.
137 uint32_t bitfield_size = valobj->GetBitfieldBitSize();
138 // Some bitfields have undefined size (e.g. result of ternary operation).
139 // The AST's `bitfield_size` of those is 0, and no promotion takes place.
140 if (bitfield_size > 0 && in_type.IsInteger()) {
141 CompilerType int_type = GetBasicType(*type_system, lldb::eBasicTypeInt);
142 CompilerType uint_type =
144 llvm::Expected<uint64_t> int_bit_size =
145 int_type.GetBitSize(m_exe_ctx.GetBestExecutionContextScope());
146 if (!int_bit_size)
147 return int_bit_size.takeError();
148 llvm::Expected<uint64_t> uint_bit_size =
149 uint_type.GetBitSize(m_exe_ctx.GetBestExecutionContextScope());
150 if (!uint_bit_size)
151 return uint_bit_size.takeError();
152 if (bitfield_size < *int_bit_size ||
153 (in_type.IsSigned() && bitfield_size == *int_bit_size)) {
154 auto result = valobj->CastToBasicType(int_type);
155 if (result->GetError().Fail())
156 return llvm::make_error<DILDiagnosticError>(
157 m_expr, result->GetError().AsCString(), location);
158 return result;
159 }
160 if (bitfield_size <= *uint_bit_size) {
161 auto result = valobj->CastToBasicType(uint_type);
162 if (result->GetError().Fail())
163 return llvm::make_error<DILDiagnosticError>(
164 m_expr, result->GetError().AsCString(), location);
165 return result;
166 }
167 // Re-create as a const value with the same underlying type
168 Scalar scalar;
169 bool resolved = valobj->ResolveValue(scalar);
170 if (!resolved)
171 return llvm::createStringError("invalid scalar value");
173 in_type, "result");
174 }
175 }
176
177 if (in_type.IsArrayType())
178 valobj = ArrayToPointerConversion(*valobj, m_exe_ctx, "result");
179
180 CompilerType promoted_type =
181 valobj->GetCompilerType().GetPromotedIntegerType();
182 if (promoted_type) {
183 auto result = valobj->CastToBasicType(promoted_type);
184 if (result->GetError().Fail())
185 return llvm::make_error<DILDiagnosticError>(
186 m_expr, result->GetError().AsCString(), location);
187 return result;
188 }
189
190 return valobj;
191}
192
193/// Basic types with a lower rank are converted to the basic type
194/// with a higher rank.
195static size_t ConversionRank(CompilerType type) {
196 switch (type.GetCanonicalType().GetBasicTypeEnumeration()) {
198 return 1;
202 return 2;
205 return 3;
208 return 4;
211 return 5;
214 return 6;
217 return 7;
219 return 8;
221 return 9;
223 return 10;
225 return 11;
226 default:
227 break;
228 }
229 return 0;
230}
231
251
252llvm::Expected<CompilerType>
254 CompilerType &rhs_type) {
255 assert(lhs_type.IsInteger() && rhs_type.IsInteger());
256 if (!lhs_type.IsSigned() && rhs_type.IsSigned()) {
257 llvm::Expected<uint64_t> lhs_size =
258 lhs_type.GetBitSize(m_exe_ctx.GetBestExecutionContextScope());
259 if (!lhs_size)
260 return lhs_size.takeError();
261 llvm::Expected<uint64_t> rhs_size =
262 rhs_type.GetBitSize(m_exe_ctx.GetBestExecutionContextScope());
263 if (!rhs_size)
264 return rhs_size.takeError();
265
266 if (*rhs_size == *lhs_size) {
267 llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
268 if (!type_system)
269 return type_system.takeError();
270 CompilerType r_type_unsigned = GetBasicType(
271 *type_system,
274 return r_type_unsigned;
275 }
276 }
277 return rhs_type;
278}
279
280llvm::Expected<CompilerType>
282 lldb::ValueObjectSP &rhs, uint32_t location) {
283 // Apply unary conversion for both operands.
284 auto lhs_or_err = UnaryConversion(lhs, location);
285 if (!lhs_or_err)
286 return lhs_or_err.takeError();
287 lhs = *lhs_or_err;
288 auto rhs_or_err = UnaryConversion(rhs, location);
289 if (!rhs_or_err)
290 return rhs_or_err.takeError();
291 rhs = *rhs_or_err;
292
293 CompilerType lhs_type = lhs->GetCompilerType();
294 CompilerType rhs_type = rhs->GetCompilerType();
295
296 // If types already match, no need for further conversions.
297 if (lhs_type.CompareTypes(rhs_type))
298 return lhs_type;
299
300 // If either of the operands is not arithmetic (e.g. pointer), we're done.
301 if (!lhs_type.IsScalarType() || !rhs_type.IsScalarType())
302 return CompilerType();
303
304 size_t l_rank = ConversionRank(lhs_type);
305 size_t r_rank = ConversionRank(rhs_type);
306 if (l_rank == 0 || r_rank == 0)
307 return llvm::make_error<DILDiagnosticError>(
308 m_expr, "unexpected basic type in arithmetic operation", location);
309
310 // If both operands are integer, check if we need to promote
311 // the higher ranked signed type.
312 if (lhs_type.IsInteger() && rhs_type.IsInteger()) {
313 using Rank = std::tuple<size_t, bool>;
314 Rank int_l_rank = {l_rank, !lhs_type.IsSigned()};
315 Rank int_r_rank = {r_rank, !rhs_type.IsSigned()};
316 if (int_l_rank < int_r_rank) {
317 auto type_or_err = PromoteSignedInteger(lhs_type, rhs_type);
318 if (!type_or_err)
319 return type_or_err.takeError();
320 return *type_or_err;
321 }
322 if (int_l_rank > int_r_rank) {
323 auto type_or_err = PromoteSignedInteger(rhs_type, lhs_type);
324 if (!type_or_err)
325 return type_or_err.takeError();
326 return *type_or_err;
327 }
328 return lhs_type;
329 }
330
331 // Handle other combinations of integer and floating point operands.
332 if (l_rank < r_rank)
333 return rhs_type;
334 return lhs_type;
335}
336
338 VariableList &variable_list) {
339 lldb::VariableSP exact_match;
340 std::vector<lldb::VariableSP> possible_matches;
341
342 for (lldb::VariableSP var_sp : variable_list) {
343 llvm::StringRef str_ref_name = var_sp->GetName().GetStringRef();
344
345 str_ref_name.consume_front("::");
346 // Check for the exact same match
347 if (str_ref_name == name.GetStringRef())
348 return var_sp;
349
350 // Check for possible matches by base name
351 if (var_sp->NameMatches(name))
352 possible_matches.push_back(var_sp);
353 }
354
355 // If there's a non-exact match, take it.
356 if (possible_matches.size() > 0)
357 return possible_matches[0];
358
359 return nullptr;
360}
361
363 ExecutionContext &exe_ctx,
364 lldb::DynamicValueType use_dynamic) {
365 // Get a global variables list without the locals from the current frame
366 auto frame_sp = exe_ctx.GetFrameSP();
367 if (!frame_sp)
368 return nullptr;
369 SymbolContext symbol_context =
370 frame_sp->GetSymbolContext(lldb::eSymbolContextCompUnit);
371 lldb::VariableListSP variable_list;
372 if (symbol_context.comp_unit)
373 variable_list = symbol_context.comp_unit->GetVariableList(true);
374
375 name_ref.consume_front("::");
376 lldb::ValueObjectSP value_sp;
377 if (variable_list) {
378 lldb::VariableSP var_sp =
379 DILFindVariable(ConstString(name_ref), *variable_list);
380 if (var_sp)
381 value_sp = frame_sp->GetValueObjectForFrameVariable(var_sp, use_dynamic);
382 }
383
384 if (value_sp)
385 return value_sp;
386
387 // Check for match in modules global variables.
388 auto target_sp = exe_ctx.GetTargetSP();
389 if (!target_sp)
390 return nullptr;
391 VariableList modules_var_list;
392 target_sp->GetImages().FindGlobalVariables(
393 ConstString(name_ref), std::numeric_limits<uint32_t>::max(),
394 modules_var_list);
395
396 if (!modules_var_list.Empty()) {
397 lldb::VariableSP var_sp =
398 DILFindVariable(ConstString(name_ref), modules_var_list);
399 if (var_sp)
401 exe_ctx.GetBestExecutionContextScope(), var_sp);
402
403 if (value_sp)
404 return value_sp;
405 }
406 return nullptr;
407}
408
410 ExecutionContext &exe_ctx,
411 lldb::LanguageType language) {
412 auto target_sp = exe_ctx.GetTargetSP();
413 if (!target_sp)
414 return nullptr;
415
416 if (name_ref.starts_with("$")) {
417 if (auto *state =
418 target_sp->GetPersistentExpressionStateForLanguage(language))
419 if (auto var_sp = state->GetVariable(name_ref))
420 if (auto valobj_sp = var_sp->GetValueObject())
421 return valobj_sp;
422 }
423 return nullptr;
424}
425
426lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref,
427 ExecutionContext &exe_ctx,
428 lldb::DynamicValueType use_dynamic) {
429 // Support $rax as a special syntax for accessing registers.
430 // Will return an invalid value in case the requested register doesn't exist.
431 auto frame_sp = exe_ctx.GetFrameSP();
432 if (!frame_sp)
433 return nullptr;
434 if (name_ref.consume_front("$")) {
435 lldb::RegisterContextSP reg_ctx(frame_sp->GetRegisterContext());
436 if (!reg_ctx)
437 return nullptr;
438
439 if (const RegisterInfo *reg_info = reg_ctx->GetRegisterInfoByName(name_ref))
441 reg_ctx, reg_info);
442
443 return nullptr;
444 }
445
446 if (!name_ref.contains("::")) {
447 // Lookup in the current frame.
448 // Try looking for a local variable in current scope.
449 lldb::VariableListSP variable_list(frame_sp->GetInScopeVariableList(false));
450
451 lldb::ValueObjectSP value_sp;
452 if (variable_list) {
453 lldb::VariableSP var_sp =
454 variable_list->FindVariable(ConstString(name_ref));
455 if (var_sp)
456 value_sp =
457 frame_sp->GetValueObjectForFrameVariable(var_sp, use_dynamic);
458 }
459
460 if (value_sp)
461 return value_sp;
462
463 // Try looking for an instance variable (class member).
464 SymbolContext sc = frame_sp->GetSymbolContext(lldb::eSymbolContextFunction |
465 lldb::eSymbolContextBlock);
466 llvm::StringRef instance_name = sc.GetInstanceName();
467 value_sp = frame_sp->FindVariable(ConstString(instance_name));
468 if (value_sp)
469 value_sp = value_sp->GetChildMemberWithName(name_ref);
470
471 if (value_sp)
472 return value_sp;
473 }
474 return nullptr;
475}
476
477lldb::ValueObjectSP LookupEnumValue(llvm::StringRef name_ref,
478 ExecutionContext &exe_ctx) {
479 if (name_ref.contains("::")) {
480 llvm::StringRef enum_typename, enumerator_name;
481 // FIXME: Change this to a structured binding for lambda capturing
482 // once we have C++20.
483 std::tie(enum_typename, enumerator_name) = name_ref.rsplit("::");
484 CompilerType enum_type = ResolveTypeByName(enum_typename.str(), exe_ctx);
485 lldb::ValueObjectSP result;
486 enum_type.ForEachEnumerator([&](const CompilerType &integer_type,
487 ConstString name,
488 const llvm::APSInt &value) -> bool {
489 if (name == enumerator_name) {
490 Scalar scalar(value);
491 result = ValueObject::CreateValueObjectFromScalar(exe_ctx, scalar,
492 enum_type, "result");
493 return false; // Stop iterating
494 }
495 return true;
496 });
497 return result;
498 }
499 return nullptr;
500}
501
502Interpreter::Interpreter(ExecutionContext &exe_ctx, llvm::StringRef expr,
503 lldb::DynamicValueType use_dynamic, uint32_t options)
504 : m_exe_ctx(exe_ctx), m_expr(expr), m_use_dynamic(use_dynamic) {
505
506 const bool check_ptr_vs_member =
508 const bool no_synth_child =
510 const bool allow_var_updates =
512 const bool disallow_globals =
514
515 m_use_synthetic = !no_synth_child;
516 m_check_ptr_vs_member = check_ptr_vs_member;
517 m_allow_var_updates = allow_var_updates;
518 m_allow_globals = !disallow_globals;
519}
520
521llvm::Expected<lldb::ValueObjectSP>
523 assert(tree && "ASTNodeUP must not contain a nullptr");
524
525 auto value_or_error = Interpreter::Evaluate(*tree);
526 if (!value_or_error) {
527 auto error = value_or_error.takeError();
529 "[Interpreter::Evaluate] DIL interpreter failed:\n{0}",
530 llvm::toStringWithoutConsuming(error));
531 return error;
532 }
533
534 return value_or_error;
535}
536
537llvm::Expected<lldb::ValueObjectSP> Interpreter::Evaluate(const ASTNode &node) {
538 // Evaluate an AST.
539 auto value_or_error = node.Accept(this);
540 // Convert SP with a nullptr to an error.
541 if (value_or_error && !*value_or_error)
542 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid value object",
543 node.GetLocation());
544 // Return the computed value-or-error. The caller is responsible for
545 // checking if an error occurred during the evaluation.
546 return value_or_error;
547}
548
549llvm::Expected<lldb::ValueObjectSP>
551 auto valobj_or_err = Evaluate(node);
552 if (!valobj_or_err)
553 return valobj_or_err;
554 lldb::ValueObjectSP valobj = *valobj_or_err;
555
557 if (valobj->GetCompilerType().IsReferenceType()) {
558 valobj = valobj->Dereference(error);
559 if (error.Fail())
560 return error.ToError();
561 }
562 return valobj;
563}
564
565llvm::Expected<lldb::ValueObjectSP>
568
569 lldb::ValueObjectSP identifier =
570 LookupIdentifier(node.GetName(), m_exe_ctx, use_dynamic);
571
572 if (!identifier && m_allow_globals)
573 identifier = LookupGlobalIdentifier(node.GetName(), m_exe_ctx, use_dynamic);
574
575 if (!identifier)
576 identifier = LookupEnumValue(node.GetName(), m_exe_ctx);
577
578 if (!identifier && node.GetName()[0] == '$') {
579 auto language = GetSourceLanguageFromCU();
580 if (language)
581 identifier =
582 LookupPersistentIdentifier(node.GetName(), m_exe_ctx, language.get());
583 else
584 // Fall through to the unknown identifier diagnostic without a CU.
585 llvm::consumeError(language.takeError());
586 }
587
588 if (!identifier && node.GetName() == "nullptr") {
589 // If we got a "nullptr" identifier, and there is no defined variable with
590 // this name, resolve it as a null pointer.
591 llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
592 if (!type_system)
593 return type_system.takeError();
594 llvm::APInt value(type_system.get()->GetPointerByteSize() * CHAR_BIT, 0);
595 Scalar scalar(value);
598 "result");
599 }
600
601 if (!identifier) {
602 std::string errMsg =
603 llvm::formatv("use of undeclared identifier '{0}'", node.GetName());
604 return llvm::make_error<DILDiagnosticError>(
605 m_expr, errMsg, node.GetLocation(), node.GetName().size());
606 }
607
608 return identifier;
609}
610
611llvm::Expected<lldb::ValueObjectSP>
614 auto op_or_err = Evaluate(node.GetOperand());
615 if (!op_or_err)
616 return op_or_err;
617
618 lldb::ValueObjectSP operand = *op_or_err;
619
620 switch (node.GetKind()) {
621 case UnaryOpKind::Deref: {
622 lldb::ValueObjectSP dynamic_op = operand->GetDynamicValue(m_use_dynamic);
623 if (dynamic_op)
624 operand = dynamic_op;
625
626 lldb::ValueObjectSP child_sp = operand->Dereference(error);
627 if (!child_sp && m_use_synthetic) {
628 if (lldb::ValueObjectSP synth_obj_sp = operand->GetSyntheticValue()) {
629 error.Clear();
630 child_sp = synth_obj_sp->Dereference(error);
631 }
632 }
633 if (error.Fail())
634 return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
635 node.GetLocation());
636
637 return child_sp;
638 }
639 case UnaryOpKind::AddrOf: {
641 lldb::ValueObjectSP value = operand->AddressOf(error);
642 if (error.Fail())
643 return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
644 node.GetLocation());
645
646 return value;
647 }
648 case UnaryOpKind::Minus: {
649 if (operand->GetCompilerType().IsReferenceType()) {
650 operand = operand->Dereference(error);
651 if (error.Fail())
652 return error.ToError();
653 }
654 llvm::Expected<lldb::ValueObjectSP> conv_op =
655 UnaryConversion(operand, node.GetOperand().GetLocation());
656 if (!conv_op)
657 return conv_op;
658 operand = *conv_op;
659 CompilerType operand_type = operand->GetCompilerType();
660 if (!operand_type.IsScalarType()) {
661 std::string errMsg =
662 llvm::formatv("invalid argument type '{0}' to unary expression",
663 operand_type.GetTypeName());
664 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
665 node.GetLocation());
666 }
667 Scalar scalar;
668 bool resolved = operand->ResolveValue(scalar);
669 if (!resolved)
670 break;
671
672 bool negated = scalar.UnaryNegate();
673 if (negated)
675 m_exe_ctx, scalar, operand->GetCompilerType(), "result");
676 break;
677 }
678 case UnaryOpKind::Plus: {
679 if (operand->GetCompilerType().IsReferenceType()) {
680 operand = operand->Dereference(error);
681 if (error.Fail())
682 return error.ToError();
683 }
684 llvm::Expected<lldb::ValueObjectSP> conv_op =
685 UnaryConversion(operand, node.GetOperand().GetLocation());
686 if (!conv_op)
687 return conv_op;
688 operand = *conv_op;
689 CompilerType operand_type = operand->GetCompilerType();
690 if (!operand_type.IsScalarType() &&
691 // Unary plus is allowed for pointers.
692 !operand_type.IsPointerType()) {
693 std::string errMsg =
694 llvm::formatv("invalid argument type '{0}' to unary expression",
695 operand_type.GetTypeName());
696 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
697 node.GetLocation());
698 }
699 return operand;
700 }
701 case UnaryOpKind::Not: {
702 if (operand->GetCompilerType().IsReferenceType()) {
703 operand = operand->Dereference(error);
704 if (error.Fail())
705 return error.ToError();
706 }
707 llvm::Expected<lldb::ValueObjectSP> conv_op =
708 UnaryConversion(operand, node.GetLocation());
709 if (!conv_op)
710 return conv_op;
711 operand = *conv_op;
712 CompilerType operand_type = operand->GetCompilerType();
713 if (!operand_type.IsInteger()) {
714 std::string errMsg =
715 llvm::formatv("invalid argument type '{0}' to unary expression",
716 operand_type.GetTypeName());
717 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
718 node.GetLocation());
719 }
720 Scalar scalar;
721 bool resolved = operand->ResolveValue(scalar);
722 if (!resolved) {
723 std::string errMsg = llvm::formatv("invalid operand value: {0}",
724 operand->GetError().AsCString());
725 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
726 node.GetLocation());
727 }
728
729 bool flipped = scalar.OnesComplement();
730 if (flipped)
732 m_exe_ctx, scalar, operand->GetCompilerType(), "result");
733 break;
734 }
735 case UnaryOpKind::LNot: {
736 if (operand->GetCompilerType().IsReferenceType()) {
737 operand = operand->Dereference(error);
738 if (error.Fail())
739 return error.ToError();
740 }
741 CompilerType operand_type = operand->GetCompilerType();
742 if (!operand_type.IsContextuallyConvertibleToBool()) {
743 std::string errMsg =
744 llvm::formatv("invalid argument type '{0}' to unary expression",
745 operand_type.GetTypeName());
746 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
747 node.GetLocation());
748 }
749 llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
750 if (!type_system)
751 return type_system.takeError();
752 auto value_or_err = operand->GetValueAsBool();
753 if (!value_or_err)
754 return value_or_err.takeError();
756 !(*value_or_err), "result");
757 }
758 }
759 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid unary operation",
760 node.GetLocation());
761}
762
763llvm::Expected<lldb::ValueObjectSP>
765 BinaryOpKind operation, uint32_t location) {
766 assert(operation == BinaryOpKind::Add || operation == BinaryOpKind::Sub);
767 if (ptr->GetCompilerType().IsPointerToVoid())
768 return llvm::make_error<DILDiagnosticError>(
769 m_expr, "arithmetic on a pointer to void", location);
770 if (ptr->GetValueAsUnsigned(0) == 0 && offset != 0)
771 return llvm::make_error<DILDiagnosticError>(
772 m_expr, "arithmetic on a nullptr is undefined", location);
773
774 bool success;
775 int64_t offset_int = offset->GetValueAsSigned(0, &success);
776 if (!success) {
777 std::string errMsg = llvm::formatv("could not get the offset: {0}",
778 offset->GetError().AsCString());
779 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
780 location);
781 }
782
783 llvm::Expected<uint64_t> byte_size =
784 ptr->GetCompilerType().GetPointeeType().GetByteSize(
785 m_exe_ctx.GetBestExecutionContextScope());
786 if (!byte_size)
787 return byte_size.takeError();
788 uint64_t ptr_addr = ptr->GetValueAsUnsigned(0);
789 if (operation == BinaryOpKind::Sub)
790 ptr_addr -= offset_int * (*byte_size);
791 else
792 ptr_addr += offset_int * (*byte_size);
793
794 Scalar scalar(ptr_addr);
796 m_exe_ctx, scalar, ptr->GetCompilerType(), "result");
797}
798
799llvm::Expected<lldb::ValueObjectSP>
801 lldb::ValueObjectSP rhs, CompilerType result_type,
802 uint32_t location) {
803 Scalar l, r;
804 bool l_resolved = lhs->ResolveValue(l);
805 if (!l_resolved) {
806 std::string errMsg =
807 llvm::formatv("invalid lhs value: {0}", lhs->GetError().AsCString());
808 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
809 }
810 bool r_resolved = rhs->ResolveValue(r);
811 if (!r_resolved) {
812 std::string errMsg =
813 llvm::formatv("invalid rhs value: {0}", rhs->GetError().AsCString());
814 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
815 }
816
817 auto value_object = [this, result_type](Scalar scalar) {
819 result_type, "result");
820 };
821
822 switch (kind) {
824 return value_object(l + r);
826 return value_object(l - r);
828 return value_object(l * r);
830 return value_object(l / r);
832 return value_object(l % r);
834 return value_object(l & r);
836 return value_object(l ^ r);
837 case BinaryOpKind::Or:
838 return value_object(l | r);
840 return value_object(l << r);
842 return value_object(l >> r);
843 case BinaryOpKind::LT:
844 return value_object(l < r);
845 case BinaryOpKind::GT:
846 return value_object(l > r);
847 case BinaryOpKind::LE:
848 return value_object(l <= r);
849 case BinaryOpKind::GE:
850 return value_object(l >= r);
851 case BinaryOpKind::EQ:
852 return value_object(l == r);
853 case BinaryOpKind::NE:
854 return value_object(l != r);
855 default:
856 break;
857 }
858 return llvm::make_error<DILDiagnosticError>(
859 m_expr, "invalid arithmetic operation", location);
860}
861
862llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryAddition(
863 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
864 // Operation '+' works for:
865 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
866 // {integer,unscoped_enum} <-> pointer
867 // pointer <-> {integer,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 return EvaluateScalarOp(BinaryOpKind::Add, lhs, rhs, result_type, location);
877
878 // Check for pointer arithmetics.
879 // One of the operands must be a pointer and the other one an integer.
880 lldb::ValueObjectSP ptr, offset;
881 if (lhs->GetCompilerType().IsPointerType()) {
882 ptr = lhs;
883 offset = rhs;
884 } else if (rhs->GetCompilerType().IsPointerType()) {
885 ptr = rhs;
886 offset = lhs;
887 }
888
889 if (!ptr || !offset->GetCompilerType().IsInteger()) {
890 std::string errMsg =
891 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
892 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
893 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
894 location);
895 }
896
897 return PointerOffset(ptr, offset, BinaryOpKind::Add, location);
898}
899
900llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinarySubtraction(
901 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
902 // Operation '-' works for:
903 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
904 // pointer <-> {integer,unscoped_enum}
905 // pointer <-> pointer (if pointee types are compatible)
906 auto orig_lhs_type = lhs->GetCompilerType();
907 auto orig_rhs_type = rhs->GetCompilerType();
908 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
909 if (!type_or_err)
910 return type_or_err.takeError();
911 CompilerType result_type = *type_or_err;
912
913 if (result_type.IsScalarType())
914 return EvaluateScalarOp(BinaryOpKind::Sub, lhs, rhs, result_type, location);
915
916 auto lhs_type = lhs->GetCompilerType();
917 auto rhs_type = rhs->GetCompilerType();
918
919 // "pointer - integer" operation.
920 if (lhs_type.IsPointerType() && rhs_type.IsInteger())
921 return PointerOffset(lhs, rhs, BinaryOpKind::Sub, location);
922
923 // "pointer - pointer" operation.
924 if (lhs_type.IsPointerType() && rhs_type.IsPointerType()) {
925 if (lhs_type.IsPointerToVoid() && rhs_type.IsPointerToVoid()) {
926 return llvm::make_error<DILDiagnosticError>(
927 m_expr, "arithmetic on pointers to void", location);
928 }
929 // Compare canonical unqualified pointer types.
930 CompilerType lhs_unqualified_type = lhs_type.GetCanonicalType();
931 CompilerType rhs_unqualified_type = rhs_type.GetCanonicalType();
932 if (!lhs_unqualified_type.CompareTypes(rhs_unqualified_type)) {
933 std::string errMsg = llvm::formatv(
934 "'{0}' and '{1}' are not pointers to compatible types",
935 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
936 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
937 }
938
939 llvm::Expected<uint64_t> lhs_byte_size =
940 lhs_type.GetPointeeType().GetByteSize(
941 m_exe_ctx.GetBestExecutionContextScope());
942 if (!lhs_byte_size)
943 return lhs_byte_size.takeError();
944 // Since pointers have compatible types, both have the same pointee size.
945 int64_t item_size = *lhs_byte_size;
946 int64_t diff = static_cast<int64_t>(lhs->GetValueAsUnsigned(0) -
947 rhs->GetValueAsUnsigned(0));
948 assert(item_size > 0 && "Pointee size cannot be 0");
949 if (diff % item_size != 0) {
950 // If address difference isn't divisible by pointee size then performing
951 // the operation is undefined behaviour.
952 return llvm::make_error<DILDiagnosticError>(
953 m_expr, "undefined pointer arithmetic", location);
954 }
955 diff /= item_size;
956
957 llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
958 if (!type_system)
959 return type_system.takeError();
960 CompilerType ptrdiff_type = type_system.get()->GetPointerDiffType(true);
961 if (!ptrdiff_type)
962 return llvm::make_error<DILDiagnosticError>(
963 m_expr, "unable to determine pointer diff type", location);
964
965 Scalar scalar(diff);
967 ptrdiff_type, "result");
968 }
969
970 std::string errMsg =
971 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
972 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
973 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
974 location);
975}
976
977llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryMultiplication(
978 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
979 // Operation '*' works for:
980 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
981 auto orig_lhs_type = lhs->GetCompilerType();
982 auto orig_rhs_type = rhs->GetCompilerType();
983 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
984 if (!type_or_err)
985 return type_or_err.takeError();
986 CompilerType result_type = *type_or_err;
987
988 if (!result_type.IsScalarType()) {
989 std::string errMsg =
990 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
991 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
992 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
993 location);
994 }
995
996 return EvaluateScalarOp(BinaryOpKind::Mul, lhs, rhs, result_type, location);
997}
998
999llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryDivision(
1000 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
1001 // Operation '/' works for:
1002 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
1003 auto orig_lhs_type = lhs->GetCompilerType();
1004 auto orig_rhs_type = rhs->GetCompilerType();
1005 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
1006 if (!type_or_err)
1007 return type_or_err.takeError();
1008 CompilerType result_type = *type_or_err;
1009
1010 if (!result_type.IsScalarType()) {
1011 std::string errMsg =
1012 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
1013 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
1014 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
1015 location);
1016 }
1017
1018 // Check for zero only for integer division.
1019 if (result_type.IsInteger() && rhs->GetValueAsSigned(-1) == 0) {
1020 return llvm::make_error<DILDiagnosticError>(
1021 m_expr, "division by zero is undefined", location);
1022 }
1023
1024 return EvaluateScalarOp(BinaryOpKind::Div, lhs, rhs, result_type, location);
1025}
1026
1027llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryRemainder(
1028 lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
1029 // Operation '%' works for:
1030 // {integer,unscoped_enum} <-> {integer,unscoped_enum}
1031 auto orig_lhs_type = lhs->GetCompilerType();
1032 auto orig_rhs_type = rhs->GetCompilerType();
1033 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
1034 if (!type_or_err)
1035 return type_or_err.takeError();
1036 CompilerType result_type = *type_or_err;
1037
1038 if (!result_type.IsInteger()) {
1039 std::string errMsg =
1040 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
1041 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
1042 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
1043 location);
1044 }
1045
1046 if (rhs->GetValueAsSigned(-1) == 0) {
1047 return llvm::make_error<DILDiagnosticError>(
1048 m_expr, "division by zero is undefined", location);
1049 }
1050
1051 return EvaluateScalarOp(BinaryOpKind::Rem, lhs, rhs, result_type, location);
1052}
1053
1055 return ct.GetTypeInfo() & lldb::eTypeIsFloat;
1056}
1057
1058static llvm::Expected<bool> VerifyAssignmentTypes(CompilerType lhs_type,
1059 CompilerType rhs_type) {
1060 // Make sure lhs is a legal type for DIL assignment.
1061 if (!lhs_type.IsInteger() && !lhs_type.IsUnscopedEnumerationType() &&
1062 !HasFloatingRepresentation(lhs_type) && !lhs_type.IsPointerType() &&
1063 !lhs_type.IsScalarType())
1064 return llvm::createStringError(
1065 "Illegal type for lhs of assignment (not scalar numeric type)");
1066
1067 // Make sure rhs is a legal type for DIL assignment.
1068 if (!rhs_type.IsInteger() && !rhs_type.IsUnscopedEnumerationType() &&
1069 !HasFloatingRepresentation(rhs_type) && !rhs_type.IsPointerType())
1070 return llvm::createStringError(
1071 "Illegal type for rhs of assignment (not scalar numeric type)");
1072
1073 // Only allow assigning pointers to pointers.
1074 if ((lhs_type.IsPointerType() && !rhs_type.IsPointerType()) ||
1075 (!lhs_type.IsPointerType() && rhs_type.IsPointerType()))
1076 return llvm::createStringError(
1077 "Invalid assignment: Can only assign pointers to pointers");
1078
1079 // For "real numbers", the types must match exactly.
1080 if ((HasFloatingRepresentation(rhs_type) ||
1081 HasFloatingRepresentation(lhs_type)) &&
1082 lhs_type != rhs_type) {
1083 std::string err_msg =
1084 llvm::formatv("Incompatible types for assignment: Cannot assign {0} "
1085 "to {1}",
1086 rhs_type.TypeDescription(), lhs_type.TypeDescription());
1087 return llvm::createStringError(err_msg);
1088 }
1089
1090 return true;
1091}
1092
1093llvm::Expected<lldb::ValueObjectSP>
1095 lldb::ValueObjectSP rhs, uint32_t location) {
1096
1097 // Verify that lhs can accept an assignment.
1098 if (llvm::Error err = lhs->CanSetValue())
1099 return err;
1100
1101 auto all_ok =
1102 VerifyAssignmentTypes(lhs->GetCompilerType(), rhs->GetCompilerType());
1103 if (!all_ok)
1104 return all_ok.takeError();
1105
1106 if (llvm::Error e = lhs->SetValueFromInteger(rhs, m_allow_var_updates))
1107 return e;
1108
1109 return lhs;
1110}
1111
1112static bool IsLiteralZero(lldb::ValueObjectSP &val, bool is_literal) {
1113 bool is_zero = val->GetValueAsUnsigned(-1) == 0;
1114 bool is_boolean = val->GetCompilerType().IsBoolean();
1115 return is_zero && !is_boolean && is_literal;
1116}
1117
1118llvm::Error
1120 lldb::ValueObjectSP &rhs, bool lhs_is_literal,
1121 bool rhs_is_literal, uint32_t location) {
1122 auto orig_lhs_type = lhs->GetCompilerType();
1123 auto orig_rhs_type = rhs->GetCompilerType();
1124
1125 bool is_ordered = (kind == BinaryOpKind::LT || kind == BinaryOpKind::LE ||
1126 kind == BinaryOpKind::GT || kind == BinaryOpKind::GE);
1127 bool lhs_nullptr_or_zero =
1128 orig_lhs_type.IsNullPtrType() || IsLiteralZero(lhs, lhs_is_literal);
1129 bool rhs_nullptr_or_zero =
1130 orig_rhs_type.IsNullPtrType() || IsLiteralZero(rhs, rhs_is_literal);
1131
1132 if (orig_lhs_type.IsArrayType())
1133 lhs = ArrayToPointerConversion(*lhs, m_exe_ctx, "result");
1134 if (orig_rhs_type.IsArrayType())
1135 rhs = ArrayToPointerConversion(*rhs, m_exe_ctx, "result");
1136
1137 CompilerType lhs_type = lhs->GetCompilerType();
1138 CompilerType rhs_type = rhs->GetCompilerType();
1139
1140 if (lhs_type == rhs_type)
1141 return llvm::Error::success();
1142
1143 lldb::ValueObjectSP lhs_child;
1144 lldb::ValueObjectSP rhs_child;
1145 bool is_signed;
1146
1147 if (!lhs_nullptr_or_zero && !lhs_type.IsPointerType() &&
1148 !lhs_type.IsIntegerOrEnumerationType(is_signed)) {
1149 // lhs is not a nullptr, pointer, enum or integer. Check to see if its
1150 // first child could be a pointer. If so, update lhs_type accordingly.
1151 lhs_child = lhs->GetChildAtIndex(0);
1152 if (lhs_child && (lhs_child->IsPointerType() ||
1153 lhs_child->GetCompilerType().IsNullPtrType()))
1154 lhs_type = lhs_child->GetCompilerType();
1155 }
1156 if (!rhs_nullptr_or_zero && !rhs_type.IsPointerType() &&
1157 !rhs_type.IsIntegerOrEnumerationType(is_signed)) {
1158 // rhs is not a nullptr, pointer, enum or integer. Check to see if its
1159 // first child could be a pointer. If so, update rhs_type accordingly.
1160 rhs_child = rhs->GetChildAtIndex(0);
1161 if (rhs_child && (rhs_child->IsPointerType() ||
1162 rhs_child->GetCompilerType().IsNullPtrType()))
1163 rhs_type = rhs_child->GetCompilerType();
1164 }
1165
1166 if ((lhs_type != orig_lhs_type) || (rhs_type != orig_rhs_type)) {
1167 if (lhs_type.IsNullPtrType() || rhs_type.IsNullPtrType())
1168 return llvm::Error::success();
1169
1170 // May be an integer or enum.
1171 if (!lhs_type.IsPointerType() || !rhs_type.IsPointerType())
1172 return llvm::Error::success();
1173
1174 CompilerType lhs_unqualified =
1176 CompilerType rhs_unqualified =
1178
1179 if (lhs_unqualified.IsPointerToVoid() || rhs_unqualified.IsPointerToVoid())
1180 return llvm::Error::success();
1181
1182 // We have two pointers, neither of which is nullptr or void *. Make
1183 // sure their types are compatible.
1184 bool comparable = lhs_unqualified.CompareTypes(rhs_unqualified);
1185 if (comparable)
1186 return llvm::Error::success();
1187
1188 std::string errMsg = llvm::formatv(
1189 "comparison of distinct pointer types ({0} and {1})",
1190 orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
1191 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
1192 }
1193
1194 if (!is_ordered && ((orig_lhs_type.IsNullPtrType() && rhs_nullptr_or_zero) ||
1195 (lhs_nullptr_or_zero && orig_rhs_type.IsNullPtrType())))
1196 return llvm::Error::success();
1197
1198 // If the operands has arithmetic or enumeration type (scoped or unscoped),
1199 // usual arithmetic conversions are performed on both operands following the
1200 // rules for arithmetic operators.
1201 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
1202 if (!type_or_err)
1203 return type_or_err.takeError();
1204
1205 lhs_type = lhs->GetCompilerType();
1206 rhs_type = rhs->GetCompilerType();
1207 if (lhs_type.IsScalarOrUnscopedEnumerationType() &&
1209 return llvm::Error::success();
1210
1211 // Scoped enums can be compared only to the instances of the same type.
1212 if (lhs_type.IsScopedEnumerationType() ||
1213 rhs_type.IsScopedEnumerationType()) {
1214 if (lhs_type.CompareTypes(rhs_type))
1215 return llvm::Error::success();
1216 std::string errMsg = llvm::formatv(
1217 "invalid operands to binary expression ({0} and {1})",
1218 orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
1219 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
1220 }
1221
1222 // Check if the value can be compared to a pointer. We allow all pointers,
1223 // integers, unscoped enumerations and a `nullptr` literal if it's an
1224 // equality/inequality comparison, including comparing a pointer with an
1225 // integer representing an address. This also allows comparing `nullptr` and
1226 // any integer, not just literal zero, e.g. `nullptr == 1` is false.
1227 auto comparable_to_pointer = [&](CompilerType t) {
1228 return t.IsPointerType() || t.IsInteger() ||
1229 t.IsUnscopedEnumerationType() || (!is_ordered && t.IsNullPtrType());
1230 };
1231
1232 if ((lhs_type.IsPointerType() && comparable_to_pointer(rhs_type)) ||
1233 (comparable_to_pointer(lhs_type) && rhs_type.IsPointerType())) {
1234 // If both are pointers, check if they have comparable types.
1235 if ((lhs_type.IsPointerType() && !lhs_type.IsPointerToVoid()) &&
1236 (rhs_type.IsPointerType() && !rhs_type.IsPointerToVoid())) {
1237 // Compare canonical unqualified pointer types.
1238 CompilerType lhs_unqualified_type =
1240 CompilerType rhs_unqualified_type =
1242 bool comparable = lhs_unqualified_type.CompareTypes(rhs_unqualified_type);
1243
1244 if (!comparable) {
1245
1246 std::string errMsg = llvm::formatv(
1247 "comparison of distinct pointer types ({0} and {1})",
1248 orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
1249 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
1250 }
1251 }
1252 // Comparing pointers to void is always allowed.
1253 return llvm::Error::success();
1254 }
1255
1256 std::string errMsg = llvm::formatv(
1257 "invalid operands to binary expression ({0} and {1})",
1258 orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
1259 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
1260}
1261
1262llvm::Expected<lldb::ValueObjectSP>
1264 lldb::ValueObjectSP rhs, bool lhs_is_literal,
1265 bool rhs_is_literal, uint32_t location) {
1266 // Comparison works for:
1267 // nullptr_t <-> {nullptr_t,integer} (if integer is literal zero)
1268 // {nullptr_t,integer} <-> nullptr_t (if integer is literal zero)
1269 // {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
1270 // scoped_enum <-> scoped_enum (if the same type)
1271 // pointer <-> pointer (if pointee types are compatible)
1272 // pointer <-> {integer,unscoped_enum,nullptr_t}
1273 // {integer,unscoped_enum,nullptr_t} <-> pointer
1274 if (auto error = ValidateComparison(kind, lhs, rhs, lhs_is_literal,
1275 rhs_is_literal, location))
1276 return error;
1277
1278 llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
1279 if (!type_system)
1280 return type_system.takeError();
1281 CompilerType boolean_type = GetBasicType(*type_system, lldb::eBasicTypeBool);
1282
1283 return EvaluateScalarOp(kind, lhs, rhs, boolean_type, location);
1284}
1285
1286llvm::Expected<lldb::ValueObjectSP>
1288 lldb::ValueObjectSP rhs, uint32_t location) {
1289 // Operations {'&', '|', '^'} work for:
1290 // {integer,unscoped_enum} <-> {integer,unscoped_enum}
1291 auto orig_lhs_type = lhs->GetCompilerType();
1292 auto orig_rhs_type = rhs->GetCompilerType();
1293 auto type_or_err = ArithmeticConversion(lhs, rhs, location);
1294 if (!type_or_err)
1295 return type_or_err.takeError();
1296 CompilerType result_type = *type_or_err;
1297
1298 if (!result_type.IsInteger()) {
1299 std::string errMsg =
1300 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
1301 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
1302 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
1303 }
1304
1305 return EvaluateScalarOp(kind, lhs, rhs, result_type, location);
1306}
1307
1308llvm::Expected<lldb::ValueObjectSP>
1310 lldb::ValueObjectSP rhs, uint32_t location) {
1311 // Operations {'>>', '<<'} work for:
1312 // {integer,unscoped_enum} <-> {integer,unscoped_enum}
1313 CompilerType orig_lhs_type = lhs->GetCompilerType();
1314 CompilerType orig_rhs_type = rhs->GetCompilerType();
1315 auto lhs_or_err = UnaryConversion(lhs, location);
1316 if (!lhs_or_err)
1317 return lhs_or_err.takeError();
1318 lhs = *lhs_or_err;
1319 auto rhs_or_err = UnaryConversion(rhs, location);
1320 if (!rhs_or_err)
1321 return rhs_or_err.takeError();
1322 rhs = *rhs_or_err;
1323
1324 CompilerType lhs_type = lhs->GetCompilerType();
1325 CompilerType rhs_type = rhs->GetCompilerType();
1326 if (!lhs_type.IsInteger() || !rhs_type.IsInteger()) {
1327 std::string errMsg =
1328 llvm::formatv("invalid operands to binary expression ('{0}' and '{1}')",
1329 orig_lhs_type.GetTypeName(), orig_rhs_type.GetTypeName());
1330 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
1331 }
1332
1333 bool success;
1334 uint64_t amount = rhs->GetValueAsUnsigned(0, &success);
1335 if (!success)
1336 return llvm::make_error<DILDiagnosticError>(
1337 m_expr, "could not get the shift amount as an integer", location);
1338 llvm::Expected<uint64_t> lhs_size =
1339 lhs_type.GetBitSize(m_exe_ctx.GetBestExecutionContextScope());
1340 if (!lhs_size)
1341 return lhs_size.takeError();
1342 if (amount >= *lhs_size)
1343 return llvm::make_error<DILDiagnosticError>(m_expr, "invalid shift amount",
1344 location);
1345
1346 return EvaluateScalarOp(kind, lhs, rhs, lhs_type, location);
1347}
1348
1349llvm::Expected<lldb::ValueObjectSP>
1351 // Operations {'&&', '||'} work for:
1352 // {IsContextuallyConvertibleToBool} <-> {IsContextuallyConvertibleToBool}
1353 // Note: These operators will not evaluate or check the type of RHS
1354 // if the result is determined after evaluating LHS.
1355 auto lhs_or_err = EvaluateAndDereference(node.GetLHS());
1356 if (!lhs_or_err)
1357 return lhs_or_err;
1358 lldb::ValueObjectSP lhs = *lhs_or_err;
1359 auto lhs_type = lhs->GetCompilerType();
1360 if (!lhs_type.IsContextuallyConvertibleToBool()) {
1361 std::string errMsg = llvm::formatv(
1362 "value of type {0} is not contextually convertible to 'bool'",
1363 lhs_type.TypeDescription());
1364 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
1365 node.GetLocation());
1366 }
1367 llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
1368 if (!type_system)
1369 return type_system.takeError();
1370
1371 // For "&&", exit early if LHS is "false"
1372 // For "||", exit early if LHS is "true".
1373 auto lvalue_or_err = lhs->GetValueAsBool();
1374 if (!lvalue_or_err)
1375 return lvalue_or_err.takeError();
1376 bool lhs_val = *lvalue_or_err;
1377 bool exit_early = node.GetKind() == BinaryOpKind::LAnd ? !lhs_val : lhs_val;
1378 if (exit_early)
1380 lhs_val, "result");
1381
1382 // If the result is to be determined, evaluate the RHS.
1383 auto rhs_or_err = EvaluateAndDereference(node.GetRHS());
1384 if (!rhs_or_err)
1385 return rhs_or_err;
1386 lldb::ValueObjectSP rhs = *rhs_or_err;
1387 auto rhs_type = rhs->GetCompilerType();
1388 if (!rhs_type.IsContextuallyConvertibleToBool()) {
1389 std::string errMsg = llvm::formatv(
1390 "value of type {0} is not contextually convertible to 'bool'",
1391 rhs_type.TypeDescription());
1392 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
1393 node.GetLocation());
1394 }
1395
1396 auto rvalue_or_err = rhs->GetValueAsBool();
1397 if (!rvalue_or_err)
1398 return rvalue_or_err.takeError();
1400 *rvalue_or_err, "result");
1401}
1402
1403llvm::Expected<lldb::ValueObjectSP>
1405 // Handle logical operators separately. They may or may not evaluate RHS.
1406 if (node.GetKind() == BinaryOpKind::LAnd ||
1407 node.GetKind() == BinaryOpKind::LOr)
1408 return EvaluateLogical(node);
1409
1410 auto lhs_or_err = EvaluateAndDereference(node.GetLHS());
1411 if (!lhs_or_err)
1412 return lhs_or_err;
1413 lldb::ValueObjectSP lhs = *lhs_or_err;
1414 auto rhs_or_err = EvaluateAndDereference(node.GetRHS());
1415 if (!rhs_or_err)
1416 return rhs_or_err;
1417 lldb::ValueObjectSP rhs = *rhs_or_err;
1418
1419 bool lhs_is_literal = node.GetLHS().IsConstLiteral();
1420 bool rhs_is_literal = node.GetRHS().IsConstLiteral();
1421 lldb::TypeSystemSP lhs_system =
1422 lhs->GetCompilerType().GetTypeSystem().GetSharedPointer();
1423 lldb::TypeSystemSP rhs_system =
1424 rhs->GetCompilerType().GetTypeSystem().GetSharedPointer();
1425 if (lhs_system->GetPluginName() != rhs_system->GetPluginName()) {
1426 // TODO: Attempt to convert values to current CU's type system
1427 return llvm::make_error<DILDiagnosticError>(
1428 m_expr, "operands have different type systems", node.GetLocation());
1429 }
1430
1431 switch (node.GetKind()) {
1433 return EvaluateAssignment(lhs, rhs, node.GetLocation());
1434 case BinaryOpKind::Add:
1435 return EvaluateBinaryAddition(lhs, rhs, node.GetLocation());
1436 case BinaryOpKind::Sub:
1437 return EvaluateBinarySubtraction(lhs, rhs, node.GetLocation());
1438 case BinaryOpKind::Mul:
1439 return EvaluateBinaryMultiplication(lhs, rhs, node.GetLocation());
1440 case BinaryOpKind::Div:
1441 return EvaluateBinaryDivision(lhs, rhs, node.GetLocation());
1442 case BinaryOpKind::Rem:
1443 return EvaluateBinaryRemainder(lhs, rhs, node.GetLocation());
1444 case BinaryOpKind::And:
1445 case BinaryOpKind::Xor:
1446 case BinaryOpKind::Or:
1447 return EvaluateBinaryBitwise(node.GetKind(), lhs, rhs, node.GetLocation());
1448 case BinaryOpKind::Shl:
1449 case BinaryOpKind::Shr:
1450 return EvaluateBinaryShift(node.GetKind(), lhs, rhs, node.GetLocation());
1452 auto ret_or_err = EvaluateBinaryAddition(lhs, rhs, node.GetLocation());
1453 if (!ret_or_err)
1454 return ret_or_err;
1455 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1456 }
1458 auto ret_or_err = EvaluateBinarySubtraction(lhs, rhs, node.GetLocation());
1459 if (!ret_or_err)
1460 return ret_or_err;
1461 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1462 }
1464 auto ret_or_err =
1465 EvaluateBinaryMultiplication(lhs, rhs, node.GetLocation());
1466 if (!ret_or_err)
1467 return ret_or_err;
1468 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1469 }
1471 auto ret_or_err = EvaluateBinaryDivision(lhs, rhs, node.GetLocation());
1472 if (!ret_or_err)
1473 return ret_or_err;
1474 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1475 }
1477 auto ret_or_err = EvaluateBinaryRemainder(lhs, rhs, node.GetLocation());
1478 if (!ret_or_err)
1479 return ret_or_err;
1480 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1481 }
1483 auto ret_or_err =
1485 if (!ret_or_err)
1486 return ret_or_err;
1487 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1488 }
1490 auto ret_or_err =
1492 if (!ret_or_err)
1493 return ret_or_err;
1494 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1495 }
1497 auto ret_or_err =
1499 if (!ret_or_err)
1500 return ret_or_err;
1501 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1502 }
1504 auto ret_or_err =
1506 if (!ret_or_err)
1507 return ret_or_err;
1508 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1509 }
1511 auto ret_or_err =
1513 if (!ret_or_err)
1514 return ret_or_err;
1515 return EvaluateAssignment(lhs, *ret_or_err, node.GetLocation());
1516 }
1517 case BinaryOpKind::EQ:
1518 case BinaryOpKind::NE:
1519 case BinaryOpKind::LT:
1520 case BinaryOpKind::LE:
1521 case BinaryOpKind::GT:
1522 case BinaryOpKind::GE:
1523 return EvaluateComparison(node.GetKind(), lhs, rhs, lhs_is_literal,
1524 rhs_is_literal, node.GetLocation());
1525 default:
1526 break;
1527 }
1528
1529 return llvm::make_error<DILDiagnosticError>(
1530 m_expr, "unimplemented binary operation", node.GetLocation());
1531}
1532
1533llvm::Expected<lldb::ValueObjectSP>
1535 if (std::optional<std::string> register_name = GetRegisterPathName(node)) {
1536 auto frame_sp = m_exe_ctx.GetFrameSP();
1537 lldb::RegisterContextSP reg_ctx_sp =
1538 frame_sp ? frame_sp->GetRegisterContext() : nullptr;
1539 if (reg_ctx_sp) {
1540 if (const RegisterInfo *reg_info =
1541 reg_ctx_sp->GetRegisterInfoByName(*register_name))
1543 m_exe_ctx.GetBestExecutionContextScope(), reg_ctx_sp, reg_info);
1544 }
1545 }
1546
1547 auto base_or_err = Evaluate(node.GetBase());
1548 if (!base_or_err)
1549 return base_or_err;
1550 bool expr_is_ptr = node.GetIsArrow();
1551 lldb::ValueObjectSP base = *base_or_err;
1552
1553 // Perform some basic type & correctness checking.
1554 if (node.GetIsArrow()) {
1555 // If we have a non-pointer type with a synthetic value then lets check
1556 // if we have a synthetic dereference specified.
1557 if (!base->IsPointerType() && base->HasSyntheticValue()) {
1558 Status deref_error;
1559 if (lldb::ValueObjectSP synth_deref_sp =
1560 base->GetSyntheticValue()->Dereference(deref_error);
1561 synth_deref_sp && deref_error.Success()) {
1562 base = std::move(synth_deref_sp);
1563 }
1564 if (!base || deref_error.Fail()) {
1565 std::string errMsg = llvm::formatv(
1566 "Failed to dereference synthetic value: {0}", deref_error);
1567 return llvm::make_error<DILDiagnosticError>(
1568 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1569 }
1570
1571 // Some synthetic plug-ins fail to set the error in Dereference
1572 if (!base) {
1573 std::string errMsg = "Failed to dereference synthetic value";
1574 return llvm::make_error<DILDiagnosticError>(
1575 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1576 }
1577 expr_is_ptr = false;
1578 }
1579 }
1580
1582 bool base_is_ptr = base->IsPointerType();
1583
1584 if (expr_is_ptr != base_is_ptr) {
1585 if (base_is_ptr) {
1586 std::string errMsg =
1587 llvm::formatv("member reference type {0} is a pointer; "
1588 "did you mean to use '->'?",
1589 base->GetCompilerType().TypeDescription());
1590 return llvm::make_error<DILDiagnosticError>(
1591 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1592 } else {
1593 std::string errMsg =
1594 llvm::formatv("member reference type {0} is not a pointer; "
1595 "did you mean to use '.'?",
1596 base->GetCompilerType().TypeDescription());
1597 return llvm::make_error<DILDiagnosticError>(
1598 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1599 }
1600 }
1601 }
1602
1603 lldb::ValueObjectSP field_obj =
1604 base->GetChildMemberWithName(node.GetFieldName());
1605 if (!field_obj) {
1606 if (m_use_synthetic) {
1607 field_obj = base->GetSyntheticValue();
1608 if (field_obj)
1609 field_obj = field_obj->GetChildMemberWithName(node.GetFieldName());
1610 }
1611
1612 if (!m_use_synthetic || !field_obj) {
1613 std::string errMsg = llvm::formatv(
1614 "\"{0}\" is not a member of \"({1}) {2}\"", node.GetFieldName(),
1615 base->GetTypeName().AsCString("<invalid type>"), base->GetName());
1616 return llvm::make_error<DILDiagnosticError>(
1617 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1618 }
1619 }
1620
1621 if (field_obj) {
1623 lldb::ValueObjectSP dynamic_val_sp =
1624 field_obj->GetDynamicValue(m_use_dynamic);
1625 if (dynamic_val_sp)
1626 field_obj = dynamic_val_sp;
1627 }
1628 return field_obj;
1629 }
1630
1631 CompilerType base_type = base->GetCompilerType();
1632 if (node.GetIsArrow() && base->IsPointerType())
1633 base_type = base_type.GetPointeeType();
1634 std::string errMsg = llvm::formatv(
1635 "\"{0}\" is not a member of \"({1}) {2}\"", node.GetFieldName(),
1636 base->GetTypeName().AsCString("<invalid type>"), base->GetName());
1637 return llvm::make_error<DILDiagnosticError>(
1638 m_expr, errMsg, node.GetLocation(), node.GetFieldName().size());
1639}
1640
1641llvm::Expected<lldb::ValueObjectSP>
1643 auto idx_or_err = EvaluateAndDereference(node.GetIndex());
1644 if (!idx_or_err)
1645 return idx_or_err;
1646 lldb::ValueObjectSP idx = *idx_or_err;
1647
1648 if (!idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
1649 return llvm::make_error<DILDiagnosticError>(
1650 m_expr, "array subscript is not an integer", node.GetLocation());
1651 }
1652
1653 StreamString var_expr_path_strm;
1654 uint64_t child_idx = idx->GetValueAsUnsigned(0);
1655 lldb::ValueObjectSP child_valobj_sp;
1656
1657 auto base_or_err = Evaluate(node.GetBase());
1658 if (!base_or_err)
1659 return base_or_err;
1660 lldb::ValueObjectSP base = *base_or_err;
1661
1662 CompilerType base_type = base->GetCompilerType().GetNonReferenceType();
1663 base->GetExpressionPath(var_expr_path_strm);
1664 if (base->GetValueType() == lldb::eValueTypeRegister &&
1665 !base_type.IsPointerType() &&
1666 child_idx > std::numeric_limits<uint32_t>::max()) {
1667 std::string err_msg = llvm::formatv(
1668 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1669 base->GetTypeName().AsCString("<invalid type>"),
1670 var_expr_path_strm.GetData());
1671 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1672 node.GetLocation());
1673 }
1674
1675 bool is_incomplete_array = false;
1676 if (base_type.IsPointerType()) {
1677 bool is_objc_pointer = true;
1678
1679 if (base->GetCompilerType().GetMinimumLanguage() != lldb::eLanguageTypeObjC)
1680 is_objc_pointer = false;
1681 else if (!base->GetCompilerType().IsPointerType())
1682 is_objc_pointer = false;
1683
1684 if (!m_use_synthetic && is_objc_pointer) {
1685 std::string err_msg = llvm::formatv(
1686 "\"({0}) {1}\" is an Objective-C pointer, and cannot be subscripted",
1687 base->GetTypeName().AsCString("<invalid type>"),
1688 var_expr_path_strm.GetData());
1689 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1690 node.GetLocation());
1691 }
1692 if (is_objc_pointer) {
1693 lldb::ValueObjectSP synthetic = base->GetSyntheticValue();
1694 if (!synthetic || synthetic == base) {
1695 std::string err_msg =
1696 llvm::formatv("\"({0}) {1}\" is not an array type",
1697 base->GetTypeName().AsCString("<invalid type>"),
1698 var_expr_path_strm.GetData());
1699 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1700 node.GetLocation());
1701 }
1702 if (static_cast<uint32_t>(child_idx) >=
1703 synthetic->GetNumChildrenIgnoringErrors()) {
1704 std::string err_msg = llvm::formatv(
1705 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1706 base->GetTypeName().AsCString("<invalid type>"),
1707 var_expr_path_strm.GetData());
1708 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1709 node.GetLocation());
1710 }
1711 child_valobj_sp = synthetic->GetChildAtIndex(child_idx);
1712 if (!child_valobj_sp) {
1713 std::string err_msg = llvm::formatv(
1714 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1715 base->GetTypeName().AsCString("<invalid type>"),
1716 var_expr_path_strm.GetData());
1717 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1718 node.GetLocation());
1719 }
1721 if (auto dynamic_sp = child_valobj_sp->GetDynamicValue(m_use_dynamic))
1722 child_valobj_sp = std::move(dynamic_sp);
1723 }
1724 return child_valobj_sp;
1725 }
1726
1727 child_valobj_sp = base->GetSyntheticArrayMember(child_idx, true);
1728 if (!child_valobj_sp) {
1729 std::string err_msg = llvm::formatv(
1730 "failed to use pointer as array for index {0} for "
1731 "\"({1}) {2}\"",
1732 child_idx, base->GetTypeName().AsCString("<invalid type>"),
1733 var_expr_path_strm.GetData());
1734 if (base_type.IsPointerToVoid())
1735 err_msg = "subscript of pointer to incomplete type 'void'";
1736 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1737 node.GetLocation());
1738 }
1739 } else if (base_type.IsArrayType(nullptr, nullptr, &is_incomplete_array) ||
1740 base_type.IsVectorType()) {
1741 child_valobj_sp = base->GetChildAtIndex(child_idx);
1742 if (!child_valobj_sp && (is_incomplete_array || m_use_synthetic))
1743 child_valobj_sp = base->GetSyntheticArrayMember(child_idx, true);
1744 if (!child_valobj_sp) {
1745 std::string err_msg = llvm::formatv(
1746 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1747 base->GetTypeName().AsCString("<invalid type>"),
1748 var_expr_path_strm.GetData());
1749 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1750 node.GetLocation());
1751 }
1752 } else if (base_type.IsScalarType()) {
1753 child_valobj_sp =
1754 base->GetSyntheticBitFieldChild(child_idx, child_idx, true);
1755 if (!child_valobj_sp) {
1756 std::string err_msg = llvm::formatv(
1757 "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", child_idx,
1758 child_idx, base->GetTypeName().AsCString("<invalid type>"),
1759 var_expr_path_strm.GetData());
1760 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1761 node.GetLocation(), 1);
1762 }
1763 } else {
1764 lldb::ValueObjectSP synthetic = base->GetSyntheticValue();
1765 if (!m_use_synthetic || !synthetic || synthetic == base) {
1766 std::string err_msg =
1767 llvm::formatv("\"{0}\" is not an array type",
1768 base->GetTypeName().AsCString("<invalid type>"));
1769 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1770 node.GetLocation(), 1);
1771 }
1772 if (static_cast<uint32_t>(child_idx) >=
1773 synthetic->GetNumChildrenIgnoringErrors(child_idx + 1)) {
1774 std::string err_msg = llvm::formatv(
1775 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1776 base->GetTypeName().AsCString("<invalid type>"),
1777 var_expr_path_strm.GetData());
1778 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1779 node.GetLocation(), 1);
1780 }
1781 child_valobj_sp = synthetic->GetChildAtIndex(child_idx);
1782 if (!child_valobj_sp) {
1783 std::string err_msg = llvm::formatv(
1784 "array index {0} is not valid for \"({1}) {2}\"", child_idx,
1785 base->GetTypeName().AsCString("<invalid type>"),
1786 var_expr_path_strm.GetData());
1787 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(err_msg),
1788 node.GetLocation(), 1);
1789 }
1790 }
1791
1792 if (child_valobj_sp) {
1794 if (auto dynamic_sp = child_valobj_sp->GetDynamicValue(m_use_dynamic))
1795 child_valobj_sp = std::move(dynamic_sp);
1796 }
1797 return child_valobj_sp;
1798 }
1799
1800 bool success;
1801 int64_t signed_child_idx = idx->GetValueAsSigned(0, &success);
1802 if (!success)
1803 return llvm::make_error<DILDiagnosticError>(
1804 m_expr, "could not get the index as an integer",
1805 node.GetIndex().GetLocation());
1806 return base->GetSyntheticArrayMember(signed_child_idx, true);
1807}
1808
1809llvm::Expected<lldb::ValueObjectSP>
1811 auto first_idx_or_err = EvaluateAndDereference(node.GetFirstIndex());
1812 if (!first_idx_or_err)
1813 return first_idx_or_err;
1814 lldb::ValueObjectSP first_idx = *first_idx_or_err;
1815 auto last_idx_or_err = EvaluateAndDereference(node.GetLastIndex());
1816 if (!last_idx_or_err)
1817 return last_idx_or_err;
1818 lldb::ValueObjectSP last_idx = *last_idx_or_err;
1819
1820 if (!first_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType() ||
1821 !last_idx->GetCompilerType().IsIntegerOrUnscopedEnumerationType()) {
1822 return llvm::make_error<DILDiagnosticError>(
1823 m_expr, "bit index is not an integer", node.GetLocation());
1824 }
1825
1826 bool success_first, success_last;
1827 int64_t first_index = first_idx->GetValueAsSigned(0, &success_first);
1828 int64_t last_index = last_idx->GetValueAsSigned(0, &success_last);
1829 if (!success_first || !success_last)
1830 return llvm::make_error<DILDiagnosticError>(
1831 m_expr, "could not get the index as an integer", node.GetLocation());
1832
1833 // Reject negative indices before the swap below, so the diagnostic reports
1834 // the range as the user wrote it. A negative index would also wrap to a huge
1835 // offset in the uint32_t GetSyntheticBitFieldChild call below.
1836 if (first_index < 0 || last_index < 0) {
1837 std::string message =
1838 llvm::formatv("bitfield range {0}:{1} is not valid (negative index)",
1839 first_index, last_index);
1840 return llvm::make_error<DILDiagnosticError>(m_expr, message,
1841 node.GetLocation());
1842 }
1843
1844 // if the format given is [high-low], swap range
1845 if (first_index > last_index)
1846 std::swap(first_index, last_index);
1847
1848 // GetMaxU64Bitfield in the data layer only supports up to 64 bits (it asserts
1849 // bitfield_bit_size <= 64 and otherwise shifts out of bounds), so reject a
1850 // wider range here.
1851 if (last_index - first_index >= 64) {
1852 std::string message =
1853 llvm::formatv("bitfield range {0}:{1} is not valid (more than 64 bits)",
1854 first_index, last_index);
1855 return llvm::make_error<DILDiagnosticError>(m_expr, message,
1856 node.GetLocation());
1857 }
1858
1859 auto base_or_err = EvaluateAndDereference(node.GetBase());
1860 if (!base_or_err)
1861 return base_or_err;
1862 lldb::ValueObjectSP base = *base_or_err;
1863
1864 // The high index must lie within the base object's storage; a bit index past
1865 // its bit size shifts out of bounds when the child is later read or formatted
1866 // (GetMaxU64Bitfield).
1867 llvm::Expected<uint64_t> base_bit_size = base->GetCompilerType().GetBitSize(
1868 m_exe_ctx.GetBestExecutionContextScope());
1869 if (!base_bit_size)
1870 return base_bit_size.takeError();
1871 if (static_cast<uint64_t>(last_index) >= *base_bit_size) {
1872 std::string message = llvm::formatv(
1873 "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", first_index,
1874 last_index, base->GetTypeName().AsCString("<invalid type>"),
1875 base->GetName().GetStringRef());
1876 return llvm::make_error<DILDiagnosticError>(m_expr, message,
1877 node.GetLocation());
1878 }
1879
1880 lldb::ValueObjectSP child_valobj_sp =
1881 base->GetSyntheticBitFieldChild(first_index, last_index, true);
1882 if (!child_valobj_sp) {
1883 std::string message = llvm::formatv(
1884 "bitfield range {0}:{1} is not valid for \"({2}) {3}\"", first_index,
1885 last_index, base->GetTypeName().AsCString("<invalid type>"),
1886 base->GetName().GetStringRef());
1887 return llvm::make_error<DILDiagnosticError>(m_expr, message,
1888 node.GetLocation());
1889 }
1890 return child_valobj_sp;
1891}
1892
1893llvm::Expected<CompilerType>
1895 ExecutionContext &exe_ctx,
1896 const IntegerLiteralNode &literal) {
1897 // Binary, Octal, Hexadecimal and literals with a U suffix are allowed to be
1898 // an unsigned integer.
1899 bool unsigned_is_allowed = literal.IsUnsigned() || literal.GetRadix() != 10;
1900 llvm::APInt apint = literal.GetValue();
1901
1902 llvm::SmallVector<std::pair<lldb::BasicType, lldb::BasicType>, 3> candidates;
1903 if (literal.GetTypeSuffix() <= IntegerTypeSuffix::None)
1904 candidates.emplace_back(lldb::eBasicTypeInt,
1905 unsigned_is_allowed ? lldb::eBasicTypeUnsignedInt
1907 if (literal.GetTypeSuffix() <= IntegerTypeSuffix::Long)
1908 candidates.emplace_back(lldb::eBasicTypeLong,
1909 unsigned_is_allowed ? lldb::eBasicTypeUnsignedLong
1911 candidates.emplace_back(lldb::eBasicTypeLongLong,
1913 for (auto [signed_, unsigned_] : candidates) {
1914 CompilerType signed_type = type_system->GetBasicTypeFromAST(signed_);
1915 if (!signed_type)
1916 continue;
1917 llvm::Expected<uint64_t> size =
1918 signed_type.GetBitSize(exe_ctx.GetBestExecutionContextScope());
1919 if (!size)
1920 return size.takeError();
1921 if (!literal.IsUnsigned() && apint.isIntN(*size - 1))
1922 return signed_type;
1923 if (unsigned_ != lldb::eBasicTypeInvalid && apint.isIntN(*size))
1924 return type_system->GetBasicTypeFromAST(unsigned_);
1925 }
1926
1927 return llvm::make_error<DILDiagnosticError>(
1928 m_expr,
1929 "integer literal is too large to be represented in any integer type",
1930 literal.GetLocation());
1931}
1932
1933llvm::Expected<lldb::ValueObjectSP>
1935 llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
1936 if (!type_system)
1937 return type_system.takeError();
1938
1939 llvm::Expected<CompilerType> type =
1940 PickIntegerType(*type_system, m_exe_ctx, node);
1941 if (!type)
1942 return type.takeError();
1943
1944 Scalar scalar = node.GetValue();
1945 // APInt from StringRef::getAsInteger comes with just enough bitwidth to
1946 // hold the value. This adjusts APInt bitwidth to match the compiler type.
1947 llvm::Expected<uint64_t> type_bitsize =
1948 type->GetBitSize(m_exe_ctx.GetBestExecutionContextScope());
1949 if (!type_bitsize)
1950 return type_bitsize.takeError();
1951 // Literal itself cannot be a negative value, so we do an unsigned extension.
1952 scalar.TruncOrExtendTo(*type_bitsize, false);
1953 // If the picked compiler type is signed, make the scalar signed as well.
1954 if (type->IsSigned())
1955 scalar.MakeSigned();
1957 "result");
1958}
1959
1960llvm::Expected<lldb::ValueObjectSP>
1962 llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
1963 if (!type_system)
1964 return type_system.takeError();
1965
1966 bool isFloat =
1967 &node.GetValue().getSemantics() == &llvm::APFloat::IEEEsingle();
1968 lldb::BasicType basic_type =
1970 CompilerType type = GetBasicType(*type_system, basic_type);
1971
1972 if (!type)
1973 return llvm::make_error<DILDiagnosticError>(
1974 m_expr, "unable to create a const literal", node.GetLocation());
1975
1976 Scalar scalar = node.GetValue();
1978 "result");
1979}
1980
1981llvm::Expected<lldb::ValueObjectSP>
1983 bool value = node.GetValue();
1984 llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
1985 if (!type_system)
1986 return type_system.takeError();
1987 return ValueObject::CreateValueObjectFromBool(m_exe_ctx, *type_system, value,
1988 "result");
1989}
1990
1991llvm::Expected<CastKind>
1993 CompilerType target_type, int location) {
1994 if (source_type.IsPointerType() || source_type.IsNullPtrType()) {
1995 // Cast from pointer to float/double is not allowed.
1996 if (target_type.GetTypeInfo() & lldb::eTypeIsFloat) {
1997 std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
1998 source_type.TypeDescription(),
1999 target_type.TypeDescription());
2000 return llvm::make_error<DILDiagnosticError>(
2001 m_expr, std::move(errMsg), location,
2002 source_type.TypeDescription().length());
2003 }
2004
2005 // Casting from pointer to bool is always valid.
2006 if (target_type.IsBoolean())
2007 return CastKind::eArithmetic;
2008
2009 // Otherwise check if the result type is at least as big as the pointer
2010 // size.
2011 uint64_t type_byte_size = 0;
2012 uint64_t rhs_type_byte_size = 0;
2013 if (auto temp =
2014 target_type.GetByteSize(m_exe_ctx.GetBestExecutionContextScope())) {
2015 type_byte_size = *temp;
2016 } else {
2017 std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
2018 target_type.TypeDescription());
2019 LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), temp.takeError(),
2020 "GetByteSize failed: {0}");
2021 return llvm::make_error<DILDiagnosticError>(
2022 m_expr, std::move(errMsg), location,
2023 target_type.TypeDescription().length());
2024 }
2025
2026 if (auto temp =
2027 source_type.GetByteSize(m_exe_ctx.GetBestExecutionContextScope())) {
2028 rhs_type_byte_size = *temp;
2029 } else {
2030 std::string errMsg = llvm::formatv("unable to get byte size for type {0}",
2031 source_type.TypeDescription());
2032 LLDB_LOG_ERROR(GetLog(LLDBLog::Expressions), temp.takeError(),
2033 "GetByteSize failed: {0}");
2034 return llvm::make_error<DILDiagnosticError>(
2035 m_expr, std::move(errMsg), location,
2036 source_type.TypeDescription().length());
2037 }
2038
2039 if (type_byte_size < rhs_type_byte_size) {
2040 std::string errMsg = llvm::formatv(
2041 "cast from pointer to smaller type {0} loses information",
2042 target_type.TypeDescription());
2043 return llvm::make_error<DILDiagnosticError>(
2044 m_expr, std::move(errMsg), location,
2045 source_type.TypeDescription().length());
2046 }
2047 } else if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
2048 // Otherwise accept only arithmetic types and enums.
2049 std::string errMsg = llvm::formatv("cannot convert {0} to {1}",
2050 source_type.TypeDescription(),
2051 target_type.TypeDescription());
2052
2053 return llvm::make_error<DILDiagnosticError>(
2054 m_expr, std::move(errMsg), location,
2055 source_type.TypeDescription().length());
2056 }
2057 return CastKind::eArithmetic;
2058}
2059
2060llvm::Expected<CastKind>
2062 CompilerType source_type, CompilerType target_type,
2063 int location) {
2064
2065 if (target_type.IsScalarType())
2066 return VerifyArithmeticCast(source_type, target_type, location);
2067
2068 if (target_type.IsEnumerationType()) {
2069 // Cast to enum type.
2070 if (!source_type.IsScalarType() && !source_type.IsEnumerationType()) {
2071 std::string errMsg = llvm::formatv("Cast from {0} to {1} is not allowed",
2072 source_type.TypeDescription(),
2073 target_type.TypeDescription());
2074
2075 return llvm::make_error<DILDiagnosticError>(
2076 m_expr, std::move(errMsg), location,
2077 source_type.TypeDescription().length());
2078 }
2080 }
2081
2082 if (target_type.IsPointerType()) {
2083 if (!source_type.IsInteger() && !source_type.IsEnumerationType() &&
2084 !source_type.IsArrayType() && !source_type.IsPointerType() &&
2085 !source_type.IsNullPtrType()) {
2086 std::string errMsg = llvm::formatv(
2087 "cannot cast from type {0} to pointer type {1}",
2088 source_type.TypeDescription(), target_type.TypeDescription());
2089
2090 return llvm::make_error<DILDiagnosticError>(
2091 m_expr, std::move(errMsg), location,
2092 source_type.TypeDescription().length());
2093 }
2094 return CastKind::ePointer;
2095 }
2096
2097 // Unsupported cast.
2098 std::string errMsg = llvm::formatv(
2099 "casting of {0} to {1} is not implemented yet",
2100 source_type.TypeDescription(), target_type.TypeDescription());
2101 return llvm::make_error<DILDiagnosticError>(
2102 m_expr, std::move(errMsg), location,
2103 source_type.TypeDescription().length());
2104}
2105
2106llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const CastNode &node) {
2107 auto operand_or_err = Evaluate(node.GetOperand());
2108
2109 if (!operand_or_err)
2110 return operand_or_err;
2111
2112 lldb::ValueObjectSP operand = *operand_or_err;
2113 CompilerType op_type = operand->GetCompilerType();
2114 CompilerType target_type = node.GetType();
2115
2116 if (op_type.IsReferenceType())
2117 op_type = op_type.GetNonReferenceType();
2118 if (target_type.IsScalarType() && op_type.IsArrayType()) {
2119 operand = ArrayToPointerConversion(*operand, m_exe_ctx,
2120 operand->GetName().GetStringRef());
2121 op_type = operand->GetCompilerType();
2122 }
2123 auto type_or_err =
2124 VerifyCastType(operand, op_type, target_type, node.GetLocation());
2125 if (!type_or_err)
2126 return type_or_err.takeError();
2127
2128 CastKind cast_kind = *type_or_err;
2129 if (operand->GetCompilerType().IsReferenceType()) {
2130 Status error;
2131 operand = operand->Dereference(error);
2132 if (error.Fail())
2133 return llvm::make_error<DILDiagnosticError>(m_expr, error.AsCString(),
2134 node.GetLocation());
2135 }
2136
2137 lldb::ValueObjectSP result;
2138 switch (cast_kind) {
2140 // FIXME: is this correct for float vector types?
2141 if (op_type.GetTypeInfo() & lldb::eTypeIsFloat || op_type.IsInteger() ||
2142 op_type.IsEnumerationType())
2143 result = operand->CastToEnumType(target_type);
2144 break;
2145 }
2146 case CastKind::eArithmetic: {
2147 if (op_type.IsPointerType() || op_type.IsNullPtrType() ||
2148 op_type.IsScalarType() || op_type.IsEnumerationType())
2149 result = operand->CastToBasicType(target_type);
2150 break;
2151 }
2152 case CastKind::ePointer: {
2153 uint64_t addr = op_type.IsArrayType()
2154 ? operand->GetLoadAddress()
2155 : (op_type.IsSigned() ? operand->GetValueAsSigned(0)
2156 : operand->GetValueAsUnsigned(0));
2157 result = ValueObject::CreateValueObjectFromAddress("result", addr,
2158 m_exe_ctx, target_type,
2159 /* do_deref */ false);
2160 break;
2161 }
2162 case CastKind::eNone: {
2163 return lldb::ValueObjectSP();
2164 }
2165 } // switch
2166
2167 if (result) {
2168 // If cast failed, retrieve the error message from the result.
2169 if (result->GetError().Fail())
2170 return llvm::make_error<DILDiagnosticError>(
2171 m_expr, result->GetError().AsCString(), node.GetLocation());
2172 return result;
2173 }
2174
2175 std::string errMsg =
2176 llvm::formatv("unable to cast from '{0}' to '{1}'",
2177 op_type.TypeDescription(), target_type.TypeDescription());
2178 return llvm::make_error<DILDiagnosticError>(m_expr, std::move(errMsg),
2179 node.GetLocation());
2180}
2181
2182llvm::Expected<lldb::ValueObjectSP>
2184 auto cond_or_err = EvaluateAndDereference(node.GetCondition());
2185 if (!cond_or_err)
2186 return cond_or_err;
2187 lldb::ValueObjectSP condition = *cond_or_err;
2188
2189 CompilerType cond_type = condition->GetCompilerType();
2190 if (!cond_type.IsContextuallyConvertibleToBool()) {
2191 std::string errMsg = llvm::formatv(
2192 "value of type {0} is not contextually convertible to 'bool'",
2193 cond_type.TypeDescription());
2194 return llvm::make_error<DILDiagnosticError>(m_expr, errMsg,
2195 node.GetLocation());
2196 }
2197 // Note: DIL evaluates only the operand chosen by the condition,
2198 // and doesn't check the type or evaluate the other operand.
2199 auto value_or_err = condition->GetValueAsBool();
2200 if (value_or_err) {
2201 if (*value_or_err) {
2202 auto true_or_err = EvaluateAndDereference(node.GetTrueOperand());
2203 if (!true_or_err)
2204 return true_or_err;
2205 return *true_or_err;
2206 }
2207 auto false_or_err = EvaluateAndDereference(node.GetFalseOperand());
2208 if (!false_or_err)
2209 return false_or_err;
2210 return *false_or_err;
2211 }
2212 return value_or_err.takeError();
2213}
2214
2215llvm::Expected<lldb::ValueObjectSP> Interpreter::Visit(const SizeOfNode &node) {
2216 CompilerType typearg = node.GetTypeArg();
2217 Scalar size;
2218 if (typearg.IsValid()) {
2219 if (typearg.IsReferenceType())
2220 typearg = typearg.GetNonReferenceType();
2221 llvm::Expected<uint64_t> byte_size =
2222 typearg.GetByteSize(m_exe_ctx.GetTargetSP().get());
2223 if (!byte_size)
2224 return byte_size.takeError();
2225 size = *byte_size;
2226 } else {
2227 auto arg_or_err = EvaluateAndDereference(node.GetNodeArg());
2228 if (!arg_or_err)
2229 return arg_or_err;
2230 lldb::ValueObjectSP arg = *arg_or_err;
2231
2232 if (arg->IsBitfield())
2233 return llvm::make_error<DILDiagnosticError>(
2234 m_expr, "invalid application of 'sizeof' to bit-field",
2235 node.GetLocation());
2236
2237 llvm::Expected<uint64_t> byte_size = arg->GetByteSize();
2238 if (!byte_size)
2239 return byte_size.takeError();
2240 size = *byte_size;
2241 }
2242
2243 llvm::Expected<lldb::TypeSystemSP> type_system = GetTypeSystemFromCU();
2244 if (!type_system)
2245 return type_system.takeError();
2246 CompilerType size_type = type_system.get()->GetSizeType();
2247 if (!size_type)
2248 return llvm::make_error<DILDiagnosticError>(
2249 m_expr, "unable to determine size type", node.GetLocation());
2250
2252 "result");
2253}
2254
2255} // namespace lldb_private::dil
static llvm::raw_ostream & error(Stream &strm)
#define LLDB_LOG(log,...)
The LLDB_LOG* macros defined below are the way to emit log messages.
Definition Log.h:375
#define LLDB_LOG_ERROR(log, error,...)
Definition Log.h:405
static llvm::StringRef GetName(XcodeSDK::Type type)
Definition XcodeSDK.cpp:21
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
bool IsScalarOrUnscopedEnumerationType() 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.
bool IsIntegerOrEnumerationType(bool &is_signed) const
bool IsScopedEnumerationType() const
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 GetFullyUnqualifiedType() const
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.
bool IsVectorType(CompilerType *element_type=nullptr, uint64_t *size=nullptr) const
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/ExecutionContext.h" A class that contains an execution context.
ExecutionContextScope * GetBestExecutionContextScope() const
const lldb::TargetSP & GetTargetSP() const
Get accessor to get the target shared pointer.
const lldb::StackFrameSP & GetFrameSP() const
Get accessor to get the frame shared pointer.
void TruncOrExtendTo(uint16_t bits, bool sign)
Convert to an integer with bits and the given signedness.
Definition Scalar.cpp:205
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:105
uint32_t GetLocation() const
Definition DILAST.h:115
NodeKind GetKind() const
Definition DILAST.h:116
virtual bool IsConstLiteral() const
Definition DILAST.h:113
virtual llvm::Expected< lldb::ValueObjectSP > Accept(Visitor *v) const =0
ASTNode & GetLHS() const
Definition DILAST.h:205
BinaryOpKind GetKind() const
Definition DILAST.h:204
ASTNode & GetRHS() const
Definition DILAST.h:206
ASTNode & GetOperand() const
Definition DILAST.h:338
CompilerType GetType() const
Definition DILAST.h:337
ASTNode & GetFalseOperand() const
Definition DILAST.h:363
ASTNode & GetTrueOperand() const
Definition DILAST.h:362
ASTNode & GetCondition() const
Definition DILAST.h:361
const llvm::APFloat & GetValue() const
Definition DILAST.h:300
std::string GetName() const
Definition DILAST.h:142
IntegerTypeSuffix GetTypeSuffix() const
Definition DILAST.h:278
const llvm::APInt & GetValue() const
Definition DILAST.h:275
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryRemainder(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:1027
llvm::Error ValidateComparison(BinaryOpKind kind, lldb::ValueObjectSP &lhs, lldb::ValueObjectSP &rhs, bool lhs_is_literal, bool rhs_is_literal, uint32_t location)
Definition DILEval.cpp:1119
llvm::Expected< lldb::ValueObjectSP > Evaluate(const ASTNode &node)
Evaluate an ASTNode.
Definition DILEval.cpp:537
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryAddition(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:862
llvm::Expected< lldb::ValueObjectSP > EvaluateAndDereference(const ASTNode &node)
Evaluate an ASTNode.
Definition DILEval.cpp:550
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:764
llvm::Expected< lldb::ValueObjectSP > EvaluateScalarOp(BinaryOpKind kind, lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, CompilerType result_type, uint32_t location)
Definition DILEval.cpp:800
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:253
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryShift(BinaryOpKind kind, lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:1309
llvm::Expected< lldb::ValueObjectSP > EvaluateLogical(const BinaryOpNode &node)
Definition DILEval.cpp:1350
llvm::Expected< lldb::ValueObjectSP > EvaluateTree(const ASTNodeUP &tree)
Evaluate an ASTNode tree.
Definition DILEval.cpp:522
Interpreter(ExecutionContext &exe_ctx, llvm::StringRef expr, lldb::DynamicValueType use_dynamic, uint32_t options)
Definition DILEval.cpp:502
llvm::Expected< lldb::ValueObjectSP > EvaluateBinarySubtraction(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:900
llvm::Expected< lldb::ValueObjectSP > UnaryConversion(lldb::ValueObjectSP valobj, uint32_t location)
Perform usual unary conversions on a value.
Definition DILEval.cpp:123
llvm::Expected< lldb::ValueObjectSP > EvaluateComparison(BinaryOpKind kind, lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, bool lhs_is_literal, bool rhs_is_literal, uint32_t location)
Definition DILEval.cpp:1263
llvm::Expected< lldb::ValueObjectSP > Visit(const IdentifierNode &node) override
Definition DILEval.cpp:566
llvm::Expected< lldb::LanguageType > GetSourceLanguageFromCU()
Retrieve the LanguageType from the compile unit of the current frame.
Definition DILEval.cpp:68
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryDivision(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:999
lldb::DynamicValueType m_use_dynamic
Definition DILEval.h:185
llvm::Expected< CompilerType > PickIntegerType(lldb::TypeSystemSP type_system, ExecutionContext &ext_ctx, const IntegerLiteralNode &literal)
Definition DILEval.cpp:1894
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:281
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryMultiplication(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:977
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:2061
llvm::Expected< lldb::ValueObjectSP > EvaluateAssignment(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:1094
llvm::Expected< CastKind > VerifyArithmeticCast(CompilerType source_type, CompilerType target_type, int location)
A helper function for VerifyCastType (below).
Definition DILEval.cpp:1992
llvm::Expected< lldb::TypeSystemSP > GetTypeSystemFromCU()
Retrieve the TypeSystem from the compile unit of the current frame.
Definition DILEval.cpp:77
llvm::Expected< lldb::ValueObjectSP > EvaluateBinaryBitwise(BinaryOpKind kind, lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location)
Definition DILEval.cpp:1287
ExecutionContext m_exe_ctx
Definition DILEval.h:182
llvm::StringRef GetFieldName() const
Definition DILAST.h:163
ASTNode & GetBase() const
Definition DILAST.h:161
ASTNode & GetNodeArg() const
Definition DILAST.h:385
CompilerType GetTypeArg() const
Definition DILAST.h:386
UnaryOpKind GetKind() const
Definition DILAST.h:183
ASTNode & GetOperand() const
Definition DILAST.h:184
CastKind
The type casts allowed by DIL.
Definition DILAST.h:84
@ eEnumeration
Casting from a scalar to an enumeration type.
Definition DILAST.h:86
@ ePointer
Casting to a pointer type.
Definition DILAST.h:87
@ eNone
Invalid promotion type (results in error).
Definition DILAST.h:88
@ eArithmetic
Casting to a scalar.
Definition DILAST.h:85
static lldb::BasicType BasicTypeToUnsigned(lldb::BasicType basic_type)
Definition DILEval.cpp:232
static bool IsLiteralZero(lldb::ValueObjectSP &val, bool is_literal)
Definition DILEval.cpp:1112
static CompilerType GetBasicType(lldb::TypeSystemSP type_system, lldb::BasicType basic_type)
Definition DILEval.cpp:31
std::unique_ptr< ASTNode > ASTNodeUP
Definition DILAST.h:123
lldb::ValueObjectSP LookupPersistentIdentifier(llvm::StringRef name_ref, ExecutionContext &exe_ctx, lldb::LanguageType language)
Given the name of a persistent identifier (i.e., one that starts with a $), find the ValueObject for ...
Definition DILEval.cpp:409
BinaryOpKind
The binary operators recognized by DIL.
Definition DILAST.h:48
static llvm::Expected< bool > VerifyAssignmentTypes(CompilerType lhs_type, CompilerType rhs_type)
Definition DILEval.cpp:1058
static lldb::ValueObjectSP ArrayToPointerConversion(ValueObject &valobj, ExecutionContext &exe_ctx, llvm::StringRef name)
Definition DILEval.cpp:39
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:195
lldb::ValueObjectSP LookupGlobalIdentifier(llvm::StringRef name_ref, ExecutionContext &exe_ctx, 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:362
lldb::ValueObjectSP LookupIdentifier(llvm::StringRef name_ref, ExecutionContext &exe_ctx, lldb::DynamicValueType use_dynamic)
Given the name of an identifier (variable name, member name, type name, etc.), find the ValueObject f...
Definition DILEval.cpp:426
static lldb::VariableSP DILFindVariable(ConstString name, VariableList &variable_list)
Definition DILEval.cpp:337
static llvm::Expected< SymbolContext > GetSymbolContexFromFrame(ExecutionContext &exe_ctx)
Definition DILEval.cpp:52
static std::optional< std::string > GetRegisterPathName(const ASTNode &node)
Definition DILEval.cpp:101
static bool HasFloatingRepresentation(CompilerType ct)
Definition DILEval.cpp:1054
lldb::ValueObjectSP LookupEnumValue(llvm::StringRef name_ref, ExecutionContext &exe_ctx)
Given the name of an identifier, attempt to find an enumeration value.
Definition DILEval.cpp:477
CompilerType ResolveTypeByName(const std::string &name, ExecutionContext &exe_ctx)
Definition DILParser.cpp:61
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.
@ eLanguageTypeUnknown
Unknown or invalid language value.
@ eLanguageTypeObjC
Objective-C.
std::shared_ptr< lldb_private::VariableList > VariableListSP
std::shared_ptr< lldb_private::Variable > VariableSP
@ eValueTypeRegister
stack frame register value
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),...