diff --git a/src/corelib/kernel/qtmocconstants.h b/src/corelib/kernel/qtmocconstants.h index 56538ca98b6..54c3f8844e7 100644 --- a/src/corelib/kernel/qtmocconstants.h +++ b/src/corelib/kernel/qtmocconstants.h @@ -29,7 +29,7 @@ namespace QtMocConstants { // and metamethods store a flag stating whether they are const // revision 11 is Qt 6.5: The metatype for void is stored in the metatypes array // revision 12 is Qt 6.6: It adds the metatype for enums -// revision 13 is Qt 6.9: It moves the location of the meta method revisions +// revision 13 is Qt 6.9: Adds support for 64-bit QFlags and moves the method revision enum { OutputRevision = 13 }; // Used by moc, qmetaobjectbuilder and qdbus enum PropertyFlags : uint { @@ -88,6 +88,7 @@ enum MetaDataFlags : uint { enum EnumFlags : uint { EnumIsFlag = 0x1, EnumIsScoped = 0x2, + EnumIs64Bit = 0x40, }; } // namespace QtMocConstants diff --git a/src/corelib/kernel/qtmochelpers.h b/src/corelib/kernel/qtmochelpers.h index e5454fbf504..8ee9d6940f1 100644 --- a/src/corelib/kernel/qtmochelpers.h +++ b/src/corelib/kernel/qtmochelpers.h @@ -83,6 +83,16 @@ template constexpr auto stringData(const char (&...strings)[Nx]) struct NoType {}; namespace detail { +template constexpr int payloadSizeForEnum() +{ + // How many uint blocks do we need to store the values of this enum and the + // string indices for the enumeration labels? We only support 8- 16-, 32- + // and 64-bit enums at the time of this writing, so this code is extra + // pedantic allowing for 48-, 96-, 128-bit, etc. + int n = int(sizeof(Enum) + sizeof(uint)) - 1; + return 1 + n / sizeof(uint); +} + template struct UintDataBlock { static constexpr uint headerSize() { return H; } @@ -207,10 +217,10 @@ struct PropertyData : detail::UintDataBlock<5, 0> }; template -struct EnumData : detail::UintDataBlock<5, 2 * N> +struct EnumData : detail::UintDataBlock<5, N * detail::payloadSizeForEnum()> { private: - static_assert(sizeof(Enum) <= sizeof(uint), "Cannot store enumeration of this size"); + static_assert(sizeof(Enum) <= 2 * sizeof(uint), "Cannot store enumeration of this size"); template struct RealEnum { using Type = T; }; template struct RealEnum> { using Type = T; }; public: @@ -219,7 +229,6 @@ public: typename RealEnum::Type value; }; - constexpr EnumData(uint nameOffset, uint aliasOffset, uint flags) { this->header[0] = nameOffset; @@ -234,7 +243,7 @@ public: this->header[2] |= QtMocConstants::EnumIsScoped; } - template constexpr auto add(const EnumEntry (&entries)[Added]) + template constexpr auto add(const EnumEntry (&entries)[Added]) const { EnumData result(this->header[0], this->header[1], this->header[2]); @@ -245,6 +254,15 @@ public: auto value = qToUnderlying(entry.value); result.payload[o++] = uint(value); } + + if constexpr (sizeof(Enum) > sizeof(uint)) { + static_assert(N == 0, "Unimplemented: merging with non-empty EnumData"); + result.header[2] |= QtMocConstants::EnumIs64Bit; + for (auto entry : entries) { + auto value = qToUnderlying(entry.value); + result.payload[o++] = uint(value >> 32); + } + } return result; } diff --git a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp index fbf695f4cbf..d79e0e82f8a 100644 --- a/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp +++ b/tests/auto/corelib/kernel/qvariant/tst_qvariant.cpp @@ -152,12 +152,12 @@ public: enum MetaEnumTest_Enum0 { MetaEnumTest_Enum0_dummy = 2, MetaEnumTest_Enum0_value = 42, MetaEnsureSignedEnum0 = -1 }; Q_ENUM(MetaEnumTest_Enum0) enum MetaEnumTest_Enum1 : qint64 { MetaEnumTest_Enum1_value = 42, MetaEnumTest_Enum1_bigValue = (Q_INT64_C(1) << 33) + 50 }; - // Q_ENUM(MetaEnumTest_Enum1) + Q_ENUM(MetaEnumTest_Enum1) enum MetaEnumTest_Enum3 : qint64 { MetaEnumTest_Enum3_value = -47, MetaEnumTest_Enum3_bigValue = (Q_INT64_C(1) << 56) + 5, MetaEnumTest_Enum3_bigNegValue = -(Q_INT64_C(1) << 56) - 3 }; - // Q_ENUM(MetaEnumTest_Enum3) + Q_ENUM(MetaEnumTest_Enum3) enum MetaEnumTest_Enum4 : quint64 { MetaEnumTest_Enum4_value = 47, MetaEnumTest_Enum4_bigValue = (Q_INT64_C(1) << 52) + 45 }; - // Q_ENUM(MetaEnumTest_Enum4) + Q_ENUM(MetaEnumTest_Enum4) enum MetaEnumTest_Enum5 : uint { MetaEnumTest_Enum5_value = 47 }; Q_ENUM(MetaEnumTest_Enum5) enum MetaEnumTest_Enum6 : uchar { MetaEnumTest_Enum6_value = 47 }; @@ -5390,13 +5390,13 @@ void tst_QVariant::metaEnums_data() QTest::newRow(#Value) << &testVariantMetaEnum << #Value; METAENUMS_TEST(MetaEnumTest_Enum0_value); - // METAENUMS_TEST(MetaEnumTest_Enum1_value); - // METAENUMS_TEST(MetaEnumTest_Enum1_bigValue); - // METAENUMS_TEST(MetaEnumTest_Enum3_value); - // METAENUMS_TEST(MetaEnumTest_Enum3_bigValue); - // METAENUMS_TEST(MetaEnumTest_Enum3_bigNegValue); - // METAENUMS_TEST(MetaEnumTest_Enum4_value); - // METAENUMS_TEST(MetaEnumTest_Enum4_bigValue); + METAENUMS_TEST(MetaEnumTest_Enum1_value); + METAENUMS_TEST(MetaEnumTest_Enum1_bigValue); + METAENUMS_TEST(MetaEnumTest_Enum3_value); + METAENUMS_TEST(MetaEnumTest_Enum3_bigValue); + METAENUMS_TEST(MetaEnumTest_Enum3_bigNegValue); + METAENUMS_TEST(MetaEnumTest_Enum4_value); + METAENUMS_TEST(MetaEnumTest_Enum4_bigValue); METAENUMS_TEST(MetaEnumTest_Enum5_value); METAENUMS_TEST(MetaEnumTest_Enum6_value); METAENUMS_TEST(MetaEnumTest_Enum8_value); diff --git a/tests/auto/tools/mochelpers/tst_mochelpers.cpp b/tests/auto/tools/mochelpers/tst_mochelpers.cpp index 089acc73f57..035b78fa31c 100644 --- a/tests/auto/tools/mochelpers/tst_mochelpers.cpp +++ b/tests/auto/tools/mochelpers/tst_mochelpers.cpp @@ -123,11 +123,17 @@ template void enumUintData_check(const E (&values)[N]) QCOMPARE(result.payload[2 * i + 0], uint(namesAndOffsets[i].nameIndex)); QCOMPARE(result.payload[2 * i + 1], uint(values[i])); } + + if constexpr (sizeof(E) > sizeof(uint)) { + using U = std::underlying_type_t; + for (uint i = 0; i < std::size(values); ++i) + QCOMPARE(result.payload[2 * N + i], uint(U(values[i]) >> 32)); + } } enum E1 { AnEnumValue }; enum class E2 { V0 = INT_MAX, V1 = INT_MIN }; -enum class E3 : int { V = 0x1111'2222, V2 = -V }; +enum class E3 : qint64 { V = 0x1111'2222'3333'4444, V2 = -V }; void tst_MocHelpers::enumUintData() { using namespace QtMocHelpers; @@ -171,12 +177,14 @@ void tst_MocHelpers::enumUintData() .add({ { 2, E3::V }, {3, E3::V2 }, }); QCOMPARE(result.header[0], 1U); QCOMPARE(result.header[1], 1U); - QCOMPARE(result.header[2], EnumIsScoped); + QCOMPARE(result.header[2], EnumIsScoped | EnumIs64Bit); QCOMPARE(result.header[3], 2U); QCOMPARE(result.payload[0], 2U); QCOMPARE(result.payload[1], uint(E3::V)); QCOMPARE(result.payload[2], 3U); QCOMPARE(result.payload[3], uint(E3::V2)); + QCOMPARE(result.payload[4], uint(quint64(E3::V) >> 32)); + QCOMPARE(result.payload[5], uint(quint64(E3::V2) >> 32)); } QTest::setThrowOnFail(true); @@ -184,6 +192,10 @@ void tst_MocHelpers::enumUintData() enum E { E0, E1 = -1, E2 = 123, E3 = INT_MIN }; enumUintData_check({E0, E1, E2, E3}); } + { + enum E : quint64 { E0, E1 = quint64(INT_MIN), E2 = 0x1'0000'0000, E3 = quint64(LLONG_MIN) }; + enumUintData_check({E0, E1, E2, E3}); + } } template void testUintData(const Data &data) @@ -223,7 +235,7 @@ template static void checkEnums(const std::array &data) // E3: QCOMPARE(header[5 + 0], 4U); QCOMPARE(header[5 + 1], 5U); - QCOMPARE(header[5 + 2], EnumIsFlag | EnumIsScoped); + QCOMPARE(header[5 + 2], EnumIsFlag | EnumIsScoped | EnumIs64Bit); QCOMPARE(header[5 + 3], 2U); QCOMPARE_GE(header[5 + 4], 14U); payload = data.data() + header[5 + 4]; @@ -231,6 +243,8 @@ template static void checkEnums(const std::array &data) QCOMPARE(payload[1], uint(E3::V)); QCOMPARE(payload[2], 8U); QCOMPARE(payload[3], uint(E3::V2)); + QCOMPARE(payload[4], uint(quint64(E3::V) >> 32)); + QCOMPARE(payload[5], uint(quint64(E3::V2) >> 32)); // E2: QCOMPARE(header[10 + 0], 7U);