https://gcc.gnu.org/bugzilla/show_bug.cgi?id=120358
Bug ID: 120358 Summary: [15/16 regression] qtbase-6.9.0 miscompiled since r15-580-gf3e5f4c58591f5 Product: gcc Version: 16.0 Status: UNCONFIRMED Keywords: needs-reduction, wrong-code Severity: normal Priority: P3 Component: tree-optimization Assignee: unassigned at gcc dot gnu.org Reporter: sjames at gcc dot gnu.org Target Milestone: --- Created attachment 61472 --> https://gcc.gnu.org/bugzilla/attachment.cgi?id=61472&action=edit tst_qstringtokenizer.cpp.ii.xz Originally reported downstream in Gentoo at https://bugs.gentoo.org/956308. qtbase-6.9.0's testsuite fails in tst_QStringTokenizer when built w/ `-O2 -march=x86-64-v4` or `-O3 -march=znver2` (I've gone with the latter, but the former issue seems to be the same). With -O2 -march=znver2: ``` /var/tmp/portage/dev-qt/qtbase-6.9.0-r1/work/qtbase-everywhere-src-6.9.0_build/tests/auto/corelib/text/qstringtokenizer $ QTEST_FATAL_FAIL=1 valgrind -q ./tst_qstringtokenizer -nocrashhandler -v1 -v2 [...] PASS : tst_QStringTokenizer::emptyResult_U16(Empty/Empty (SkipEmptyParts)) INFO : tst_QStringTokenizer::cleanupTestCase() entering PASS : tst_QStringTokenizer::cleanupTestCase() Totals: 24 passed, 0 failed, 0 skipped, 0 blacklisted, 190ms ********* Finished testing of tst_QStringTokenizer ********* ``` With -O3 -march=znver2: ``` /var/tmp/portage/dev-qt/qtbase-6.9.0-r1/work/qtbase-everywhere-src-6.9.0_build/tests/auto/corelib/text/qstringtokenizer $ QTEST_FATAL_FAIL=1 valgrind -q ./tst_qstringtokenizer -nocrashhandler -v1 -v2 ********* Start testing of tst_QStringTokenizer ********* Config: Using QtTest library 6.9.0, Qt 6.9.0 (x86_64-little_endian-lp64 shared (dynamic) release build; by GCC 15.1.1 20250517), gentoo 2.17 INFO : tst_QStringTokenizer::initTestCase() entering PASS : tst_QStringTokenizer::initTestCase() INFO : tst_QStringTokenizer::constExpr() entering PASS : tst_QStringTokenizer::constExpr() INFO : tst_QStringTokenizer::basics() entering [...] INFO : tst_QStringTokenizer::basics(SkipEmptyParts/CaseSensitive) QCOMPARE(toQStringList(qTokenize(u",a,b,c,d,e,", u',', cs, sb)), expected) 18:17:37 [14/9235] Loc: [/var/tmp/portage/dev-qt/qtbase-6.9.0-r1/work/qtbase-everywhere-src-6.9.0/tests/auto/corelib/text/qstringtokenizer/tst_qstringtokenizer.cpp(102)] INFO : tst_QStringTokenizer::basics(SkipEmptyParts/CaseSensitive) QCOMPARE(toQStringList(tok), expected) Loc: [/var/tmp/portage/dev-qt/qtbase-6.9.0-r1/work/qtbase-everywhere-src-6.9.0/tests/auto/corelib/text/qstringtokenizer/tst_qstringtokenizer.cpp(108)] INFO : tst_QStringTokenizer::basics(SkipEmptyParts/CaseSensitive) QCOMPARE(toQStringList(tok), expected) Loc: [/var/tmp/portage/dev-qt/qtbase-6.9.0-r1/work/qtbase-everywhere-src-6.9.0/tests/auto/corelib/text/qstringtokenizer/tst_qstringtokenizer.cpp(115)] ==717527== Conditional jump or move depends on uninitialised value(s) ==717527== at 0x4B087A0: qustrlen_sse2 (qstring.cpp:410) ==717527== by 0x4B087A0: QtPrivate::qustrlen(char16_t const*) (qstring.cpp:661) ==717527== by 0x4B24D37: QString::QString(QChar const*, long long) (qstring.cpp:2494) ==717527== by 0x400450E: QString (qstring.h:213) ==717527== by 0x400450E: toString (qstring.h:1207) ==717527== by 0x400450E: toQString (tst_qstringtokenizer.cpp:51) ==717527== by 0x400450E: toQStringList<QStringTokenizer<QString, QChar> > (tst_qstringtokenizer.cpp:59) ==717527== by 0x400450E: (anonymous namespace)::tst_QStringTokenizer::basics() const [clone .isra.0] (tst_qstringtokenizer.cpp:120) ==717527== by 0x4C4153E: QMetaMethodInvoker::invokeImpl(QMetaMethod, void*, Qt::ConnectionType, long long, void const* const*, char const* const*, QtPrivate::QMetaTypeInterface const* const*) (qmetaobject.cpp:2801) ==717527== by 0x4C41EA9: QMetaMethod::invokeImpl(QMetaMethod, void*, Qt::ConnectionType, long long, void const* const*, char const* const*, QtPrivate::QMetaTypeInterface const* const*) (qmetaobject.cpp:2640) ==717527== by 0x48B1C45: invoke<void> (qmetaobject.h:150) ==717527== by 0x48B1C45: invoke<> (qmetaobject.h:162) ==717527== by 0x48B1C45: invokeTestMethodIfValid (qtestcase.cpp:434) ==717527== by 0x48B1C45: QTest::TestMethods::invokeTestOnData(int) const (qtestcase.cpp:1050) ==717527== by 0x48B2BB5: operator() (qtestcase.cpp:1368) ==717527== by 0x48B2BB5: runWithWatchdog<QTest::TestMethods::invokeTest(int, QLatin1StringView, std::optional<QTest::WatchDog>&) const::<lambda()> > (qtestcase.cpp:1251) ==717527== by 0x48B2BB5: QTest::TestMethods::invokeTest(int, QLatin1String, std::optional<QTest::WatchDog>&) const (qtestcase.cpp:1367) ==717527== by 0x48B3BDB: QTest::TestMethods::invokeTests(QObject*) const (qtestcase.cpp:1710) ==717527== by 0x48C175E: QTest::qRun() (qtestcase.cpp:1951) ==717527== by 0x48C1ABD: QTest::qExec(QObject*, int, char**) (qtestcase.cpp:1823) ==717527== by 0x40010A1: main (tst_qstringtokenizer.cpp:217) ==717527== ==717527== Conditional jump or move depends on uninitialised value(s) ==717527== at 0x4B24D3E: QString::QString(QChar const*, long long) (qstring.cpp:2495) ==717527== by 0x400450E: QString (qstring.h:213) ==717527== by 0x400450E: toString (qstring.h:1207) ==717527== by 0x400450E: toQString (tst_qstringtokenizer.cpp:51) ==717527== by 0x400450E: toQStringList<QStringTokenizer<QString, QChar> > (tst_qstringtokenizer.cpp:59) ==717527== by 0x400450E: (anonymous namespace)::tst_QStringTokenizer::basics() const [clone .isra.0] (tst_qstringtokenizer.cpp:120) ==717527== by 0x4C4153E: QMetaMethodInvoker::invokeImpl(QMetaMethod, void*, Qt::ConnectionType, long long, void const* const*, char const* const*, QtPrivate::QMetaTypeInterface const* const*) (qmetaobject.cpp:2801) ==717527== by 0x4C41EA9: QMetaMethod::invokeImpl(QMetaMethod, void*, Qt::ConnectionType, long long, void const* const*, char const* const*, QtPrivate::QMetaTypeInterface const* const* ) (qmetaobject.cpp:2640) ==717527== by 0x48B1C45: invoke<void> (qmetaobject.h:150) ==717527== by 0x48B1C45: invoke<> (qmetaobject.h:162) ==717527== by 0x48B1C45: invokeTestMethodIfValid (qtestcase.cpp:434) ==717527== by 0x48B1C45: QTest::TestMethods::invokeTestOnData(int) const (qtestcase.cpp:1050) ==717527== by 0x48B2BB5: operator() (qtestcase.cpp:1368) ==717527== by 0x48B2BB5: runWithWatchdog<QTest::TestMethods::invokeTest(int, QLatin1StringView, std::optional<QTest::WatchDog>&) const::<lambda()> > (qtestcase.cpp:1251) ==717527== by 0x48B2BB5: QTest::TestMethods::invokeTest(int, QLatin1String, std::optional<QTest::WatchDog>&) const (qtestcase.cpp:1367) ==717527== by 0x48B3BDB: QTest::TestMethods::invokeTests(QObject*) const (qtestcase.cpp:1710) ==717527== by 0x48C175E: QTest::qRun() (qtestcase.cpp:1951) ==717527== by 0x48C1ABD: QTest::qExec(QObject*, int, char**) (qtestcase.cpp:1823) ==717527== by 0x40010A1: main (tst_qstringtokenizer.cpp:217) ==717527== INFO : tst_QStringTokenizer::basics(SkipEmptyParts/CaseSensitive) QCOMPARE(toQStringList(tok), expected) Loc: [/var/tmp/portage/dev-qt/qtbase-6.9.0-r1/work/qtbase-everywhere-src-6.9.0/tests/auto/corelib/text/qstringtokenizer/tst_qstringtokenizer.cpp(120)] FAIL! : tst_QStringTokenizer::basics(SkipEmptyParts/CaseSensitive) Compared lists have different sizes. Actual (toQStringList(tok)) size: 6 Expected (expected) size: 5 Loc: [/var/tmp/portage/dev-qt/qtbase-6.9.0-r1/work/qtbase-everywhere-src-6.9.0/tests/auto/corelib/text/qstringtokenizer/tst_qstringtokenizer.cpp(120)] terminate called without an active exception Aborted (core dumped) QTEST_FATAL_FAIL=1 valgrind -q ./tst_qstringtokenizer -nocrashhandler -v1 -v2 ``` tst_qstringtokenizer.cpp.o is what gets miscompiled. Building just that object and relinking tst_qstringtokenizer makes things pass, as does optimize("O0") or optimize("no-tree-pta") on tst_QStringTokenizer::basics. Looking at dumps between r15-579-ga9251ab3c91c8c and r15-580-gf3e5f4c58591f5, there's a lot of noise like: ``` - # PT = nonlocal escaped null { D.387695 D.418643 } (nonlocal, escaped) - # USE = nonlocal escaped null { D.387695 D.418643 } (nonlocal, escaped) - # CLB = nonlocal escaped null { D.387695 D.418643 } (nonlocal, escaped) + # PT = nonlocal escaped null const-pool { D.387695 D.418643 } (nonlocal, escaped) + # USE = nonlocal escaped null const-pool { D.387695 D.418643 } (nonlocal, escaped) + # CLB = nonlocal escaped null const-pool { D.387695 D.418643 } (nonlocal, escaped) ```