llvmbot wrote:

<!--LLVM PR SUMMARY COMMENT-->

@llvm/pr-subscribers-lldb

Author: Ilia Kuklin (kuilpd)

<details>
<summary>Changes</summary>

A draft to discuss scalar literal node implementation

---

Patch is 26.08 KiB, truncated to 20.00 KiB below, full version: 
https://github.com/llvm/llvm-project/pull/147064.diff


8 Files Affected:

- (modified) lldb/include/lldb/ValueObject/DILAST.h (+58) 
- (modified) lldb/include/lldb/ValueObject/DILEval.h (+15) 
- (modified) lldb/include/lldb/ValueObject/DILLexer.h (+1) 
- (modified) lldb/include/lldb/ValueObject/DILParser.h (+3) 
- (modified) lldb/source/ValueObject/DILAST.cpp (+21) 
- (modified) lldb/source/ValueObject/DILEval.cpp (+405) 
- (modified) lldb/source/ValueObject/DILLexer.cpp (+6-4) 
- (modified) lldb/source/ValueObject/DILParser.cpp (+72-2) 


``````````diff
diff --git a/lldb/include/lldb/ValueObject/DILAST.h 
b/lldb/include/lldb/ValueObject/DILAST.h
index 709f0639135f1..a9d244031d55f 100644
--- a/lldb/include/lldb/ValueObject/DILAST.h
+++ b/lldb/include/lldb/ValueObject/DILAST.h
@@ -9,6 +9,7 @@
 #ifndef LLDB_VALUEOBJECT_DILAST_H
 #define LLDB_VALUEOBJECT_DILAST_H
 
+#include "lldb/ValueObject/DILLexer.h"
 #include "lldb/ValueObject/ValueObject.h"
 #include "llvm/Support/Error.h"
 #include <cstdint>
@@ -19,10 +20,12 @@ namespace lldb_private::dil {
 /// The various types DIL AST nodes (used by the DIL parser).
 enum class NodeKind {
   eArraySubscriptNode,
+  eBinaryOpNode,
   eBitExtractionNode,
   eErrorNode,
   eIdentifierNode,
   eMemberOfNode,
+  eScalarLiteralNode,
   eUnaryOpNode,
 };
 
@@ -32,6 +35,14 @@ enum class UnaryOpKind {
   Deref,  // "*"
 };
 
+enum class BinaryOpKind {
+  Add, // "+"
+  Sub, // "-"
+};
+
+/// Translates DIL tokens to BinaryOpKind.
+BinaryOpKind GetBinaryOpKindFromToken(Token::Kind token_kind);
+
 /// Forward declaration, for use in DIL AST nodes. Definition is at the very
 /// end of this file.
 class Visitor;
@@ -178,6 +189,49 @@ class BitFieldExtractionNode : public ASTNode {
   int64_t m_last_index;
 };
 
+class ScalarLiteralNode : public ASTNode {
+public:
+  ScalarLiteralNode(uint32_t location, lldb::BasicType type, Scalar value)
+      : ASTNode(location, NodeKind::eScalarLiteralNode), m_type(type),
+        m_value(value) {}
+
+  llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override;
+
+  lldb::BasicType GetType() const { return m_type; }
+  Scalar GetValue() const & { return m_value; }
+
+  static bool classof(const ASTNode *node) {
+    return node->GetKind() == NodeKind::eScalarLiteralNode;
+  }
+
+private:
+  lldb::BasicType m_type;
+  Scalar m_value;
+};
+
+class BinaryOpNode : public ASTNode {
+public:
+  BinaryOpNode(uint32_t location, BinaryOpKind kind, ASTNodeUP lhs,
+               ASTNodeUP rhs)
+      : ASTNode(location, NodeKind::eBinaryOpNode), m_kind(kind),
+        m_lhs(std::move(lhs)), m_rhs(std::move(rhs)) {}
+
+  llvm::Expected<lldb::ValueObjectSP> Accept(Visitor *v) const override;
+
+  BinaryOpKind GetKind() const { return m_kind; }
+  ASTNode *GetLHS() const { return m_lhs.get(); }
+  ASTNode *GetRHS() const { return m_rhs.get(); }
+
+  static bool classof(const ASTNode *node) {
+    return node->GetKind() == NodeKind::eBinaryOpNode;
+  }
+
+private:
+  BinaryOpKind m_kind;
+  ASTNodeUP m_lhs;
+  ASTNodeUP m_rhs;
+};
+
 /// This class contains one Visit method for each specialized type of
 /// DIL AST node. The Visit methods are used to dispatch a DIL AST node to
 /// the correct function in the DIL expression evaluator for evaluating that
@@ -195,6 +249,10 @@ class Visitor {
   Visit(const ArraySubscriptNode *node) = 0;
   virtual llvm::Expected<lldb::ValueObjectSP>
   Visit(const BitFieldExtractionNode *node) = 0;
+  virtual llvm::Expected<lldb::ValueObjectSP>
+  Visit(const ScalarLiteralNode *node) = 0;
+  virtual llvm::Expected<lldb::ValueObjectSP>
+  Visit(const BinaryOpNode *node) = 0;
 };
 
 } // namespace lldb_private::dil
