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