diff options
Diffstat (limited to 'src/corelib/global')
24 files changed, 770 insertions, 373 deletions
diff --git a/src/corelib/global/qassert.cpp b/src/corelib/global/qassert.cpp index 6a29cbfa21..7c0064ac2f 100644 --- a/src/corelib/global/qassert.cpp +++ b/src/corelib/global/qassert.cpp @@ -195,36 +195,6 @@ void qBadAlloc() */ /*! - \macro QT_TERMINATE_ON_EXCEPTION(expr) - \relates <QtGlobal> - \internal - - In general, use of the Q_DECL_NOEXCEPT macro is preferred over - Q_DECL_NOTHROW, because it exhibits well-defined behavior and - supports the more powerful Q_DECL_NOEXCEPT_EXPR variant. However, - use of Q_DECL_NOTHROW has the advantage that Windows builds - benefit on a wide range or compiler versions that do not yet - support the C++11 noexcept feature. - - It may therefore be beneficial to use Q_DECL_NOTHROW and emulate - the C++11 behavior manually with an embedded try/catch. - - Qt provides the QT_TERMINATE_ON_EXCEPTION(expr) macro for this - purpose. It either expands to \c expr (if Qt is compiled without - exception support or the compiler supports C++11 noexcept - semantics) or to - \snippet code/src_corelib_global_qglobal.cpp qterminate - otherwise. - - Since this macro expands to just \c expr if the compiler supports - C++11 noexcept, expecting the compiler to take over responsibility - of calling std::terminate() in that case, it should not be used - outside Q_DECL_NOTHROW functions. - - \sa Q_DECL_NOEXCEPT, Q_DECL_NOTHROW, qTerminate() -*/ - -/*! \macro void Q_UNREACHABLE() \relates <QtAssert> \since 5.0 diff --git a/src/corelib/global/qcompare.cpp b/src/corelib/global/qcompare.cpp index ac220b8434..4df6146b10 100644 --- a/src/corelib/global/qcompare.cpp +++ b/src/corelib/global/qcompare.cpp @@ -149,6 +149,7 @@ CHECK(strong, equivalent); /*! \class Qt::strong_ordering \inmodule QtCore + \inheaderfile QtCompare \brief Qt::strong_ordering represents a comparison where equivalent values are indistinguishable. \sa Qt::weak_ordering, Qt::partial_ordering, {Comparison types overview} @@ -334,6 +335,7 @@ CHECK(strong, equivalent); /*! \class Qt::weak_ordering \inmodule QtCore + \inheaderfile QtCompare \brief Qt::weak_ordering represents a comparison where equivalent values are still distinguishable. \sa Qt::strong_ordering, Qt::partial_ordering, {Comparison types overview} @@ -484,6 +486,7 @@ CHECK(strong, equivalent); /*! \class Qt::partial_ordering \inmodule QtCore + \inheaderfile QtCompare \brief Qt::partial_ordering represents the result of a comparison that allows for unordered results. \sa Qt::strong_ordering, Qt::weak_ordering, {Comparison types overview} @@ -1271,9 +1274,12 @@ CHECK(strong, equivalent); \l Qt::partial_ordering::unordered is returned. */ +#if QT_DEPRECATED_SINCE(6, 8) /*! \fn template <typename LeftType, typename RightType, Qt::if_compatible_pointers<LeftType, RightType> = true> Qt::compareThreeWay(const LeftType *lhs, const RightType *rhs) \since 6.7 + \deprecated [6.8] Wrap the pointers into Qt::totally_ordered_wrapper and + use the respective Qt::compareThreeWay() overload instead. \relates <QtCompare> \overload @@ -1286,6 +1292,7 @@ CHECK(strong, equivalent); Returns an instance of \l Qt::strong_ordering that represents the relation between \a lhs and \a rhs. */ +#endif // QT_DEPRECATED_SINCE(6, 8) /*! \fn template <class Enum, Qt::if_enum<Enum> = true> Qt::compareThreeWay(Enum lhs, Enum rhs) @@ -1306,6 +1313,86 @@ CHECK(strong, equivalent); */ /*! + \fn template <typename T, typename U, Qt::if_compatible_pointers<T, U> = true> Qt::compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, Qt::totally_ordered_wrapper<U*> rhs) + \since 6.8 + \relates <QtCompare> + \overload + + Implements three-way comparison of pointers that are wrapped into + \l Qt::totally_ordered_wrapper. Uses + \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order} + {strict total order over pointers} when doing the comparison. + + \note This function participates in overload resolution if \c T and \c U + are the same type, or base and derived types. + + Returns an instance of \l Qt::strong_ordering that represents the relation + between \a lhs and \a rhs. +*/ + +/*! + \fn template <typename T, typename U, Qt::if_compatible_pointers<T, U> = true> Qt::compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, U *rhs) + \since 6.8 + \relates <QtCompare> + \overload + + Implements three-way comparison of a pointer wrapped into + \l Qt::totally_ordered_wrapper with a normal pointer. Uses + \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order} + {strict total order over pointers} when doing the comparison. + + \note This function participates in overload resolution if \c T and \c U + are the same type, or base and derived types. + + Returns an instance of \l Qt::strong_ordering that represents the relation + between \a lhs and \a rhs. +*/ + +/*! + \fn template <typename T, typename U, Qt::if_compatible_pointers<T, U> = true> Qt::compareThreeWay(U *lhs, Qt::totally_ordered_wrapper<T*> rhs) + \since 6.8 + \relates <QtCompare> + \overload + + Implements three-way comparison of a normal pointer with a pointer wrapped + into \l Qt::totally_ordered_wrapper. Uses + \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order} + {strict total order over pointers} when doing the comparison. + + \note This function participates in overload resolution if \c T and \c U + are the same type, or base and derived types. + + Returns an instance of \l Qt::strong_ordering that represents the relation + between \a lhs and \a rhs. +*/ + +/*! + \fn template <typename T> Qt::compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, std::nullptr_t rhs) + \since 6.8 + \relates <QtCompare> + \overload + + Implements three-way comparison of a pointer wrapped into + \l Qt::totally_ordered_wrapper with \c {std::nullptr_t}. + + Returns an instance of \l Qt::strong_ordering that represents the relation + between \a lhs and \a rhs. +*/ + +/*! + \fn template <typename T> Qt::compareThreeWay(std::nullptr_t lhs, Qt::totally_ordered_wrapper<T*> rhs) + \since 6.8 + \relates <QtCompare> + \overload + + Implements three-way comparison of \c {std::nullptr_t} with a pointer + wrapped into \l Qt::totally_ordered_wrapper. + + Returns an instance of \l Qt::strong_ordering that represents the relation + between \a lhs and \a rhs. +*/ + +/*! \fn template <typename LeftType, typename RightType> qCompareThreeWay(const LeftType &lhs, const RightType &rhs) \since 6.7 \relates <QtCompare> @@ -1354,4 +1441,57 @@ CHECK(strong, equivalent); \sa Qt::partial_ordering, Qt::weak_ordering, Qt::strong_ordering */ +/*! + \class Qt::totally_ordered_wrapper + \inmodule QtCore + \inheaderfile QtCompare + \brief Qt::totally_ordered_wrapper is a wrapper type that provides strict + total order for the wrapped types. + \since 6.8 + + One of its primary usecases is to prevent \e {Undefined Behavior} (UB) when + comparing pointers. + + Consider the following simple class: + + \code + template <typename T> + struct PointerWrapperBad { + int val; + T *ptr; + }; + \endcode + + Lexicographical comparison of the two instances of the \c PointerWrapperBad + type would result in UB, because it will call \c {operator<()} or + \c {operator<=>()} on the \c {ptr} members. + + To fix it, use the new wrapper type: + + \code + template <typename T> + struct PointerWrapperGood { + int val; + Qt::totally_ordered_wrapper<T *> ptr; + + friend bool + operator==(PointerWrapperGood lhs, PointerWrapperGood rhs) noexcept = default; + friend auto + operator<=>(PointerWrapperGood lhs, PointerWrapperGood rhs) noexecpt = default; + }; + \endcode + + The \c {operator<()} and (if available) \c {operator<=>()} operators for + the \c {Qt::totally_ordered_wrapper} type use the + \l {https://en.cppreference.com/w/cpp/utility/functional/less}{std::less} + and \l {https://en.cppreference.com/w/cpp/utility/compare/compare_three_way} + {std::compare_three_way} function objects respectively, providing + \l {https://en.cppreference.com/w/cpp/language/operator_comparison#Pointer_total_order} + {strict total order over pointers} when doing the comparison. + + As a result, the relational operators for \c {PointerWrapperGood::ptr} + member will be well-defined, and we can even \c {=default} the relational + operators for the \c {PointerWrapperGood} class, like it's shown above. +*/ + QT_END_NAMESPACE diff --git a/src/corelib/global/qcomparehelpers.h b/src/corelib/global/qcomparehelpers.h index 0e43ac296b..2da7fbd825 100644 --- a/src/corelib/global/qcomparehelpers.h +++ b/src/corelib/global/qcomparehelpers.h @@ -16,6 +16,7 @@ #include <QtCore/qoverload.h> #include <QtCore/qttypetraits.h> +#include <QtCore/qtypeinfo.h> #include <QtCore/qtypes.h> #ifdef __cpp_lib_three_way_comparison @@ -23,7 +24,7 @@ #endif #include <QtCore/q20type_traits.h> -#include <functional> // std::less +#include <functional> // std::less, std::hash QT_BEGIN_NAMESPACE @@ -145,8 +146,8 @@ template <typename In> constexpr auto to_Qt(In in) noexcept noexcept(noexcept(compareThreeWay(rhs, lhs))) \ { \ const auto r = compareThreeWay(rhs, lhs); \ - if (r > 0) return std::strong_ordering::less; \ - if (r < 0) return std::strong_ordering::greater; \ + if (is_gt(r)) return std::strong_ordering::less; \ + if (is_lt(r)) return std::strong_ordering::greater; \ return r; \ } @@ -157,8 +158,8 @@ template <typename In> constexpr auto to_Qt(In in) noexcept noexcept(noexcept(compareThreeWay(rhs, lhs))) \ { \ const auto r = compareThreeWay(rhs, lhs); \ - if (r > 0) return std::weak_ordering::less; \ - if (r < 0) return std::weak_ordering::greater; \ + if (is_gt(r)) return std::weak_ordering::less; \ + if (is_lt(r)) return std::weak_ordering::greater; \ return r; \ } @@ -169,8 +170,8 @@ template <typename In> constexpr auto to_Qt(In in) noexcept noexcept(noexcept(compareThreeWay(rhs, lhs))) \ { \ const auto r = compareThreeWay(rhs, lhs); \ - if (r > 0) return std::partial_ordering::less; \ - if (r < 0) return std::partial_ordering::greater; \ + if (is_gt(r)) return std::partial_ordering::less; \ + if (is_lt(r)) return std::partial_ordering::greater; \ return r; \ } @@ -218,19 +219,19 @@ template <typename In> constexpr auto to_Qt(In in) noexcept Attributes \ friend Constexpr bool operator<(LeftType const &lhs, RightType const &rhs) \ noexcept(noexcept(compareThreeWay(lhs, rhs))) \ - { return compareThreeWay(lhs, rhs) < 0; } \ + { return is_lt(compareThreeWay(lhs, rhs)); } \ Attributes \ friend Constexpr bool operator>(LeftType const &lhs, RightType const &rhs) \ noexcept(noexcept(compareThreeWay(lhs, rhs))) \ - { return compareThreeWay(lhs, rhs) > 0; } \ + { return is_gt(compareThreeWay(lhs, rhs)); } \ Attributes \ friend Constexpr bool operator<=(LeftType const &lhs, RightType const &rhs) \ noexcept(noexcept(compareThreeWay(lhs, rhs))) \ - { return compareThreeWay(lhs, rhs) <= 0; } \ + { return is_lteq(compareThreeWay(lhs, rhs)); } \ Attributes \ friend Constexpr bool operator>=(LeftType const &lhs, RightType const &rhs) \ noexcept(noexcept(compareThreeWay(lhs, rhs))) \ - { return compareThreeWay(lhs, rhs) >= 0; } + { return is_gteq(compareThreeWay(lhs, rhs)); } #define QT_DECLARE_ORDERING_HELPER_PARTIAL(LeftType, RightType, Constexpr, Attributes) \ QT_DECLARE_ORDERING_HELPER_TEMPLATE(Qt::partial_ordering, LeftType, RightType, Constexpr, \ @@ -255,19 +256,19 @@ template <typename In> constexpr auto to_Qt(In in) noexcept Attributes \ friend Constexpr bool operator<(RightType const &lhs, LeftType const &rhs) \ noexcept(noexcept(compareThreeWay(rhs, lhs))) \ - { return compareThreeWay(rhs, lhs) > 0; } \ + { return is_gt(compareThreeWay(rhs, lhs)); } \ Attributes \ friend Constexpr bool operator>(RightType const &lhs, LeftType const &rhs) \ noexcept(noexcept(compareThreeWay(rhs, lhs))) \ - { return compareThreeWay(rhs, lhs) < 0; } \ + { return is_lt(compareThreeWay(rhs, lhs)); } \ Attributes \ friend Constexpr bool operator<=(RightType const &lhs, LeftType const &rhs) \ noexcept(noexcept(compareThreeWay(rhs, lhs))) \ - { return compareThreeWay(rhs, lhs) >= 0; } \ + { return is_gteq(compareThreeWay(rhs, lhs)); } \ Attributes \ friend Constexpr bool operator>=(RightType const &lhs, LeftType const &rhs) \ noexcept(noexcept(compareThreeWay(rhs, lhs))) \ - { return compareThreeWay(rhs, lhs) <= 0; } + { return is_lteq(compareThreeWay(rhs, lhs)); } #define QT_DECLARE_REVERSED_ORDERING_HELPER_PARTIAL(LeftType, RightType, Constexpr, Attributes) \ QT_DECLARE_REVERSED_ORDERING_HELPER_TEMPLATE(Qt::partial_ordering, LeftType, RightType, \ @@ -450,6 +451,26 @@ constexpr bool IsFloatType_v<QtPrivate::NativeFloat16Type> = true; } // namespace QtPrivate +namespace QtOrderingPrivate { + +template <typename T, typename U> +constexpr Qt::strong_ordering +strongOrderingCompareDefaultImpl(T lhs, U rhs) noexcept +{ +#ifdef __cpp_lib_three_way_comparison + return lhs <=> rhs; +#else + if (lhs == rhs) + return Qt::strong_ordering::equivalent; + else if (lhs < rhs) + return Qt::strong_ordering::less; + else + return Qt::strong_ordering::greater; +#endif // __cpp_lib_three_way_comparison +} + +} // namespace QtOrderingPrivate + namespace Qt { template <typename T> @@ -526,8 +547,11 @@ constexpr Qt::partial_ordering compareThreeWay(FloatType lhs, IntType rhs) noexc return compareThreeWay(lhs, FloatType(rhs)); } +#if QT_DEPRECATED_SINCE(6, 8) + template <typename LeftType, typename RightType, if_compatible_pointers<LeftType, RightType> = true> +QT_DEPRECATED_VERSION_X_6_8("Wrap the pointers into Qt::totally_ordered_wrapper and use the respective overload instead.") constexpr Qt::strong_ordering compareThreeWay(const LeftType *lhs, const RightType *rhs) noexcept { #ifdef __cpp_lib_three_way_comparison @@ -543,25 +567,194 @@ constexpr Qt::strong_ordering compareThreeWay(const LeftType *lhs, const RightTy } template <typename T> +QT_DEPRECATED_VERSION_X_6_8("Wrap the pointer into Qt::totally_ordered_wrapper and use the respective overload instead.") constexpr Qt::strong_ordering compareThreeWay(const T *lhs, std::nullptr_t rhs) noexcept { return compareThreeWay(lhs, static_cast<const T *>(rhs)); } template <typename T> +QT_DEPRECATED_VERSION_X_6_8("Wrap the pointer into Qt::totally_ordered_wrapper and use the respective overload instead.") constexpr Qt::strong_ordering compareThreeWay(std::nullptr_t lhs, const T *rhs) noexcept { return compareThreeWay(static_cast<const T *>(lhs), rhs); } +#endif // QT_DEPRECATED_SINCE(6, 8) + template <class Enum, if_enum<Enum> = true> constexpr Qt::strong_ordering compareThreeWay(Enum lhs, Enum rhs) noexcept { return compareThreeWay(qToUnderlying(lhs), qToUnderlying(rhs)); } - } // namespace Qt +namespace QtOrderingPrivate { + +template <typename Head, typename...Tail, std::size_t...Is> +constexpr std::tuple<Tail...> qt_tuple_pop_front_impl(const std::tuple<Head, Tail...> &t, + std::index_sequence<Is...>) noexcept +{ + return std::tuple<Tail...>(std::get<Is + 1>(t)...); +} + +template <typename Head, typename...Tail> +constexpr std::tuple<Tail...> qt_tuple_pop_front(const std::tuple<Head, Tail...> &t) noexcept +{ + return qt_tuple_pop_front_impl(t, std::index_sequence_for<Tail...>{}); +} + +template <typename LhsHead, typename...LhsTail, typename RhsHead, typename...RhsTail> +constexpr auto compareThreeWayMulti(const std::tuple<LhsHead, LhsTail...> &lhs, // ie. not empty + const std::tuple<RhsHead, RhsTail...> &rhs) noexcept +{ + static_assert(sizeof...(LhsTail) == sizeof...(RhsTail), + // expanded together below, but provide a nicer error message: + "The tuple arguments have to have the same size."); + + using Qt::compareThreeWay; + using R = std::common_type_t< + decltype(compareThreeWay(std::declval<LhsHead>(), std::declval<RhsHead>())), + decltype(compareThreeWay(std::declval<LhsTail>(), std::declval<RhsTail>()))... + >; + + const auto &l = std::get<0>(lhs); + const auto &r = std::get<0>(rhs); + static_assert(noexcept(compareThreeWay(l, r)), + "This function requires all relational operators to be noexcept."); + const auto res = compareThreeWay(l, r); + if constexpr (sizeof...(LhsTail) > 0) { + if (is_eq(res)) + return R{compareThreeWayMulti(qt_tuple_pop_front(lhs), qt_tuple_pop_front(rhs))}; + } + return R{res}; +} + +} //QtOrderingPrivate + +namespace Qt { +// A wrapper class that adapts the wrappee to use the strongly-ordered +// <functional> function objects for implementing the relational operators. +// Mostly useful to avoid UB on pointers (which it currently mandates P to be), +// because all the comparison helpers (incl. std::compare_three_way on +// std::tuple<T*>!) will use the language-level operators. +// +template <typename P> +class totally_ordered_wrapper +{ + static_assert(std::is_pointer_v<P>); + using T = std::remove_pointer_t<P>; + + P ptr; +public: + totally_ordered_wrapper() noexcept = default; + Q_IMPLICIT constexpr totally_ordered_wrapper(std::nullptr_t) + // requires std::is_pointer_v<P> + : totally_ordered_wrapper(P{nullptr}) {} + explicit constexpr totally_ordered_wrapper(P p) noexcept : ptr(p) {} + + constexpr P get() const noexcept { return ptr; } + constexpr void reset(P p) noexcept { ptr = p; } + constexpr P operator->() const noexcept { return get(); } + constexpr T& operator*() const noexcept { return *get(); } + + explicit constexpr operator bool() const noexcept { return get(); } + +private: + // TODO: Replace the constraints with std::common_type_t<P, U> when + // a bug in VxWorks is fixed! + template <typename T, typename U> + using if_compatible_types = + std::enable_if_t<std::conjunction_v<std::is_pointer<T>, + std::is_pointer<U>, + std::disjunction<std::is_convertible<T, U>, + std::is_convertible<U, T>>>, + bool>; + +#define MAKE_RELOP(Ret, op, Op) \ + template <typename U = P, if_compatible_types<P, U> = true> \ + friend constexpr Ret operator op (const totally_ordered_wrapper<P> &lhs, const totally_ordered_wrapper<U> &rhs) noexcept \ + { return std:: Op {}(lhs.ptr, rhs.get()); } \ + template <typename U = P, if_compatible_types<P, U> = true> \ + friend constexpr Ret operator op (const totally_ordered_wrapper<P> &lhs, const U &rhs) noexcept \ + { return std:: Op {}(lhs.ptr, rhs ); } \ + template <typename U = P, if_compatible_types<P, U> = true> \ + friend constexpr Ret operator op (const U &lhs, const totally_ordered_wrapper<P> &rhs) noexcept \ + { return std:: Op {}(lhs, rhs.ptr); } \ + friend constexpr Ret operator op (const totally_ordered_wrapper &lhs, std::nullptr_t) noexcept \ + { return std:: Op {}(lhs.ptr, P(nullptr)); } \ + friend constexpr Ret operator op (std::nullptr_t, const totally_ordered_wrapper &rhs) noexcept \ + { return std:: Op {}(P(nullptr), rhs.ptr); } \ + /* end */ + MAKE_RELOP(bool, ==, equal_to<>) + MAKE_RELOP(bool, !=, not_equal_to<>) + MAKE_RELOP(bool, < , less<>) + MAKE_RELOP(bool, <=, less_equal<>) + MAKE_RELOP(bool, > , greater<>) + MAKE_RELOP(bool, >=, greater_equal<>) +#ifdef __cpp_lib_three_way_comparison + MAKE_RELOP(auto, <=>, compare_three_way) +#endif +#undef MAKE_RELOP + friend void qt_ptr_swap(totally_ordered_wrapper &lhs, totally_ordered_wrapper &rhs) noexcept + { qt_ptr_swap(lhs.ptr, rhs.ptr); } + friend void swap(totally_ordered_wrapper &lhs, totally_ordered_wrapper &rhs) noexcept + { qt_ptr_swap(lhs, rhs); } + friend size_t qHash(totally_ordered_wrapper key, size_t seed = 0) noexcept + { return qHash(key.ptr, seed); } +}; + +template <typename T, typename U, if_compatible_pointers<T, U> = true> +constexpr Qt::strong_ordering +compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, Qt::totally_ordered_wrapper<U*> rhs) noexcept +{ + return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs); +} + +template <typename T, typename U, if_compatible_pointers<T, U> = true> +constexpr Qt::strong_ordering +compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, U *rhs) noexcept +{ + return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs); +} + +template <typename T, typename U, if_compatible_pointers<T, U> = true> +constexpr Qt::strong_ordering +compareThreeWay(U *lhs, Qt::totally_ordered_wrapper<T*> rhs) noexcept +{ + return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs); +} + +template <typename T> +constexpr Qt::strong_ordering +compareThreeWay(Qt::totally_ordered_wrapper<T*> lhs, std::nullptr_t rhs) noexcept +{ + return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs); +} + +template <typename T> +constexpr Qt::strong_ordering +compareThreeWay(std::nullptr_t lhs, Qt::totally_ordered_wrapper<T*> rhs) noexcept +{ + return QtOrderingPrivate::strongOrderingCompareDefaultImpl(lhs, rhs); +} + +} //Qt + +template <typename P> +class QTypeInfo<Qt::totally_ordered_wrapper<P>> : public QTypeInfo<P> {}; + QT_END_NAMESPACE +namespace std { + template <typename P> + struct hash<QT_PREPEND_NAMESPACE(Qt::totally_ordered_wrapper)<P>> + { + using argument_type = QT_PREPEND_NAMESPACE(Qt::totally_ordered_wrapper)<P>; + using result_type = size_t; + constexpr result_type operator()(argument_type w) const noexcept + { return std::hash<P>{}(w.get()); } + }; +} + #endif // QCOMPAREHELPERS_H diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h index 4d80f23786..c2fe4661f6 100644 --- a/src/corelib/global/qconfig-bootstrapped.h +++ b/src/corelib/global/qconfig-bootstrapped.h @@ -72,6 +72,8 @@ # define QT_FEATURE_linkat -1 #endif #define QT_FEATURE_lttng -1 +#define QT_FEATURE_memmem -1 +#define QT_FEATURE_memrchr -1 #define QT_NO_QOBJECT #define QT_FEATURE_process -1 #define QT_FEATURE_regularexpression 1 diff --git a/src/corelib/global/qexceptionhandling.h b/src/corelib/global/qexceptionhandling.h index 76c6185c3e..7ffd0798f6 100644 --- a/src/corelib/global/qexceptionhandling.h +++ b/src/corelib/global/qexceptionhandling.h @@ -28,17 +28,11 @@ Q_NORETURN Q_DECL_COLD_FUNCTION Q_CORE_EXPORT void qTerminate() noexcept; # define QT_CATCH(A) else # define QT_THROW(A) qt_noop() # define QT_RETHROW qt_noop() -# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (false) #else # define QT_TRY try # define QT_CATCH(A) catch (A) # define QT_THROW(A) throw A # define QT_RETHROW throw -# ifdef Q_COMPILER_NOEXCEPT -# define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (false) -# else -# define QT_TERMINATE_ON_EXCEPTION(expr) do { try { expr; } catch (...) { qTerminate(); } } while (false) -# endif #endif QT_END_NAMESPACE diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 222c008f8a..6ce7f97580 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -63,6 +63,7 @@ using namespace Qt::StringLiterals; \row \li <QFlags> \li Type-safe way of combining enum values \row \li \l <QForeach> \li Qt's implementation of foreach and forever loops \row \li \l <QFunctionPointer> \li Typedef for a pointer-to-function type + \row \li \l <QApplicationStatic> \li For Q_APPLICATION_STATIC \row \li <QGlobalStatic> \li Thread-safe initialization of global static objects \row \li \l <QOverload> \li Helpers for resolving member function overloads \row \li <QSysInfo> \li A helper class to get system information @@ -170,6 +171,19 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) } /*! + \macro QT_NO_KEYWORDS + \relates <QtGlobal> + + Define this macro to disable the Qt-specific keywords that are usually enabled, + such as \c signals and \c slots. Use \c Q_SIGNALS and \c Q_SLOTS instead. + + Libraries should define this macro to make sure that they don't use the generic + keywords without the \c Q_ prefix in their public headers. + + \sa QT_NO_FOREACH +*/ + +/*! \macro QT_NAMESPACE \internal diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index 1009057bad..2d70e82370 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -67,8 +67,9 @@ #include <QtCore/qtresource.h> #include <QtCore/qttranslation.h> #include <QtCore/qttypetraits.h> +#if QT_CONFIG(version_tagging) #include <QtCore/qversiontagging.h> - +#endif #endif /* __cplusplus */ #endif /* QGLOBAL_H */ diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index 1b03733d2a..e09d2c72e1 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -516,79 +516,122 @@ QLibraryInfoPrivate::LocationInfo QLibraryInfoPrivate::locationInfo(QLibraryInfo /*! \since 6.0 Returns the path specified by \a p. + + If there is more than one path listed in qt.conf, it will + only return the first one. + \sa paths */ QString QLibraryInfo::path(LibraryPath p) { return QLibraryInfoPrivate::path(p); } +/*! + \since 6.8 + Returns all paths specificied by \a p. -/* - Returns the path specified by \a p. - - The usage mode can be set to UsedFromQtBinDir to enable special handling for executables that - live in <install-prefix>/bin. + \sa path */ -QString QLibraryInfoPrivate::path(QLibraryInfo::LibraryPath p, UsageMode usageMode) +QStringList QLibraryInfo::paths(LibraryPath p) +{ + return QLibraryInfoPrivate::paths(p); +} + +static bool keepQtBuildDefaults() +{ +#if QT_CONFIG(settings) + QSettings *config = QLibraryInfoPrivate::configuration(); + Q_ASSERT(config != nullptr); + return config->value("Config/MergeQtConf", false).toBool(); +#else + return false; +#endif +} + +#if QT_CONFIG(settings) +static QString normalizePath(QString ret) +{ + qsizetype startIndex = 0; + /* We support placeholders of the form $(<ENV_VAR>) in qt.conf. + The loop below tries to find all such placeholders, and replaces + them with the actual value of the ENV_VAR environment variable + */ + while (true) { + startIndex = ret.indexOf(u'$', startIndex); + if (startIndex < 0) + break; + if (ret.size() < startIndex + 3) + break; + if (ret.at(startIndex + 1) != u'(') { + startIndex++; + continue; + } + qsizetype endIndex = ret.indexOf(u')', startIndex + 2); + if (endIndex < 0) + break; + auto envVarName = QStringView{ret}.sliced(startIndex + 2, endIndex - startIndex - 2); + QString value = qEnvironmentVariable(envVarName.toLocal8Bit().constData()); + ret.replace(startIndex, endIndex - startIndex + 1, value); + startIndex += value.size(); + } + return QDir::fromNativeSeparators(ret); +}; + +static QVariant libraryPathToValue(QLibraryInfo::LibraryPath loc) +{ + QVariant value; + auto li = QLibraryInfoPrivate::locationInfo(loc); + if (li.key.isNull()) + return value; + QSettings *config = QLibraryInfoPrivate::configuration(); + Q_ASSERT(config != nullptr); + // if keepQtBuildDefaults returns true, + // we only consider explicit values listed in qt.conf + QVariant defaultValue = keepQtBuildDefaults() + ? QVariant() + : QVariant(li.defaultValue); + config->beginGroup("Paths"_L1); + auto cleanup = qScopeGuard([&]() { config->endGroup(); }); + if (li.fallbackKey.isNull()) { + value = config->value(li.key, defaultValue); + } else { + value = config->value(li.key); + if (!value.isValid()) + value = config->value(li.fallbackKey, defaultValue); + } + return value; +} +#endif // settings + +QStringList QLibraryInfoPrivate::paths(QLibraryInfo::LibraryPath p, + UsageMode usageMode) { const QLibraryInfo::LibraryPath loc = p; - QString ret; + QList<QString> ret; bool fromConf = false; #if QT_CONFIG(settings) if (havePaths()) { fromConf = true; - auto li = QLibraryInfoPrivate::locationInfo(loc); - if (!li.key.isNull()) { - QSettings *config = QLibraryInfoPrivate::configuration(); - Q_ASSERT(config != nullptr); - config->beginGroup("Paths"_L1); - - if (li.fallbackKey.isNull()) { - ret = config->value(li.key, li.defaultValue).toString(); - } else { - QVariant v = config->value(li.key); - if (!v.isValid()) - v = config->value(li.fallbackKey, li.defaultValue); - ret = v.toString(); - } - - qsizetype startIndex = 0; - /* We support placeholders of the form $(<ENV_VAR>) in qt.conf. - The loop below tries to find all such placeholders, and replaces - them with the actual value of the ENV_VAR environment variable - */ - while (true) { - startIndex = ret.indexOf(u'$', startIndex); - if (startIndex < 0) - break; - if (ret.size() < startIndex + 3) - break; - if (ret.at(startIndex + 1) != u'(') { - startIndex++; - continue; - } - qsizetype endIndex = ret.indexOf(u')', startIndex + 2); - if (endIndex < 0) - break; - auto envVarName = QStringView{ret}.mid(startIndex + 2, endIndex - startIndex - 2); - QString value = QString::fromLocal8Bit(qgetenv(envVarName.toLocal8Bit().constData())); - ret.replace(startIndex, endIndex - startIndex + 1, value); - startIndex += value.size(); - } - - config->endGroup(); + QVariant value = libraryPathToValue(loc); + if (value.isValid()) { - ret = QDir::fromNativeSeparators(ret); + if (auto *asList = get_if<QList<QString>>(&value)) + ret = std::move(*asList); + else + ret = QList<QString>({ std::move(value).toString()}); + for (qsizetype i = 0, end = ret.size(); i < end; ++i) + ret[i] = normalizePath(ret[i]); } } #endif // settings - if (!fromConf) { + if (!fromConf || keepQtBuildDefaults()) { + QString noConfResult; if (loc == QLibraryInfo::PrefixPath) { - ret = getPrefix(usageMode); + noConfResult = getPrefix(usageMode); } else if (int(loc) <= qt_configure_strs.count()) { - ret = QString::fromLocal8Bit(qt_configure_strs.viewAt(loc - 1)); + noConfResult = QString::fromLocal8Bit(qt_configure_strs.viewAt(loc - 1)); #ifndef Q_OS_WIN // On Windows we use the registry } else if (loc == QLibraryInfo::SettingsPath) { // Use of volatile is a hack to discourage compilers from calling @@ -596,24 +639,39 @@ QString QLibraryInfoPrivate::path(QLibraryInfo::LibraryPath p, UsageMode usageMo // compile-time, as Qt installers binary-patch the path, replacing // the dummy path seen at compile-time, typically changing length. const char *volatile path = QT_CONFIGURE_SETTINGS_PATH; - ret = QString::fromLocal8Bit(path); + noConfResult = QString::fromLocal8Bit(path); #endif } + if (!noConfResult.isEmpty()) + ret.push_back(std::move(noConfResult)); } + if (ret.isEmpty()) + return ret; - if (!ret.isEmpty() && QDir::isRelativePath(ret)) { - QString baseDir; - if (loc == QLibraryInfo::PrefixPath) { - baseDir = prefixFromAppDirHelper(); - } else { - // we make any other path absolute to the prefix directory - baseDir = path(QLibraryInfo::PrefixPath, usageMode); - } - ret = QDir::cleanPath(baseDir + u'/' + ret); + QString baseDir; + if (loc == QLibraryInfo::PrefixPath) { + baseDir = prefixFromAppDirHelper(); + } else { + // we make any other path absolute to the prefix directory + baseDir = QLibraryInfoPrivate::path(QLibraryInfo::PrefixPath, usageMode); } + for (qsizetype i = 0, end = ret.size(); i < end; ++i) + if (QDir::isRelativePath(ret[i])) + ret[i] = QDir::cleanPath(baseDir + u'/' + std::move(ret[i])); return ret; } +/* + Returns the path specified by \a p. + + The usage mode can be set to UsedFromQtBinDir to enable special handling for executables that + live in <install-prefix>/bin. + */ +QString QLibraryInfoPrivate::path(QLibraryInfo::LibraryPath p, UsageMode usageMode) +{ + return paths(p, usageMode).value(0, QString()); +} + /*! Returns additional arguments to the platform plugin matching \a platformName which can be specified as a string list using diff --git a/src/corelib/global/qlibraryinfo.h b/src/corelib/global/qlibraryinfo.h index d4e8f8b050..6cac6c83b0 100644 --- a/src/corelib/global/qlibraryinfo.h +++ b/src/corelib/global/qlibraryinfo.h @@ -42,6 +42,7 @@ public: SettingsPath = 100 }; static QString path(LibraryPath p); + static QStringList paths(LibraryPath p); #if QT_DEPRECATED_SINCE(6, 0) using LibraryLocation = LibraryPath; QT_DEPRECATED_VERSION_X_6_0("Use path()") diff --git a/src/corelib/global/qlibraryinfo_p.h b/src/corelib/global/qlibraryinfo_p.h index 4b471b932e..b9ca6b4d18 100644 --- a/src/corelib/global/qlibraryinfo_p.h +++ b/src/corelib/global/qlibraryinfo_p.h @@ -50,6 +50,7 @@ public: }; static QString path(QLibraryInfo::LibraryPath p, UsageMode usageMode = RegularUsage); + static QList<QString> paths(QLibraryInfo::LibraryPath p, UsageMode usageMode = RegularUsage); }; QT_END_NAMESPACE diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index dec16e4a77..efeec37094 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -834,7 +834,7 @@ void QMessageLogger::fatal(const QLoggingCategory &cat, const char *msg, ...) co va_list ap; va_start(ap, msg); // use variable arg list - QT_TERMINATE_ON_EXCEPTION(qt_message(QtFatalMsg, ctxt, msg, ap)); + qt_message(QtFatalMsg, ctxt, msg, ap); va_end(ap); #ifndef Q_CC_MSVC_ONLY @@ -858,7 +858,7 @@ void QMessageLogger::fatal(QMessageLogger::CategoryFunction catFunc, va_list ap; va_start(ap, msg); // use variable arg list - QT_TERMINATE_ON_EXCEPTION(qt_message(QtFatalMsg, ctxt, msg, ap)); + qt_message(QtFatalMsg, ctxt, msg, ap); va_end(ap); #ifndef Q_CC_MSVC_ONLY @@ -877,7 +877,7 @@ void QMessageLogger::fatal(const char *msg, ...) const noexcept QInternalMessageLogContext ctxt(context); va_list ap; va_start(ap, msg); // use variable arg list - QT_TERMINATE_ON_EXCEPTION(qt_message(QtFatalMsg, ctxt, msg, ap)); + qt_message(QtFatalMsg, ctxt, msg, ap); va_end(ap); #ifndef Q_CC_MSVC_ONLY @@ -2621,7 +2621,7 @@ QMessageLogContext &QMessageLogContext::copyContextFrom(const QMessageLogContext This enum describes the messages that can be sent to a message handler (QtMessageHandler). You can use the enum to identify and associate the various message types with the appropriate - actions. + actions. Its values are, in order of increasing severity: \value QtDebugMsg A message generated by the qDebug() function. @@ -2635,8 +2635,6 @@ QMessageLogContext &QMessageLogContext::copyContextFrom(const QMessageLogContext A message generated by the qFatal() function. \omitvalue QtSystemMsg - \c QtInfoMsg was added in Qt 5.5. - \sa QtMessageHandler, qInstallMessageHandler() */ diff --git a/src/corelib/global/qlogging.h b/src/corelib/global/qlogging.h index aa0ab93a2d..b4ec1a1235 100644 --- a/src/corelib/global/qlogging.h +++ b/src/corelib/global/qlogging.h @@ -28,10 +28,11 @@ class QNoDebug; enum QtMsgType { QtDebugMsg, + QT7_ONLY(QtInfoMsg,) QtWarningMsg, QtCriticalMsg, QtFatalMsg, - QtInfoMsg, + QT6_ONLY(QtInfoMsg,) #if QT_DEPRECATED_SINCE(6, 7) QtSystemMsg Q_DECL_ENUMERATOR_DEPRECATED_X("Use QtCriticalMsg instead.") = QtCriticalMsg #endif diff --git a/src/corelib/global/qminmax.h b/src/corelib/global/qminmax.h index e6fb62bf9d..fca13e047e 100644 --- a/src/corelib/global/qminmax.h +++ b/src/corelib/global/qminmax.h @@ -11,31 +11,10 @@ #include <QtCore/qassert.h> #include <QtCore/qtconfigmacros.h> - -#include <type_traits> +#include <QtCore/qttypetraits.h> QT_BEGIN_NAMESPACE -namespace QTypeTraits { - -namespace detail { -template<typename T, typename U, - typename = std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U> && - std::is_floating_point_v<T> == std::is_floating_point_v<U> && - std::is_signed_v<T> == std::is_signed_v<U> && - !std::is_same_v<T, bool> && !std::is_same_v<U, bool> && - !std::is_same_v<T, char> && !std::is_same_v<U, char>>> -struct Promoted -{ - using type = decltype(T() + U()); -}; -} - -template <typename T, typename U> -using Promoted = typename detail::Promoted<T, U>::type; - -} - template <typename T> constexpr inline const T &qMin(const T &a, const T &b) { return (a < b) ? a : b; } template <typename T> diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 2398c0a1a4..b81ad1375d 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -423,7 +423,7 @@ namespace Qt { enum ApplicationAttribute { // AA_ImmediateWidgetCreation = 0, - AA_QtQuickUseDefaultSizePolicy = 1 QT_TECH_PREVIEW_API, + AA_QtQuickUseDefaultSizePolicy = 1, AA_DontShowIconsInMenus = 2, AA_NativeWindows = 3, AA_DontCreateNativeWidgetSiblings = 4, @@ -462,7 +462,7 @@ namespace Qt { AA_DisableShaderDiskCache = 27, AA_DontShowShortcutsInContextMenus = 28, AA_CompressTabletEvents = 29, - AA_DontUsePopupWindows = 30, + // AA_DisableWindowContextHelpButton = 30, (in Qt 5) AA_DisableSessionManager = 31, // Add new attributes before this line @@ -1356,6 +1356,11 @@ namespace Qt { PreventContextMenu }; + enum class ContextMenuTrigger { + Press, + Release, + }; + enum InputMethodQuery { ImEnabled = 0x1, ImCursorRectangle = 0x2, @@ -1731,6 +1736,7 @@ namespace Qt { Q_ENUM_NS(ScrollBarPolicy) Q_ENUM_NS(FocusPolicy) Q_ENUM_NS(ContextMenuPolicy) + Q_ENUM_NS(ContextMenuTrigger) Q_ENUM_NS(ArrowType) Q_ENUM_NS(ToolButtonStyle) Q_ENUM_NS(PenStyle) diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index ddfade675a..64da69c0ac 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -93,13 +93,13 @@ with the layout can be overridden by explicitly setting \l{Layout::fillWidth}{Layout.fillWidth} or \l{Layout::fillHeight}{Layout.fillHeight}. - \b Note: This API is considered tech preview and may change or be removed in future - versions of Qt. - \value AA_DontShowIconsInMenus Actions with the Icon property won't be shown in any menus unless specifically set by the - QAction::iconVisibleInMenu property. + QAction::iconVisibleInMenu property. The default value of this + attribute depends on the platform. To override the default + behavior, set the attribute after QGuiApplication has been + instantiated. Menus that are currently open or menus already created in the native \macos menubar \e{may not} pick up a change in this attribute. Changes in the QAction::iconVisibleInMenu property will always be picked up. @@ -279,11 +279,6 @@ level windows, unless required by the implementation. This value was added in Qt 6.8. - \value AA_DontUsePopupWindows When this attribute is set, popups will always appear - as items in the scene, rather than having their own dedicated windows. - Setting this attribute will only affect Qt Quick applications. - This value was added in Qt 6.8. - \omitvalue AA_AttributeCount \omitvalue AA_EnableHighDpiScaling \omitvalue AA_UseHighDpiPixmaps @@ -2087,6 +2082,18 @@ */ /*! + \enum Qt::ContextMenuTrigger + \since 6.8 + + This enum type defines the mouse event used to trigger a context menu event. + + \value Press context menu on mouse press event, default on UNIX systems. + \value Release context menu on mouse release event, default on Windows. + + \sa QStyleHints::contextMenuTrigger +*/ + +/*! \enum Qt::FocusPolicy This enum type defines the various policies a widget can have with @@ -3251,7 +3258,7 @@ The underlying type is \c int. You can use \l qToUnderlying() to convert Qt::TimerId to \c int. - \value Invalid Represents a no-op timer ID; it's usage depends on the + \value Invalid Represents a no-op timer ID; its usage depends on the context, for example, this is the value returned by QObject::startTimer() to indicate it failed to start a timer; whereas QChronoTimer::id() returns this value when the timer is inactive, that is, \c timer.isActive() diff --git a/src/corelib/global/qnativeinterface_p.h b/src/corelib/global/qnativeinterface_p.h index aa7705e153..c6d216460a 100644 --- a/src/corelib/global/qnativeinterface_p.h +++ b/src/corelib/global/qnativeinterface_p.h @@ -21,7 +21,7 @@ QT_BEGIN_NAMESPACE namespace QtPrivate { -Q_DECLARE_EXPORTED_LOGGING_CATEGORY(lcNativeInterface, Q_CORE_EXPORT) +QT_DECLARE_EXPORTED_QT_LOGGING_CATEGORY(lcNativeInterface, Q_CORE_EXPORT) } // Provides a definition for the interface destructor diff --git a/src/corelib/global/qoperatingsystemversion.cpp b/src/corelib/global/qoperatingsystemversion.cpp index cf6063fca0..98e2f57357 100644 --- a/src/corelib/global/qoperatingsystemversion.cpp +++ b/src/corelib/global/qoperatingsystemversion.cpp @@ -565,6 +565,12 @@ const QOperatingSystemVersionBase QOperatingSystemVersion::MacOSVentura; */ /*! + \variable QOperatingSystemVersion::MacOSSequoia + \brief a version corresponding to macOS Sequoia (version 15). + \since 6.8 +*/ + +/*! \variable QOperatingSystemVersion::AndroidJellyBean \brief a version corresponding to Android Jelly Bean (version 4.1, API level 16). \since 5.9 diff --git a/src/corelib/global/qoperatingsystemversion.h b/src/corelib/global/qoperatingsystemversion.h index a9f30dc275..7a32fc93a9 100644 --- a/src/corelib/global/qoperatingsystemversion.h +++ b/src/corelib/global/qoperatingsystemversion.h @@ -142,6 +142,7 @@ class QOperatingSystemVersion : public QOperatingSystemVersionBase // ### Qt7: Regroup with the rest below static constexpr QOperatingSystemVersionBase MacOSSonoma { QOperatingSystemVersionBase::MacOS, 14, 0 }; + static constexpr QOperatingSystemVersionBase MacOSSequoia { QOperatingSystemVersionBase::MacOS, 15, 0 }; static constexpr QOperatingSystemVersionBase Android14 { QOperatingSystemVersionBase::Android, 14, 0 }; static constexpr QOperatingSystemVersionBase Windows11_23H2 { QOperatingSystemVersionBase::Windows, 10, 0, 22631 }; diff --git a/src/corelib/global/qtconfigmacros.h b/src/corelib/global/qtconfigmacros.h index 018161eac4..b643122d5c 100644 --- a/src/corelib/global/qtconfigmacros.h +++ b/src/corelib/global/qtconfigmacros.h @@ -9,6 +9,8 @@ #endif #include <QtCore/qtconfiginclude.h> +#include <QtCore/qtdeprecationdefinitions.h> +#include <QtCore/qtversionchecks.h> #include <assert.h> diff --git a/src/corelib/global/qtdeprecationdefinitions.h.in b/src/corelib/global/qtdeprecationdefinitions.h.in new file mode 100644 index 0000000000..0570f63a5a --- /dev/null +++ b/src/corelib/global/qtdeprecationdefinitions.h.in @@ -0,0 +1,28 @@ +// Copyright (C) 2024 The Qt Company Ltd. +// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only + +#ifndef QTDEPRECATIONDEFINITIONS_H +#define QTDEPRECATIONDEFINITIONS_H + +#ifndef QT_DISABLE_DEPRECATED_UP_TO +# ifdef QT_DISABLE_DEPRECATED_BEFORE // If the deprecated macro is defined, use its value +# define QT_DISABLE_DEPRECATED_UP_TO QT_DISABLE_DEPRECATED_BEFORE +# else +# define QT_DISABLE_DEPRECATED_UP_TO @QT_DISABLE_DEPRECATED_UP_TO@ +# endif +#endif + +#if QT_DISABLE_DEPRECATED_UP_TO < @QT_DISABLE_DEPRECATED_UP_TO@ +# warning QT_DISABLE_DEPRECATED_UP_TO is set to the version that is lower than the version that \ + Qt was built with. This may lead to linking issues. +#endif + +#ifndef QT_WARN_DEPRECATED_UP_TO +# ifdef QT_DEPRECATED_WARNINGS_SINCE // If the deprecated macro is defined, use its value +# define QT_WARN_DEPRECATED_UP_TO QT_DEPRECATED_WARNINGS_SINCE +# else +# define QT_WARN_DEPRECATED_UP_TO @QT_WARN_DEPRECATED_UP_TO@ +# endif +#endif + +#endif // QTDEPRECATIONDEFINITIONS_H diff --git a/src/corelib/global/qtdeprecationmarkers.h b/src/corelib/global/qtdeprecationmarkers.h index 6df5ebce6d..68f4fda186 100644 --- a/src/corelib/global/qtdeprecationmarkers.h +++ b/src/corelib/global/qtdeprecationmarkers.h @@ -5,6 +5,7 @@ #define QTDEPRECATIONMARKERS_H #include <QtCore/qtconfigmacros.h> +#include <QtCore/qtdeprecationdefinitions.h> #include <QtCore/qtversionchecks.h> #include <QtCore/qcompilerdetection.h> // for Q_DECL_DEPRECATED @@ -44,28 +45,6 @@ QT_BEGIN_NAMESPACE # define Q_DECL_ENUMERATOR_DEPRECATED_X(ignored) #endif -// If the deprecated macro is defined, use its value -#if !defined(QT_DISABLE_DEPRECATED_UP_TO) && defined(QT_DISABLE_DEPRECATED_BEFORE) -# define QT_DISABLE_DEPRECATED_UP_TO QT_DISABLE_DEPRECATED_BEFORE -#endif - -// If the deprecated macro is defined, use its value -#if !defined(QT_WARN_DEPRECATED_UP_TO) && defined(QT_DEPRECATED_WARNINGS_SINCE) -# define QT_WARN_DEPRECATED_UP_TO QT_DEPRECATED_WARNINGS_SINCE -#endif - -#ifndef QT_WARN_DEPRECATED_UP_TO -# ifdef QT_DISABLE_DEPRECATED_UP_TO -# define QT_WARN_DEPRECATED_UP_TO QT_DISABLE_DEPRECATED_UP_TO -# else -# define QT_WARN_DEPRECATED_UP_TO QT_VERSION -# endif -#endif - -#ifndef QT_DISABLE_DEPRECATED_UP_TO -#define QT_DISABLE_DEPRECATED_UP_TO QT_VERSION_CHECK(5, 0, 0) -#endif - /* QT_DEPRECATED_SINCE(major, minor) evaluates as true if the Qt version is greater than the deprecation point specified. diff --git a/src/corelib/global/qttypetraits.h b/src/corelib/global/qttypetraits.h index 1efb24bf70..2cd68c73cb 100644 --- a/src/corelib/global/qttypetraits.h +++ b/src/corelib/global/qttypetraits.h @@ -7,8 +7,11 @@ #include <QtCore/qtconfigmacros.h> #include <QtCore/qtdeprecationmarkers.h> +#include <optional> +#include <tuple> #include <type_traits> #include <utility> +#include <variant> #if 0 #pragma qt_class(QtTypeTraits) @@ -60,6 +63,212 @@ template <typename T> struct type_dependent_false : std::false_type {}; template <auto T> struct value_dependent_false : std::false_type {}; } +namespace QTypeTraits { + +namespace detail { +template<typename T, typename U, + typename = std::enable_if_t<std::is_arithmetic_v<T> && std::is_arithmetic_v<U> && + std::is_floating_point_v<T> == std::is_floating_point_v<U> && + std::is_signed_v<T> == std::is_signed_v<U> && + !std::is_same_v<T, bool> && !std::is_same_v<U, bool> && + !std::is_same_v<T, char> && !std::is_same_v<U, char>>> +struct Promoted +{ + using type = decltype(T() + U()); +}; +} + +template <typename T, typename U> +using Promoted = typename detail::Promoted<T, U>::type; + +/* + The templates below aim to find out whether one can safely instantiate an operator==() or + operator<() for a type. + + This is tricky for containers, as most containers have unconstrained comparison operators, even though they + rely on the corresponding operators for its content. + This is especially true for all of the STL template classes that have a comparison operator defined, and + leads to the situation, that the compiler would try to instantiate the operator, and fail if any + of its template arguments does not have the operator implemented. + + The code tries to cover the relevant cases for Qt and the STL, by checking (recusrsively) the value_type + of a container (if it exists), and checking the template arguments of pair, tuple and variant. +*/ +namespace detail { + +// find out whether T is a conteiner +// this is required to check the value type of containers for the existence of the comparison operator +template <typename, typename = void> +struct is_container : std::false_type {}; +template <typename T> +struct is_container<T, std::void_t< + typename T::value_type, + std::is_convertible<decltype(std::declval<T>().begin() != std::declval<T>().end()), bool> +>> : std::true_type {}; + + +// Checks the existence of the comparison operator for the class itself +QT_WARNING_PUSH +QT_WARNING_DISABLE_FLOAT_COMPARE +template <typename, typename = void> +struct has_operator_equal : std::false_type {}; +template <typename T> +struct has_operator_equal<T, std::void_t<decltype(bool(std::declval<const T&>() == std::declval<const T&>()))>> + : std::true_type {}; +QT_WARNING_POP + +// Two forward declarations +template<typename T, bool = is_container<T>::value> +struct expand_operator_equal_container; +template<typename T> +struct expand_operator_equal_tuple; + +// the entry point for the public method +template<typename T> +using expand_operator_equal = expand_operator_equal_container<T>; + +// if T isn't a container check if it's a tuple like object +template<typename T, bool> +struct expand_operator_equal_container : expand_operator_equal_tuple<T> {}; +// if T::value_type exists, check first T::value_type, then T itself +template<typename T> +struct expand_operator_equal_container<T, true> : + std::conjunction< + std::disjunction< + std::is_same<T, typename T::value_type>, // avoid endless recursion + expand_operator_equal<typename T::value_type> + >, expand_operator_equal_tuple<T>> {}; + +// recursively check the template arguments of a tuple like object +template<typename ...T> +using expand_operator_equal_recursive = std::conjunction<expand_operator_equal<T>...>; + +template<typename T> +struct expand_operator_equal_tuple : has_operator_equal<T> {}; +template<typename T> +struct expand_operator_equal_tuple<std::optional<T>> : expand_operator_equal_recursive<T> {}; +template<typename T1, typename T2> +struct expand_operator_equal_tuple<std::pair<T1, T2>> : expand_operator_equal_recursive<T1, T2> {}; +template<typename ...T> +struct expand_operator_equal_tuple<std::tuple<T...>> : expand_operator_equal_recursive<T...> {}; +template<typename ...T> +struct expand_operator_equal_tuple<std::variant<T...>> : expand_operator_equal_recursive<T...> {}; + +// the same for operator<(), see above for explanations +template <typename, typename = void> +struct has_operator_less_than : std::false_type{}; +template <typename T> +struct has_operator_less_than<T, std::void_t<decltype(bool(std::declval<const T&>() < std::declval<const T&>()))>> + : std::true_type{}; + +template<typename T, bool = is_container<T>::value> +struct expand_operator_less_than_container; +template<typename T> +struct expand_operator_less_than_tuple; + +template<typename T> +using expand_operator_less_than = expand_operator_less_than_container<T>; + +template<typename T, bool> +struct expand_operator_less_than_container : expand_operator_less_than_tuple<T> {}; +template<typename T> +struct expand_operator_less_than_container<T, true> : + std::conjunction< + std::disjunction< + std::is_same<T, typename T::value_type>, + expand_operator_less_than<typename T::value_type> + >, expand_operator_less_than_tuple<T> + > {}; + +template<typename ...T> +using expand_operator_less_than_recursive = std::conjunction<expand_operator_less_than<T>...>; + +template<typename T> +struct expand_operator_less_than_tuple : has_operator_less_than<T> {}; +template<typename T> +struct expand_operator_less_than_tuple<std::optional<T>> : expand_operator_less_than_recursive<T> {}; +template<typename T1, typename T2> +struct expand_operator_less_than_tuple<std::pair<T1, T2>> : expand_operator_less_than_recursive<T1, T2> {}; +template<typename ...T> +struct expand_operator_less_than_tuple<std::tuple<T...>> : expand_operator_less_than_recursive<T...> {}; +template<typename ...T> +struct expand_operator_less_than_tuple<std::variant<T...>> : expand_operator_less_than_recursive<T...> {}; + +} + +template<typename T, typename = void> +struct is_dereferenceable : std::false_type {}; + +template<typename T> +struct is_dereferenceable<T, std::void_t<decltype(std::declval<T>().operator->())> > + : std::true_type {}; + +template <typename T> +inline constexpr bool is_dereferenceable_v = is_dereferenceable<T>::value; + +template<typename T> +struct has_operator_equal : detail::expand_operator_equal<T> {}; +template<typename T> +inline constexpr bool has_operator_equal_v = has_operator_equal<T>::value; + +template <typename Container, typename T> +using has_operator_equal_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_equal<T>>; + +template<typename T> +struct has_operator_less_than : detail::expand_operator_less_than<T> {}; +template<typename T> +inline constexpr bool has_operator_less_than_v = has_operator_less_than<T>::value; + +template <typename Container, typename T> +using has_operator_less_than_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_less_than<T>>; + +template <typename ...T> +using compare_eq_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal<T>...>, bool>; + +template <typename Container, typename ...T> +using compare_eq_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal_container<Container, T>...>, bool>; + +template <typename ...T> +using compare_lt_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than<T>...>, bool>; + +template <typename Container, typename ...T> +using compare_lt_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than_container<Container, T>...>, bool>; + +namespace detail { + +template<typename T> +const T &const_reference(); +template<typename T> +T &reference(); + +} + +template <typename Stream, typename, typename = void> +struct has_ostream_operator : std::false_type {}; +template <typename Stream, typename T> +struct has_ostream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() << detail::const_reference<T>())>> + : std::true_type {}; +template <typename Stream, typename T> +inline constexpr bool has_ostream_operator_v = has_ostream_operator<Stream, T>::value; + +template <typename Stream, typename Container, typename T> +using has_ostream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_ostream_operator<Stream, T>>; + +template <typename Stream, typename, typename = void> +struct has_istream_operator : std::false_type {}; +template <typename Stream, typename T> +struct has_istream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() >> detail::reference<T>())>> + : std::true_type {}; +template <typename Stream, typename T> +inline constexpr bool has_istream_operator_v = has_istream_operator<Stream, T>::value; +template <typename Stream, typename Container, typename T> +using has_istream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_istream_operator<Stream, T>>; + +template <typename Stream, typename T> +inline constexpr bool has_stream_operator_v = has_ostream_operator_v<Stream, T> && has_istream_operator_v<Stream, T>; + +} // namespace QTypeTraits + QT_END_NAMESPACE #endif // QTTYPETRAITS_H diff --git a/src/corelib/global/qtypeinfo.h b/src/corelib/global/qtypeinfo.h index 255a2b33c6..e9dfbc34a4 100644 --- a/src/corelib/global/qtypeinfo.h +++ b/src/corelib/global/qtypeinfo.h @@ -8,9 +8,6 @@ #include <QtCore/qcompilerdetection.h> #include <QtCore/qcontainerfwd.h> -#include <variant> -#include <optional> -#include <tuple> #include <type_traits> QT_BEGIN_NAMESPACE @@ -186,197 +183,5 @@ template<typename T> class QFlags; template<typename T> Q_DECLARE_TYPEINFO_BODY(QFlags<T>, Q_PRIMITIVE_TYPE); -namespace QTypeTraits -{ - -/* - The templates below aim to find out whether one can safely instantiate an operator==() or - operator<() for a type. - - This is tricky for containers, as most containers have unconstrained comparison operators, even though they - rely on the corresponding operators for its content. - This is especially true for all of the STL template classes that have a comparison operator defined, and - leads to the situation, that the compiler would try to instantiate the operator, and fail if any - of its template arguments does not have the operator implemented. - - The code tries to cover the relevant cases for Qt and the STL, by checking (recusrsively) the value_type - of a container (if it exists), and checking the template arguments of pair, tuple and variant. -*/ -namespace detail { - -// find out whether T is a conteiner -// this is required to check the value type of containers for the existence of the comparison operator -template <typename, typename = void> -struct is_container : std::false_type {}; -template <typename T> -struct is_container<T, std::void_t< - typename T::value_type, - std::is_convertible<decltype(std::declval<T>().begin() != std::declval<T>().end()), bool> ->> : std::true_type {}; - - -// Checks the existence of the comparison operator for the class itself -QT_WARNING_PUSH -QT_WARNING_DISABLE_FLOAT_COMPARE -template <typename, typename = void> -struct has_operator_equal : std::false_type {}; -template <typename T> -struct has_operator_equal<T, std::void_t<decltype(bool(std::declval<const T&>() == std::declval<const T&>()))>> - : std::true_type {}; -QT_WARNING_POP - -// Two forward declarations -template<typename T, bool = is_container<T>::value> -struct expand_operator_equal_container; -template<typename T> -struct expand_operator_equal_tuple; - -// the entry point for the public method -template<typename T> -using expand_operator_equal = expand_operator_equal_container<T>; - -// if T isn't a container check if it's a tuple like object -template<typename T, bool> -struct expand_operator_equal_container : expand_operator_equal_tuple<T> {}; -// if T::value_type exists, check first T::value_type, then T itself -template<typename T> -struct expand_operator_equal_container<T, true> : - std::conjunction< - std::disjunction< - std::is_same<T, typename T::value_type>, // avoid endless recursion - expand_operator_equal<typename T::value_type> - >, expand_operator_equal_tuple<T>> {}; - -// recursively check the template arguments of a tuple like object -template<typename ...T> -using expand_operator_equal_recursive = std::conjunction<expand_operator_equal<T>...>; - -template<typename T> -struct expand_operator_equal_tuple : has_operator_equal<T> {}; -template<typename T> -struct expand_operator_equal_tuple<std::optional<T>> : expand_operator_equal_recursive<T> {}; -template<typename T1, typename T2> -struct expand_operator_equal_tuple<std::pair<T1, T2>> : expand_operator_equal_recursive<T1, T2> {}; -template<typename ...T> -struct expand_operator_equal_tuple<std::tuple<T...>> : expand_operator_equal_recursive<T...> {}; -template<typename ...T> -struct expand_operator_equal_tuple<std::variant<T...>> : expand_operator_equal_recursive<T...> {}; - -// the same for operator<(), see above for explanations -template <typename, typename = void> -struct has_operator_less_than : std::false_type{}; -template <typename T> -struct has_operator_less_than<T, std::void_t<decltype(bool(std::declval<const T&>() < std::declval<const T&>()))>> - : std::true_type{}; - -template<typename T, bool = is_container<T>::value> -struct expand_operator_less_than_container; -template<typename T> -struct expand_operator_less_than_tuple; - -template<typename T> -using expand_operator_less_than = expand_operator_less_than_container<T>; - -template<typename T, bool> -struct expand_operator_less_than_container : expand_operator_less_than_tuple<T> {}; -template<typename T> -struct expand_operator_less_than_container<T, true> : - std::conjunction< - std::disjunction< - std::is_same<T, typename T::value_type>, - expand_operator_less_than<typename T::value_type> - >, expand_operator_less_than_tuple<T> - > {}; - -template<typename ...T> -using expand_operator_less_than_recursive = std::conjunction<expand_operator_less_than<T>...>; - -template<typename T> -struct expand_operator_less_than_tuple : has_operator_less_than<T> {}; -template<typename T> -struct expand_operator_less_than_tuple<std::optional<T>> : expand_operator_less_than_recursive<T> {}; -template<typename T1, typename T2> -struct expand_operator_less_than_tuple<std::pair<T1, T2>> : expand_operator_less_than_recursive<T1, T2> {}; -template<typename ...T> -struct expand_operator_less_than_tuple<std::tuple<T...>> : expand_operator_less_than_recursive<T...> {}; -template<typename ...T> -struct expand_operator_less_than_tuple<std::variant<T...>> : expand_operator_less_than_recursive<T...> {}; - -} - -template<typename T, typename = void> -struct is_dereferenceable : std::false_type {}; - -template<typename T> -struct is_dereferenceable<T, std::void_t<decltype(std::declval<T>().operator->())> > - : std::true_type {}; - -template <typename T> -inline constexpr bool is_dereferenceable_v = is_dereferenceable<T>::value; - -template<typename T> -struct has_operator_equal : detail::expand_operator_equal<T> {}; -template<typename T> -inline constexpr bool has_operator_equal_v = has_operator_equal<T>::value; - -template <typename Container, typename T> -using has_operator_equal_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_equal<T>>; - -template<typename T> -struct has_operator_less_than : detail::expand_operator_less_than<T> {}; -template<typename T> -inline constexpr bool has_operator_less_than_v = has_operator_less_than<T>::value; - -template <typename Container, typename T> -using has_operator_less_than_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_operator_less_than<T>>; - -template <typename ...T> -using compare_eq_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal<T>...>, bool>; - -template <typename Container, typename ...T> -using compare_eq_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_equal_container<Container, T>...>, bool>; - -template <typename ...T> -using compare_lt_result = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than<T>...>, bool>; - -template <typename Container, typename ...T> -using compare_lt_result_container = std::enable_if_t<std::conjunction_v<QTypeTraits::has_operator_less_than_container<Container, T>...>, bool>; - -namespace detail { - -template<typename T> -const T &const_reference(); -template<typename T> -T &reference(); - -} - -template <typename Stream, typename, typename = void> -struct has_ostream_operator : std::false_type {}; -template <typename Stream, typename T> -struct has_ostream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() << detail::const_reference<T>())>> - : std::true_type {}; -template <typename Stream, typename T> -inline constexpr bool has_ostream_operator_v = has_ostream_operator<Stream, T>::value; - -template <typename Stream, typename Container, typename T> -using has_ostream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_ostream_operator<Stream, T>>; - -template <typename Stream, typename, typename = void> -struct has_istream_operator : std::false_type {}; -template <typename Stream, typename T> -struct has_istream_operator<Stream, T, std::void_t<decltype(detail::reference<Stream>() >> detail::reference<T>())>> - : std::true_type {}; -template <typename Stream, typename T> -inline constexpr bool has_istream_operator_v = has_istream_operator<Stream, T>::value; -template <typename Stream, typename Container, typename T> -using has_istream_operator_container = std::disjunction<std::is_base_of<Container, T>, QTypeTraits::has_istream_operator<Stream, T>>; - -template <typename Stream, typename T> -inline constexpr bool has_stream_operator_v = has_ostream_operator_v<Stream, T> && has_istream_operator_v<Stream, T>; - -} - - QT_END_NAMESPACE #endif // QTYPEINFO_H diff --git a/src/corelib/global/qversiontagging.h b/src/corelib/global/qversiontagging.h index 965d53e88f..fa2dd23728 100644 --- a/src/corelib/global/qversiontagging.h +++ b/src/corelib/global/qversiontagging.h @@ -13,6 +13,8 @@ #include <QtCore/qtversionchecks.h> #include <QtCore/qtypes.h> +QT_REQUIRE_CONFIG(version_tagging); + QT_BEGIN_NAMESPACE /* |