Back to home page

EIC code displayed by LXR

 
 

    


File indexing completed on 2026-09-17 09:25:04

0001 // Copyright (C) 2021 The Qt Company Ltd.
0002 // SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
0003 // Qt-Security score:significant reason:default
0004 
0005 #ifndef QNATIVEINTERFACE_H
0006 #define QNATIVEINTERFACE_H
0007 
0008 #include <QtCore/qglobal.h>
0009 
0010 QT_BEGIN_NAMESPACE
0011 
0012 // We declare a virtual non-inline function in the form
0013 // of the destructor, making it the key function. This
0014 // ensures that the typeinfo of the class is exported.
0015 // By being protected, we also ensure that pointers to
0016 // the interface can't be deleted.
0017 #define QT_DECLARE_NATIVE_INTERFACE_3(NativeInterface, Revision, BaseType) \
0018     protected: \
0019         virtual ~NativeInterface(); \
0020         \
0021         struct TypeInfo { \
0022             using baseType = BaseType; \
0023             static constexpr char const *name = QT_STRINGIFY(NativeInterface); \
0024             static constexpr int revision = Revision; \
0025         }; \
0026         \
0027         template <typename, typename> \
0028         friend struct QNativeInterface::Private::has_type_info; \
0029         \
0030         template <typename> \
0031         friend bool constexpr QNativeInterface::Private::hasTypeInfo(); \
0032         \
0033         template <typename> \
0034         friend struct QNativeInterface::Private::TypeInfo; \
0035     public: \
0036         NativeInterface() = default; \
0037         Q_DISABLE_COPY_MOVE(NativeInterface)
0038 
0039 // Revisioned interfaces only make sense when exposed through a base
0040 // type via QT_DECLARE_NATIVE_INTERFACE_ACCESSOR, as the revision
0041 // checks happen at that level (and not for normal dynamic_casts).
0042 #define QT_DECLARE_NATIVE_INTERFACE_2(NativeInterface, Revision) \
0043     static_assert(false, "Must provide a base type when specifying revision");
0044 
0045 #define QT_DECLARE_NATIVE_INTERFACE_1(NativeInterface) \
0046     QT_DECLARE_NATIVE_INTERFACE_3(NativeInterface, 0, void)
0047 
0048 #define QT_DECLARE_NATIVE_INTERFACE(...) \
0049     QT_OVERLOADED_MACRO(QT_DECLARE_NATIVE_INTERFACE, __VA_ARGS__)
0050 
0051 namespace QNativeInterface::Private {
0052 
0053     // Basic type-trait to verify that a given native interface has
0054     // all the required type information for us to evaluate it.
0055     template <typename NativeInterface, typename = void>
0056     struct has_type_info : std::false_type {};
0057 
0058     // The type-trait is friended by TypeInfo, so that we can
0059     // evaluate TypeInfo in the template arguments.
0060     template <typename NativeInterface>
0061     struct has_type_info<NativeInterface, std::void_t<
0062         typename NativeInterface::TypeInfo,
0063         typename NativeInterface::TypeInfo::baseType,
0064         decltype(&NativeInterface::TypeInfo::name),
0065         decltype(&NativeInterface::TypeInfo::revision)
0066         >> : std::true_type {};
0067 
0068     // We need to wrap the instantiation of has_type_info in a
0069     // function friended by TypeInfo, otherwise MSVC will not
0070     // let us evaluate TypeInfo in the template arguments.
0071     template <typename NativeInterface>
0072     bool constexpr hasTypeInfo()
0073     {
0074         return has_type_info<NativeInterface>::value;
0075     }
0076 
0077     template <typename NativeInterface>
0078     struct TypeInfo
0079     {
0080         // To ensure SFINAE works for hasTypeInfo we can't use it in a constexpr
0081         // variable that also includes an expression that relies on the type
0082         // info. This helper variable is okey, as it it self contained.
0083         static constexpr bool haveTypeInfo = hasTypeInfo<NativeInterface>();
0084 
0085         // We can then use the helper variable in a constexpr condition in a
0086         // function, which does not break SFINAE if haveTypeInfo is false.
0087         template <typename BaseType>
0088         static constexpr bool isCompatibleHelper()
0089         {
0090             if constexpr (haveTypeInfo)
0091                 return std::is_base_of<typename NativeInterface::TypeInfo::baseType, BaseType>::value;
0092             else
0093                 return false;
0094         }
0095 
0096         // MSVC however doesn't like constexpr functions in enable_if_t conditions,
0097         // so we need to wrap it yet again in a constexpr variable. This is fine,
0098         // as all the SFINAE magic has been resolved at this point.
0099         template <typename BaseType>
0100         static constexpr bool isCompatibleWith = isCompatibleHelper<BaseType>();
0101 
0102         // The revision and name accessors are not used in enable_if_t conditions,
0103         // so we can leave them as constexpr functions. As this class template is
0104         // friended by TypeInfo we can access the protected members of TypeInfo.
0105         static constexpr int revision()
0106         {
0107             if constexpr (haveTypeInfo)
0108                 return NativeInterface::TypeInfo::revision;
0109             else
0110                 return 0;
0111         }
0112 
0113         static constexpr char const *name()
0114         {
0115             if constexpr (haveTypeInfo)
0116                 return NativeInterface::TypeInfo::name;
0117             else
0118                 return nullptr;
0119         }
0120     };
0121 
0122     // Wrapper type to make the error message in case
0123     // of incompatible interface types read better.
0124     template <typename I>
0125     struct NativeInterface : TypeInfo<I> {};
0126 } // QNativeInterface::Private
0127 
0128 // Declares an accessor for the native interface
0129 #ifdef Q_QDOC
0130 #define QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(T) \
0131     template <typename QNativeInterface> \
0132     QNativeInterface *nativeInterface() const;
0133 #else
0134 #define QT_DECLARE_NATIVE_INTERFACE_ACCESSOR(T) \
0135     template <typename NativeInterface, typename TypeInfo = QNativeInterface::Private::NativeInterface<NativeInterface>, \
0136     typename BaseType = T, std::enable_if_t<TypeInfo::template isCompatibleWith<T>, bool> = true> \
0137     NativeInterface *nativeInterface() const \
0138     { \
0139         return static_cast<NativeInterface*>(resolveInterface( \
0140             TypeInfo::name(), TypeInfo::revision())); \
0141     } \
0142     protected: \
0143         void *resolveInterface(const char *name, int revision) const; \
0144     public:
0145 #endif
0146 
0147 QT_END_NAMESPACE
0148 
0149 #endif // QNATIVEINTERFACE_H