diff --git a/lldb/include/lldb/ValueObject/DILEval.h 
b/lldb/include/lldb/ValueObject/DILEval.h
index 45e29b3ddcd7b..9e9028f6122fd 100644
--- a/lldb/include/lldb/ValueObject/DILEval.h
+++ b/lldb/include/lldb/ValueObject/DILEval.h
@@ -54,6 +54,21 @@ class Interpreter : Visitor {
   Visit(const ArraySubscriptNode *node) override;
   llvm::Expected<lldb::ValueObjectSP>
   Visit(const BitFieldExtractionNode *node) override;
+  llvm::Expected<lldb::ValueObjectSP>
+  Visit(const ScalarLiteralNode *node) override;
+  llvm::Expected<lldb::ValueObjectSP> Visit(const BinaryOpNode *node) override;
+
+  lldb::ValueObjectSP
+  ConvertValueObjectToTypeSystem(lldb::ValueObjectSP valobj,
+                                 lldb::TypeSystemSP type_system);
+
+  llvm::Error PrepareBinaryAddition(lldb::ValueObjectSP &lhs,
+                                    lldb::ValueObjectSP &rhs,
+                                    uint32_t location);
+
+  llvm::Expected<lldb::ValueObjectSP>
+  EvaluateBinaryAddition(lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs,
+                         uint32_t location);
 
   // Used by the interpreter to create objects, perform casts, etc.
   lldb::TargetSP m_target;
diff --git a/lldb/include/lldb/ValueObject/DILLexer.h 
b/lldb/include/lldb/ValueObject/DILLexer.h
index 9c1ba97680253..58059657bf3a5 100644
--- a/lldb/include/lldb/ValueObject/DILLexer.h
+++ b/lldb/include/lldb/ValueObject/DILLexer.h
@@ -34,6 +34,7 @@ class Token {
     minus,
     numeric_constant,
     period,
+    plus,
     r_paren,
     r_square,
     star,
diff --git a/lldb/include/lldb/ValueObject/DILParser.h 
b/lldb/include/lldb/ValueObject/DILParser.h
index 9eda7bac4a364..c57ef0cf28022 100644
--- a/lldb/include/lldb/ValueObject/DILParser.h
+++ b/lldb/include/lldb/ValueObject/DILParser.h
@@ -87,6 +87,7 @@ class DILParser {
   ASTNodeUP Run();
 
   ASTNodeUP ParseExpression();
+  ASTNodeUP ParseAdditiveExpression();
   ASTNodeUP ParseUnaryExpression();
   ASTNodeUP ParsePostfixExpression();
   ASTNodeUP ParsePrimaryExpression();
@@ -96,6 +97,8 @@ class DILParser {
   std::string ParseIdExpression();
   std::string ParseUnqualifiedId();
   std::optional<int64_t> ParseIntegerConstant();
+  ASTNodeUP ParseNumericLiteral();
+  ASTNodeUP ParseNumericConstant();
 
   void BailOut(const std::string &error, uint32_t loc, uint16_t err_len);
 
diff --git a/lldb/source/ValueObject/DILAST.cpp 
b/lldb/source/ValueObject/DILAST.cpp
index b1cd824c2299e..7aee692f2b28a 100644
--- a/lldb/source/ValueObject/DILAST.cpp
+++ b/lldb/source/ValueObject/DILAST.cpp
@@ -11,6 +11,18 @@
 
 namespace lldb_private::dil {
 
+BinaryOpKind GetBinaryOpKindFromToken(Token::Kind token_kind) {
+  switch (token_kind) {
+  case Token::minus:
+    return BinaryOpKind::Sub;
+  case Token::plus:
+    return BinaryOpKind::Add;
+  default:
+    break;
+  }
+  llvm_unreachable("Unknown binary operator kind.");
+}
+
 llvm::Expected<lldb::ValueObjectSP> ErrorNode::Accept(Visitor *v) const {
   llvm_unreachable("Attempting to Visit a DIL ErrorNode.");
 }
@@ -37,4 +49,13 @@ BitFieldExtractionNode::Accept(Visitor *v) const {
   return v->Visit(this);
 }
 
+llvm::Expected<lldb::ValueObjectSP>
+ScalarLiteralNode::Accept(Visitor *v) const {
+  return v->Visit(this);
+}
+
+llvm::Expected<lldb::ValueObjectSP> BinaryOpNode::Accept(Visitor *v) const {
+  return v->Visit(this);
+}
+
 } // namespace lldb_private::dil
diff --git a/lldb/source/ValueObject/DILEval.cpp 
b/lldb/source/ValueObject/DILEval.cpp
index 8ca9b4215985d..2e42b57e93042 100644
--- a/lldb/source/ValueObject/DILEval.cpp
+++ b/lldb/source/ValueObject/DILEval.cpp
@@ -7,7 +7,9 @@
 
//===----------------------------------------------------------------------===//
 
 #include "lldb/ValueObject/DILEval.h"
+#include "lldb/Core/Module.h"
 #include "lldb/Symbol/CompileUnit.h"
+#include "lldb/Symbol/TypeSystem.h"
 #include "lldb/Symbol/VariableList.h"
 #include "lldb/Target/RegisterContext.h"
 #include "lldb/ValueObject/DILAST.h"
@@ -401,4 +403,407 @@ Interpreter::Visit(const BitFieldExtractionNode *node) {
   return child_valobj_sp;
 }
 
+static CompilerType GetBasicTypeFromCU(std::shared_ptr<StackFrame> ctx,
+                                       lldb::BasicType basic_type) {
+  SymbolContext symbol_context =
+      ctx->GetSymbolContext(lldb::eSymbolContextCompUnit);
+  auto language = symbol_context.comp_unit->GetLanguage();
+
+  symbol_context = ctx->GetSymbolContext(lldb::eSymbolContextModule);
+  auto type_system =
+      symbol_context.module_sp->GetTypeSystemForLanguage(language);
+
+  if (type_system)
+    if (auto compiler_type = 
type_system.get()->GetBasicTypeFromAST(basic_type))
+      return compiler_type;
+
+  CompilerType empty_type;
+  return empty_type;
+}
+
+llvm::Expected<lldb::ValueObjectSP>
+Interpreter::Visit(const ScalarLiteralNode *node) {
+  CompilerType result_type =
+      GetBasicTypeFromCU(m_exe_ctx_scope, node->GetType());
+  Scalar value = node->GetValue();
+
+  // Scalar later could be float or bool
+  if (result_type.IsInteger() || result_type.IsNullPtrType() ||
+      result_type.IsPointerType()) {
+    llvm::APInt val = value.GetAPSInt();
+    return ValueObject::CreateValueObjectFromAPInt(m_target, val, result_type,
+                                                   "result");
+  }
+
+  return lldb::ValueObjectSP();
+}
+
+static CompilerType GetBasicType(lldb::TypeSystemSP type_system,
+                                 lldb::BasicType basic_type) {
+  if (type_system)
+    if (auto compiler_type = 
type_system.get()->GetBasicTypeFromAST(basic_type))
+      return compiler_type;
+
+  CompilerType empty_type;
+  return empty_type;
+}
+
+static CompilerType DoIntegralPromotion(CompilerType from,
+                                        std::shared_ptr<StackFrame> ctx) {
+  if (!from.IsInteger() && !from.IsUnscopedEnumerationType())
+    return from;
+
+  if (!from.IsPromotableIntegerType())
+    return from;
+
+  if (from.IsUnscopedEnumerationType())
+    return DoIntegralPromotion(from.GetEnumerationIntegerType(), ctx);
+  lldb::BasicType builtin_type =
+      from.GetCanonicalType().GetBasicTypeEnumeration();
+  lldb::TypeSystemSP type_system = from.GetTypeSystem().GetSharedPointer();
+
+  uint64_t from_size = 0;
+  if (builtin_type == lldb::eBasicTypeWChar ||
+      builtin_type == lldb::eBasicTypeSignedWChar ||
+      builtin_type == lldb::eBasicTypeUnsignedWChar ||
+      builtin_type == lldb::eBasicTypeChar16 ||
+      builtin_type == lldb::eBasicTypeChar32) {
+    // Find the type that can hold the entire range of values for our type.
+    bool is_signed = from.IsSigned();
+    if (auto temp = from.GetByteSize(ctx.get()))
+      from_size = *temp;
+
+    CompilerType promote_types[] = {
+        GetBasicType(type_system, lldb::eBasicTypeInt),
+        GetBasicType(type_system, lldb::eBasicTypeUnsignedInt),
+        GetBasicType(type_system, lldb::eBasicTypeLong),
+        GetBasicType(type_system, lldb::eBasicTypeUnsignedLong),
+        GetBasicType(type_system, lldb::eBasicTypeLongLong),
+        GetBasicType(type_system, lldb::eBasicTypeUnsignedLongLong),
+    };
+    for (auto &type : promote_types) {
+      uint64_t byte_size = 0;
+      if (auto temp = type.GetByteSize(ctx.get()))
+        byte_size = *temp;
+      if (from_size < byte_size ||
+          (from_size == byte_size &&
+           is_signed == (bool)(type.GetTypeInfo() & lldb::eTypeIsSigned))) {
+        return type;
+      }
+    }
+
+    llvm_unreachable("char type should fit into long long");
+  }
+
+  // Here we can promote only to "int" or "unsigned int".
+  CompilerType int_type = GetBasicType(type_system, lldb::eBasicTypeInt);
+  uint64_t int_byte_size = 0;
+  if (auto temp = int_type.GetByteSize(ctx.get()))
+    int_byte_size = *temp;
+
+  // Signed integer types can be safely promoted to "int".
+  if (from.IsSigned()) {
+    return int_type;
+  }
+  // Unsigned integer types are promoted to "unsigned int" if "int" cannot hold
+  // their entire value range.
+  return (from_size == int_byte_size)
+             ? GetBasicType(type_system, lldb::eBasicTypeUnsignedInt)
+             : int_type;
+}
+
+static lldb::ValueObjectSP UnaryConversion(lldb::ValueObjectSP valobj,
+                                           std::shared_ptr<StackFrame> ctx) {
+  // Perform usual conversions for unary operators.
+  CompilerType in_type = valobj->GetCompilerType();
+  CompilerType result_type;
+
+  if (valobj->GetCompilerType().IsInteger() ||
+      valobj->GetCompilerType().IsUnscopedEnumerationType()) {
+    CompilerType promoted_type =
+        DoIntegralPromotion(valobj->GetCompilerType(), ctx);
+    if (!promoted_type.CompareTypes(valobj->GetCompilerType()))
+      return valobj->CastToBasicType(promoted_type);
+  }
+
+  return valobj;
+}
+
+static size_t ConversionRank(CompilerType type) {
+  // Get integer conversion rank
+  // https://eel.is/c++draft/conv.rank
+  switch (type.GetCanonicalType().GetBasicTypeEnumeration()) {
+  case lldb::eBasicTypeBool:
+    return 1;
+  case lldb::eBasicTypeChar:
+  case lldb::eBasicTypeSignedChar:
+  case lldb::eBasicTypeUnsignedChar:
+    return 2;
+  case lldb::eBasicTypeShort:
+  case lldb::eBasicTypeUnsignedShort:
+    return 3;
+  case lldb::eBasicTypeInt:
+  case lldb::eBasicTypeUnsignedInt:
+    return 4;
+  case lldb::eBasicTypeLong:
+  case lldb::eBasicTypeUnsignedLong:
+    return 5;
+  case lldb::eBasicTypeLongLong:
+  case lldb::eBasicTypeUnsignedLongLong:
+    return 6;
+
+    // The ranks of char16_t, char32_t, and wchar_t are equal to the
+    // ranks of their underlying types.
+  case lldb::eBasicTypeWChar:
+  case lldb::eBasicTypeSignedWChar:
+  case lldb::eBasicTypeUnsignedWChar:
+    return 3;
+  case lldb::eBasicTypeChar16:
+    return 3;
+  case lldb::eBasicTypeChar32:
+    return 4;
+
+  default:
+    break;
+  }
+  return 0;
+}
+
+static lldb::BasicType BasicTypeToUnsigned(lldb::BasicType basic_type) {
+  switch (basic_type) {
+  case lldb::eBasicTypeInt:
+    return lldb::eBasicTypeUnsignedInt;
+  case lldb::eBasicTypeLong:
+    return lldb::eBasicTypeUnsignedLong;
+  case lldb::eBasicTypeLongLong:
+    return lldb::eBasicTypeUnsignedLongLong;
+  default:
+    return basic_type;
+  }
+}
+
+static void PerformIntegerConversions(std::shared_ptr<StackFrame> ctx,
+                                      lldb::ValueObjectSP &lhs,
+                                      lldb::ValueObjectSP &rhs,
+                                      bool convert_lhs, bool convert_rhs) {
+  CompilerType l_type = lhs->GetCompilerType();
+  CompilerType r_type = rhs->GetCompilerType();
+  if (r_type.IsSigned() && !l_type.IsSigned()) {
+    uint64_t l_size = 0;
+    uint64_t r_size = 0;
+    if (auto temp = l_type.GetByteSize(ctx.get()))
+      l_size = *temp;
+    ;
+    if (auto temp = r_type.GetByteSize(ctx.get()))
+      r_size = *temp;
+    if (l_size <= r_size) {
+      if (r_size == l_size) {
+        lldb::TypeSystemSP type_system =
+            l_type.GetTypeSystem().GetSharedPointer();
+        auto r_type_unsigned = GetBasicType(
+            type_system,
+            BasicTypeToUnsigned(
+                r_type.GetCanonicalType().GetBasicTypeEnumeration()));
+        if (convert_rhs)
+          rhs = rhs->CastToBasicType(r_type_unsigned);
+      }
+    }
+  }
+  if (convert_lhs)
+    lhs = lhs->CastToBasicType(rhs->GetCompilerType());
+}
+
+static CompilerType ArithmeticConversions(lldb::ValueObjectSP &lhs,
+                                          lldb::ValueObjectSP &rhs,
+                                          std::shared_ptr<StackFrame> ctx) {
+  // Apply unary conversion (e.g. intergal promotion) for both operands.
+  lhs = UnaryConversion(lhs, ctx);
+  rhs = UnaryConversion(rhs, ctx);
+
+  CompilerType lhs_type = lhs->GetCompilerType();
+  CompilerType rhs_type = rhs->GetCompilerType();
+
+  if (lhs_type.CompareTypes(rhs_type))
+    return lhs_type;
+
+  // If either of the operands is not arithmetic (e.g. pointer), we're done.
+  if (!lhs_type.IsScalarType() || !rhs_type.IsScalarType()) {
+    CompilerType bad_type;
+    return bad_type;
+  }
+
+  // Removed floating point conversions
+  if (lhs_type.IsFloat() || rhs_type.IsFloat()) {
+    CompilerType bad_type;
+    return bad_type;
+  }
+
+  if (lhs_type.IsInteger() && rhs_type.IsInteger()) {
+    using Rank = std::tuple<size_t, bool>;
+    Rank l_rank = {ConversionRank(lhs_type), !lhs_type.IsSigned()};
+    Rank r_rank = {ConversionRank(rhs_type), !rhs_type.IsSigned()};
+
+    if (l_rank < r_rank) {
+      PerformIntegerConversions(ctx, lhs, rhs, true, true);
+    } else if (l_rank > r_rank) {
+      PerformIntegerConversions(ctx, rhs, lhs, true, true);
+    }
+  }
+
+  return rhs_type;
+}
+
+llvm::Error Interpreter::PrepareBinaryAddition(lldb::ValueObjectSP &lhs,
+                                               lldb::ValueObjectSP &rhs,
+                                               uint32_t location) {
+  // Operation '+' works for:
+  //
+  //  {scalar,unscoped_enum} <-> {scalar,unscoped_enum}
+  //  {integer,unscoped_enum} <-> pointer
+  //  pointer <-> {integer,unscoped_enum}
+  auto orig_lhs_type = lhs->GetCompilerType();
+  auto orig_rhs_type = rhs->GetCompilerType();
+  auto result_type = ArithmeticConversions(lhs, rhs, m_exe_ctx_scope);
+
+  if (result_type.IsScalarType())
+    return llvm::Error::success();
+
+  // Removed pointer arithmetics
+  return llvm::make_error<DILDiagnosticError>(m_expr, "unimplemented",
+                                              location);
+}
+
+static lldb::ValueObjectSP EvaluateArithmeticOpInteger(lldb::TargetSP target,
+                                                       BinaryOpKind kind,
+                                                       lldb::ValueObjectSP lhs,
+                                                       lldb::ValueObjectSP rhs,
+                                                       CompilerType rtype) {
+  assert(lhs->GetCompilerType().IsInteger() &&
+         rhs->GetCompilerType().IsInteger() &&
+         "invalid ast: both operands must be integers");
+
+  auto wrap = [target, rtype](auto value) {
+    return ValueObject::CreateValueObjectFromAPInt(target, value, rtype,
+                                                   "result");
+  };
+
+  llvm::Expected<llvm::APSInt> l_value = lhs->GetValueAsAPSInt();
+  llvm::Expected<llvm::APSInt> r_value = rhs->GetValueAsAPSInt();
+
+  if (l_value && r_value) {
+    llvm::APSInt l = *l_value;
+    llvm::APSInt r = *r_value;
+
+    switch (kind) {
+    case BinaryOpKind::Add:
+      return wrap(l + r);
+
+    default:
+      assert(false && "invalid ast: invalid arithmetic operation");
+      return lldb::ValueObjectSP();
+    }
+  } else {
+    return lldb::ValueObjectSP();
+  }
+}
+
+static lldb::ValueObjectSP EvaluateArithmeticOp(lldb::TargetSP target,
+                                                BinaryOpKind kind,
+                                                lldb::ValueObjectSP lhs,
+                                                lldb::ValueObjectSP rhs,
+                                                CompilerType rtype) {
+  assert((rtype.IsInteger() || rtype.IsFloat()) &&
+         "invalid ast: result type must either integer or floating point");
+
+  // Evaluate arithmetic operation for two integral values.
+  if (rtype.IsInteger()) {
+    return EvaluateArithmeticOpInteger(target, kind, lhs, rhs, rtype);
+  }
+
+  // Removed floating point arithmetics
+
+  return lldb::ValueObjectSP();
+}
+
+llvm::Expected<lldb::ValueObjectSP> Interpreter::EvaluateBinaryAddition(
+    lldb::ValueObjectSP lhs, lldb::ValueObjectSP rhs, uint32_t location) {
+  // Addition of two arithmetic types.
+  if (lhs->GetCompilerType().IsScalarType() &&
+      rhs->GetCompilerType().IsScalarType()) {
+    return EvaluateArithmeticOp(m_target, BinaryOpKind::Add, lhs, rhs,
+                                lhs->GetCompilerType().GetCanonicalType());
+  }
+
+  // Removed pointer arithmetics
+  return llvm::make_error<DILDiagnosticError>(m_expr, "unimplemented",
+                                              location);
+}
+
+lldb::ValueObjectSP
+Interpreter::ConvertValueObjectToTypeSystem(lldb::ValueObjectSP valobj,
+                                            lldb::TypeSystemSP type_system) {
+  auto apsint = valobj->GetValueAsAPSInt();
+  if (apsint) {
+    llvm::APInt value = *apsint;
+    if (type_system) {
+      lldb::BasicType basic_type = valobj->GetCompilerType()
+                                       .GetCanonicalType()
+                                       .GetBasicTypeEnumeration();
+      if (auto compiler_type =
+              type_system.get()->GetBasicTypeFromAST(basic_type)) {
+        valobj->GetValue().SetCompilerType(compiler_type);
+        return ValueObject::CreateValueObjectFromAPInt(m_target, value,
+                                                       compiler_type, 
"result");
+      }
+    }
+  }
+
+  return lldb::ValueObjectSP();
+}
+
+llvm::Expected<lldb::ValueObjectSP>
+Interpreter::Visit(const BinaryOpNode *node) {
+  auto lhs_or_err = Evaluate(node->GetLHS());
+  if (!lhs_or_err)
+    return lhs_or_err;
+  lldb::ValueObjectSP lhs = *lhs_or_err;
+  auto rhs_or_err = Evaluate(node->GetRHS());
+  if (!rhs_or_err)
+    return rhs_or_err;
+  lldb::ValueObjectSP rhs = *rhs_or_err;
+
+  lldb::TypeSystemSP lhs_system =
+      lh...
[truncated]

``````````

</details>


https://github.com/llvm/llvm-project/pull/147064
_______________________________________________
lldb-commits mailing list
lldb-commits@lists.llvm.org
https://lists.llvm.org/cgi-bin/mailman/listinfo/lldb-commits

Reply via email to