llvm-project icon indicating copy to clipboard operation
llvm-project copied to clipboard

[LLDB] Operators <= and >= return a wrong result when comparing with a floating point NaN in expression evaluation

Open kuilpd opened this issue 1 year ago • 4 comments

Operators <= and >= are defined through operator< (Scalar.cpp:857), which in turn calls a compare function. If the compare function returns cmpUnordered, operator< return false, which gets negated and operators <= and >= return an incorrect value true.

Source file with 2 comparisons, to see the operator results from the compiler:

#include <limits>

int main() {
  float fnan = std::numeric_limits<float>::quiet_NaN();
  double dnan = std::numeric_limits<double>::quiet_NaN();
  bool float_comparison = 1.0f <= fnan;
  bool double_comparison = 1.0 >= dnan;
  return 0;
}

LLDB log:

(lldb) expr float_comparison
(bool) $0 = false
(lldb) expr double_comparison
(bool) $1 = false
(lldb) expr 1.0f <= fnan
(bool) $2 = true
(lldb) expr 1.0 >= dnan
(bool) $3 = true

Maybe operators <= and >= should analyze result separately, like in APFloat.h:1240.

kuilpd avatar Mar 20 '24 15:03 kuilpd

@llvm/issue-subscribers-lldb

Author: Ilia Kuklin (kuilpd)

Operators `<=` and `>=` are defined through `operator<` ([Scalar.cpp:857](https://github.com/llvm/llvm-project/blob/7812fcf3d79ef7fe9ec6bcdfc8fd9143864956cb/lldb/source/Utility/Scalar.cpp#L857)), which in turn calls a compare function. If the compare function returns `cmpUnordered`, `operator<` return `false`, which gets negated and operators `<=` and `>=` return an incorrect value `true`.

Source file with 2 comparisons, to see the operator results from the compiler:

#include &lt;limits&gt;

int main() {
  float fnan = std::numeric_limits&lt;float&gt;::quiet_NaN();
  double dnan = std::numeric_limits&lt;double&gt;::quiet_NaN();
  bool float_comparison = 1.0f &lt;= fnan;
  bool double_comparison = 1.0 &gt;= dnan;
  return 0;
}

LLDB log:

(lldb) expr float_comparison
(bool) $0 = false
(lldb) expr double_comparison
(bool) $1 = false
(lldb) expr 1.0f &lt;= fnan
(bool) $2 = true
(lldb) expr 1.0 &gt;= dnan
(bool) $3 = true

Maybe operators &lt;= and &gt;= should analyze result separately, like in APFloat.h:1240.

llvmbot avatar Mar 20 '24 15:03 llvmbot

Maybe operators <= and >= should analyze result separately, like in APFloat.h:1240.

Thanks for the report and analysis. Agreed, checking for the possibility of an unordered comparison result seems like the way to go. operator== suffers from the same issue I guess

Michael137 avatar Mar 20 '24 15:03 Michael137

operator== suffers from the same issue I guess

In this particular case 1.0f != fnan is supposed to be true anyway. Although there might be other cases where just negating the result of == is incorrect, I'm not sure.

kuilpd avatar Mar 20 '24 18:03 kuilpd

Wait. Wasn't the != relation meant to cover unordered result in terms of IEEE 754?

(a != b) and !(a == b) should be strictly equivalent. It is the <> relation that might need to address the unordered results.

Explorer09 avatar Mar 24 '24 14:03 Explorer09