[Lldb-commits] [lldb] [lldb] Add comparison operators to DIL (PR #208832)
Ilia Kuklin via lldb-commits
lldb-commits at lists.llvm.org
Tue Aug 4 08:01:19 PDT 2026
================
@@ -906,6 +918,186 @@ Interpreter::EvaluateAssignment(lldb::ValueObjectSP lhs,
return lhs;
}
+static bool IsLiteralZero(lldb::ValueObjectSP &val, bool is_literal) {
+ bool is_zero = val->GetValueAsUnsigned(-1) == 0;
+ bool is_boolean = val->GetCompilerType().IsBoolean();
+ return is_zero && !is_boolean && is_literal;
+}
+
+llvm::Error
+Interpreter::ValidateComparison(BinaryOpKind kind, lldb::ValueObjectSP &lhs,
+ lldb::ValueObjectSP &rhs, bool lhs_is_literal,
+ bool rhs_is_literal, uint32_t location) {
+ auto orig_lhs_type = lhs->GetCompilerType();
+ auto orig_rhs_type = rhs->GetCompilerType();
+
+ if (orig_lhs_type == orig_rhs_type)
+ return llvm::Error::success();
+
+ bool is_ordered = (kind == BinaryOpKind::LT || kind == BinaryOpKind::LE ||
+ kind == BinaryOpKind::GT || kind == BinaryOpKind::GE);
+ bool lhs_nullptr_or_zero =
+ orig_lhs_type.IsNullPtrType() || IsLiteralZero(lhs, lhs_is_literal);
+ bool rhs_nullptr_or_zero =
+ orig_rhs_type.IsNullPtrType() || IsLiteralZero(rhs, rhs_is_literal);
+
+ if (orig_lhs_type.IsArrayType())
+ lhs = ArrayToPointerConversion(*lhs, m_stack_frame, "result");
+ if (orig_rhs_type.IsArrayType())
+ rhs = ArrayToPointerConversion(*rhs, m_stack_frame, "result");
+
+ CompilerType lhs_type = lhs->GetCompilerType();
+ CompilerType rhs_type = rhs->GetCompilerType();
+ lldb::ValueObjectSP lhs_child;
+ lldb::ValueObjectSP rhs_child;
+ bool is_signed;
+
+ if (!lhs_nullptr_or_zero && !lhs_type.IsPointerType() &&
+ !lhs_type.IsIntegerOrEnumerationType(is_signed)) {
+ // lhs is not a nullptr, pointer, enum or integer. Check to see if its
+ // first child could be a pointer. If so, update lhs_type accordingly.
+ lhs_child = lhs->GetChildAtIndex(0);
+ if (lhs_child && (lhs_child->IsPointerType() ||
+ lhs_child->GetCompilerType().IsNullPtrType()))
+ lhs_type = lhs_child->GetCompilerType();
+ }
+ if (!rhs_nullptr_or_zero && !rhs_type.IsPointerType() &&
+ !rhs_type.IsIntegerOrEnumerationType(is_signed)) {
+ // rhs is not a nullptr, pointer, enum or integer. Check to see if its
+ // first child could be a pointer. If so, update rhs_type accordingly.
+ rhs_child = rhs->GetChildAtIndex(0);
+ if (rhs_child && (rhs_child->IsPointerType() ||
+ rhs_child->GetCompilerType().IsNullPtrType()))
+ rhs_type = rhs_child->GetCompilerType();
+ }
+
+ if ((lhs_type != orig_lhs_type) || (rhs_type != orig_rhs_type)) {
+ if (lhs_type.IsNullPtrType() || rhs_type.IsNullPtrType())
+ return llvm::Error::success();
+
+ // May be an integer or enum.
+ if (!lhs_type.IsPointerType() || !rhs_type.IsPointerType())
+ return llvm::Error::success();
+
+ CompilerType lhs_unqualified =
+ lhs_type.GetCanonicalType().GetFullyUnqualifiedType();
+ CompilerType rhs_unqualified =
+ rhs_type.GetCanonicalType().GetFullyUnqualifiedType();
+
+ if (lhs_unqualified.IsPointerToVoid() || rhs_unqualified.IsPointerToVoid())
+ return llvm::Error::success();
+
+ // We have two pointers, neither of which is nullptr or void *. Make
+ // sure their types are compatible.
+ bool comparable = lhs_unqualified.CompareTypes(rhs_unqualified);
+ if (comparable)
+ return llvm::Error::success();
+
+ std::string errMsg = llvm::formatv(
+ "comparison of distinct pointer types ({0} and {1})",
+ orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
+ return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
+ }
+
+ if (!is_ordered && ((orig_lhs_type.IsNullPtrType() && rhs_nullptr_or_zero) ||
+ (lhs_nullptr_or_zero && orig_rhs_type.IsNullPtrType())))
+ return llvm::Error::success();
+
+ // If the operands has arithmetic or enumeration type (scoped or unscoped),
+ // usual arithmetic conversions are performed on both operands following the
+ // rules for arithmetic operators.
+ auto type_or_err = ArithmeticConversion(lhs, rhs, location);
+ if (!type_or_err)
+ return type_or_err.takeError();
+
+ lhs_type = lhs->GetCompilerType();
+ rhs_type = rhs->GetCompilerType();
+ if (lhs_type.IsScalarOrUnscopedEnumerationType() &&
+ rhs_type.IsScalarOrUnscopedEnumerationType())
+ return llvm::Error::success();
+
+ // Scoped enums can be compared only to the instances of the same type.
+ if (lhs_type.IsScopedEnumerationType() ||
+ rhs_type.IsScopedEnumerationType()) {
+ if (lhs_type.CompareTypes(rhs_type))
+ return llvm::Error::success();
+ std::string errMsg = llvm::formatv(
+ "invalid operands to binary expression ({0} and {1})",
+ orig_lhs_type.TypeDescription(), orig_rhs_type.TypeDescription());
+ return llvm::make_error<DILDiagnosticError>(m_expr, errMsg, location);
+ }
+
+ // Check if the value can be compared to a pointer. We allow all pointers,
+ // integers, unscoped enumerations and a nullptr literal if it's an
+ // equality/inequality comparison. For "pointer <-> integer" C++ allows only
----------------
kuilpd wrote:
@adrian-prantl
I ended up rephasing it and removing C++ mentions.
https://github.com/llvm/llvm-project/pull/208832
More information about the lldb-commits
mailing list