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