Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2025-10-29 08:53:06

0001 // Copyright (C) 2022 Intel Corporation.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 
0004 #ifndef QTMOCHELPERS_H
0005 #define QTMOCHELPERS_H
0006 
0007 //
0008 //  W A R N I N G
0009 //  -------------
0010 //
0011 // This file is not part of the Qt API. It exists to be used by the code that
0012 // moc generates. This file will not change quickly, but it over the long term,
0013 // it will likely change or even be removed.
0014 //
0015 // We mean it.
0016 //
0017 
0018 #include <QtCore/qmetatype.h>
0019 #include <QtCore/qtmocconstants.h>
0020 
0021 #include <QtCore/q20algorithm.h>    // std::min, std::copy_n
0022 #include <QtCore/q23type_traits.h>  // std::is_scoped_enum
0023 #include <limits>
0024 
0025 #if 0
0026 #pragma qt_no_master_include
0027 #endif
0028 
0029 QT_BEGIN_NAMESPACE
0030 namespace QtMocHelpers {
0031 // The maximum Size of a string literal is 2 GB on 32-bit and 4 GB on 64-bit
0032 // (but the compiler is likely to give up before you get anywhere near that much)
0033 static constexpr size_t MaxStringSize =
0034         (std::min)(size_t((std::numeric_limits<uint>::max)()),
0035                    size_t((std::numeric_limits<qsizetype>::max)()));
0036 
0037 template <uint UCount, uint SCount, size_t SSize, uint MCount> struct MetaObjectContents
0038 {
0039     struct StaticContent {
0040         uint data[UCount];
0041         uint stringdata[SCount];
0042         char strings[SSize];
0043     } staticData = {};
0044     struct RelocatingContent {
0045         const QtPrivate::QMetaTypeInterface *metaTypes[MCount];
0046     } relocatingData = {};
0047 };
0048 
0049 template <int Count, size_t StringSize> struct StringData
0050 {
0051     static_assert(StringSize <= MaxStringSize, "Meta Object data is too big");
0052     uint offsetsAndSizes[Count] = {};
0053     char stringdata0[StringSize] = {};
0054     constexpr StringData() = default;
0055 };
0056 
0057 template <typename... Strings> struct StringRefStorage
0058 {
0059     static constexpr size_t stringSizeHelper() noexcept
0060     {
0061         // same as:
0062         //   return (0 + ... + std::extent_v<Strings>);
0063         // but not using the fold expression to avoid exceeding compiler limits
0064         size_t total = 0;
0065         int sizes[] = { std::extent_v<Strings>... };
0066         for (int n : sizes)
0067             total += n;
0068         return size_t(total);
0069     }
0070 
0071     static constexpr int StringCount = sizeof...(Strings);
0072     static constexpr size_t StringSize = stringSizeHelper();
0073     static_assert(StringSize <= MaxStringSize, "Meta Object data is too big");
0074     const char *inputs[StringCount];
0075 
0076     constexpr StringRefStorage(const Strings &... strings) noexcept
0077         : inputs{ strings... }
0078     { }
0079 
0080     constexpr void
0081     writeTo(uint (&offsets)[2 * StringCount], char (&data)[StringSize]) const noexcept
0082     {
0083         int sizes[] = { std::extent_v<Strings>... };
0084 
0085         uint offset = 0;
0086         char *output = data;
0087         for (size_t i = 0; i < sizeof...(Strings); ++i) {
0088             // copy the input string, including the terminating null
0089             int len = sizes[i];
0090             for (int j = 0; j < len; ++j)
0091                 output[offset + j] = inputs[i][j];
0092             offsets[2 * i] = offset + sizeof(offsets);
0093             offsets[2 * i + 1] = len - 1;
0094             offset += len;
0095         }
0096     }
0097 
0098     constexpr auto create() const noexcept
0099     {
0100         StringData<2 * StringCount, StringSize>  result;
0101         writeTo(result.offsetsAndSizes, result.stringdata0);
0102         return result;
0103     }
0104 };
0105 
0106 template <uint... Nx> constexpr auto stringData(const char (&...strings)[Nx])
0107 {
0108     return StringRefStorage(strings...).create();
0109 }
0110 
0111 template <typename FuncType> inline bool indexOfMethod(void **_a, FuncType f, int index) noexcept
0112 {
0113     int *result = static_cast<int *>(_a[0]);
0114     auto candidate = reinterpret_cast<FuncType *>(_a[1]);
0115     if (*candidate != f)
0116         return false;
0117     *result = index;
0118     return true;
0119 }
0120 
0121 template <typename Prop, typename Value> inline bool setProperty(Prop &property, Value &&value)
0122 {
0123     if (property == value)
0124         return false;
0125     property = std::forward<Value>(value);
0126     return true;
0127 }
0128 
0129 struct NoType {};
0130 
0131 namespace detail {
0132 template<typename Enum> constexpr int payloadSizeForEnum()
0133 {
0134     // How many uint blocks do we need to store the values of this enum and the
0135     // string indices for the enumeration labels? We only support 8- 16-, 32-
0136     // and 64-bit enums at the time of this writing, so this code is extra
0137     // pedantic allowing for 48-, 96-, 128-bit, etc.
0138     int n = int(sizeof(Enum) + sizeof(uint)) - 1;
0139     return 1 + n / sizeof(uint);
0140 }
0141 
0142 template <uint H, uint P> struct UintDataBlock
0143 {
0144     static constexpr uint headerSize() { return H; }
0145     static constexpr uint payloadSize() { return P; }
0146     uint header[H ? H : 1] = {};
0147     uint payload[P ? P : 1] = {};
0148 };
0149 
0150 // By default, we allow metatypes for incomplete types to be stored in the
0151 // metatype array, but we provide a way to require them to be complete by using
0152 // void as the Unique type (used by moc if --require-complete-types is passed
0153 // or some internal heuristic for QML matches) or by using the enum below, for
0154 // properties and enums.
0155 enum TypeCompletenessForMetaType : bool {
0156     TypeMayBeIncomplete = false,
0157     TypeMustBeComplete = true,
0158 };
0159 
0160 template <bool TypeMustBeComplete, typename... T> struct MetaTypeList
0161 {
0162     static constexpr int count() { return sizeof...(T); }
0163     template <typename Unique, typename Result> static constexpr void
0164     copyTo(Result &result, uint &metatypeoffset)
0165     {
0166         if constexpr (count()) {
0167             using namespace QtPrivate;
0168             using U = std::conditional_t<TypeMustBeComplete, void, Unique>;
0169             const QMetaTypeInterface *metaTypes[] = {
0170                 qTryMetaTypeInterfaceForType<U, T>()...
0171             };
0172             for (const QMetaTypeInterface *mt : metaTypes)
0173                 result.relocatingData.metaTypes[metatypeoffset++] = mt;
0174         }
0175     }
0176 };
0177 
0178 template <int Idx, typename T> struct UintDataEntry
0179 {
0180     T entry;
0181     constexpr UintDataEntry(T &&entry_) : entry(std::move(entry_)) {}
0182 };
0183 
0184 // This storage type is designed similar to libc++'s std::tuple, in that it
0185 // derives from a type unique to each of the types in the template parameter
0186 // pack (even if they are the same type). That way, we can refer to each of
0187 // entries uniquely by just casting *this to that unique type.
0188 //
0189 // Testing reveals this to compile MUCH faster than recursive approaches and
0190 // avoids compiler constexpr-time limits.
0191 template <typename Idx, typename... T> struct UintDataStorage;
0192 template <int... Idx, typename... T> struct UintDataStorage<std::integer_sequence<int, Idx...>, T...>
0193         : UintDataEntry<Idx, T>...
0194 {
0195     constexpr UintDataStorage(T &&... data)
0196         : UintDataEntry<Idx, T>(std::move(data))...
0197     {}
0198 
0199     template <typename F> constexpr void forEach(F &&f) const
0200     {
0201         [[maybe_unused]] auto invoke = [&f](const auto &entry) { f(entry.entry); return 0; };
0202         int dummy[] = {
0203             0,
0204             invoke(static_cast<const UintDataEntry<Idx, T> &>(*this))...
0205         };
0206         (void) dummy;
0207     }
0208 };
0209 } // namespace detail
0210 
0211 template <typename... Block> struct UintData
0212 {
0213     constexpr UintData(Block &&... data_)
0214         : data(std::move(data_)...)
0215     {}
0216 
0217     static constexpr uint count() { return sizeof...(Block); }
0218     static constexpr uint headerSize()
0219     {
0220         // same as:
0221         //   return (0 + ... + Block::headerSize());
0222         // but not using the fold expression to avoid exceeding compiler limits
0223         // (calculation done using int to get compile-time overflow checking)
0224         int total = 0;
0225         int sizes[] = { 0, Block::headerSize()... };
0226         for (int n : sizes)
0227             total += n;
0228         return total;
0229     }
0230     static constexpr uint payloadSize()
0231     {
0232         // ditto
0233         int total = 0;
0234         int sizes[] = { 0, Block::payloadSize()... };
0235         for (int n : sizes)
0236             total += n;
0237         return total;
0238     }
0239     static constexpr uint dataSize() { return headerSize() + payloadSize(); }
0240     static constexpr int metaTypeCount()
0241     {
0242         // ditto again
0243         int total = 0;
0244         int sizes[] = { 0, decltype(Block::metaTypes())::count()... };
0245         for (int n : sizes)
0246             total += n;
0247         return total;
0248     }
0249 
0250     template <typename Unique, typename Result> constexpr void
0251     copyTo(Result &result, size_t dataoffset, uint &metatypeoffset) const
0252     {
0253         uint *ptr = result.staticData.data;
0254         size_t payloadoffset = dataoffset + headerSize();
0255         data.forEach([&](const auto &input) {
0256             // copy the uint data
0257             q20::copy_n(input.header, input.headerSize(), ptr + dataoffset);
0258             q20::copy_n(input.payload, input.payloadSize(), ptr + payloadoffset);
0259             input.adjustOffsets(ptr, uint(dataoffset), uint(payloadoffset), metatypeoffset);
0260 
0261             // copy the metatypes
0262             decltype(input.metaTypes())::template copyTo<Unique>(result, metatypeoffset);
0263 
0264             dataoffset += input.headerSize();
0265             payloadoffset += input.payloadSize();
0266         });
0267     }
0268 
0269     template <typename F> constexpr void forEach(F &&f) const
0270     {
0271         data.forEach(std::forward<F>(f));
0272     }
0273 
0274 private:
0275     detail::UintDataStorage<std::make_integer_sequence<int, count()>, Block...> data;
0276 };
0277 
0278 template <int N> struct ClassInfos : detail::UintDataBlock<2 * N, 0>
0279 {
0280     constexpr ClassInfos() = default;
0281     constexpr ClassInfos(const std::array<uint, 2> (&infos)[N])
0282     {
0283         uint *out = this->header;
0284         for (int i = 0; i < N; ++i) {
0285             *out++ = infos[i][0];
0286             *out++ = infos[i][1];
0287         }
0288     }
0289 };
0290 
0291 template <typename PropertyType> struct PropertyData : detail::UintDataBlock<5, 0>
0292 {
0293     constexpr PropertyData(uint nameIndex, uint typeIndex, uint flags, uint notifyId = uint(-1), uint revision = 0)
0294     {
0295         this->header[0] = nameIndex;
0296         this->header[1] = typeIndex;
0297         this->header[2] = flags;
0298         this->header[3] = notifyId;
0299         this->header[4] = revision;
0300     }
0301 
0302     static constexpr auto metaTypes()
0303     { return detail::MetaTypeList<detail::TypeMustBeComplete, PropertyType>{}; }
0304 
0305     static constexpr void adjustOffsets(uint *, uint, uint, uint) noexcept {}
0306 };
0307 
0308 template <typename Enum, int N = 0>
0309 struct EnumData : detail::UintDataBlock<5, N * detail::payloadSizeForEnum<Enum>()>
0310 {
0311 private:
0312     static_assert(sizeof(Enum) <= 2 * sizeof(uint), "Cannot store enumeration of this size");
0313     template <typename T> struct RealEnum { using Type = T; };
0314     template <typename T> struct RealEnum<QFlags<T>> { using Type = T; };
0315 public:
0316     struct EnumEntry {
0317         int nameIndex;
0318         typename RealEnum<Enum>::Type value;
0319     };
0320 
0321     constexpr EnumData(uint nameOffset, uint aliasOffset, uint flags)
0322     {
0323         this->header[0] = nameOffset;
0324         this->header[1] = aliasOffset;
0325         this->header[2] = flags;
0326         this->header[3] = N;
0327         this->header[4] = 0;        // will be set in adjustOffsets()
0328 
0329         if (nameOffset != aliasOffset || QtPrivate::IsQFlags<Enum>::value)
0330             this->header[2] |= QtMocConstants::EnumIsFlag;
0331         if constexpr (q23::is_scoped_enum_v<Enum>)
0332             this->header[2] |= QtMocConstants::EnumIsScoped;
0333     }
0334 
0335     template <int Added> constexpr auto add(const EnumEntry (&entries)[Added]) const
0336     {
0337         EnumData<Enum, N + Added> result(this->header[0], this->header[1], this->header[2]);
0338 
0339         q20::copy_n(this->payload, this->payloadSize(), result.payload);
0340         uint o = this->payloadSize();
0341         for (auto entry : entries) {
0342             result.payload[o++] = uint(entry.nameIndex);
0343             auto value = qToUnderlying(entry.value);
0344             result.payload[o++] = uint(value);
0345         }
0346 
0347         if constexpr (sizeof(Enum) > sizeof(uint)) {
0348             static_assert(N == 0, "Unimplemented: merging with non-empty EnumData");
0349             result.header[2] |= QtMocConstants::EnumIs64Bit;
0350             for (auto entry : entries) {
0351                 auto value = qToUnderlying(entry.value);
0352                 result.payload[o++] = uint(value >> 32);
0353             }
0354         }
0355         return result;
0356     }
0357 
0358     static constexpr auto metaTypes()
0359     { return detail::MetaTypeList<detail::TypeMustBeComplete, Enum>{}; }
0360 
0361     static constexpr void
0362     adjustOffsets(uint *ptr, uint dataoffset, uint payloadoffset, uint metatypeoffset) noexcept
0363     {
0364         ptr[dataoffset + 4] += uint(payloadoffset);
0365         (void) metatypeoffset;
0366     }
0367 };
0368 
0369 template <typename F, uint ExtraFlags> struct FunctionData;
0370 template <typename Ret, typename... Args, uint ExtraFlags>
0371 struct FunctionData<Ret (Args...), ExtraFlags>
0372     : detail::UintDataBlock<6, 2 * sizeof...(Args) + 1 + (ExtraFlags & QtMocConstants::MethodRevisioned ? 1 : 0)>
0373 {
0374     static constexpr bool IsRevisioned = (ExtraFlags & QtMocConstants::MethodRevisioned) != 0;
0375     struct FunctionParameter {
0376         uint typeIdx;   // or static meta type ID
0377         uint nameIdx;
0378     };
0379     using ParametersArray = std::array<FunctionParameter, sizeof...(Args)>;
0380 
0381     static auto metaTypes()
0382     {
0383         using namespace QtMocConstants;
0384         if constexpr (std::is_same_v<Ret, NoType>) {
0385             // constructors have no return type
0386             static_assert((ExtraFlags & MethodConstructor) == MethodConstructor,
0387                     "NoType return type used on a non-constructor");
0388             static_assert((ExtraFlags & MethodIsConst) == 0,
0389                     "Constructors cannot be const");
0390             return detail::MetaTypeList<detail::TypeMayBeIncomplete, Args...>{};
0391         } else {
0392             static_assert((ExtraFlags & MethodConstructor) != MethodConstructor,
0393                     "Constructors must use NoType as return type");
0394             return detail::MetaTypeList<detail::TypeMayBeIncomplete, Ret, Args...>{};
0395         }
0396     }
0397 
0398     static constexpr void
0399     adjustOffsets(uint *ptr, uint dataoffset, uint payloadoffset, uint metatypeoffset) noexcept
0400     {
0401         if constexpr (IsRevisioned)
0402             ++payloadoffset;
0403         ptr[dataoffset + 2] += uint(payloadoffset);
0404         ptr[dataoffset + 5] = metatypeoffset;
0405     }
0406 
0407     constexpr
0408     FunctionData(uint nameIndex, uint tagIndex, uint flags,
0409                  uint returnType, ParametersArray params = {})
0410     {
0411         this->header[0] = nameIndex;
0412         this->header[1] = sizeof...(Args);
0413         this->header[2] = 0;        // will be set in adjustOffsets()
0414         this->header[3] = tagIndex;
0415         this->header[4] = flags | ExtraFlags;
0416         this->header[5] = 0;        // will be set in adjustOffsets()
0417 
0418         uint *p = this->payload;
0419         if constexpr (ExtraFlags & QtMocConstants::MethodRevisioned)
0420             ++p;
0421         *p++ = returnType;
0422         if constexpr (sizeof...(Args)) {
0423             for (uint i = 0; i < sizeof...(Args); ++i)
0424                 *p++ = params[i].typeIdx;
0425             for (uint i = 0; i < sizeof...(Args); ++i)
0426                 *p++ = params[i].nameIdx;
0427         } else {
0428             Q_UNUSED(params);
0429         }
0430     }
0431 
0432     constexpr
0433     FunctionData(uint nameIndex, uint tagIndex, uint flags, uint revision,
0434                  uint returnType, ParametersArray params = {})
0435 #ifdef __cpp_concepts
0436             requires(IsRevisioned)
0437 #endif
0438         : FunctionData(nameIndex, tagIndex, flags, returnType, params)
0439     {
0440         // note: we place the revision differently from meta object revision 12
0441         this->payload[0] = revision;
0442     }
0443 };
0444 
0445 template <typename Ret, typename... Args, uint ExtraFlags>
0446 struct FunctionData<Ret (Args...) const, ExtraFlags>
0447     : FunctionData<Ret (Args...), ExtraFlags | QtMocConstants::MethodIsConst>
0448 {
0449     using FunctionData<Ret (Args...), ExtraFlags | QtMocConstants::MethodIsConst>::FunctionData;
0450 };
0451 
0452 template <typename F> struct MethodData : FunctionData<F, QtMocConstants::MethodMethod>
0453 {
0454     using FunctionData<F, QtMocConstants::MethodMethod>::FunctionData;
0455 };
0456 
0457 template <typename F> struct SignalData : FunctionData<F, QtMocConstants::MethodSignal>
0458 {
0459     using FunctionData<F, QtMocConstants::MethodSignal>::FunctionData;
0460 };
0461 
0462 template <typename F> struct SlotData : FunctionData<F, QtMocConstants::MethodSlot>
0463 {
0464     using FunctionData<F, QtMocConstants::MethodSlot>::FunctionData;
0465 };
0466 
0467 template <typename F> struct ConstructorData : FunctionData<F, QtMocConstants::MethodConstructor>
0468 {
0469     using Base = FunctionData<F, QtMocConstants::MethodConstructor>;
0470 
0471     // the name for a constructor is always the class name (string index zero)
0472     // and it has no return type
0473     constexpr ConstructorData(uint tagIndex, uint flags, typename Base::ParametersArray params = {})
0474         : Base(0, tagIndex, flags, QMetaType::UnknownType, params)
0475     {}
0476 };
0477 
0478 template <typename F> struct RevisionedMethodData :
0479         FunctionData<F, QtMocConstants::MethodRevisioned | QtMocConstants::MethodMethod>
0480 {
0481     using FunctionData<F, QtMocConstants::MethodRevisioned | QtMocConstants::MethodMethod>::FunctionData;
0482 };
0483 
0484 template <typename F> struct RevisionedSignalData :
0485         FunctionData<F, QtMocConstants::MethodRevisioned | QtMocConstants::MethodSignal>
0486 {
0487     using FunctionData<F, QtMocConstants::MethodRevisioned | QtMocConstants::MethodSignal>::FunctionData;
0488 };
0489 
0490 template <typename F> struct RevisionedSlotData :
0491         FunctionData<F, QtMocConstants::MethodRevisioned | QtMocConstants::MethodSlot>
0492 {
0493     using FunctionData<F, QtMocConstants::MethodRevisioned | QtMocConstants::MethodSlot>::FunctionData;
0494 };
0495 
0496 template <typename F> struct RevisionedConstructorData :
0497         FunctionData<F, QtMocConstants::MethodRevisioned | QtMocConstants::MethodConstructor>
0498 {
0499     using Base = FunctionData<F, QtMocConstants::MethodRevisioned | QtMocConstants::MethodConstructor>;
0500 
0501     // the name for a constructor is always the class name (string index zero)
0502     // and it has no return type
0503     constexpr RevisionedConstructorData(uint tagIndex, uint flags, uint revision,
0504                                         typename Base::ParametersArray params = {})
0505         : Base(0, tagIndex, flags, revision, QMetaType::UnknownType, params)
0506     {}
0507 };
0508 
0509 template <typename ObjectType, typename Unique, typename Strings,
0510           typename Methods, typename Properties, typename Enums,
0511           typename Constructors = UintData<>, typename ClassInfo = detail::UintDataBlock<0, 0>>
0512 constexpr auto metaObjectData(uint flags, const Strings &strings,
0513                               const Methods &methods, const Properties &properties,
0514                               const Enums &enums, const Constructors &constructors = {},
0515                               const ClassInfo &classInfo = {})
0516 {
0517     constexpr uint MetaTypeCount = Properties::metaTypeCount()
0518             + Enums::metaTypeCount()
0519             + 1     // the gadget's or void
0520             + Methods::metaTypeCount()
0521             + Constructors::metaTypeCount();
0522 
0523     constexpr uint HeaderSize = 14;
0524     constexpr uint TotalSize = HeaderSize
0525             + Properties::dataSize()
0526             + Enums::dataSize()
0527             + Methods::dataSize()
0528             + Constructors::dataSize()
0529             + ClassInfo::headerSize() // + ClassInfo::payloadSize()
0530             + 1;    // empty EOD
0531 
0532     MetaObjectContents<TotalSize, 2 * Strings::StringCount, Strings::StringSize,
0533             MetaTypeCount> result = {};
0534     strings.writeTo(result.staticData.stringdata, result.staticData.strings);
0535 
0536     uint dataoffset = HeaderSize;
0537     uint metatypeoffset = 0;
0538     uint *data = result.staticData.data;
0539 
0540     data[0] = QtMocConstants::OutputRevision;
0541     data[1] = 0;     // class name index (it's always 0)
0542 
0543     data[2] = ClassInfo::headerSize() / 2;
0544     data[3] = ClassInfo::headerSize() ? dataoffset : 0;
0545     q20::copy_n(classInfo.header, classInfo.headerSize(), data + dataoffset);
0546     dataoffset += ClassInfo::headerSize();
0547 
0548     data[6] = properties.count();
0549     data[7] = properties.count() ? dataoffset : 0;
0550     properties.template copyTo<Unique>(result, dataoffset, metatypeoffset);
0551     dataoffset += properties.dataSize();
0552 
0553     data[8] = enums.count();
0554     data[9] = enums.count() ? dataoffset : 0;
0555     enums.template copyTo<Unique>(result, dataoffset, metatypeoffset);
0556     dataoffset += enums.dataSize();
0557 
0558     // the meta type referring to the object itself
0559     result.relocatingData.metaTypes[metatypeoffset++] = QMetaType::fromType<ObjectType>().iface();
0560 
0561     data[4] = methods.count();
0562     data[5] = methods.count() ? dataoffset : 0;
0563     methods.template copyTo<Unique>(result, dataoffset, metatypeoffset);
0564     dataoffset += methods.dataSize();
0565 
0566     data[10] = constructors.count();
0567     data[11] = constructors.count() ? dataoffset : 0;
0568     constructors.template copyTo<Unique>(result, dataoffset, metatypeoffset);
0569     dataoffset += constructors.dataSize();
0570 
0571     data[12] = flags;
0572 
0573     // count the number of signals
0574     if constexpr (Methods::count()) {
0575         constexpr uint MethodHeaderSize = Methods::headerSize() / Methods::count();
0576         const uint *ptr = &data[data[5]];
0577         const uint *end = &data[data[5] + MethodHeaderSize * Methods::count()];
0578         for ( ; ptr < end; ptr += MethodHeaderSize) {
0579             if ((ptr[4] & QtMocConstants::MethodSignal) == 0)
0580                 break;
0581             ++data[13];
0582         }
0583     }
0584 
0585     return result;
0586 }
0587 
0588 template <typename T> inline std::enable_if_t<std::is_enum_v<T>> assignFlags(void *v, T t) noexcept
0589 {
0590     *static_cast<T *>(v) = t;
0591 }
0592 
0593 template <typename T> inline std::enable_if_t<QtPrivate::IsQFlags<T>::value> assignFlags(void *v, T t) noexcept
0594 {
0595     *static_cast<T *>(v) = t;
0596 }
0597 
0598 #if QT_VERSION < QT_VERSION_CHECK(7, 0, 0)
0599 template <typename T>
0600 Q_DECL_DEPRECATED_X("Returning int/uint from a Q_PROPERTY that is a Q_FLAG is deprecated; "
0601                     "please update to return the actual property's type")
0602 inline void assignFlagsFromInteger(QFlags<T> &f, int i) noexcept
0603 {
0604      f = QFlag(i);
0605 }
0606 
0607 template <typename T, typename I>
0608 inline std::enable_if_t<QtPrivate::IsQFlags<T>::value && sizeof(T) == sizeof(int) && std::is_integral_v<I>>
0609 assignFlags(void *v, I i) noexcept
0610 {
0611     assignFlagsFromInteger(*static_cast<T *>(v), i);
0612 }
0613 #endif  // Qt 7
0614 
0615 } // namespace QtMocHelpers
0616 QT_END_NAMESPACE
0617 
0618 QT_USE_NAMESPACE
0619 
0620 #endif // QTMOCHELPERS_H