Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-06 09:18:15

0001 // Copyright (C) 2016 The Qt Company Ltd.
0002 // Copyright (C) 2016 Intel Corporation.
0003 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0004 // Qt-Security score:significant reason:default
0005 
0006 #ifndef QTYPEINFO_H
0007 #define QTYPEINFO_H
0008 
0009 #include <QtCore/qcompilerdetection.h>
0010 #include <QtCore/qcontainerfwd.h>
0011 
0012 #include <type_traits>
0013 
0014 QT_BEGIN_NAMESPACE
0015 
0016 class QDebug;
0017 
0018 /*
0019    QTypeInfo     - type trait functionality
0020 */
0021 
0022 namespace QtPrivate {
0023 
0024 // Helper for QTypeInfo<T>::isComplex, which used to be simply
0025 // !std::is_trivial_v but P3247 deprecated it for C++26. It used to be defined
0026 // (since C++11) by [class]/7 as: "A trivial class is a class that is trivially
0027 // copyable and has one or more default constructors, all of which are either
0028 // trivial or deleted and at least one of which is not deleted. [ Note: In
0029 // particular, a trivially copyable or trivial class does not have virtual
0030 // functions or virtual base classes. — end note ]".
0031 
0032 template <typename T>
0033 inline constexpr bool qIsComplex =
0034         !std::is_trivially_default_constructible_v<T> || !std::is_trivially_copyable_v<T>;
0035 
0036 // A trivially copyable class must also have a trivial, non-deleted
0037 // destructor [class.prop/1.3], CWG1734. Some implementations don't
0038 // check for a trivial destructor, because of backwards compatibility
0039 // with C++98's definition of trivial copyability.
0040 // Since trivial copiability has implications for the ABI, implementations
0041 // can't "just fix" their traits. So, although formally redundant, we
0042 // explicitly check for trivial destruction here.
0043 template <typename T>
0044 inline constexpr bool qIsRelocatable =  std::is_trivially_copyable_v<T> && std::is_trivially_destructible_v<T>;
0045 
0046 // Denotes types that are trivially default constructible, and for which
0047 // value-initialization can be achieved by filling their storage with 0 bits.
0048 // There is no type trait we can use for this, so we hardcode a list of
0049 // possibilities that we know are OK on the architectures that we support.
0050 // The most notable exception are pointers to data members, which for instance
0051 // on the Itanium ABI are initialized to -1.
0052 template <typename T>
0053 inline constexpr bool qIsValueInitializationBitwiseZero =
0054         std::is_scalar_v<T> && !std::is_member_object_pointer_v<T>;
0055 
0056 }
0057 
0058 /*
0059   The catch-all template.
0060 */
0061 
0062 template <typename T>
0063 class QTypeInfo
0064 {
0065 public:
0066     enum {
0067         isPointer [[deprecated("Use std::is_pointer instead")]] = std::is_pointer_v<T>,
0068         isIntegral [[deprecated("Use std::is_integral instead")]] = std::is_integral_v<T>,
0069         isComplex = QtPrivate::qIsComplex<T>,
0070         isRelocatable = QtPrivate::qIsRelocatable<T>,
0071         isValueInitializationBitwiseZero = QtPrivate::qIsValueInitializationBitwiseZero<T>,
0072     };
0073 };
0074 
0075 template<>
0076 class QTypeInfo<void>
0077 {
0078 public:
0079     enum {
0080         isPointer [[deprecated("Use std::is_pointer instead")]] = false,
0081         isIntegral [[deprecated("Use std::is_integral instead")]] = false,
0082         isComplex = false,
0083         isRelocatable = false,
0084         isValueInitializationBitwiseZero = false,
0085     };
0086 };
0087 
0088 /*!
0089     \class QTypeInfoMerger
0090     \inmodule QtCore
0091     \internal
0092 
0093     \brief QTypeInfoMerger merges the QTypeInfo flags of T1, T2... and presents them
0094     as a QTypeInfo<T> would do.
0095 
0096     Let's assume that we have a simple set of structs:
0097 
0098     \snippet code/src_corelib_global_qglobal.cpp 50
0099 
0100     To create a proper QTypeInfo specialization for A struct, we have to check
0101     all sub-components; B, C and D, then take the lowest common denominator and call
0102     Q_DECLARE_TYPEINFO with the resulting flags. An easier and less fragile approach is to
0103     use QTypeInfoMerger, which does that automatically. So struct A would have
0104     the following QTypeInfo definition:
0105 
0106     \snippet code/src_corelib_global_qglobal.cpp 51
0107 */
0108 template <class T, class...Ts>
0109 class QTypeInfoMerger
0110 {
0111     static_assert(sizeof...(Ts) > 0);
0112 public:
0113     static constexpr bool isComplex = ((QTypeInfo<Ts>::isComplex) || ...);
0114     static constexpr bool isRelocatable = ((QTypeInfo<Ts>::isRelocatable) && ...);
0115     [[deprecated("Use std::is_pointer instead")]] static constexpr bool isPointer = false;
0116     [[deprecated("Use std::is_integral instead")]] static constexpr bool isIntegral = false;
0117     static constexpr bool isValueInitializationBitwiseZero = false;
0118     static_assert(!isRelocatable ||
0119                   std::is_copy_constructible_v<T> ||
0120                   std::is_move_constructible_v<T>,
0121                   "All Ts... are Q_RELOCATABLE_TYPE, but T is neither copy- nor move-constructible, "
0122                   "so cannot be Q_RELOCATABLE_TYPE. Please mark T as Q_COMPLEX_TYPE manually.");
0123 };
0124 
0125 // QTypeInfo for std::pair:
0126 //   std::pair is spec'ed to be struct { T1 first; T2 second; }, so, unlike tuple<>,
0127 //   we _can_ specialize QTypeInfo for pair<>:
0128 template <class T1, class T2>
0129 class QTypeInfo<std::pair<T1, T2>> : public QTypeInfoMerger<std::pair<T1, T2>, T1, T2> {};
0130 
0131 #define Q_DECLARE_MOVABLE_CONTAINER(CONTAINER) \
0132 template <typename ...T> \
0133 class QTypeInfo<CONTAINER<T...>> \
0134 { \
0135 public: \
0136     enum { \
0137         isPointer [[deprecated("Use std::is_pointer instead")]] = false, \
0138         isIntegral [[deprecated("Use std::is_integral instead")]] = false, \
0139         isComplex = true, \
0140         isRelocatable = true, \
0141         isValueInitializationBitwiseZero = false, \
0142     }; \
0143 }
0144 
0145 Q_DECLARE_MOVABLE_CONTAINER(QList);
0146 Q_DECLARE_MOVABLE_CONTAINER(QQueue);
0147 Q_DECLARE_MOVABLE_CONTAINER(QStack);
0148 Q_DECLARE_MOVABLE_CONTAINER(QSet);
0149 Q_DECLARE_MOVABLE_CONTAINER(QMap);
0150 Q_DECLARE_MOVABLE_CONTAINER(QMultiMap);
0151 Q_DECLARE_MOVABLE_CONTAINER(QHash);
0152 Q_DECLARE_MOVABLE_CONTAINER(QMultiHash);
0153 Q_DECLARE_MOVABLE_CONTAINER(QCache);
0154 
0155 #undef Q_DECLARE_MOVABLE_CONTAINER
0156 
0157 /*
0158    Specialize a specific type with:
0159 
0160      Q_DECLARE_TYPEINFO(type, flags);
0161 
0162    where 'type' is the name of the type to specialize and 'flags' is
0163    logically-OR'ed combination of the flags below.
0164 */
0165 enum { /* TYPEINFO flags */
0166     Q_COMPLEX_TYPE = 0,
0167     Q_PRIMITIVE_TYPE = 0x1,
0168     Q_RELOCATABLE_TYPE = 0x2,
0169     Q_MOVABLE_TYPE = 0x2,
0170     Q_DUMMY_TYPE = 0x4,
0171 };
0172 
0173 #define Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS) \
0174 class QTypeInfo<TYPE > \
0175 { \
0176 public: \
0177     enum { \
0178         isComplex = (((FLAGS) & Q_PRIMITIVE_TYPE) == 0) && QtPrivate::qIsComplex<TYPE>, \
0179         isRelocatable = !isComplex || ((FLAGS) & Q_RELOCATABLE_TYPE) || QtPrivate::qIsRelocatable<TYPE>, \
0180         isPointer [[deprecated("Use std::is_pointer instead")]] = std::is_pointer_v< TYPE >, \
0181         isIntegral [[deprecated("Use std::is_integral instead")]] = std::is_integral< TYPE >::value, \
0182         isValueInitializationBitwiseZero = QtPrivate::qIsValueInitializationBitwiseZero<TYPE>, \
0183     }; \
0184     static_assert(!QTypeInfo<TYPE>::isRelocatable || \
0185                   std::is_copy_constructible_v<TYPE > || \
0186                   std::is_move_constructible_v<TYPE >, \
0187                   #TYPE " is neither copy- nor move-constructible, so cannot be Q_RELOCATABLE_TYPE"); \
0188 }
0189 
0190 #define Q_DECLARE_TYPEINFO(TYPE, FLAGS) \
0191 template<> \
0192 Q_DECLARE_TYPEINFO_BODY(TYPE, FLAGS)
0193 
0194 /* Specialize QTypeInfo for QFlags<T> */
0195 template<typename T> class QFlags;
0196 template<typename T>
0197 Q_DECLARE_TYPEINFO_BODY(QFlags<T>, Q_PRIMITIVE_TYPE);
0198 
0199 QT_END_NAMESPACE
0200 #endif // QTYPEINFO_H