[Lldb-commits] [lldb] Draft: [LLDB] Add scalar literal node (PR #147064)
via lldb-commits
lldb-commits at lists.llvm.org
Fri Jul 4 07:25:13 PDT 2025
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
More information about the lldb-commits
mailing list