diff --git a/src/corelib/global/qtenvironmentvariables.cpp b/src/corelib/global/qtenvironmentvariables.cpp index ffafbdf4180..aab7e516d8e 100644 --- a/src/corelib/global/qtenvironmentvariables.cpp +++ b/src/corelib/global/qtenvironmentvariables.cpp @@ -174,6 +174,8 @@ bool qEnvironmentVariableIsEmpty(const char *varName) noexcept #endif } +QT_WARNING_PUSH +QT_WARNING_DISABLE_GCC("-Wmaybe-uninitialized") // older GCC don't like libstdc++'s std::optional /*! \relates \since 5.5 @@ -195,11 +197,14 @@ bool qEnvironmentVariableIsEmpty(const char *varName) noexcept */ int qEnvironmentVariableIntValue(const char *varName, bool *ok) noexcept { - std::optional value = qEnvironmentVariableIntegerValue(varName); + std::optional value = qEnvironmentVariableIntegerValue(varName); + if (value && *value != int(*value)) + value = std::nullopt; if (ok) *ok = bool(value); return value.value_or(0); } +QT_WARNING_POP /*! \relates @@ -232,11 +237,11 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) noexcept \sa qgetenv(), qEnvironmentVariable(), qEnvironmentVariableIsSet() */ -std::optional qEnvironmentVariableIntegerValue(const char *varName) noexcept +std::optional qEnvironmentVariableIntegerValue(const char *varName) noexcept { static const int NumBinaryDigitsPerOctalDigit = 3; static const int MaxDigitsForOctalInt = - (std::numeric_limits::digits + NumBinaryDigitsPerOctalDigit - 1) / NumBinaryDigitsPerOctalDigit + (std::numeric_limits::digits + NumBinaryDigitsPerOctalDigit - 1) / NumBinaryDigitsPerOctalDigit + 1 // sign + 1; // "0" base prefix @@ -255,7 +260,7 @@ std::optional qEnvironmentVariableIntegerValue(const char *varName) noexcep return std::nullopt; #endif auto r = QLocaleData::bytearrayToLongLong(QByteArrayView(buffer, size), 0); - if (!r.ok() || int(r.result) != r.result) + if (!r.ok()) return std::nullopt; return r.result; } diff --git a/src/corelib/global/qtenvironmentvariables.h b/src/corelib/global/qtenvironmentvariables.h index 24658c415e5..9f650d35aff 100644 --- a/src/corelib/global/qtenvironmentvariables.h +++ b/src/corelib/global/qtenvironmentvariables.h @@ -7,6 +7,7 @@ #include #include #include +#include #include @@ -34,7 +35,7 @@ Q_CORE_EXPORT bool qunsetenv(const char *varName); Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) noexcept; Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) noexcept; Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) noexcept; -Q_CORE_EXPORT std::optional qEnvironmentVariableIntegerValue(const char *varName) noexcept; +Q_CORE_EXPORT std::optional qEnvironmentVariableIntegerValue(const char *varName) noexcept; QT_END_NAMESPACE diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp index 9e38353e419..7bc2e0bc673 100644 --- a/src/gui/kernel/qhighdpiscaling.cpp +++ b/src/gui/kernel/qhighdpiscaling.cpp @@ -394,7 +394,7 @@ void QHighDpiScaling::initHighDpiScaling() // Read environment variables static const char* envDebugStr = "environment variable set:"; - std::optional envEnableHighDpiScaling = qEnvironmentVariableIntegerValue(enableHighDpiScalingEnvVar); + std::optional envEnableHighDpiScaling = qEnvironmentVariableIntegerValue(enableHighDpiScalingEnvVar); if (envEnableHighDpiScaling.has_value()) qCDebug(lcHighDpi) << envDebugStr << enableHighDpiScalingEnvVar << envEnableHighDpiScaling.value(); @@ -406,7 +406,7 @@ void QHighDpiScaling::initHighDpiScaling() if (envScreenFactors.has_value()) qCDebug(lcHighDpi) << envDebugStr << screenFactorsEnvVar << envScreenFactors.value(); - std::optional envUsePhysicalDpi = qEnvironmentVariableIntegerValue(usePhysicalDpiEnvVar); + std::optional envUsePhysicalDpi = qEnvironmentVariableIntegerValue(usePhysicalDpiEnvVar); if (envUsePhysicalDpi.has_value()) qCDebug(lcHighDpi) << envDebugStr << usePhysicalDpiEnvVar << envUsePhysicalDpi.value(); diff --git a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp index 01be9463813..c932fe85706 100644 --- a/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp +++ b/tests/auto/corelib/global/qgetputenv/tst_qgetputenv.cpp @@ -6,6 +6,9 @@ #include #include + +#include + #ifdef Q_OS_WIN #include #endif @@ -136,17 +139,17 @@ void tst_QGetPutEnv::encoding() void tst_QGetPutEnv::intValue_data() { QTest::addColumn("value"); - QTest::addColumn("expected"); + QTest::addColumn("expected"); QTest::addColumn("ok"); // some repetition from what is tested in getSetCheck() - QTest::newRow("empty") << QByteArray() << 0 << false; - QTest::newRow("spaces-heading") << QByteArray(" \n\r\t1") << 1 << true; - QTest::newRow("spaces-trailing") << QByteArray("1 \n\r\t") << 1 << true; - QTest::newRow("junk-heading") << QByteArray("x1") << 0 << false; - QTest::newRow("junk-trailing") << QByteArray("1x") << 0 << false; + QTest::newRow("empty") << QByteArray() << qint64(0) << false; + QTest::newRow("spaces-heading") << QByteArray(" \n\r\t1") << qint64(1) << true; + QTest::newRow("spaces-trailing") << QByteArray("1 \n\r\t") << qint64(1) << true; + QTest::newRow("junk-heading") << QByteArray("x1") << qint64(0) << false; + QTest::newRow("junk-trailing") << QByteArray("1x") << qint64(0) << false; - auto addRow = [](const char *text, int expected, bool ok) { + auto addRow = [](const char *text, qint64 expected, bool ok) { QTest::newRow(text) << QByteArray(text) << expected << ok; }; addRow("auto", 0, false); @@ -168,10 +171,8 @@ void tst_QGetPutEnv::intValue_data() addRow("-1", -1, true); addRow("-010", -8, true); addRow("-000000000000000000000000000000000000000000000000001", 0, false); - // addRow("0xffffffff", -1, true); // could be expected, but not how QByteArray::toInt() works - addRow("0xffffffff", 0, false); - auto addNumWithBase = [](qlonglong num, int base) { + auto addNumWithBase = [](auto num, int base) { QByteArray text; { QTextStream s(&text); @@ -179,42 +180,53 @@ void tst_QGetPutEnv::intValue_data() s << Qt::showbase << num; } QTestData &row = QTest::addRow("%s", text.constData()) << text; - if (num == int(num)) - row << int(num) << true; + bool ok = true; + if constexpr (std::is_same_v) + ok = num <= quint64(LLONG_MAX); + if (ok) + row << qint64(num) << true; else - row << 0 << false; + row << qint64(0) << false; }; for (int base : {10, 8, 16}) { addNumWithBase(INT_MAX, base); addNumWithBase(qlonglong(INT_MAX) + 1, base); + addNumWithBase(UINT_MAX, base); addNumWithBase(INT_MIN, base); addNumWithBase(qlonglong(INT_MIN) - 1 , base); + addNumWithBase(LLONG_MAX, base); + addNumWithBase(LLONG_MIN, base); + addNumWithBase(ULLONG_MAX, base); }; } void tst_QGetPutEnv::intValue() { - const int maxlen = (sizeof(int) * CHAR_BIT + 2) / 3; + const int maxlen = (sizeof(qint64) * CHAR_BIT + 2) / 3; const char varName[] = "should_not_exist"; QFETCH(QByteArray, value); - QFETCH(int, expected); + QFETCH(qint64, expected); QFETCH(bool, ok); bool actualOk = !ok; + bool is32Bit = q20::in_range(expected); // Self-test: confirm that it was like the docs said it should be if (value.size() < maxlen) { - QCOMPARE(value.toInt(&actualOk, 0), expected); + // 32-bit + QCOMPARE(value.toInt(&actualOk, 0), is32Bit ? expected : 0); + QCOMPARE(actualOk, ok && is32Bit); + QCOMPARE(value.toLongLong(&actualOk, 0), expected); QCOMPARE(actualOk, ok); } actualOk = !ok; QVERIFY(qputenv(varName, value)); - QCOMPARE(qEnvironmentVariableIntValue(varName), expected); - QCOMPARE(qEnvironmentVariableIntValue(varName, &actualOk), expected); - QCOMPARE(actualOk, ok); - if (actualOk) + QCOMPARE(qEnvironmentVariableIntValue(varName), is32Bit ? expected : 0); + QCOMPARE(qEnvironmentVariableIntValue(varName, &actualOk), is32Bit ? expected : 0); + QCOMPARE(actualOk, ok && is32Bit); + if (ok) QCOMPARE(qEnvironmentVariableIntegerValue(varName), expected); else QCOMPARE(qEnvironmentVariableIntegerValue(varName), std::nullopt);