diff options
Diffstat (limited to 'src/corelib/global')
23 files changed, 1208 insertions, 769 deletions
diff --git a/src/corelib/global/global.pri b/src/corelib/global/global.pri index 0f8935d4b5..2b4fd6d661 100644 --- a/src/corelib/global/global.pri +++ b/src/corelib/global/global.pri @@ -39,6 +39,27 @@ SOURCES += \ global/qrandom.cpp \ global/qhooks.cpp +# Only add global/qfloat16_f16c.c if qfloat16.cpp can't #include it. +# Any compiler: if it is already generating F16C code, let qfloat16.cpp do it +# Clang: ICE if not generating F16C code, so use qfloat16_f16c.c +# ICC: miscompiles if not generating F16C code, so use qfloat16_f16c.c +# GCC: if it can use F16C intrinsics, let qfloat16.cpp do it +# MSVC: if it is already generating AVX code, let qfloat16.cpp do it +# MSVC: otherwise, it generates poorly-performing code, so use qfloat16_f16c.c +contains(QT_CPU_FEATURES.$$QT_ARCH, f16c): \ + f16c_cxx = true +else: clang|intel_icl|intel_icc: \ + f16c_cxx = false +else: gcc:f16c:x86SimdAlways: \ + f16c_cxx = true +else: msvc:contains(QT_CPU_FEATURES.$$QT_ARCH, avx): \ + f16c_cxx = true +else: \ + f16c_cxx = false +$$f16c_cxx: DEFINES += QFLOAT16_INCLUDE_FAST +else: F16C_SOURCES += global/qfloat16_f16c.c +unset(f16c_cxx) + VERSIONTAGGING_SOURCES = global/qversiontagging.cpp darwin: SOURCES += global/qoperatingsystemversion_darwin.mm diff --git a/src/corelib/global/qcompilerdetection.h b/src/corelib/global/qcompilerdetection.h index 231ac2c9b0..f3f3139d1a 100644 --- a/src/corelib/global/qcompilerdetection.h +++ b/src/corelib/global/qcompilerdetection.h @@ -89,9 +89,6 @@ # define Q_CC_MSVC (_MSC_VER) # define Q_CC_MSVC_NET # define Q_OUTOFLINE_TEMPLATE inline -# if _MSC_VER < 1600 -# define Q_NO_TEMPLATE_FRIENDS -# endif # define Q_COMPILER_MANGLES_RETURN_TYPE # define Q_FUNC_INFO __FUNCSIG__ # define Q_ALIGNOF(type) __alignof(type) @@ -105,12 +102,8 @@ # endif # define Q_DECL_EXPORT __declspec(dllexport) # define Q_DECL_IMPORT __declspec(dllimport) -# if _MSC_VER >= 1800 -# define QT_MAKE_UNCHECKED_ARRAY_ITERATOR(x) stdext::make_unchecked_array_iterator(x) -# endif -# if _MSC_VER >= 1500 -# define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N) stdext::make_checked_array_iterator(x, size_t(N)) -# endif +# define QT_MAKE_UNCHECKED_ARRAY_ITERATOR(x) stdext::make_unchecked_array_iterator(x) // Since _MSC_VER >= 1800 +# define QT_MAKE_CHECKED_ARRAY_ITERATOR(x, N) stdext::make_checked_array_iterator(x, size_t(N)) // Since _MSC_VER >= 1500 /* Intel C++ disguising as Visual C++: the `using' keyword avoids warnings */ # if defined(__INTEL_COMPILER) # define Q_DECL_VARIABLE_DEPRECATED @@ -243,6 +236,7 @@ # define Q_REQUIRED_RESULT __attribute__ ((__warn_unused_result__)) # define Q_DECL_PURE_FUNCTION __attribute__((pure)) # define Q_DECL_CONST_FUNCTION __attribute__((const)) +# define Q_DECL_COLD_FUNCTION __attribute__((cold)) # if !defined(QT_MOC_CPP) # define Q_PACKED __attribute__ ((__packed__)) # ifndef __ARM_EABI__ @@ -563,7 +557,7 @@ */ #ifdef __cplusplus -# if __cplusplus < 201103L && !(defined(Q_CC_MSVC) && Q_CC_MSVC >= 1800) +# if __cplusplus < 201103L && !defined(Q_CC_MSVC) # error Qt requires a C++11 compiler and yours does not seem to be that. # endif #endif @@ -635,21 +629,11 @@ # define Q_COMPILER_THREAD_LOCAL # define Q_COMPILER_UDL # endif -# ifdef _MSC_VER -# if _MSC_VER == 1700 -// <initializer_list> is missing with MSVC 2012 (it's present in 2010, 2013 and up) -# undef Q_COMPILER_INITIALIZER_LISTS -# endif -# if _MSC_VER < 1900 -// ICC disables unicode string support when compatibility mode with MSVC 2013 or lower is active -# undef Q_COMPILER_UNICODE_STRINGS -// Even though ICC knows about ref-qualified members, MSVC 2013 or lower doesn't, so -// certain member functions (like QString::toUpper) may be missing from the DLLs. -# undef Q_COMPILER_REF_QUALIFIERS -// Disable constexpr unless the MS headers have constexpr in all the right places too -// (like std::numeric_limits<T>::max()) -# undef Q_COMPILER_CONSTEXPR -# endif +# elif defined(__STDC_VERSION__) && __STDC_VERSION__ > 199901L s +// C11 features supported. Only tested with ICC 17 and up. +# define Q_COMPILER_STATIC_ASSERT +# if __has_include(<threads.h>) +# define Q_COMPILER_THREAD_LOCAL # endif # endif #endif @@ -803,6 +787,17 @@ # endif # endif +# if defined(__STDC_VERSION__) +# if __has_feature(c_static_assert) +# define Q_COMPILER_STATIC_ASSERT +# endif +# if __has_feature(c_thread_local) && __has_include(<threads.h>) +# if !defined(__FreeBSD__) /* FreeBSD clang fails on __cxa_thread_atexit */ +# define Q_COMPILER_THREAD_LOCAL +# endif +# endif +# endif + # if defined(__has_warning) # if __has_warning("-Wunused-private-field") # define Q_DECL_UNUSED_MEMBER Q_DECL_UNUSED @@ -898,15 +893,25 @@ # define Q_COMPILER_RETURN_TYPE_DEDUCTION # endif # endif +# if defined(__STDC_VERSION__) && __STDC_VERSION__ > 199901L +# if Q_CC_GNU >= 407 + /* C11 features supported in GCC 4.7: */ +# define Q_COMPILER_STATIC_ASSERT +# endif +# if Q_CC_GNU >= 409 + /* C11 features supported in GCC 4.9: */ +# if __has_include(<threads.h>) +# define Q_COMPILER_THREAD_LOCAL +# endif +# endif +# endif #endif #if defined(Q_CC_MSVC) # if defined(__cplusplus) -# if _MSC_VER >= 1400 /* C++11 features supported in VC8 = VC2005: */ # define Q_COMPILER_VARIADIC_MACROS -# ifndef __cplusplus_cli /* 2005 supports the override and final contextual keywords, in the same positions as the C++11 variants, but 'final' is called 'sealed' instead: @@ -915,12 +920,7 @@ "virtual" keyword to be present too, so don't define for that. So don't define Q_COMPILER_EXPLICIT_OVERRIDES (since it's not the same as the C++11 version), but define the Q_DECL_* flags - accordingly: */ -# define Q_DECL_OVERRIDE override -# define Q_DECL_FINAL sealed -# endif -# endif -# if _MSC_VER >= 1600 + accordingly. */ /* C++11 features supported in VC10 = VC2010: */ # define Q_COMPILER_AUTO_FUNCTION # define Q_COMPILER_AUTO_TYPE @@ -930,57 +930,31 @@ # define Q_COMPILER_NULLPTR # define Q_COMPILER_RVALUE_REFS # define Q_COMPILER_STATIC_ASSERT -// MSVC's library has std::initializer_list, but the compiler does not support the braces initialization -//# define Q_COMPILER_INITIALIZER_LISTS -//# define Q_COMPILER_UNIFORM_INIT -# endif -# if _MSC_VER >= 1700 /* C++11 features supported in VC11 = VC2012: */ -# undef Q_DECL_OVERRIDE /* undo 2005/2008 settings... */ -# undef Q_DECL_FINAL /* undo 2005/2008 settings... */ # define Q_COMPILER_EXPLICIT_OVERRIDES /* ...and use std C++11 now */ # define Q_COMPILER_CLASS_ENUM # define Q_COMPILER_ATOMICS -# endif /* VC 11 */ -# if _MSC_VER >= 1800 /* C++11 features in VC12 = VC2013 */ -/* Implemented, but can't be used on move special members */ -/* # define Q_COMPILER_DEFAULT_MEMBERS */ # define Q_COMPILER_DELETE_MEMBERS # define Q_COMPILER_DELEGATING_CONSTRUCTORS # define Q_COMPILER_EXPLICIT_CONVERSIONS # define Q_COMPILER_NONSTATIC_MEMBER_INIT -// implemented, but nested initialization fails (eg tst_qvector): http://connect.microsoft.com/VisualStudio/feedback/details/800364/initializer-list-calls-object-destructor-twice -// #define Q_COMPILER_INITIALIZER_LISTS -// implemented in principle, but has a bug that makes it unusable: http://connect.microsoft.com/VisualStudio/feedback/details/802058/c-11-unified-initialization-fails-with-c-style-arrays -// #define Q_COMPILER_UNIFORM_INIT # define Q_COMPILER_RAW_STRINGS # define Q_COMPILER_TEMPLATE_ALIAS # define Q_COMPILER_VARIADIC_TEMPLATES -# endif /* VC 12 */ -# if _MSC_FULL_VER >= 180030324 // VC 12 SP 2 RC -# define Q_COMPILER_INITIALIZER_LISTS -# endif /* VC 12 SP 2 RC */ -# if _MSC_VER >= 1900 +# define Q_COMPILER_INITIALIZER_LISTS // VC 12 SP 2 RC /* C++11 features in VC14 = VC2015 */ # define Q_COMPILER_DEFAULT_MEMBERS # define Q_COMPILER_ALIGNAS # define Q_COMPILER_ALIGNOF -// Partial support, insufficient for Qt -//# define Q_COMPILER_CONSTEXPR # define Q_COMPILER_INHERITING_CONSTRUCTORS # define Q_COMPILER_NOEXCEPT # define Q_COMPILER_RANGE_FOR # define Q_COMPILER_REF_QUALIFIERS # define Q_COMPILER_THREAD_LOCAL -// Broken, see QTBUG-47224 and https://connect.microsoft.com/VisualStudio/feedback/details/1549785 -//# define Q_COMPILER_THREADSAFE_STATICS # define Q_COMPILER_UDL # define Q_COMPILER_UNICODE_STRINGS -// Uniform initialization is not working yet -- build errors with QUuid -//# define Q_COMPILER_UNIFORM_INIT # define Q_COMPILER_UNRESTRICTED_UNIONS -# endif # if _MSC_FULL_VER >= 190023419 # define Q_COMPILER_ATTRIBUTES // Almost working, see https://connect.microsoft.com/VisualStudio/feedback/details/2011648 @@ -1246,6 +1220,9 @@ #ifndef Q_DECL_CONST_FUNCTION # define Q_DECL_CONST_FUNCTION Q_DECL_PURE_FUNCTION #endif +#ifndef Q_DECL_COLD_FUNCTION +# define Q_DECL_COLD_FUNCTION +#endif #ifndef QT_MAKE_UNCHECKED_ARRAY_ITERATOR # define QT_MAKE_UNCHECKED_ARRAY_ITERATOR(x) (x) #endif @@ -1282,7 +1259,7 @@ # define QT_WARNING_DISABLE_CLANG(text) # define QT_WARNING_DISABLE_GCC(text) # define QT_WARNING_DISABLE_DEPRECATED QT_WARNING_DISABLE_INTEL(1478 1786) -#elif defined(Q_CC_MSVC) && _MSC_VER >= 1500 && !defined(Q_CC_CLANG) +#elif defined(Q_CC_MSVC) && !defined(Q_CC_CLANG) # undef QT_DO_PRAGMA /* not needed */ # define QT_WARNING_PUSH __pragma(warning(push)) # define QT_WARNING_POP __pragma(warning(pop)) diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h index dabb715607..86ef1a2613 100644 --- a/src/corelib/global/qconfig-bootstrapped.h +++ b/src/corelib/global/qconfig-bootstrapped.h @@ -78,6 +78,7 @@ #define QT_FEATURE_cxx11_random (QT_HAS_INCLUDE(<random>) ? 1 : -1) #define QT_NO_DATASTREAM #define QT_FEATURE_datetimeparser -1 +#define QT_FEATURE_etw -1 #define QT_FEATURE_getauxval (QT_HAS_INCLUDE(<sys/auxv.h>) ? 1 : -1) #define QT_FEATURE_getentropy -1 #define QT_NO_GEOM_VARIANT @@ -92,8 +93,10 @@ #else # define QT_FEATURE_linkat -1 #endif +#define QT_FEATURE_lttng -1 #define QT_NO_QOBJECT #define QT_FEATURE_process -1 +#define QT_FEATURE_regularexpression -1 #define QT_FEATURE_renameat2 -1 #define QT_FEATURE_sharedmemory -1 #define QT_FEATURE_slog2 -1 diff --git a/src/corelib/global/qendian.h b/src/corelib/global/qendian.h index 3337829de0..a14fce23f8 100644 --- a/src/corelib/global/qendian.h +++ b/src/corelib/global/qendian.h @@ -272,7 +272,8 @@ public: static Q_DECL_CONSTEXPR T fromSpecial(T source) { return qFromBigEndian(source); } }; -#ifdef Q_QDOC +#ifdef Q_CLANG_QDOC +template<typename T> class QLEInteger { public: explicit Q_DECL_CONSTEXPR QLEInteger(T i); @@ -292,6 +293,7 @@ public: QLEInteger &operator ^=(T i); }; +template<typename T> class QBEInteger { public: explicit Q_DECL_CONSTEXPR QBEInteger(T i); diff --git a/src/corelib/global/qendian.qdoc b/src/corelib/global/qendian.qdoc index 2ccdea5979..65df25a205 100644 --- a/src/corelib/global/qendian.qdoc +++ b/src/corelib/global/qendian.qdoc @@ -34,8 +34,8 @@ */ /*! + \fn template <typename T> T qFromUnaligned(const void *ptr) \internal - \fn T qFromUnaligned(const void *ptr) \since 5.5 Loads a \c{T} from address \a ptr, which may be misaligned. @@ -45,8 +45,8 @@ */ /*! + \fn template <typename T> void qToUnaligned(const T t, void *ptr) \internal - \fn void qToUnaligned(T t, void *ptr) \since 4.5 Stores \a t to address \a ptr, which may be misaligned. @@ -57,7 +57,7 @@ /*! - \fn T qFromBigEndian(const void *src) + \fn template <typename T> T qFromBigEndian(const void *src) \since 4.3 \relates <QtEndian> @@ -78,7 +78,7 @@ \sa qToLittleEndian() */ /*! - \fn T qFromBigEndian(T src) + \fn template <typename T> T qFromBigEndian(T src) \since 4.3 \relates <QtEndian> \overload @@ -90,7 +90,7 @@ unmodified. */ /*! - \fn T qFromLittleEndian(const void *src) + \fn template <typename T> T qFromLittleEndian(const void *src) \since 4.3 \relates <QtEndian> @@ -111,7 +111,7 @@ \sa qToLittleEndian() */ /*! - \fn T qFromLittleEndian(T src) + \fn template <typename T> T qFromLittleEndian(T src) \since 4.3 \relates <QtEndian> \overload @@ -123,7 +123,7 @@ unmodified. */ /*! - \fn void qToBigEndian(T src, void *dest) + \fn template <typename T> void qToBigEndian(T src, void *dest) \since 4.3 \relates <QtEndian> @@ -141,7 +141,7 @@ \sa qToLittleEndian() */ /*! - \fn T qToBigEndian(T src) + \fn template <typename T> T qToBigEndian(T src) \since 4.3 \relates <QtEndian> \overload @@ -153,7 +153,7 @@ unmodified. */ /*! - \fn void qToLittleEndian(T src, void *dest) + \fn template <typename T> void qToLittleEndian(T src, void *dest) \since 4.3 \relates <QtEndian> @@ -171,7 +171,7 @@ \sa qToBigEndian() */ /*! - \fn T qToLittleEndian(T src) + \fn template <typename T> T qToLittleEndian(T src) \since 4.3 \relates <QtEndian> \overload @@ -203,100 +203,100 @@ an exact endian is needed. */ -/*! \fn QLEInteger::QLEInteger(T value) +/*! \fn template <typename T> QLEInteger<T>::QLEInteger(T value) Constructs a QLEInteger with the given \a value. */ -/*! \fn QLEInteger &QLEInteger::operator=(T value) +/*! \fn template <typename T> QLEInteger &QLEInteger<T>::operator=(T i) - Assigns \a value to this QLEInteger and returns a reference to + Assigns \a i to this QLEInteger and returns a reference to this QLEInteger. */ /*! - \fn QLEInteger::operator T() const + \fn template <typename T> QLEInteger<T>::operator T() const Returns the value of this QLEInteger as a native integer. */ /*! - \fn bool QLEInteger::operator==(QLEInteger other) const + \fn template <typename T> bool QLEInteger<T>::operator==(QLEInteger other) const Returns \c true if the value of this QLEInteger is equal to the value of \a other. */ /*! - \fn bool QLEInteger::operator!=(QLEInteger other) const + \fn template <typename T> bool QLEInteger<T>::operator!=(QLEInteger other) const Returns \c true if the value of this QLEInteger is not equal to the value of \a other. */ /*! - \fn QLEInteger &QLEInteger::operator+=(T i) + \fn template <typename T> QLEInteger &QLEInteger<T>::operator+=(T i) Adds \a i to this QLEInteger and returns a reference to this object. */ /*! - \fn QLEInteger &QLEInteger::operator-=(T i) + \fn template <typename T> QLEInteger &QLEInteger<T>::operator-=(T i) Subtracts \a i from this QLEInteger and returns a reference to this object. */ /*! - \fn QLEInteger &QLEInteger::operator*=(T i) + \fn template <typename T> QLEInteger &QLEInteger<T>::operator*=(T i) Multiplies \a i with this QLEInteger and returns a reference to this object. */ /*! - \fn QLEInteger &QLEInteger::operator/=(T i) + \fn template <typename T> QLEInteger &QLEInteger<T>::operator/=(T i) Divides this QLEInteger with \a i and returns a reference to this object. */ /*! - \fn QLEInteger &QLEInteger::operator%=(T i) + \fn template <typename T> QLEInteger &QLEInteger<T>::operator%=(T i) Sets this QLEInteger to the remainder of a division by \a i and returns a reference to this object. */ /*! - \fn QLEInteger &QLEInteger::operator>>=(T i) + \fn template <typename T> QLEInteger &QLEInteger<T>::operator>>=(T i) Performs a left-shift by \a i on this QLEInteger and returns a reference to this object. */ /*! - \fn QLEInteger &QLEInteger::operator<<=(T i) + \fn template <typename T> QLEInteger &QLEInteger<T>::operator<<=(T i) Performs a right-shift by \a i on this QLEInteger and returns a reference to this object. */ /*! - \fn QLEInteger &QLEInteger::operator|=(T i) + \fn template <typename T> QLEInteger &QLEInteger<T>::operator|=(T i) Performs a bitwise OR with \a i onto this QLEInteger and returns a reference to this object. */ /*! - \fn QLEInteger &QLEInteger::operator&=(T i) + \fn template <typename T> QLEInteger &QLEInteger<T>::operator&=(T i) Performs a bitwise AND with \a i onto this QLEInteger and returns a reference to this object. */ /*! - \fn QLEInteger &QLEInteger::operator^=(T i) + \fn template <typename T> QLEInteger &QLEInteger<T>::operator^=(T i) Performs a bitwise XOR with \a i onto this QLEInteger and returns a reference to this object. @@ -322,100 +322,100 @@ an exact endian is needed. */ -/*! \fn QBEInteger::QBEInteger(T value) +/*! \fn template <typename T> QBEInteger<T>::QBEInteger(T value) Constructs a QBEInteger with the given \a value. */ -/*! \fn QBEInteger &QBEInteger::operator=(T value) +/*! \fn template <typename T> QBEInteger &QBEInteger<T>::operator=(T i) - Assigns \a value to this QBEInteger and returns a reference to + Assigns \a i to this QBEInteger and returns a reference to this QBEInteger. */ /*! - \fn QBEInteger::operator T() const + \fn template <typename T> QBEInteger<T>::operator T() const Returns the value of this QBEInteger as a native integer. */ /*! - \fn bool QBEInteger::operator==(QBEInteger other) const + \fn template <typename T> bool QBEInteger<T>::operator==(QBEInteger other) const Returns \c true if the value of this QBEInteger is equal to the value of \a other. */ /*! - \fn bool QBEInteger::operator!=(QBEInteger other) const + \fn template <typename T> bool QBEInteger<T>::operator!=(QBEInteger other) const Returns \c true if the value of this QBEInteger is not equal to the value of \a other. */ /*! - \fn QBEInteger &QBEInteger::operator+=(T i) + \fn template <typename T> QBEInteger &QBEInteger<T>::operator+=(T i) Adds \a i to this QBEInteger and returns a reference to this object. */ /*! - \fn QBEInteger &QBEInteger::operator-=(T i) + \fn template <typename T> QBEInteger &QBEInteger<T>::operator-=(T i) Subtracts \a i from this QBEInteger and returns a reference to this object. */ /*! - \fn QBEInteger &QBEInteger::operator*=(T i) + \fn template <typename T> QBEInteger &QBEInteger<T>::operator*=(T i) Multiplies \a i with this QBEInteger and returns a reference to this object. */ /*! - \fn QBEInteger &QBEInteger::operator/=(T i) + \fn template <typename T> QBEInteger &QBEInteger<T>::operator/=(T i) Divides this QBEInteger with \a i and returns a reference to this object. */ /*! - \fn QBEInteger &QBEInteger::operator%=(T i) + \fn template <typename T> QBEInteger &QBEInteger<T>::operator%=(T i) Sets this QBEInteger to the remainder of a division by \a i and returns a reference to this object. */ /*! - \fn QBEInteger &QBEInteger::operator>>=(T i) + \fn template <typename T> QBEInteger &QBEInteger<T>::operator>>=(T i) Performs a left-shift by \a i on this QBEInteger and returns a reference to this object. */ /*! - \fn QBEInteger &QBEInteger::operator<<=(T i) + \fn template <typename T> QBEInteger &QBEInteger<T>::operator<<=(T i) Performs a right-shift by \a i on this QBEInteger and returns a reference to this object. */ /*! - \fn QBEInteger &QBEInteger::operator|=(T i) + \fn template <typename T> QBEInteger &QBEInteger<T>::operator|=(T i) Performs a bitwise OR with \a i onto this QBEInteger and returns a reference to this object. */ /*! - \fn QBEInteger &QBEInteger::operator&=(T i) + \fn template <typename T> QBEInteger &QBEInteger<T>::operator&=(T i) Performs a bitwise AND with \a i onto this QBEInteger and returns a reference to this object. */ /*! - \fn QBEInteger &QBEInteger::operator^=(T i) + \fn template <typename T> QBEInteger &QBEInteger<T>::operator^=(T i) Performs a bitwise XOR with \a i onto this QBEInteger and returns a reference to this object. diff --git a/src/corelib/global/qflags.h b/src/corelib/global/qflags.h index 72b0a689ff..e9fee5f23e 100644 --- a/src/corelib/global/qflags.h +++ b/src/corelib/global/qflags.h @@ -54,20 +54,20 @@ class QFlag { int i; public: - Q_DECL_CONSTEXPR inline QFlag(int ai) Q_DECL_NOTHROW : i(ai) {} + Q_DECL_CONSTEXPR inline QFlag(int value) Q_DECL_NOTHROW : i(value) {} Q_DECL_CONSTEXPR inline operator int() const Q_DECL_NOTHROW { return i; } #if !defined(Q_CC_MSVC) // Microsoft Visual Studio has buggy behavior when it comes to // unsigned enums: even if the enum is unsigned, the enum tags are // always signed -# if !defined(__LP64__) && !defined(Q_QDOC) - Q_DECL_CONSTEXPR inline QFlag(long ai) Q_DECL_NOTHROW : i(int(ai)) {} - Q_DECL_CONSTEXPR inline QFlag(ulong ai) Q_DECL_NOTHROW : i(int(long(ai))) {} +# if !defined(__LP64__) && !defined(Q_CLANG_QDOC) + Q_DECL_CONSTEXPR inline QFlag(long value) Q_DECL_NOTHROW : i(int(value)) {} + Q_DECL_CONSTEXPR inline QFlag(ulong value) Q_DECL_NOTHROW : i(int(long(value))) {} # endif - Q_DECL_CONSTEXPR inline QFlag(uint ai) Q_DECL_NOTHROW : i(int(ai)) {} - Q_DECL_CONSTEXPR inline QFlag(short ai) Q_DECL_NOTHROW : i(int(ai)) {} - Q_DECL_CONSTEXPR inline QFlag(ushort ai) Q_DECL_NOTHROW : i(int(uint(ai))) {} + Q_DECL_CONSTEXPR inline QFlag(uint value) Q_DECL_NOTHROW : i(int(value)) {} + Q_DECL_CONSTEXPR inline QFlag(short value) Q_DECL_NOTHROW : i(int(value)) {} + Q_DECL_CONSTEXPR inline QFlag(ushort value) Q_DECL_NOTHROW : i(int(uint(value))) {} Q_DECL_CONSTEXPR inline operator uint() const Q_DECL_NOTHROW { return uint(i); } #endif }; @@ -82,7 +82,7 @@ public: }; Q_DECLARE_TYPEINFO(QIncompatibleFlag, Q_PRIMITIVE_TYPE); -Q_DECL_CONSTEXPR inline QIncompatibleFlag::QIncompatibleFlag(int ai) Q_DECL_NOTHROW : i(ai) {} +Q_DECL_CONSTEXPR inline QIncompatibleFlag::QIncompatibleFlag(int value) Q_DECL_NOTHROW : i(value) {} #ifndef Q_NO_TYPESAFE_FLAGS @@ -100,7 +100,7 @@ class QFlags template <typename E> friend QDataStream &operator>>(QDataStream &, QFlags<E> &); template <typename E> friend QDataStream &operator<<(QDataStream &, QFlags<E>); public: -#if defined(Q_CC_MSVC) || defined(Q_QDOC) +#if defined(Q_CC_MSVC) || defined(Q_CLANG_QDOC) // see above for MSVC // the definition below is too complex for qdoc typedef int Int; @@ -113,13 +113,13 @@ public: #endif typedef Enum enum_type; // compiler-generated copy/move ctor/assignment operators are fine! -#ifdef Q_QDOC +#ifdef Q_CLANG_QDOC Q_DECL_CONSTEXPR inline QFlags(const QFlags &other); Q_DECL_CONSTEXPR inline QFlags &operator=(const QFlags &other); #endif - Q_DECL_CONSTEXPR inline QFlags(Enum f) Q_DECL_NOTHROW : i(Int(f)) {} + Q_DECL_CONSTEXPR inline QFlags(Enum flags) Q_DECL_NOTHROW : i(Int(flags)) {} Q_DECL_CONSTEXPR inline QFlags(Zero = Q_NULLPTR) Q_DECL_NOTHROW : i(0) {} - Q_DECL_CONSTEXPR inline QFlags(QFlag f) Q_DECL_NOTHROW : i(f) {} + Q_DECL_CONSTEXPR inline QFlags(QFlag flag) Q_DECL_NOTHROW : i(flag) {} #ifdef Q_COMPILER_INITIALIZER_LISTS Q_DECL_CONSTEXPR inline QFlags(std::initializer_list<Enum> flags) Q_DECL_NOTHROW @@ -129,28 +129,28 @@ public: Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(int mask) Q_DECL_NOTHROW { i &= mask; return *this; } Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(uint mask) Q_DECL_NOTHROW { i &= mask; return *this; } Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator&=(Enum mask) Q_DECL_NOTHROW { i &= Int(mask); return *this; } - Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator|=(QFlags f) Q_DECL_NOTHROW { i |= f.i; return *this; } - Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator|=(Enum f) Q_DECL_NOTHROW { i |= Int(f); return *this; } - Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator^=(QFlags f) Q_DECL_NOTHROW { i ^= f.i; return *this; } - Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator^=(Enum f) Q_DECL_NOTHROW { i ^= Int(f); return *this; } + Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator|=(QFlags other) Q_DECL_NOTHROW { i |= other.i; return *this; } + Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator|=(Enum other) Q_DECL_NOTHROW { i |= Int(other); return *this; } + Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator^=(QFlags other) Q_DECL_NOTHROW { i ^= other.i; return *this; } + Q_DECL_RELAXED_CONSTEXPR inline QFlags &operator^=(Enum other) Q_DECL_NOTHROW { i ^= Int(other); return *this; } Q_DECL_CONSTEXPR inline operator Int() const Q_DECL_NOTHROW { return i; } - Q_DECL_CONSTEXPR inline QFlags operator|(QFlags f) const Q_DECL_NOTHROW { return QFlags(QFlag(i | f.i)); } - Q_DECL_CONSTEXPR inline QFlags operator|(Enum f) const Q_DECL_NOTHROW { return QFlags(QFlag(i | Int(f))); } - Q_DECL_CONSTEXPR inline QFlags operator^(QFlags f) const Q_DECL_NOTHROW { return QFlags(QFlag(i ^ f.i)); } - Q_DECL_CONSTEXPR inline QFlags operator^(Enum f) const Q_DECL_NOTHROW { return QFlags(QFlag(i ^ Int(f))); } + Q_DECL_CONSTEXPR inline QFlags operator|(QFlags other) const Q_DECL_NOTHROW { return QFlags(QFlag(i | other.i)); } + Q_DECL_CONSTEXPR inline QFlags operator|(Enum other) const Q_DECL_NOTHROW { return QFlags(QFlag(i | Int(other))); } + Q_DECL_CONSTEXPR inline QFlags operator^(QFlags other) const Q_DECL_NOTHROW { return QFlags(QFlag(i ^ other.i)); } + Q_DECL_CONSTEXPR inline QFlags operator^(Enum other) const Q_DECL_NOTHROW { return QFlags(QFlag(i ^ Int(other))); } Q_DECL_CONSTEXPR inline QFlags operator&(int mask) const Q_DECL_NOTHROW { return QFlags(QFlag(i & mask)); } Q_DECL_CONSTEXPR inline QFlags operator&(uint mask) const Q_DECL_NOTHROW { return QFlags(QFlag(i & mask)); } - Q_DECL_CONSTEXPR inline QFlags operator&(Enum f) const Q_DECL_NOTHROW { return QFlags(QFlag(i & Int(f))); } + Q_DECL_CONSTEXPR inline QFlags operator&(Enum other) const Q_DECL_NOTHROW { return QFlags(QFlag(i & Int(other))); } Q_DECL_CONSTEXPR inline QFlags operator~() const Q_DECL_NOTHROW { return QFlags(QFlag(~i)); } Q_DECL_CONSTEXPR inline bool operator!() const Q_DECL_NOTHROW { return !i; } - Q_DECL_CONSTEXPR inline bool testFlag(Enum f) const Q_DECL_NOTHROW { return (i & Int(f)) == Int(f) && (Int(f) != 0 || i == Int(f) ); } - Q_DECL_RELAXED_CONSTEXPR inline QFlags &setFlag(Enum f, bool on = true) Q_DECL_NOTHROW + Q_DECL_CONSTEXPR inline bool testFlag(Enum flag) const Q_DECL_NOTHROW { return (i & Int(flag)) == Int(flag) && (Int(flag) != 0 || i == Int(flag) ); } + Q_DECL_RELAXED_CONSTEXPR inline QFlags &setFlag(Enum flag, bool on = true) Q_DECL_NOTHROW { - return on ? (*this |= f) : (*this &= ~Int(f)); + return on ? (*this |= flag) : (*this &= ~Int(flag)); } private: diff --git a/src/corelib/global/qfloat16.cpp b/src/corelib/global/qfloat16.cpp index 89edfc8787..fd608efe55 100644 --- a/src/corelib/global/qfloat16.cpp +++ b/src/corelib/global/qfloat16.cpp @@ -38,6 +38,7 @@ ****************************************************************************/ #include "qfloat16_p.h" +#include "private/qsimd_p.h" QT_BEGIN_NAMESPACE @@ -113,4 +114,102 @@ Q_REQUIRED_RESULT bool qIsFinite(qfloat16 f) Q_DECL_NOTHROW { return qt_is_finit exactness is stronger the smaller the numbers are. */ +#if QT_COMPILER_SUPPORTS(F16C) +static inline bool hasFastF16() +{ + // All processors with F16C also support AVX, but YMM registers + // might not be supported by the OS, or they might be disabled. + return qCpuHasFeature(F16C) && qCpuHasFeature(AVX); +} + +extern "C" { +#ifdef QFLOAT16_INCLUDE_FAST +# define f16cextern static +#else +# define f16cextern extern +#endif + +f16cextern void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) Q_DECL_NOTHROW; +f16cextern void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) Q_DECL_NOTHROW; + +#undef f16cextern +} + +#elif defined(__ARM_FP16_FORMAT_IEEE) && defined(__ARM_NEON__) +static inline bool hasFastF16() +{ + return true; +} + +static void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) Q_DECL_NOTHROW +{ + __fp16 *out_f16 = reinterpret_cast<__fp16 *>(out); + qsizetype i = 0; + for (; i < len - 3; i += 4) + vst1_f16(out_f16 + i, vcvt_f16_f32(vld1q_f32(in + i))); + SIMD_EPILOGUE(i, len, 3) + out_f16[i] = __fp16(in[i]); +} + +static void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) Q_DECL_NOTHROW +{ + const __fp16 *in_f16 = reinterpret_cast<const __fp16 *>(in); + qsizetype i = 0; + for (; i < len - 3; i += 4) + vst1q_f32(out + i, vcvt_f32_f16(vld1_f16(in_f16 + i))); + SIMD_EPILOGUE(i, len, 3) + out[i] = float(in_f16[i]); +} +#else +static inline bool hasFastF16() +{ + return false; +} + +static void qFloatToFloat16_fast(quint16 *, const float *, qsizetype) Q_DECL_NOTHROW +{ + Q_UNREACHABLE(); +} + +static void qFloatFromFloat16_fast(float *, const quint16 *, qsizetype) Q_DECL_NOTHROW +{ + Q_UNREACHABLE(); +} +#endif +/*! + \since 5.11 + \relates <QFloat16> + + Converts \a len floats from \a in to qfloat16 and stores them in \a out. + Both \a in and \a out must have \a len allocated entries. +*/ +Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *out, const float *in, qsizetype len) Q_DECL_NOTHROW +{ + if (hasFastF16()) + return qFloatToFloat16_fast(reinterpret_cast<quint16 *>(out), in, len); + + for (qsizetype i = 0; i < len; ++i) + out[i] = qfloat16(in[i]); +} + +/*! + \since 5.11 + \relates <QFloat16> + + Converts \a len qfloat16 from \a in to floats and stores them in \a out. + Both \a in and \a out must have \a len allocated entries. +*/ +Q_CORE_EXPORT void qFloatFromFloat16(float *out, const qfloat16 *in, qsizetype len) Q_DECL_NOTHROW +{ + if (hasFastF16()) + return qFloatFromFloat16_fast(out, reinterpret_cast<const quint16 *>(in), len); + + for (qsizetype i = 0; i < len; ++i) + out[i] = float(in[i]); +} + QT_END_NAMESPACE + +#ifdef QFLOAT16_INCLUDE_FAST +# include "qfloat16_f16c.c" +#endif diff --git a/src/corelib/global/qfloat16.h b/src/corelib/global/qfloat16.h index 72e28edf63..a8befd7adb 100644 --- a/src/corelib/global/qfloat16.h +++ b/src/corelib/global/qfloat16.h @@ -88,6 +88,9 @@ private: Q_DECLARE_TYPEINFO(qfloat16, Q_PRIMITIVE_TYPE); +Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *, const float *, qsizetype length) Q_DECL_NOTHROW; +Q_CORE_EXPORT void qFloatFromFloat16(float *, const qfloat16 *, qsizetype length) Q_DECL_NOTHROW; + Q_REQUIRED_RESULT Q_CORE_EXPORT bool qIsInf(qfloat16 f) Q_DECL_NOTHROW; // complements qnumeric.h Q_REQUIRED_RESULT Q_CORE_EXPORT bool qIsNaN(qfloat16 f) Q_DECL_NOTHROW; // complements qnumeric.h Q_REQUIRED_RESULT Q_CORE_EXPORT bool qIsFinite(qfloat16 f) Q_DECL_NOTHROW; // complements qnumeric.h diff --git a/src/corelib/global/qfloat16_f16c.c b/src/corelib/global/qfloat16_f16c.c new file mode 100644 index 0000000000..a7eadc71b7 --- /dev/null +++ b/src/corelib/global/qfloat16_f16c.c @@ -0,0 +1,91 @@ +/**************************************************************************** +** +** Copyright (C) 2017 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "private/qsimd_p.h" + +// The x86 F16C instructions operate on AVX registers, so AVX support is +// required. We don't need to check for __F16C__ because we this file wouldn't +// have been compiled if the support was missing in the first place, and not +// all compilers define it. Technically, we didn't need to check for __AVX__ +// either. +#if !QT_COMPILER_SUPPORTS_HERE(AVX) +# error "AVX support required" +#endif + +#ifdef __cplusplus +QT_BEGIN_NAMESPACE +extern "C" { +#endif + +QT_FUNCTION_TARGET(F16C) +void qFloatToFloat16_fast(quint16 *out, const float *in, qsizetype len) Q_DECL_NOTHROW +{ + qsizetype i = 0; + int epilog_i; + for (; i < len - 7; i += 8) + _mm_storeu_si128((__m128i *)(out + i), _mm256_cvtps_ph(_mm256_loadu_ps(in + i), 0)); + if (i < len - 3) { + _mm_storel_epi64((__m128i *)(out + i), _mm_cvtps_ph(_mm_loadu_ps(in + i), 0)); + i += 4; + } + // Inlining "qfloat16::qfloat16(float f)": + for (epilog_i = 0; i < len && epilog_i < 3; ++i, ++epilog_i) + out[i] = _mm_extract_epi16(_mm_cvtps_ph(_mm_set_ss(in[i]), 0), 0); +} + +QT_FUNCTION_TARGET(F16C) +void qFloatFromFloat16_fast(float *out, const quint16 *in, qsizetype len) Q_DECL_NOTHROW +{ + qsizetype i = 0; + int epilog_i; + for (; i < len - 7; i += 8) + _mm256_storeu_ps(out + i, _mm256_cvtph_ps(_mm_loadu_si128((const __m128i *)(in + i)))); + if (i < len - 3) { + _mm_storeu_ps(out + i, _mm_cvtph_ps(_mm_loadl_epi64((const __m128i *)(in + i)))); + i += 4; + } + // Inlining "qfloat16::operator float()": + for (epilog_i = 0; i < len && epilog_i < 3; ++i, ++epilog_i) + out[i] = _mm_cvtss_f32(_mm_cvtph_ps(_mm_cvtsi32_si128(in[i]))); +} + +#ifdef __cplusplus +} // extern "C" +QT_END_NAMESPACE +#endif diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 87b79531ed..2d8b860c5b 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2017 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -76,6 +76,10 @@ #include <Ws2tcpip.h> #endif // Q_OS_WINRT +#ifdef Q_OS_WIN +# include <qt_windows.h> +#endif + #if defined(Q_OS_VXWORKS) && defined(_WRS_KERNEL) # include <envLib.h> #endif @@ -181,28 +185,28 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); /*! \fn QFlag::QFlag(int value) - Constructs a QFlag object that stores the given \a value. + Constructs a QFlag object that stores the \a value. */ /*! \fn QFlag::QFlag(uint value) \since 5.3 - Constructs a QFlag object that stores the given \a value. + Constructs a QFlag object that stores the \a value. */ /*! \fn QFlag::QFlag(short value) \since 5.3 - Constructs a QFlag object that stores the given \a value. + Constructs a QFlag object that stores the \a value. */ /*! \fn QFlag::QFlag(ushort value) \since 5.3 - Constructs a QFlag object that stores the given \a value. + Constructs a QFlag object that stores the \a value. */ /*! @@ -297,29 +301,28 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); */ /*! - \fn QFlags::QFlags(const QFlags &other) + \fn template<typename Enum> QFlags<Enum>::QFlags(const QFlags &other) Constructs a copy of \a other. */ /*! - \fn QFlags::QFlags(Enum flag) + \fn template <typename Enum> QFlags<Enum>::QFlags(Enum flags) - Constructs a QFlags object storing the given \a flag. + Constructs a QFlags object storing the \a flags. */ /*! - \fn QFlags::QFlags(Zero zero) + \fn template <typename Enum> QFlags<Enum>::QFlags(Zero) - Constructs a QFlags object with no flags set. \a zero must be a + Constructs a QFlags object with no flags set. The parameter must be a literal 0 value. */ /*! - \fn QFlags::QFlags(QFlag value) + \fn template <typename Enum> QFlags<Enum>::QFlags(QFlag flag) - Constructs a QFlags object initialized with the given integer \a - value. + Constructs a QFlags object initialized with the integer \a flag. The QFlag type is a helper type. By using it here instead of \c int, we effectively ensure that arbitrary enum values cannot be @@ -328,7 +331,7 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); */ /*! - \fn QFlags::QFlags(std::initializer_list<Enum> flags) + \fn template <typename Enum> QFlags<Enum>::QFlags(std::initializer_list<Enum> flags) \since 5.4 Constructs a QFlags object initialized with all \a flags @@ -338,14 +341,14 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); */ /*! - \fn QFlags &QFlags::operator=(const QFlags &other) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator=(const QFlags &other) Assigns \a other to this object and returns a reference to this object. */ /*! - \fn QFlags &QFlags::operator&=(int mask) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator&=(int mask) Performs a bitwise AND operation with \a mask and stores the result in this QFlags object. Returns a reference to this object. @@ -354,19 +357,19 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); */ /*! - \fn QFlags &QFlags::operator&=(uint mask) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator&=(uint mask) \overload */ /*! - \fn QFlags &QFlags::operator&=(Enum mask) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator&=(Enum mask) \overload */ /*! - \fn QFlags &QFlags::operator|=(QFlags other) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator|=(QFlags other) Performs a bitwise OR operation with \a other and stores the result in this QFlags object. Returns a reference to this object. @@ -375,13 +378,13 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); */ /*! - \fn QFlags &QFlags::operator|=(Enum other) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator|=(Enum other) \overload */ /*! - \fn QFlags &QFlags::operator^=(QFlags other) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator^=(QFlags other) Performs a bitwise XOR operation with \a other and stores the result in this QFlags object. Returns a reference to this object. @@ -390,13 +393,13 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); */ /*! - \fn QFlags &QFlags::operator^=(Enum other) + \fn template <typename Enum> QFlags &QFlags<Enum>::operator^=(Enum other) \overload */ /*! - \fn QFlags::operator Int() const + \fn template <typename Enum> QFlags<Enum>::operator Int() const Returns the value stored in the QFlags object as an integer. @@ -404,7 +407,7 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); */ /*! - \fn QFlags QFlags::operator|(QFlags other) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator|(QFlags other) const Returns a QFlags object containing the result of the bitwise OR operation on this object and \a other. @@ -413,13 +416,13 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); */ /*! - \fn QFlags QFlags::operator|(Enum other) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator|(Enum other) const \overload */ /*! - \fn QFlags QFlags::operator^(QFlags other) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator^(QFlags other) const Returns a QFlags object containing the result of the bitwise XOR operation on this object and \a other. @@ -428,13 +431,13 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); */ /*! - \fn QFlags QFlags::operator^(Enum other) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator^(Enum other) const \overload */ /*! - \fn QFlags QFlags::operator&(int mask) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator&(int mask) const Returns a QFlags object containing the result of the bitwise AND operation on this object and \a mask. @@ -443,19 +446,19 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); */ /*! - \fn QFlags QFlags::operator&(uint mask) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator&(uint mask) const \overload */ /*! - \fn QFlags QFlags::operator&(Enum mask) const + \fn template <typename Enum> QFlags QFlags<Enum>::operator&(Enum mask) const \overload */ /*! - \fn QFlags QFlags::operator~() const + \fn template <typename Enum> QFlags QFlags<Enum>::operator~() const Returns a QFlags object that contains the bitwise negation of this object. @@ -464,24 +467,24 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); */ /*! - \fn bool QFlags::operator!() const + \fn template <typename Enum> bool QFlags<Enum>::operator!() const Returns \c true if no flag is set (i.e., if the value stored by the QFlags object is 0); otherwise returns \c false. */ /*! - \fn bool QFlags::testFlag(Enum flag) const + \fn template <typename Enum> bool QFlags<Enum>::testFlag(Enum flag) const \since 4.2 - Returns \c true if the \a flag is set, otherwise \c false. + Returns \c true if the flag \a flag is set, otherwise \c false. */ /*! - \fn QFlags QFlags::setFlag(Enum flag, bool on) + \fn template <typename Enum> QFlags QFlags<Enum>::setFlag(Enum flag, bool on) \since 5.7 - Sets the indicated \a flag if \a on is \c true or unsets it if + Sets the flag \a flag if \a on is \c true or unsets it if \a on is \c false. Returns a reference to this object. */ @@ -919,11 +922,11 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); \sa quint64, qlonglong */ -/*! \fn T qAbs(const T &value) +/*! \fn template <typename T> T qAbs(const T &t) \relates <QtGlobal> - Compares \a value to the 0 of type T and returns the absolute - value. Thus if T is \e {double}, then \a value is compared to + Compares \a t to the 0 of type T and returns the absolute + value. Thus if T is \e {double}, then \a t is compared to \e{(double) 0}. Example: @@ -931,50 +934,50 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); \snippet code/src_corelib_global_qglobal.cpp 10 */ -/*! \fn int qRound(double value) +/*! \fn int qRound(double d) \relates <QtGlobal> - Rounds \a value to the nearest integer. + Rounds \a d to the nearest integer. Example: \snippet code/src_corelib_global_qglobal.cpp 11A */ -/*! \fn int qRound(float value) +/*! \fn int qRound(float d) \relates <QtGlobal> - Rounds \a value to the nearest integer. + Rounds \a d to the nearest integer. Example: \snippet code/src_corelib_global_qglobal.cpp 11B */ -/*! \fn qint64 qRound64(double value) +/*! \fn qint64 qRound64(double d) \relates <QtGlobal> - Rounds \a value to the nearest 64-bit integer. + Rounds \a d to the nearest 64-bit integer. Example: \snippet code/src_corelib_global_qglobal.cpp 12A */ -/*! \fn qint64 qRound64(float value) +/*! \fn qint64 qRound64(float d) \relates <QtGlobal> - Rounds \a value to the nearest 64-bit integer. + Rounds \a d to the nearest 64-bit integer. Example: \snippet code/src_corelib_global_qglobal.cpp 12B */ -/*! \fn const T &qMin(const T &value1, const T &value2) +/*! \fn template <typename T> const T &qMin(const T &a, const T &b) \relates <QtGlobal> - Returns the minimum of \a value1 and \a value2. + Returns the minimum of \a a and \a b. Example: @@ -983,10 +986,10 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); \sa qMax(), qBound() */ -/*! \fn const T &qMax(const T &value1, const T &value2) +/*! \fn template <typename T> const T &qMax(const T &a, const T &b) \relates <QtGlobal> - Returns the maximum of \a value1 and \a value2. + Returns the maximum of \a a and \a b. Example: @@ -995,11 +998,11 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); \sa qMin(), qBound() */ -/*! \fn const T &qBound(const T &min, const T &value, const T &max) +/*! \fn template <typename T> const T &qBound(const T &min, const T &val, const T &max) \relates <QtGlobal> - Returns \a value bounded by \a min and \a max. This is equivalent - to qMax(\a min, qMin(\a value, \a max)). + Returns \a val bounded by \a min and \a max. This is equivalent + to qMax(\a min, qMin(\a val, \a max)). Example: @@ -1008,7 +1011,7 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); \sa qMin(), qMax() */ -/*! \fn auto qOverload(T functionPointer) +/*! \fn template <typename T> auto qOverload(T functionPointer) \relates <QtGlobal> \since 5.7 @@ -1030,7 +1033,7 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); and Functor-Based Connections} */ -/*! \fn auto qConstOverload(T memberFunctionPointer) +/*! \fn template <typename T> auto qConstOverload(T memberFunctionPointer) \relates <QtGlobal> \since 5.7 @@ -1042,7 +1045,7 @@ Q_STATIC_ASSERT((std::is_same<qsizetype, qptrdiff>::value)); and Functor-Based Connections} */ -/*! \fn auto qNonConstOverload(T memberFunctionPointer) +/*! \fn template <typename T> auto qNonConstOverload(T memberFunctionPointer) \relates <QtGlobal> \since 5.7 @@ -1431,13 +1434,6 @@ bool qSharedBuild() Q_DECL_NOTHROW */ /*! - \macro Q_OS_ULTRIX - \relates <QtGlobal> - - Defined on DEC Ultrix. -*/ - -/*! \macro Q_OS_LINUX \relates <QtGlobal> @@ -1473,41 +1469,6 @@ bool qSharedBuild() Q_DECL_NOTHROW */ /*! - \macro Q_OS_BSDI - \relates <QtGlobal> - - Defined on BSD/OS. -*/ - -/*! - \macro Q_OS_IRIX - \relates <QtGlobal> - - Defined on SGI Irix. -*/ - -/*! - \macro Q_OS_OSF - \relates <QtGlobal> - - Defined on HP Tru64 UNIX. -*/ - -/*! - \macro Q_OS_SCO - \relates <QtGlobal> - - Defined on SCO OpenServer 5. -*/ - -/*! - \macro Q_OS_UNIXWARE - \relates <QtGlobal> - - Defined on UnixWare 7, Open UNIX 8. -*/ - -/*! \macro Q_OS_AIX \relates <QtGlobal> @@ -1522,27 +1483,6 @@ bool qSharedBuild() Q_DECL_NOTHROW */ /*! - \macro Q_OS_DGUX - \relates <QtGlobal> - - Defined on DG/UX. -*/ - -/*! - \macro Q_OS_RELIANT - \relates <QtGlobal> - - Defined on Reliant UNIX. -*/ - -/*! - \macro Q_OS_DYNIX - \relates <QtGlobal> - - Defined on DYNIX/ptx. -*/ - -/*! \macro Q_OS_QNX \relates <QtGlobal> @@ -2884,10 +2824,11 @@ QString QSysInfo::prettyProductName() This function returns the same as QHostInfo::localHostName(). - \sa QHostInfo::localDomainName + \sa QHostInfo::localDomainName, machineUniqueId() */ QString QSysInfo::machineHostName() { + // the hostname can change, so we can't cache it #if defined(Q_OS_LINUX) // gethostname(3) on Linux just calls uname(2), so do it ourselves // and avoid a memcpy @@ -2910,6 +2851,119 @@ QString QSysInfo::machineHostName() } #endif // QT_BOOTSTRAPPED +enum { + UuidStringLen = sizeof("00000000-0000-0000-0000-000000000000") - 1 +}; + +/*! + \since 5.10 + + Returns a unique ID for this machine, if one can be determined. If no + unique ID could be determined, this function returns an empty byte array. + Unlike machineHostName(), the value returned by this function is likely + globally unique. + + A unique ID is useful in network operations to identify this machine for an + extended period of time, when the IP address could change or if this + machine could have more than one IP address. For example, the ID could be + used when communicating with a server or when storing device-specific data + in shared network storage. + + Note that on some systems, this value will persist across reboots and on + some it will not. Applications should not blindly depend on this fact + without verifying the OS capabilities. In particular, on Linux systems, + this ID is usually permanent and it matches the D-Bus machine ID, except + for nodes without their own storage (replicated nodes). + + \sa machineHostName(), bootUniqueId() +*/ +QByteArray QSysInfo::machineUniqueId() +{ +#ifdef Q_OS_BSD4 + char uuid[UuidStringLen]; + size_t uuidlen = sizeof(uuid); +# ifdef KERN_HOSTUUID + int name[] = { CTL_KERN, KERN_HOSTUUID }; + if (sysctl(name, sizeof name / sizeof name[0], &uuid, &uuidlen, nullptr, 0) == 0 + && uuidlen == sizeof(uuid)) + return QByteArray(uuid, uuidlen); + +# else + // Darwin: no fixed value, we need to search by name + if (sysctlbyname("kern.uuid", uuid, &uuidlen, nullptr, 0) == 0 && uuidlen == sizeof(uuid)) + return QByteArray(uuid, uuidlen); +# endif +#elif defined(Q_OS_UNIX) + // The modern name on Linux is /etc/machine-id, but that path is + // unlikely to exist on non-Linux (non-systemd) systems. The old + // path is more than enough. + static const char fullfilename[] = "/usr/local/var/lib/dbus/machine-id"; + const char *firstfilename = fullfilename + sizeof("/usr/local") - 1; + int fd = qt_safe_open(firstfilename, O_RDONLY); + if (fd == -1 && errno == ENOENT) + fd = qt_safe_open(fullfilename, O_RDONLY); + + if (fd != -1) { + char buffer[32]; // 128 bits, hex-encoded + qint64 len = qt_safe_read(fd, buffer, sizeof(buffer)); + qt_safe_close(fd); + + if (len != -1) + return QByteArray(buffer, len); + } +#elif defined(Q_OS_WIN) && !defined(Q_OS_WINRT) + // Let's poke at the registry + HKEY key = NULL; + if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Cryptography", 0, KEY_READ, &key) + == ERROR_SUCCESS) { + wchar_t buffer[UuidStringLen + 1]; + DWORD size = sizeof(buffer); + bool ok = (RegQueryValueEx(key, L"MachineGuid", NULL, NULL, (LPBYTE)buffer, &size) == + ERROR_SUCCESS); + RegCloseKey(key); + if (ok) + return QStringView(buffer, (size - 1) / 2).toLatin1(); + } +#endif + return QByteArray(); +} + +/*! + \since 5.10 + + Returns a unique ID for this machine's boot, if one can be determined. If + no unique ID could be determined, this function returns an empty byte + array. This value is expected to change after every boot and can be + considered globally unique. + + This function is currently only implemented for Linux and Apple operating + systems. + + \sa machineUniqueId() +*/ +QByteArray QSysInfo::bootUniqueId() +{ +#ifdef Q_OS_LINUX + // use low-level API here for simplicity + int fd = qt_safe_open("/proc/sys/kernel/random/boot_id", O_RDONLY); + if (fd != -1) { + char uuid[UuidStringLen]; + qint64 len = qt_safe_read(fd, uuid, sizeof(uuid)); + qt_safe_close(fd); + if (len == UuidStringLen) + return QByteArray(uuid, UuidStringLen); + } +#elif defined(Q_OS_DARWIN) + // "kern.bootsessionuuid" is only available by name + char uuid[UuidStringLen]; + size_t uuidlen = sizeof(uuid); + if (sysctlbyname("kern.bootsessionuuid", uuid, &uuidlen, nullptr, 0) == 0 + && uuidlen == sizeof(uuid)) + return QByteArray(uuid, uuidlen); +#endif + return QByteArray(); +}; + /*! \macro void Q_ASSERT(bool test) \relates <QtGlobal> @@ -3053,10 +3107,10 @@ QString QSysInfo::machineHostName() */ /*! - \fn T *q_check_ptr(T *pointer) + \fn template <typename T> T *q_check_ptr(T *p) \relates <QtGlobal> - Uses Q_CHECK_PTR on \a pointer, then returns \a pointer. + Uses Q_CHECK_PTR on \a p, then returns \a p. This can be used as an inline version of Q_CHECK_PTR. */ @@ -3195,7 +3249,7 @@ static QBasicMutex environmentMutex; QByteArray qgetenv(const char *varName) { QMutexLocker locker(&environmentMutex); -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#ifdef Q_CC_MSVC size_t requiredSize = 0; QByteArray buffer; getenv_s(&requiredSize, 0, 0, varName); @@ -3214,6 +3268,8 @@ QByteArray qgetenv(const char *varName) /*! + QString qEnvironmentVariable(const char *varName, const QString &defaultValue); + \relates <QtGlobal> \since 5.10 @@ -3288,6 +3344,9 @@ QString qEnvironmentVariable(const char *varName, const QString &defaultValue) #endif } +/*! + \internal +*/ QString qEnvironmentVariable(const char *varName) { return qEnvironmentVariable(varName, QString()); @@ -3310,7 +3369,7 @@ QString qEnvironmentVariable(const char *varName) bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT { QMutexLocker locker(&environmentMutex); -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#ifdef Q_CC_MSVC // we provide a buffer that can only hold the empty string, so // when the env.var isn't empty, we'll get an ERANGE error (buffer // too small): @@ -3351,7 +3410,7 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT (std::numeric_limits<uint>::digits + NumBinaryDigitsPerOctalDigit - 1) / NumBinaryDigitsPerOctalDigit; QMutexLocker locker(&environmentMutex); -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#ifdef Q_CC_MSVC // we provide a buffer that can hold any int value: char buffer[MaxDigitsForOctalInt + 2]; // +1 for NUL +1 for optional '-' size_t dummy; @@ -3398,7 +3457,7 @@ int qEnvironmentVariableIntValue(const char *varName, bool *ok) Q_DECL_NOEXCEPT bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT { QMutexLocker locker(&environmentMutex); -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#ifdef Q_CC_MSVC size_t requiredSize = 0; (void)getenv_s(&requiredSize, 0, 0, varName); return requiredSize != 0; @@ -3428,7 +3487,7 @@ bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT bool qputenv(const char *varName, const QByteArray& value) { QMutexLocker locker(&environmentMutex); -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#if defined(Q_CC_MSVC) return _putenv_s(varName, value.constData()) == 0; #elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_HAIKU) // POSIX.1-2001 has setenv @@ -3459,7 +3518,7 @@ bool qputenv(const char *varName, const QByteArray& value) bool qunsetenv(const char *varName) { QMutexLocker locker(&environmentMutex); -#if defined(_MSC_VER) && _MSC_VER >= 1400 +#if defined(Q_CC_MSVC) return _putenv_s(varName, "") == 0; #elif (defined(_POSIX_VERSION) && (_POSIX_VERSION-0) >= 200112L) || defined(Q_OS_BSD4) || defined(Q_OS_HAIKU) // POSIX.1-2001, BSD and Haiku have unsetenv @@ -3551,7 +3610,7 @@ bool qunsetenv(const char *varName) */ /*! - \fn qAsConst(T &t) + \fn template <typename T> typename std::add_const<T>::type &qAsConst(T &t) \relates <QtGlobal> \since 5.7 @@ -3603,7 +3662,7 @@ bool qunsetenv(const char *varName) */ /*! - \fn qAsConst(const T &&t) + \fn template <typename T> void qAsConst(const T &&t) \relates <QtGlobal> \since 5.7 \overload @@ -4015,43 +4074,6 @@ bool QInternal::activateCallbacks(Callback cb, void **parameters) */ /*! - \macro Q_GLOBAL_STATIC(type, name) - \internal - - Declares a global static variable with the given \a type and \a name. - - Use this macro to instantiate an object in a thread-safe way, creating - a global pointer that can be used to refer to it. - - \warning This macro is subject to a race condition that can cause the object - to be constructed twice. However, if this occurs, the second instance will - be immediately deleted. - - See also - \l{http://www.aristeia.com/publications.html}{"C++ and the perils of Double-Checked Locking"} - by Scott Meyers and Andrei Alexandrescu. -*/ - -/*! - \macro Q_GLOBAL_STATIC_WITH_ARGS(type, name, arguments) - \internal - - Declares a global static variable with the specified \a type and \a name. - - Use this macro to instantiate an object using the \a arguments specified - in a thread-safe way, creating a global pointer that can be used to refer - to it. - - \warning This macro is subject to a race condition that can cause the object - to be constructed twice. However, if this occurs, the second instance will - be immediately deleted. - - See also - \l{http://www.aristeia.com/publications.html}{"C++ and the perils of Double-Checked Locking"} - by Scott Meyers and Andrei Alexandrescu. -*/ - -/*! \macro QT_NAMESPACE \internal diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index b85b008f70..aa9446221b 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -47,6 +47,7 @@ # include <utility> #endif #ifndef __ASSEMBLER__ +# include <assert.h> # include <stddef.h> #endif @@ -87,6 +88,11 @@ #if QT_VERSION >= QT_VERSION_CHECK(6,0,0) # define QT_NO_UNSHARABLE_CONTAINERS +# define QT6_VIRTUAL virtual +# define QT6_NOT_VIRTUAL +#else +# define QT6_VIRTUAL +# define QT6_NOT_VIRTUAL virtual #endif /* These two macros makes it possible to turn the builtin line expander into a @@ -105,6 +111,32 @@ # define Q_OF_MACH_O #endif +/* + Avoid "unused parameter" warnings +*/ +#define Q_UNUSED(x) (void)x; + +#if defined(__cplusplus) && defined(Q_COMPILER_STATIC_ASSERT) +# define Q_STATIC_ASSERT(Condition) static_assert(bool(Condition), #Condition) +# define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message) +#elif defined(Q_COMPILER_STATIC_ASSERT) +// C11 mode - using the _S version in case <assert.h> doesn't do the right thing +# define Q_STATIC_ASSERT(Condition) _Static_assert(!!(Condition), #Condition) +# define Q_STATIC_ASSERT_X(Condition, Message) _Static_assert(!!(Condition), Message) +#else +// C89 & C99 version +# define Q_STATIC_ASSERT_PRIVATE_JOIN(A, B) Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) +# define Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) A ## B +# ifdef __COUNTER__ +# define Q_STATIC_ASSERT(Condition) \ + typedef char Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __COUNTER__) [(Condition) ? 1 : -1]; +# else +# define Q_STATIC_ASSERT(Condition) \ + typedef char Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __LINE__) [(Condition) ? 1 : -1]; +# endif /* __COUNTER__ */ +# define Q_STATIC_ASSERT_X(Condition, Message) Q_STATIC_ASSERT(Condition) +#endif + #ifdef __cplusplus #include <algorithm> @@ -219,6 +251,15 @@ typedef unsigned long long quint64; /* 64 bit unsigned */ typedef qint64 qlonglong; typedef quint64 qulonglong; +#ifndef __cplusplus +// In C++ mode, we define below using QIntegerForSize template +Q_STATIC_ASSERT_X(sizeof(ptrdiff_t) == sizeof(size_t), "Weird ptrdiff_t and size_t definitions"); +typedef ptrdiff_t qptrdiff; +typedef ptrdiff_t qsizetype; +typedef ptrdiff_t qintptr; +typedef size_t quintptr; +#endif + /* Useful type definitions for Qt */ @@ -676,7 +717,7 @@ inline void qt_noop(void) {} # define QT_CATCH(A) catch (A) # define QT_THROW(A) throw A # define QT_RETHROW throw -Q_NORETURN Q_CORE_EXPORT void qTerminate() Q_DECL_NOTHROW; +Q_NORETURN Q_DECL_COLD_FUNCTION Q_CORE_EXPORT void qTerminate() Q_DECL_NOTHROW; # ifdef Q_COMPILER_NOEXCEPT # define QT_TERMINATE_ON_EXCEPTION(expr) do { expr; } while (false) # else @@ -694,11 +735,6 @@ Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qSharedBuild() Q_DECL_NOTHROW; #endif /* - Avoid "unused parameter" warnings -*/ -#define Q_UNUSED(x) (void)x; - -/* Debugging and error handling */ @@ -724,11 +760,13 @@ Q_CORE_EXPORT Q_DECL_CONST_FUNCTION bool qSharedBuild() Q_DECL_NOTHROW; #endif class QString; +Q_DECL_COLD_FUNCTION Q_CORE_EXPORT QString qt_error_string(int errorCode = -1); #ifndef Q_CC_MSVC Q_NORETURN #endif +Q_DECL_COLD_FUNCTION Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line) Q_DECL_NOTHROW; #if !defined(Q_ASSERT) @@ -746,6 +784,7 @@ Q_CORE_EXPORT void qt_assert(const char *assertion, const char *file, int line) #ifndef Q_CC_MSVC Q_NORETURN #endif +Q_DECL_COLD_FUNCTION Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char *file, int line) Q_DECL_NOTHROW; #if !defined(Q_ASSERT_X) @@ -756,28 +795,8 @@ Q_CORE_EXPORT void qt_assert_x(const char *where, const char *what, const char * # endif #endif - -#ifdef Q_COMPILER_STATIC_ASSERT -#define Q_STATIC_ASSERT(Condition) static_assert(bool(Condition), #Condition) -#define Q_STATIC_ASSERT_X(Condition, Message) static_assert(bool(Condition), Message) -#else -// Intentionally undefined -template <bool Test> class QStaticAssertFailure; -template <> class QStaticAssertFailure<true> {}; - -#define Q_STATIC_ASSERT_PRIVATE_JOIN(A, B) Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) -#define Q_STATIC_ASSERT_PRIVATE_JOIN_IMPL(A, B) A ## B -#ifdef __COUNTER__ -#define Q_STATIC_ASSERT(Condition) \ - enum {Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __COUNTER__) = sizeof(QStaticAssertFailure<!!(Condition)>)} -#else -#define Q_STATIC_ASSERT(Condition) \ - enum {Q_STATIC_ASSERT_PRIVATE_JOIN(q_static_assert_result, __LINE__) = sizeof(QStaticAssertFailure<!!(Condition)>)} -#endif /* __COUNTER__ */ -#define Q_STATIC_ASSERT_X(Condition, Message) Q_STATIC_ASSERT(Condition) -#endif - Q_NORETURN Q_CORE_EXPORT void qt_check_pointer(const char *, int) Q_DECL_NOTHROW; +Q_DECL_COLD_FUNCTION Q_CORE_EXPORT void qBadAlloc(); #ifdef QT_NO_EXCEPTIONS @@ -919,13 +938,7 @@ QT_WARNING_DISABLE_MSVC(4514) /* unreferenced inline function has been removed * QT_WARNING_DISABLE_MSVC(4800) /* 'type' : forcing value to bool 'true' or 'false' (performance warning) */ QT_WARNING_DISABLE_MSVC(4097) /* typedef-name 'identifier1' used as synonym for class-name 'identifier2' */ QT_WARNING_DISABLE_MSVC(4706) /* assignment within conditional expression */ -# if _MSC_VER <= 1310 // MSVC 2003 -QT_WARNING_DISABLE_MSVC(4786) /* 'identifier' : identifier was truncated to 'number' characters in the debug information */ -# endif QT_WARNING_DISABLE_MSVC(4355) /* 'this' : used in base member initializer list */ -# if _MSC_VER < 1800 // MSVC 2013 -QT_WARNING_DISABLE_MSVC(4231) /* nonstandard extension used : 'identifier' before template explicit instantiation */ -# endif QT_WARNING_DISABLE_MSVC(4710) /* function not inlined */ QT_WARNING_DISABLE_MSVC(4530) /* C++ exception handler used, but unwind semantics are not enabled. Specify /EHsc */ # elif defined(Q_CC_BOR) @@ -1132,19 +1145,15 @@ template <typename... Args> Q_CONSTEXPR Q_DECL_UNUSED QNonConstOverload<Args...> class QByteArray; Q_CORE_EXPORT QByteArray qgetenv(const char *varName); -#ifdef Q_QDOC -Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName, - const QString &defaultValue = QString()); -#else // need it as two functions because QString is only forward-declared here +// need it as two functions because QString is only forward-declared here Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName); Q_CORE_EXPORT QString qEnvironmentVariable(const char *varName, const QString &defaultValue); -#endif Q_CORE_EXPORT bool qputenv(const char *varName, const QByteArray& value); Q_CORE_EXPORT bool qunsetenv(const char *varName); Q_CORE_EXPORT bool qEnvironmentVariableIsEmpty(const char *varName) Q_DECL_NOEXCEPT; Q_CORE_EXPORT bool qEnvironmentVariableIsSet(const char *varName) Q_DECL_NOEXCEPT; -Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=Q_NULLPTR) Q_DECL_NOEXCEPT; +Q_CORE_EXPORT int qEnvironmentVariableIntValue(const char *varName, bool *ok=nullptr) Q_DECL_NOEXCEPT; inline int qIntCast(double f) { return int(f); } inline int qIntCast(float f) { return int(f); } diff --git a/src/corelib/global/qglobalstatic.qdoc b/src/corelib/global/qglobalstatic.qdoc index 8c34739d38..63cc968d1c 100644 --- a/src/corelib/global/qglobalstatic.qdoc +++ b/src/corelib/global/qglobalstatic.qdoc @@ -368,7 +368,7 @@ */ /*! - \fn bool QGlobalStatic::isDestroyed() const + \fn template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> bool QGlobalStatic<T, innerFunction, guard>::isDestroyed() const This function returns \c true if the global static object has already completed destruction (that is, if the destructor for the type has already @@ -398,7 +398,7 @@ */ /*! - \fn bool QGlobalStatic::exists() const + \fn template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> bool QGlobalStatic<T, innerFunction, guard>::exists() const This function returns \c true if the global static object has already completed initialization (that is, if the constructor for the type has @@ -447,7 +447,7 @@ */ /*! - \fn QGlobalStatic::operator Type*() + \fn template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> QGlobalStatic<T, innerFunction, guard>::operator Type*() This function returns the address of the contents of this global static. If the contents have not yet been created, they will be created thread-safely @@ -480,7 +480,7 @@ */ /*! - \fn Type *QGlobalStatic::operator()() + \fn template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> Type *QGlobalStatic<T, innerFunction, guard>::operator()() \deprecated This function returns the address of the contents of this global static. If @@ -495,7 +495,7 @@ */ /*! - \fn Type *QGlobalStatic::operator->() + \fn template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> Type *QGlobalStatic<T, innerFunction, guard>::operator->() This function returns the address of the contents of this global static. If the contents have not yet been created, they will be created thread-safely @@ -508,7 +508,7 @@ */ /*! - \fn Type &QGlobalStatic::operator*() + \fn template <typename T, T *(&innerFunction)(), QBasicAtomicInt &guard> Type &QGlobalStatic<T, innerFunction, guard>::operator*() This function returns a reference to the contents of this global static. If the contents have not yet been created, they will be created thread-safely diff --git a/src/corelib/global/qlibraryinfo.cpp b/src/corelib/global/qlibraryinfo.cpp index b4ba0b5b2e..422d08f32c 100644 --- a/src/corelib/global/qlibraryinfo.cpp +++ b/src/corelib/global/qlibraryinfo.cpp @@ -318,15 +318,7 @@ QLibraryInfo::buildDate() #elif defined(Q_CC_GNU) # define COMPILER_STRING "GCC " __VERSION__ #elif defined(Q_CC_MSVC) -# if _MSC_VER < 1600 -# define COMPILER_STRING "MSVC 2008" -# elif _MSC_VER < 1700 -# define COMPILER_STRING "MSVC 2010" -# elif _MSC_VER < 1800 -# define COMPILER_STRING "MSVC 2012" -# elif _MSC_VER < 1900 -# define COMPILER_STRING "MSVC 2013" -# elif _MSC_VER < 1910 +# if _MSC_VER < 1910 # define COMPILER_STRING "MSVC 2015" # elif _MSC_VER < 2000 # define COMPILER_STRING "MSVC 2017" diff --git a/src/corelib/global/qlogging.cpp b/src/corelib/global/qlogging.cpp index 3206a43599..9f1fe7cabb 100644 --- a/src/corelib/global/qlogging.cpp +++ b/src/corelib/global/qlogging.cpp @@ -71,6 +71,10 @@ #include <android/log.h> #endif +#ifdef Q_OS_DARWIN +#include <QtCore/private/qcore_mac_p.h> +#endif + #if QT_CONFIG(journald) # define SD_JOURNAL_SUPPRESS_LOCATION # include <systemd/sd-journal.h> @@ -155,6 +159,7 @@ Q_NORETURN #endif static void qt_message_fatal(QtMsgType, const QMessageLogContext &context, const QString &message); static void qt_message_print(QtMsgType, const QMessageLogContext &context, const QString &message); +static void qt_message_print(const QString &message); static int checked_var_value(const char *varname) { @@ -194,13 +199,16 @@ static bool isFatal(QtMsgType msgType) return false; } +static bool isDefaultCategory(const char *category) +{ + return !category || strcmp(category, "default") == 0; +} + static bool willLogToConsole() { #if defined(Q_OS_WINRT) // these systems have no stderr, so always log to the system log return false; -#elif defined(QT_BOOTSTRAPPED) - return true; #else // rules to determine if we'll log preferably to the console: // 1) if QT_LOGGING_TO_CONSOLE is set, it determines behavior: @@ -1209,20 +1217,10 @@ void QMessagePattern::setPattern(const QString &pattern) error += QLatin1String("QT_MESSAGE_PATTERN: %{if-*} cannot be nested\n"); else if (inIf) error += QLatin1String("QT_MESSAGE_PATTERN: missing %{endif}\n"); - if (!error.isEmpty()) { -#if defined(Q_OS_WINRT) - OutputDebugString(reinterpret_cast<const wchar_t*>(error.utf16())); - if (0) -#elif defined(Q_OS_WIN) && defined(QT_BUILD_CORE_LIB) - if (!qt_logging_to_console()) { - OutputDebugString(reinterpret_cast<const wchar_t*>(error.utf16())); - } else -#endif - { - fprintf(stderr, "%s", error.toLocal8Bit().constData()); - fflush(stderr); - } - } + + if (!error.isEmpty()) + qt_message_print(error); + literals = new const char*[literalsVar.size() + 1]; literals[literalsVar.size()] = 0; memcpy(literals, literalsVar.constData(), literalsVar.size() * sizeof(const char*)); @@ -1250,7 +1248,7 @@ static QStringList backtraceFramesForLogMessage(int frameCount) static QRegularExpression rx(QStringLiteral("^(?:[^(]*/)?([^(/]+)\\(([^+]*)(?:[\\+[a-f0-9x]*)?\\) \\[[a-f0-9x]*\\]$"), QRegularExpression::OptimizeOnFirstUsageOption); - QVarLengthArray<void*, 32> buffer(7 + frameCount); + QVarLengthArray<void*, 32> buffer(8 + frameCount); int n = backtrace(buffer.data(), buffer.size()); if (n > 0) { int numberPrinted = 0; @@ -1312,57 +1310,6 @@ static QString formatBacktraceForLogMessage(const QMessagePattern::BacktracePara } #endif // QLOGGING_HAVE_BACKTRACE && !QT_BOOTSTRAPPED -#if QT_CONFIG(slog2) -#ifndef QT_LOG_CODE -#define QT_LOG_CODE 9000 -#endif - -static void slog2_default_handler(QtMsgType msgType, const char *message) -{ - if (slog2_set_default_buffer((slog2_buffer_t)-1) == 0) { - slog2_buffer_set_config_t buffer_config; - slog2_buffer_t buffer_handle; - - buffer_config.buffer_set_name = __progname; - buffer_config.num_buffers = 1; - buffer_config.verbosity_level = SLOG2_DEBUG1; - buffer_config.buffer_config[0].buffer_name = "default"; - buffer_config.buffer_config[0].num_pages = 8; - - if (slog2_register(&buffer_config, &buffer_handle, 0) == -1) { - fprintf(stderr, "Error registering slogger2 buffer!\n"); - fprintf(stderr, "%s", message); - fflush(stderr); - return; - } - - // Set as the default buffer - slog2_set_default_buffer(buffer_handle); - } - int severity; - //Determines the severity level - switch (msgType) { - case QtDebugMsg: - severity = SLOG2_DEBUG1; - break; - case QtInfoMsg: - severity = SLOG2_INFO; - break; - case QtWarningMsg: - severity = SLOG2_NOTICE; - break; - case QtCriticalMsg: - severity = SLOG2_WARNING; - break; - case QtFatalMsg: - severity = SLOG2_ERROR; - break; - } - //writes to the slog2 buffer - slog2c(NULL, QT_LOG_CODE, severity, message); -} -#endif // slog2 - Q_GLOBAL_STATIC(QMessagePattern, qMessagePattern) /*! @@ -1480,7 +1427,7 @@ QString qFormatLogMessage(QtMsgType type, const QMessageLogContext &context, con } #endif // !QT_BOOTSTRAPPED } else if (token == ifCategoryTokenC) { - if (!context.category || (strcmp(context.category, "default") == 0)) + if (isDefaultCategory(context.category)) skip = true; #define HANDLE_IF_TOKEN(LEVEL) \ } else if (token == if##LEVEL##TokenC) { \ @@ -1512,11 +1459,80 @@ static QBasicAtomicPointer<void (QtMsgType, const char*)> msgHandler = Q_BASIC_A // pointer to QtMessageHandler debug handler (with context) static QBasicAtomicPointer<void (QtMsgType, const QMessageLogContext &, const QString &)> messageHandler = Q_BASIC_ATOMIC_INITIALIZER(qDefaultMessageHandler); +// ------------------------ Alternate logging sinks ------------------------- + +#if defined(QT_BOOTSTRAPPED) + // Boostrapped tools always print to stderr, so no need for alternate sinks +#else + +#if QT_CONFIG(slog2) +#ifndef QT_LOG_CODE +#define QT_LOG_CODE 9000 +#endif + +static bool slog2_default_handler(QtMsgType type, const QMessageLogContext &context, const QString &message) +{ + if (qt_logging_to_console()) + return false; + + QString formattedMessage = qFormatLogMessage(type, context, message); + formattedMessage.append(QLatin1Char('\n')); + if (slog2_set_default_buffer((slog2_buffer_t)-1) == 0) { + slog2_buffer_set_config_t buffer_config; + slog2_buffer_t buffer_handle; + + buffer_config.buffer_set_name = __progname; + buffer_config.num_buffers = 1; + buffer_config.verbosity_level = SLOG2_DEBUG1; + buffer_config.buffer_config[0].buffer_name = "default"; + buffer_config.buffer_config[0].num_pages = 8; + + if (slog2_register(&buffer_config, &buffer_handle, 0) == -1) { + fprintf(stderr, "Error registering slogger2 buffer!\n"); + fprintf(stderr, "%s", formattedMessage.toLocal8Bit().constData()); + fflush(stderr); + return false; + } + + // Set as the default buffer + slog2_set_default_buffer(buffer_handle); + } + int severity; + //Determines the severity level + switch (type) { + case QtDebugMsg: + severity = SLOG2_DEBUG1; + break; + case QtInfoMsg: + severity = SLOG2_INFO; + break; + case QtWarningMsg: + severity = SLOG2_NOTICE; + break; + case QtCriticalMsg: + severity = SLOG2_WARNING; + break; + case QtFatalMsg: + severity = SLOG2_ERROR; + break; + } + //writes to the slog2 buffer + slog2c(NULL, QT_LOG_CODE, severity, formattedMessage.toLocal8Bit().constData()); + + return true; // Prevent further output to stderr +} +#endif // slog2 + #if QT_CONFIG(journald) -static void systemd_default_message_handler(QtMsgType type, +static bool systemd_default_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message) { + if (qt_logging_to_console()) + return false; + + QString formattedMessage = qFormatLogMessage(type, context, message); + int priority = LOG_INFO; // Informational switch (type) { case QtDebugMsg: @@ -1536,19 +1552,26 @@ static void systemd_default_message_handler(QtMsgType type, break; } - sd_journal_send("MESSAGE=%s", message.toUtf8().constData(), + sd_journal_send("MESSAGE=%s", formattedMessage.toUtf8().constData(), "PRIORITY=%i", priority, "CODE_FUNC=%s", context.function ? context.function : "unknown", "CODE_LINE=%d", context.line, "CODE_FILE=%s", context.file ? context.file : "unknown", "QT_CATEGORY=%s", context.category ? context.category : "unknown", NULL); + + return true; // Prevent further output to stderr } #endif #if QT_CONFIG(syslog) -static void syslog_default_message_handler(QtMsgType type, const char *message) +static bool syslog_default_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message) { + if (qt_logging_to_console()) + return false; + + QString formattedMessage = qFormatLogMessage(type, context, message); + int priority = LOG_INFO; // Informational switch (type) { case QtDebugMsg: @@ -1568,15 +1591,22 @@ static void syslog_default_message_handler(QtMsgType type, const char *message) break; } - syslog(priority, "%s", message); + syslog(priority, "%s", formattedMessage.toUtf8().constData()); + + return true; // Prevent further output to stderr } #endif #if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) -static void android_default_message_handler(QtMsgType type, +static bool android_default_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message) { + if (qt_logging_to_console()) + return false; + + QString formattedMessage = qFormatLogMessage(type, context, message); + android_LogPriority priority = ANDROID_LOG_DEBUG; switch (type) { case QtDebugMsg: priority = ANDROID_LOG_DEBUG; break; @@ -1588,50 +1618,81 @@ static void android_default_message_handler(QtMsgType type, __android_log_print(priority, qPrintable(QCoreApplication::applicationName()), "%s:%d (%s): %s\n", context.file, context.line, - context.function, qPrintable(message)); + context.function, qPrintable(formattedMessage)); + + return true; // Prevent further output to stderr } #endif //Q_OS_ANDROID -/*! - \internal -*/ -static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context, - const QString &buf) +#ifdef Q_OS_WIN +static bool win_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message) { - QString logMessage = qFormatLogMessage(type, context, buf); + if (qt_logging_to_console()) + return false; + + QString formattedMessage = qFormatLogMessage(type, context, message); + formattedMessage.append(QLatin1Char('\n')); + OutputDebugString(reinterpret_cast<const wchar_t *>(formattedMessage.utf16())); + + return true; // Prevent further output to stderr +} +#endif + +#endif // Bootstrap check + +// -------------------------------------------------------------------------- + +static void stderr_message_handler(QtMsgType type, const QMessageLogContext &context, const QString &message) +{ + QString formattedMessage = qFormatLogMessage(type, context, message); // print nothing if message pattern didn't apply / was empty. // (still print empty lines, e.g. because message itself was empty) - if (logMessage.isNull()) + if (formattedMessage.isNull()) return; - if (!qt_logging_to_console()) { -#if defined(Q_OS_WIN) - logMessage.append(QLatin1Char('\n')); - OutputDebugString(reinterpret_cast<const wchar_t *>(logMessage.utf16())); - return; -#elif QT_CONFIG(slog2) - logMessage.append(QLatin1Char('\n')); - slog2_default_handler(type, logMessage.toLocal8Bit().constData()); - return; -#elif QT_CONFIG(journald) - systemd_default_message_handler(type, context, logMessage); - return; -#elif QT_CONFIG(syslog) - syslog_default_message_handler(type, logMessage.toUtf8().constData()); - return; -#elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) - android_default_message_handler(type, context, logMessage); - return; -#endif - } - fprintf(stderr, "%s\n", logMessage.toLocal8Bit().constData()); + fprintf(stderr, "%s\n", formattedMessage.toLocal8Bit().constData()); fflush(stderr); } /*! \internal */ +static void qDefaultMessageHandler(QtMsgType type, const QMessageLogContext &context, + const QString &message) +{ + bool handledStderr = false; + + // A message sink logs the message to a structured or unstructured destination, + // optionally formatting the message if the latter, and returns true if the sink + // handled stderr output as well, which will shortcut our default stderr output. + // In the future, if we allow multiple/dynamic sinks, this will be iterating + // a list of sinks. + +#if !defined(QT_BOOTSTRAPPED) +# if defined(Q_OS_WIN) + handledStderr |= win_message_handler(type, context, message); +# elif QT_CONFIG(slog2) + handledStderr |= slog2_default_handler(type, context, message); +# elif QT_CONFIG(journald) + handledStderr |= systemd_default_message_handler(type, context, message); +# elif QT_CONFIG(syslog) + handledStderr |= syslog_default_message_handler(type, context, message); +# elif defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) + handledStderr |= android_default_message_handler(type, context, message); +# elif defined(QT_USE_APPLE_UNIFIED_LOGGING) + if (__builtin_available(macOS 10.12, iOS 10, tvOS 10, watchOS 3, *)) + handledStderr |= AppleUnifiedLogger::messageHandler(type, context, message); +# endif +#endif + + if (!handledStderr) + stderr_message_handler(type, context, message); +} + +/*! + \internal +*/ static void qDefaultMsgHandler(QtMsgType type, const char *buf) { QMessageLogContext emptyContext; @@ -1665,7 +1726,7 @@ static void qt_message_print(QtMsgType msgType, const QMessageLogContext &contex { #ifndef QT_BOOTSTRAPPED // qDebug, qWarning, ... macros do not check whether category is enabled - if (!context.category || (strcmp(context.category, "default") == 0)) { + if (isDefaultCategory(context.category)) { if (QLoggingCategory *defaultCategory = QLoggingCategory::defaultCategory()) { if (!defaultCategory->isEnabled(msgType)) return; @@ -1689,6 +1750,21 @@ static void qt_message_print(QtMsgType msgType, const QMessageLogContext &contex } } +static void qt_message_print(const QString &message) +{ +#if defined(Q_OS_WINRT) + OutputDebugString(reinterpret_cast<const wchar_t*>(message.utf16())); + return; +#elif defined(Q_OS_WIN) && !defined(QT_BOOTSTRAPPED) + if (!qt_logging_to_console()) { + OutputDebugString(reinterpret_cast<const wchar_t*>(message.utf16())); + return; + } +#endif + fprintf(stderr, "%s", message.toLocal8Bit().constData()); + fflush(stderr); +} + static void qt_message_fatal(QtMsgType, const QMessageLogContext &context, const QString &message) { #if defined(Q_CC_MSVC) && defined(QT_DEBUG) && defined(_DEBUG) && defined(_CRT_ERROR) @@ -1886,6 +1962,10 @@ void qErrnoWarning(int code, const char *msg, ...) environment variable; if both \l qSetMessagePattern() is called and QT_MESSAGE_PATTERN is set, the environment variable takes precedence. + \note The message pattern only applies to unstructured logging, such as the default + \c stderr output. Structured logging such as systemd will record the message as is, + along with as much structured information as can be captured. + Custom message handlers can use qFormatLogMessage() to take \a pattern into account. \sa qInstallMessageHandler(), {Debugging Techniques}, {QLoggingCategory} diff --git a/src/corelib/global/qlogging.h b/src/corelib/global/qlogging.h index ec21198784..16e01183bd 100644 --- a/src/corelib/global/qlogging.h +++ b/src/corelib/global/qlogging.h @@ -64,7 +64,7 @@ class QMessageLogContext Q_DISABLE_COPY(QMessageLogContext) public: Q_DECL_CONSTEXPR QMessageLogContext() - : version(2), line(0), file(Q_NULLPTR), function(Q_NULLPTR), category(Q_NULLPTR) {} + : version(2), line(0), file(nullptr), function(nullptr), category(nullptr) {} Q_DECL_CONSTEXPR QMessageLogContext(const char *fileName, int lineNumber, const char *functionName, const char *categoryName) : version(2), line(lineNumber), file(fileName), function(functionName), category(categoryName) {} @@ -97,7 +97,9 @@ public: void noDebug(const char *, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(2, 3) {} void info(const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(2, 3); + Q_DECL_COLD_FUNCTION void warning(const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(2, 3); + Q_DECL_COLD_FUNCTION void critical(const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(2, 3); typedef const QLoggingCategory &(*CategoryFunction)(); @@ -106,14 +108,19 @@ public: void debug(CategoryFunction catFunc, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4); void info(const QLoggingCategory &cat, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4); void info(CategoryFunction catFunc, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4); + Q_DECL_COLD_FUNCTION void warning(const QLoggingCategory &cat, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4); + Q_DECL_COLD_FUNCTION void warning(CategoryFunction catFunc, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4); + Q_DECL_COLD_FUNCTION void critical(const QLoggingCategory &cat, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4); + Q_DECL_COLD_FUNCTION void critical(CategoryFunction catFunc, const char *msg, ...) const Q_ATTRIBUTE_FORMAT_PRINTF(3, 4); #ifndef Q_CC_MSVC Q_NORETURN #endif + Q_DECL_COLD_FUNCTION void fatal(const char *msg, ...) const Q_DECL_NOTHROW Q_ATTRIBUTE_FORMAT_PRINTF(2, 3); #ifndef QT_NO_DEBUG_STREAM @@ -150,9 +157,9 @@ private: #define QT_MESSAGELOG_LINE __LINE__ #define QT_MESSAGELOG_FUNC Q_FUNC_INFO #else - #define QT_MESSAGELOG_FILE Q_NULLPTR + #define QT_MESSAGELOG_FILE nullptr #define QT_MESSAGELOG_LINE 0 - #define QT_MESSAGELOG_FUNC Q_NULLPTR + #define QT_MESSAGELOG_FUNC nullptr #endif #define qDebug QMessageLogger(QT_MESSAGELOG_FILE, QT_MESSAGELOG_LINE, QT_MESSAGELOG_FUNC).debug @@ -179,8 +186,8 @@ private: Q_CORE_EXPORT void qt_message_output(QtMsgType, const QMessageLogContext &context, const QString &message); -Q_CORE_EXPORT void qErrnoWarning(int code, const char *msg, ...); -Q_CORE_EXPORT void qErrnoWarning(const char *msg, ...); +Q_CORE_EXPORT Q_DECL_COLD_FUNCTION void qErrnoWarning(int code, const char *msg, ...); +Q_CORE_EXPORT Q_DECL_COLD_FUNCTION void qErrnoWarning(const char *msg, ...); #if QT_DEPRECATED_SINCE(5, 0)// deprecated. Use qInstallMessageHandler instead! typedef void (*QtMsgHandler)(QtMsgType, const char *); diff --git a/src/corelib/global/qnamespace.h b/src/corelib/global/qnamespace.h index 2a8345195d..31b1823690 100644 --- a/src/corelib/global/qnamespace.h +++ b/src/corelib/global/qnamespace.h @@ -243,7 +243,7 @@ public: // size of a multi-variant string. TextLongestVariant = 0x80000 -#if QT_VERSION < QT_VERSION_CHECK(6, 0, 0) +#if QT_DEPRECATED_SINCE(5, 11) && QT_VERSION < QT_VERSION_CHECK(6, 0, 0) , TextBypassShaping = 0x100000 #endif }; @@ -848,6 +848,36 @@ public: Key_Dead_Belowdot = 0x01001260, Key_Dead_Hook = 0x01001261, Key_Dead_Horn = 0x01001262, + Key_Dead_Stroke = 0x01001263, + Key_Dead_Abovecomma = 0x01001264, + Key_Dead_Abovereversedcomma = 0x01001265, + Key_Dead_Doublegrave = 0x01001266, + Key_Dead_Belowring = 0x01001267, + Key_Dead_Belowmacron = 0x01001268, + Key_Dead_Belowcircumflex = 0x01001269, + Key_Dead_Belowtilde = 0x0100126a, + Key_Dead_Belowbreve = 0x0100126b, + Key_Dead_Belowdiaeresis = 0x0100126c, + Key_Dead_Invertedbreve = 0x0100126d, + Key_Dead_Belowcomma = 0x0100126e, + Key_Dead_Currency = 0x0100126f, + Key_Dead_a = 0x01001280, + Key_Dead_A = 0x01001281, + Key_Dead_e = 0x01001282, + Key_Dead_E = 0x01001283, + Key_Dead_i = 0x01001284, + Key_Dead_I = 0x01001285, + Key_Dead_o = 0x01001286, + Key_Dead_O = 0x01001287, + Key_Dead_u = 0x01001288, + Key_Dead_U = 0x01001289, + Key_Dead_Small_Schwa = 0x0100128a, + Key_Dead_Capital_Schwa = 0x0100128b, + Key_Dead_Greek = 0x0100128c, + Key_Dead_Lowline = 0x01001290, + Key_Dead_Aboveverticalline = 0x01001291, + Key_Dead_Belowverticalline = 0x01001292, + Key_Dead_Longsolidusoverlay = 0x01001293, // multimedia/internet keys - ignored by default - see QKeyEvent c'tor Key_Back = 0x01000061, @@ -1376,6 +1406,9 @@ public: ImhMultiLine = 0x400, + ImhNoEditMenu = 0x800, + ImhNoTextHandles = 0x1000, + ImhDigitsOnly = 0x10000, ImhFormattedNumbersOnly = 0x20000, ImhUppercaseOnly = 0x40000, @@ -1831,6 +1864,16 @@ public: static bool activateCallbacks(Callback, void **); }; +#if defined(Q_CLANG_QDOC) +// Declared here for qdoc; actual declarations in qtextdocument.h +namespace Qt +{ + bool mightBeRichText(const QString&); + QString convertFromPlainText(const QString &plain, WhiteSpaceMode mode = WhiteSpacePre); + QTextCodec *codecForHtml(const QByteArray &ba); +} +#endif // Q_CLANG_QDOC + QT_END_NAMESPACE #endif // QNAMESPACE_H diff --git a/src/corelib/global/qnamespace.qdoc b/src/corelib/global/qnamespace.qdoc index e64fb221d3..11c431d015 100644 --- a/src/corelib/global/qnamespace.qdoc +++ b/src/corelib/global/qnamespace.qdoc @@ -993,12 +993,7 @@ \value WA_LayoutUsesWidgetRect Ignore the layout item rect from the style when laying out this widget with QLayout. - \value WA_MacNoClickThrough When a widget that has this attribute set - is clicked, and its window is inactive, the click will make the window - active but won't be seen by the widget. Typical use of this attribute - is on widgets with "destructive" actions, such as a "Delete" button. - WA_MacNoClickThrough also applies to all child widgets of the widget - that has it set. + \value WA_MacNoClickThrough This value is obsolete and has no effect. \value WA_MacOpaqueSizeGrip Indicates that the native Carbon size grip should be opaque instead of transparent (the default). This attribute @@ -1027,9 +1022,7 @@ alternative sizes for widgets to avoid clipping. This attribute is only applicable to \macos. - \value WA_MacBrushedMetal Indicates the widget should be drawn in - the brushed metal style as supported by the windowing system. This - attribute is only applicable to \macos. + \value WA_MacBrushedMetal This value is obsolete and has no effect. \omitvalue WA_MacMetalStyle @@ -1284,9 +1277,7 @@ has no effect on non-X11 platforms. \b Note: Qt automatically sets this attribute on the feedback widget used during a drag. - \value WA_MacFrameworkScaled Enables resolution independence aware mode - on Mac when using Carbon. This attribute has no effect on Cocoa. - The attribute is off by default and can be enabled on a per-window basis. + \value WA_MacFrameworkScaled This value is obsolete and has no effect. \value WA_AcceptTouchEvents Allows touch events (see QTouchEvent) to be sent to the widget. Must be set on all widgets that can @@ -1338,6 +1329,7 @@ \omitvalue WA_WState_WindowOpacitySet \omitvalue WA_WState_AcceptedTouchBeginEvent \omitvalue WA_MacNoShadow + \omitvalue WA_ContentsMarginsRespectsSafeArea */ /*! \typedef Qt::HANDLE @@ -1613,6 +1605,36 @@ \value Key_Dead_Belowdot \value Key_Dead_Hook \value Key_Dead_Horn + \value Key_Dead_Stroke + \value Key_Dead_Abovecomma + \value Key_Dead_Abovereversedcomma + \value Key_Dead_Doublegrave + \value Key_Dead_Belowring + \value Key_Dead_Belowmacron + \value Key_Dead_Belowcircumflex + \value Key_Dead_Belowtilde + \value Key_Dead_Belowbreve + \value Key_Dead_Belowdiaeresis + \value Key_Dead_Invertedbreve + \value Key_Dead_Belowcomma + \value Key_Dead_Currency + \value Key_Dead_a + \value Key_Dead_A + \value Key_Dead_e + \value Key_Dead_E + \value Key_Dead_i + \value Key_Dead_I + \value Key_Dead_o + \value Key_Dead_O + \value Key_Dead_u + \value Key_Dead_U + \value Key_Dead_Small_Schwa + \value Key_Dead_Capital_Schwa + \value Key_Dead_Greek + \value Key_Dead_Lowline + \value Key_Dead_Aboveverticalline + \value Key_Dead_Belowverticalline + \value Key_Dead_Longsolidusoverlay \value Key_Back \value Key_Forward \value Key_Stop @@ -2129,7 +2151,7 @@ with a somewhat lighter frame. It can also be combined with Qt::FramelessWindowHint. On \macos, tool windows correspond to the - \l{http://developer.apple.com/documentation/Carbon/Conceptual/HandlingWindowsControls/hitb-wind_cont_concept/chapter_2_section_2.html}{Floating} + \l{https://developer.apple.com/documentation/appkit/nspanel}{NSPanel} class of windows. This means that the window lives on a level above normal windows making it impossible to put a normal window on top of it. By default, tool windows will disappear @@ -2564,6 +2586,9 @@ \value ImhMultiLine Multiple lines can be entered into the text field. + \value ImhNoEditMenu Do not use built-in edit menu. This flag was introduced in Qt 5.11. + \value ImhNoTextHandles Do not use built-in text cursor and selection handles. This flag was introduced in Qt 5.11. + Flags that restrict input (exclusive flags): \value ImhDigitsOnly Only digits are allowed. @@ -3077,9 +3102,8 @@ it is displayed regardless of device type. The keypad is used to implement a virtual cursor, unless the device has an analog mouse type of input device (e.g. touchpad) - - \note In 4.6, cursor navigation is only implemented for Symbian OS. - On other platforms, it behaves as NavigationModeNone. + \note Cursor navigation is not currently implemented on any platform + and behaves as NavigationModeNone. \sa QApplication::setNavigationMode() \sa QApplication::navigationMode() */ @@ -3192,3 +3216,37 @@ \value ChecksumItuV41 Checksum calculation based on ITU-V.41. */ + +/*! + \fn bool Qt::mightBeRichText(const QString& text) + + Returns \c true if the string \a text is likely to be rich text; + otherwise returns \c false. + + This function uses a fast and therefore simple heuristic. It + mainly checks whether there is something that looks like a tag + before the first line break. Although the result may be correct + for common cases, there is no guarantee. + + This function is defined in the \c <QTextDocument> header file. +*/ + +/*! + \fn QString Qt::convertFromPlainText(const QString &plain, Qt::WhiteSpaceMode mode) + + Converts the plain text string \a plain to an HTML-formatted + paragraph while preserving most of its look. + + \a mode defines how whitespace is handled. + + This function is defined in the \c <QTextDocument> header file. + + \sa escape(), mightBeRichText() +*/ + +/*! + \fn QTextCodec *Qt::codecForHtml(const QByteArray &ba) + \internal + + This function is defined in the \c <QTextDocument> header file. +*/ diff --git a/src/corelib/global/qnumeric_p.h b/src/corelib/global/qnumeric_p.h index 37eddfa9b5..9b86a16516 100644 --- a/src/corelib/global/qnumeric_p.h +++ b/src/corelib/global/qnumeric_p.h @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2018 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -58,8 +58,6 @@ #if defined(Q_CC_MSVC) # include <intrin.h> -#elif defined(Q_CC_INTEL) -# include <immintrin.h> // for _addcarry_u<nn> #endif #if defined(Q_CC_MSVC) @@ -163,10 +161,34 @@ Q_DECL_CONST_FUNCTION static inline bool qt_is_finite(float f) return qnumeric_std_wrapper::isfinite(f); } -// -// Unsigned overflow math -// +#ifndef Q_CLANG_QDOC namespace { +// Overflow math. +// This provides efficient implementations for int, unsigned, qsizetype and +// size_t. Implementations for 8- and 16-bit types will work but may not be as +// efficient. Implementations for 64-bit may be missing on 32-bit platforms. + +#if (defined(Q_CC_GNU) && (Q_CC_GNU >= 500) || defined(Q_CC_INTEL)) || QT_HAS_BUILTIN(__builtin_add_overflowx) +// GCC 5, ICC 18, and Clang 3.8 have builtins to detect overflows + +template <typename T> inline +typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type +add_overflow(T v1, T v2, T *r) +{ return __builtin_add_overflow(v1, v2, r); } + +template <typename T> inline +typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type +sub_overflow(T v1, T v2, T *r) +{ return __builtin_sub_overflow(v1, v2, r); } + +template <typename T> inline +typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type +mul_overflow(T v1, T v2, T *r) +{ return __builtin_mul_overflow(v1, v2, r); } + +#else +// Generic implementations + template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type add_overflow(T v1, T v2, T *r) { @@ -175,69 +197,92 @@ add_overflow(T v1, T v2, T *r) return v1 > T(v1 + v2); } +template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type +add_overflow(T v1, T v2, T *r) +{ + // Here's how we calculate the overflow: + // 1) unsigned addition is well-defined, so we can always execute it + // 2) conversion from unsigned back to signed is implementation- + // defined and in the implementations we use, it's a no-op. + // 3) signed integer overflow happens if the sign of the two input operands + // is the same but the sign of the result is different. In other words, + // the sign of the result must be the same as the sign of either + // operand. + + using U = typename std::make_unsigned<T>::type; + *r = T(U(v1) + U(v2)); + + // If int is two's complement, assume all integer types are too. + if (std::is_same<int32_t, int>::value) { + // Two's complement equivalent (generates slightly shorter code): + // x ^ y is negative if x and y have different signs + // x & y is negative if x and y are negative + // (x ^ z) & (y ^ z) is negative if x and z have different signs + // AND y and z have different signs + return ((v1 ^ *r) & (v2 ^ *r)) < 0; + } + + bool s1 = (v1 < 0); + bool s2 = (v2 < 0); + bool sr = (*r < 0); + return s1 != sr && s2 != sr; + // also: return s1 == s2 && s1 != sr; +} + template <typename T> inline typename std::enable_if<std::is_unsigned<T>::value, bool>::type +sub_overflow(T v1, T v2, T *r) +{ + // unsigned subtractions are well-defined + *r = v1 - v2; + return v1 < v2; +} + +template <typename T> inline typename std::enable_if<std::is_signed<T>::value, bool>::type +sub_overflow(T v1, T v2, T *r) +{ + // See above for explanation. This is the same with some signs reversed. + // We can't use add_overflow(v1, -v2, r) because it would be UB if + // v2 == std::numeric_limits<T>::min(). + + using U = typename std::make_unsigned<T>::type; + *r = T(U(v1) - U(v2)); + + if (std::is_same<int32_t, int>::value) + return ((v1 ^ *r) & (~v2 ^ *r)) < 0; + + bool s1 = (v1 < 0); + bool s2 = !(v2 < 0); + bool sr = (*r < 0); + return s1 != sr && s2 != sr; + // also: return s1 == s2 && s1 != sr; +} + +template <typename T> inline +typename std::enable_if<std::is_unsigned<T>::value || std::is_signed<T>::value, bool>::type mul_overflow(T v1, T v2, T *r) { // use the next biggest type // Note: for 64-bit systems where __int128 isn't supported, this will cause an error. - // A fallback is present below. - typedef typename QIntegerForSize<sizeof(T) * 2>::Unsigned Larger; + using LargerInt = QIntegerForSize<sizeof(T) * 2>; + using Larger = typename std::conditional<std::is_signed<T>::value, + typename LargerInt::Signed, typename LargerInt::Unsigned>::type; Larger lr = Larger(v1) * Larger(v2); *r = T(lr); - return lr > std::numeric_limits<T>::max(); + return lr > std::numeric_limits<T>::max() || lr < std::numeric_limits<T>::min(); } -#if defined(__SIZEOF_INT128__) -# define HAVE_MUL64_OVERFLOW -#endif - -// GCC 5 and Clang have builtins to detect overflows -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uadd_overflow) +# if defined(Q_CC_MSVC) && defined(Q_PROCESSOR_X86) +// We can use intrinsics for the unsigned operations with MSVC template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r) -{ return __builtin_uadd_overflow(v1, v2, r); } -#endif -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uaddl_overflow) -template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r) -{ return __builtin_uaddl_overflow(v1, v2, r); } -#endif -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_uaddll_overflow) -template <> inline bool add_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r) -{ return __builtin_uaddll_overflow(v1, v2, r); } -#endif +{ return _addcarry_u32(0, v1, v2, r); } -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umul_overflow) -template <> inline bool mul_overflow(unsigned v1, unsigned v2, unsigned *r) -{ return __builtin_umul_overflow(v1, v2, r); } -#endif -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umull_overflow) -template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r) -{ return __builtin_umull_overflow(v1, v2, r); } -#endif -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_umulll_overflow) -template <> inline bool mul_overflow(unsigned long long v1, unsigned long long v2, unsigned long long *r) -{ return __builtin_umulll_overflow(v1, v2, r); } -# define HAVE_MUL64_OVERFLOW -#endif +// 32-bit mul_overflow is fine with the generic code above -#if ((defined(Q_CC_MSVC) && _MSC_VER >= 1800) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86) && !QT_HAS_BUILTIN(__builtin_uadd_overflow) -template <> inline bool add_overflow(unsigned v1, unsigned v2, unsigned *r) -{ return _addcarry_u32(0, v1, v2, r); } -# ifdef Q_CC_MSVC // longs are 32-bit -template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r) -{ return _addcarry_u32(0, v1, v2, reinterpret_cast<unsigned *>(r)); } -# endif -#endif -#if ((defined(Q_CC_MSVC) && _MSC_VER >= 1800) || defined(Q_CC_INTEL)) && defined(Q_PROCESSOR_X86_64) && !QT_HAS_BUILTIN(__builtin_uadd_overflow) +# if defined(Q_PROCESSOR_X86_64) template <> inline bool add_overflow(quint64 v1, quint64 v2, quint64 *r) { return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r)); } -# ifndef Q_CC_MSVC // longs are 64-bit -template <> inline bool add_overflow(unsigned long v1, unsigned long v2, unsigned long *r) -{ return _addcarry_u64(0, v1, v2, reinterpret_cast<unsigned __int64 *>(r)); } -# endif -#endif -#if defined(Q_CC_MSVC) && (defined(Q_PROCESSOR_X86_64) || defined(Q_PROCESSOR_IA64)) && !QT_HAS_BUILTIN(__builtin_uadd_overflow) -#pragma intrinsic(_umul128) +# pragma intrinsic(_umul128) template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r) { // use 128-bit multiplication with the _umul128 intrinsic @@ -246,117 +291,30 @@ template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r) *r = _umul128(v1, v2, &high); return high; } -# define HAVE_MUL64_OVERFLOW -#endif - -#if !defined(HAVE_MUL64_OVERFLOW) && defined(__LP64__) -// no 128-bit multiplication, we need to figure out with a slow division -template <> inline bool mul_overflow(quint64 v1, quint64 v2, quint64 *r) -{ - if (v2 && v1 > std::numeric_limits<quint64>::max() / v2) - return true; - *r = v1 * v2; - return false; -} -template <> inline bool mul_overflow(unsigned long v1, unsigned long v2, unsigned long *r) -{ - return mul_overflow<quint64>(v1, v2, reinterpret_cast<quint64 *>(r)); -} -#else -# undef HAVE_MUL64_OVERFLOW -#endif - -// -// Signed overflow math -// -// In C++, signed overflow math is Undefined Behavior. However, many CPUs do implement some way to -// check for overflow. Some compilers expose intrinsics to use this functionality. If the no -// intrinsic is exposed, overflow checking can be done by widening the result type and "manually" -// checking for overflow. Or, alternatively, by using inline assembly to use the CPU features. -// -// Only int overflow checking is implemented, because it's the only one used. -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_sadd_overflow) -inline bool add_overflow(int v1, int v2, int *r) -{ return __builtin_sadd_overflow(v1, v2, r); } -#elif defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86) -inline bool add_overflow(int v1, int v2, int *r) -{ - quint8 overflow = 0; - int res = v1; - - asm ("addl %2, %1\n" - "seto %0" - : "=q" (overflow), "=r" (res) - : "r" (v2), "1" (res) - : "cc" - ); - *r = res; - return overflow; -} -#else -inline bool add_overflow(int v1, int v2, int *r) -{ - qint64 t = qint64(v1) + v2; - *r = static_cast<int>(t); - return t > std::numeric_limits<int>::max() || t < std::numeric_limits<int>::min(); -} -#endif -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_ssub_overflow) -inline bool sub_overflow(int v1, int v2, int *r) -{ return __builtin_ssub_overflow(v1, v2, r); } -#elif defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86) -inline bool sub_overflow(int v1, int v2, int *r) +# pragma intrinsic(_mul128) +template <> inline bool mul_overflow(qint64 v1, qint64 v2, qint64 *r) { - quint8 overflow = 0; - int res = v1; - - asm ("subl %2, %1\n" - "seto %0" - : "=q" (overflow), "=r" (res) - : "r" (v2), "1" (res) - : "cc" - ); - *r = res; - return overflow; + // Use 128-bit multiplication with the _mul128 intrinsic + // https://msdn.microsoft.com/en-us/library/82cxdw50.aspx + + // This is slightly more complex than the unsigned case above: the sign bit + // of 'low' must be replicated as the entire 'high', so the only valid + // values for 'high' are 0 and -1. + + qint64 high; + *r = _mul128(v1, v2, &high); + if (high == 0) + return *r < 0; + if (high == -1) + return *r >= 0; + return true; } -#else -inline bool sub_overflow(int v1, int v2, int *r) -{ - qint64 t = qint64(v1) - v2; - *r = static_cast<int>(t); - return t > std::numeric_limits<int>::max() || t < std::numeric_limits<int>::min(); -} -#endif - -#if (defined(Q_CC_GNU) && !defined(Q_CC_INTEL) && Q_CC_GNU >= 500) || QT_HAS_BUILTIN(__builtin_smul_overflow) -inline bool mul_overflow(int v1, int v2, int *r) -{ return __builtin_smul_overflow(v1, v2, r); } -#elif defined(Q_CC_GNU) && defined(Q_PROCESSOR_X86) -inline bool mul_overflow(int v1, int v2, int *r) -{ - quint8 overflow = 0; - int res = v1; - - asm ("imul %2, %1\n" - "seto %0" - : "=q" (overflow), "=r" (res) - : "r" (v2), "1" (res) - : "cc" - ); - *r = res; - return overflow; -} -#else -inline bool mul_overflow(int v1, int v2, int *r) -{ - qint64 t = qint64(v1) * v2; - *r = static_cast<int>(t); - return t > std::numeric_limits<int>::max() || t < std::numeric_limits<int>::min(); -} -#endif - +# endif // x86-64 +# endif // MSVC x86 +#endif // !GCC } +#endif // Q_CLANG_QDOC QT_END_NAMESPACE diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp index 72ba299280..9143e04d45 100644 --- a/src/corelib/global/qrandom.cpp +++ b/src/corelib/global/qrandom.cpp @@ -671,7 +671,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel */ /*! - \fn QRandomGenerator::QRandomGenerator(const quint32 (&seedBuffer)[N]) + \fn template <qsizetype N> QRandomGenerator::QRandomGenerator(const quint32 (&seedBuffer)[N]) \overload Initializes this QRandomGenerator object with the values found in the @@ -765,9 +765,9 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel /*! \typedef QRandomGenerator::result_type - A typedef to the type that operator()() returns. That is, quint32. + A typedef to the type that operator() returns. That is, quint32. - \sa {QRandomGenerator::operator()}{operator()()} + \sa operator() */ /*! @@ -837,7 +837,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel */ /*! - \fn void QRandomGenerator::generate(ForwardIterator begin, ForwardIterator end) + \fn template <typename ForwardIterator> void QRandomGenerator::generate(ForwardIterator begin, ForwardIterator end) Generates 32-bit quantities and stores them in the range between \a begin and \a end. This function is equivalent to (and is implemented as): @@ -874,7 +874,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel */ /*! - \fn void QRandomGenerator::fillRange(UInt *buffer, qsizetype count) + \fn template <typename UInt> void QRandomGenerator::fillRange(UInt *buffer, qsizetype count) Generates \a count 32- or 64-bit quantities (depending on the type \c UInt) and stores them in the buffer pointed by \a buffer. This is the most @@ -894,7 +894,7 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel */ /*! - \fn void QRandomGenerator::fillRange(UInt (&buffer)[N}) + \fn template <typename UInt, size_t N> void QRandomGenerator::fillRange(UInt (&buffer)[N]) Generates \c N 32- or 64-bit quantities (depending on the type \c UInt) and stores them in the \a buffer array. This is the most efficient way to @@ -1108,18 +1108,11 @@ inline QRandomGenerator::SystemGenerator &QRandomGenerator::SystemGenerator::sel */ /*! - \fn QRandomGenerator64::QRandomGenerator64(const QRandomGenerator &other) - \internal - - Creates a copy. -*/ - -/*! \typedef QRandomGenerator64::result_type - A typedef to the type that operator()() returns. That is, quint64. + A typedef to the type that operator() returns. That is, quint64. - \sa {QRandomGenerator64::operator()}{operator()()} + \sa operator() */ /*! @@ -1285,20 +1278,56 @@ void QRandomGenerator::_fillRange(void *buffer, void *bufferEnd) std::generate(begin, end, [this]() { return storage.engine()(); }); } -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) && (__ANDROID_API__ < 21) -typedef QThreadStorage<QJNIObjectPrivate> AndroidRandomStorage; -Q_GLOBAL_STATIC(AndroidRandomStorage, randomTLS) +namespace { +struct QRandEngine +{ + std::minstd_rand engine; + QRandEngine() : engine(1) {} -#elif defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) -using SeedStorageType = QtPrivate::FunctionPointer<decltype(&srand)>::Arguments::Car; + int generate() + { + std::minstd_rand::result_type v = engine(); + if (std::numeric_limits<int>::max() != RAND_MAX) + v %= uint(RAND_MAX) + 1; + + return int(v); + } + + void seed(std::minstd_rand::result_type q) + { + engine.seed(q); + } +}; +} -typedef QThreadStorage<SeedStorageType *> SeedStorage; -Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value +#if defined(QT_NO_THREAD) || defined(Q_OS_WIN) +// On Windows srand() and rand() already use Thread-Local-Storage +// to store the seed between calls +static inline QRandEngine *randTLS() +{ + return nullptr; +} +#elif defined(Q_COMPILER_THREAD_LOCAL) +static inline QRandEngine *randTLS() +{ + thread_local QRandEngine r; + return &r; +} +#else +Q_GLOBAL_STATIC(QThreadStorage<QRandEngine>, g_randTLS) +static inline QRandEngine *randTLS() +{ + auto tls = g_randTLS(); + if (!tls) + return nullptr; + return &tls->localData(); +} #endif /*! \relates <QtGlobal> + \deprecated \since 4.2 Thread-safe version of the standard C++ \c srand() function. @@ -1310,49 +1339,23 @@ Q_GLOBAL_STATIC(SeedStorage, randTLS) // Thread Local Storage for seed value if two threads call qsrand(1) and subsequently call qrand(), the threads will get the same random number sequence. + \note This function is deprecated. In new applications, use + QRandomGenerator instead. + \sa qrand(), QRandomGenerator */ void qsrand(uint seed) { -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) && (__ANDROID_API__ < 21) - if (randomTLS->hasLocalData()) { - randomTLS->localData().callMethod<void>("setSeed", "(J)V", jlong(seed)); - return; - } - - QJNIObjectPrivate random("java/util/Random", - "(J)V", - jlong(seed)); - if (!random.isValid()) { - srand(seed); - return; - } - - randomTLS->setLocalData(random); -#elif defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) - SeedStorage *seedStorage = randTLS(); - if (seedStorage) { - SeedStorageType *pseed = seedStorage->localData(); - if (!pseed) - seedStorage->setLocalData(pseed = new SeedStorageType); - *pseed = seed; - } else { - //global static seed storage should always exist, - //except after being deleted by QGlobalStaticDeleter. - //But since it still can be called from destructor of another - //global static object, fallback to srand(seed) + auto prng = randTLS(); + if (prng) + prng->seed(seed); + else srand(seed); - } -#else - // On Windows srand() and rand() already use Thread-Local-Storage - // to store the seed between calls - // this is also valid for QT_NO_THREAD - srand(seed); -#endif } /*! \relates <QtGlobal> + \deprecated \since 4.2 Thread-safe version of the standard C++ \c rand() function. @@ -1366,52 +1369,18 @@ void qsrand(uint seed) step is skipped, then the sequence will be pre-seeded with a constant value. - \sa qsrand(), QRandomGenerator + \note This function is deprecated. In new applications, use + QRandomGenerator instead. + + \sa qrand(), QRandomGenerator */ int qrand() { -#if defined(Q_OS_ANDROID) && !defined(Q_OS_ANDROID_EMBEDDED) && (__ANDROID_API__ < 21) - AndroidRandomStorage *randomStorage = randomTLS(); - if (!randomStorage) + auto prng = randTLS(); + if (prng) + return prng->generate(); + else return rand(); - - if (randomStorage->hasLocalData()) { - return randomStorage->localData().callMethod<jint>("nextInt", - "(I)I", - RAND_MAX); - } - - QJNIObjectPrivate random("java/util/Random", - "(J)V", - jlong(1)); - - if (!random.isValid()) - return rand(); - - randomStorage->setLocalData(random); - return random.callMethod<jint>("nextInt", "(I)I", RAND_MAX); -#elif defined(Q_OS_UNIX) && !defined(QT_NO_THREAD) && defined(_POSIX_THREAD_SAFE_FUNCTIONS) && (_POSIX_THREAD_SAFE_FUNCTIONS - 0 > 0) - SeedStorage *seedStorage = randTLS(); - if (seedStorage) { - SeedStorageType *pseed = seedStorage->localData(); - if (!pseed) { - seedStorage->setLocalData(pseed = new SeedStorageType); - *pseed = 1; - } - return rand_r(pseed); - } else { - //global static seed storage should always exist, - //except after being deleted by QGlobalStaticDeleter. - //But since it still can be called from destructor of another - //global static object, fallback to rand() - return rand(); - } -#else - // On Windows srand() and rand() already use Thread-Local-Storage - // to store the seed between calls - // this is also valid for QT_NO_THREAD - return rand(); -#endif } QT_END_NAMESPACE diff --git a/src/corelib/global/qsysinfo.h b/src/corelib/global/qsysinfo.h index 6b73a17dc5..a3fa0fcb27 100644 --- a/src/corelib/global/qsysinfo.h +++ b/src/corelib/global/qsysinfo.h @@ -240,6 +240,8 @@ QT_WARNING_POP static QString prettyProductName(); static QString machineHostName(); + static QByteArray machineUniqueId(); + static QByteArray bootUniqueId(); }; #undef QT_SYSINFO_DEPRECATED_X diff --git a/src/corelib/global/qsystemdetection.h b/src/corelib/global/qsystemdetection.h index 4a2c3f79bb..ff0e03108b 100644 --- a/src/corelib/global/qsystemdetection.h +++ b/src/corelib/global/qsystemdetection.h @@ -52,30 +52,18 @@ IOS - iOS WATCHOS - watchOS TVOS - tvOS - MSDOS - MS-DOS and Windows - OS2 - OS/2 - OS2EMX - XFree86 on OS/2 (not PM) WIN32 - Win32 (Windows 2000/XP/Vista/7 and Windows Server 2003/2008) - WINRT - WinRT (Windows 8 Runtime) + WINRT - WinRT (Windows Runtime) CYGWIN - Cygwin SOLARIS - Sun Solaris HPUX - HP-UX - ULTRIX - DEC Ultrix LINUX - Linux [has variants] FREEBSD - FreeBSD [has variants] NETBSD - NetBSD OPENBSD - OpenBSD - BSDI - BSD/OS INTERIX - Interix - IRIX - SGI Irix - OSF - HP Tru64 UNIX - SCO - SCO OpenServer 5 - UNIXWARE - UnixWare 7, Open UNIX 8 AIX - AIX HURD - GNU Hurd - DGUX - DG/UX - RELIANT - Reliant UNIX - DYNIX - DYNIX/ptx QNX - QNX [has variants] QNX6 - QNX RTP 6.1 LYNX - LynxOS @@ -147,10 +135,6 @@ # define Q_OS_SOLARIS #elif defined(hpux) || defined(__hpux) # define Q_OS_HPUX -#elif defined(__ultrix) || defined(ultrix) -# define Q_OS_ULTRIX -#elif defined(sinix) -# define Q_OS_RELIANT #elif defined(__native_client__) # define Q_OS_NACL #elif defined(__linux__) || defined(__linux) @@ -167,34 +151,17 @@ #elif defined(__OpenBSD__) # define Q_OS_OPENBSD # define Q_OS_BSD4 -#elif defined(__bsdi__) -# define Q_OS_BSDI -# define Q_OS_BSD4 #elif defined(__INTERIX) # define Q_OS_INTERIX # define Q_OS_BSD4 -#elif defined(__sgi) -# define Q_OS_IRIX -#elif defined(__osf__) -# define Q_OS_OSF #elif defined(_AIX) # define Q_OS_AIX #elif defined(__Lynx__) # define Q_OS_LYNX #elif defined(__GNU__) # define Q_OS_HURD -#elif defined(__DGUX__) -# define Q_OS_DGUX #elif defined(__QNXNTO__) # define Q_OS_QNX -#elif defined(_SEQUENT_) -# define Q_OS_DYNIX -#elif defined(_SCO_DS) /* SCO OpenServer 5 + GCC */ -# define Q_OS_SCO -#elif defined(__USLC__) /* all SCO platforms + UDK or OUDK */ -# define Q_OS_UNIXWARE -#elif defined(__svr4__) && defined(i386) /* Open UNIX 8 + GCC */ -# define Q_OS_UNIXWARE #elif defined(__INTEGRITY) # define Q_OS_INTEGRITY #elif defined(VXWORKS) /* there is no "real" VxWorks define - this has to be set in the mkspec! */ diff --git a/src/corelib/global/qtrace_p.h b/src/corelib/global/qtrace_p.h new file mode 100644 index 0000000000..ab8fc14af5 --- /dev/null +++ b/src/corelib/global/qtrace_p.h @@ -0,0 +1,126 @@ +/**************************************************************************** +** +** Copyright (C) 2017 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com, author Rafael Roquetto <rafael.roquetto@kdab.com> +** Contact: https://www.qt.io/licensing/ +** +** This file is part of the QtCore module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPL3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl-3.0.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or (at your option) the GNU General +** Public license version 3 or any later version approved by the KDE Free +** Qt Foundation. The licenses are as published by the Free Software +** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3 +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-2.0.html and +** https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef QTRACE_P_H +#define QTRACE_P_H + +// +// W A R N I N G +// ------------- +// +// This file is not part of the Qt API. It exists purely as an +// implementation detail. This header file may change from version to +// version without notice, or even be removed. +// +// We mean it. +// + +/* + * The Qt tracepoints API consists of only three macros: + * + * - Q_TRACE(tracepoint, args...) + * Fires 'tracepoint' if it is enabled. + * + * - Q_UNCONDITIONAL_TRACE(tracepoint, args...) + * Fires 'tracepoint' unconditionally: no check is performed to query + * whether 'tracepoint' is enabled. + * + * - Q_TRACE_ENABLED(tracepoint) + * Returns 'true' if 'tracepoint' is enabled; false otherwise. + * + * When using LTTNG, Q_TRACE, Q_UNCONDITIONAL_TRACE and Q_TRACE_ENABLED map + * ultimately to tracepoint(), do_tracepoint() and tracepoint_enabled(), + * respectively, described on the lttng-ust manpage (man 3 lttng-ust). + * + * On ETW, Q_TRACE() and Q_UNCONDITIONAL_TRACE() are equivalent, ultimately + * amounting to a call to TraceLoggingWrite(), whereas Q_TRACE_ENABLED() + * wraps around TraceLoggingProviderEnabled(). + * + * A tracepoint provider is defined in a separate file, that follows the + * following format: + * + * tracepoint_name(arg_type arg_name, ...) + * + * For instance: + * + * qcoreapplication_ctor(int argc, const char * const argv) + * qcoreapplication_foo(int argc, const char[10] argv) + * qcoreapplication_baz(const char[len] some_string, unsigned int len) + * qcoreapplication_qstring(const QString &foo) + * qcoreapplication_qrect(const QRect &rect) + * + * The provider file is then parsed by src/tools/tracegen, which can be + * switched to output either ETW or LTTNG tracepoint definitions. The provider + * name is deduced to be basename(provider_file). + * + * To use the above (inside qtcore), you need to include + * <providername_tracepoints_p.h>. After that, the following call becomes + * possible: + * + * Q_TRACE(qcoreapplication_qrect, myRect); + * + * Currently, all C++ primitive non-pointer types are supported for + * arguments. Additionally, char * is supported, and is assumed to + * be a NULL-terminated string. Finally, the following subset of Qt types also + * currently supported: + * + * - QString + * - QByteArray + * - QUrl + * - QRect + * + * Dynamic arrays are supported using the syntax illustrated by + * qcoreapplication_baz above. + */ + +QT_BEGIN_NAMESPACE + +#if defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED) +# define Q_TRACE(x, ...) QtPrivate::trace_ ## x(__VA_ARGS__) +# define Q_UNCONDITIONAL_TRACE(x, ...) QtPrivate::do_trace_ ## x(__VA_ARGS__) +# define Q_TRACE_ENABLED(x) QtPrivate::trace_ ## x ## _enabled() +#else +# define Q_TRACE(x, ...) +# define Q_UNCONDITIONAL_TRACE(x, ...) +# define Q_TRACE_ENABLED(x) false +#endif // defined(Q_TRACEPOINT) && !defined(QT_BOOTSTRAPPED) + +QT_END_NAMESPACE + +#endif // QTRACE_P_H diff --git a/src/corelib/global/qversiontagging.cpp b/src/corelib/global/qversiontagging.cpp index e3d4037a16..cbfd93f135 100644 --- a/src/corelib/global/qversiontagging.cpp +++ b/src/corelib/global/qversiontagging.cpp @@ -84,6 +84,16 @@ make_versioned_symbol(SYM, QT_VERSION_MAJOR, 8, "@"); make_versioned_symbol(SYM, QT_VERSION_MAJOR, 9, "@"); #endif #if QT_VERSION_MINOR > 10 +make_versioned_symbol(SYM, QT_VERSION_MAJOR, 10, "@"); +#endif +#if QT_VERSION_MINOR > 11 +make_versioned_symbol(SYM, QT_VERSION_MAJOR, 11, "@"); +#endif +#if QT_VERSION_MINOR > 12 +make_versioned_symbol(SYM, QT_VERSION_MAJOR, 12, "@"); +#endif +#if QT_VERSION_MINOR > 13 +// We don't expect there will be a Qt 5.13 # error "Please update this file with more Qt versions." #endif |