[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