Uploaded image for project: 'Qt'
  1. Qt
  2. QTBUG-125889

tst_qfloat16::ordering - conversion of floating to integral exercise undefined behaviour

XMLWordPrintable

    • Icon: Bug Bug
    • Resolution: Fixed
    • Icon: Not Evaluated Not Evaluated
    • 6.7.2, 6.8.0 FF
    • 6.7.0 Beta1, 6.7.0 Beta2, 6.7.0 Beta3, 6.7.0 RC, 6.7.0 RC2, 6.7.0, 6.7.1
    • Core: Other
    • None
    • VxWorks 7 24.03 on the BD-SL-i.MX6 board (32bit arm)
    • VxWorks
    • 3c9bb0daa (dev), b927ef2ce (6.7)

      The test fails with the log:

      FAIL!  : tst_qfloat16::ordering(0.000000_vs_1300000.000000) The computed value is expected to be equal to the baseline, but is not
         Computed (lhs < rhs)                         : 0
         Baseline (!expectedUnordered && expectedLess): 1
         Loc: [/home/qt/work/install/target/include/QtTest/6.8.0/QtTest/private/qcomparisontesthelper_p.h(255)]
      QDEBUG : tst_qfloat16::ordering(0.000000_vs_1300000.000000) qfloat16 vs qint16 comparison failed
      FAIL!  : tst_qfloat16::ordering(0.000000_vs_-1300000.000000) The computed value is expected to be equal to the baseline, but is not
         Computed (lhs < rhs)                         : 1
         Baseline (!expectedUnordered && expectedLess): 0
         Loc: [/home/qt/work/install/target/include/QtTest/6.8.0/QtTest/private/qcomparisontesthelper_p.h(255)]
      QDEBUG : tst_qfloat16::ordering(0.000000_vs_-1300000.000000) qfloat16 vs qint16 comparison failed 

      It fails on the VxWorks platform because it exercises Undefined Behaviour, which returns something different on this platform than on other platforms.

      Analysis

      While testing tst_qfloat16::ordering, there is a code that checks qfloat16 against various integer types:

      CHECK_INT(int);
      CHECK_INT(qint8);
      CHECK_INT(signed char);
      CHECK_INT(qint16);
      CHECK_INT(qint32);
      CHECK_INT(qint64); 

      The macro expands to the following:

      #define CHECK_INT(RHS) \
          do { \
              const auto rhs = static_cast<RHS>(right); \
              const auto expectedRes = Qt::compareThreeWay(left, rhs); \
              QTestPrivate::testAllComparisonOperators(lhs, rhs, expectedRes); \
              POSTCHECK("qfloat16 vs " #RHS " comparison failed") \
          } while (false) \
          /* END */ 

      The problematic line is the following:

      const auto rhs = static_cast<RHS>(right); 

      Where the right variable has various floating values - one of the problematic values is 
      13e5f. The conversion is defined as truncating the fraction part, but the result is undefined if the resulting value cannot be represented in the destination type (see: https://eel.is/c++draft/conv#fpint-1).
       
      On the VxWorks platform, the static_cast<qint16>(13e5f) returns 0, which leads to the failing tests. The return value is ok as it is an undefined behavior.
       
      You can check it also here: https://godbolt.org/z/dqGzc1Ghn It returns different results on every run - in my case, it returns the following:

      29024
      13696
      13696
      1300000
      1300000
      1300000 

        No reviews matched the request. Check your Options in the drop-down menu of this sections header.

            thiago Thiago Macieira
            filip.sajdak Filip Sajdak
            Votes:
            0 Vote for this issue
            Watchers:
            3 Start watching this issue

              Created:
              Updated:
              Resolved:

                There are no open Gerrit changes