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

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

    XMLWordPrintable

Details

    • Bug
    • Resolution: Fixed
    • 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)

    Description

      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 

      Attachments

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

        Activity

          People

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

            Dates

              Created:
              Updated:
              Resolved:

              Gerrit Reviews

                There are no open Gerrit changes