diff --git a/src/corelib/global/qglobal.cpp b/src/corelib/global/qglobal.cpp index 2d5e647739..a0a8d8c395 100644 --- a/src/corelib/global/qglobal.cpp +++ b/src/corelib/global/qglobal.cpp @@ -826,9 +826,28 @@ static_assert(sizeof(qint64) == 8, "Internal error, qint64 is misdefined"); Note that qintptr is signed. Use quintptr for unsigned values. + In order to print values of this type by using formatted-output + facilities such as \c{printf()}, qDebug(), QString::asprintf() and + so on, you can use the \c{PRIdQINTPTR} and \c{PRIiQINTPTR} + macros as format specifiers. They will both print the value as a + base 10 number. + + \code + qintptr p = 123; + printf("The pointer is %" PRIdQINTPTR "\n", p); + \endcode + \sa qptrdiff, qint32, qint64 */ +/*! + \macro PRIdQINTPTR + \macro PRIiQINTPTR + \since 6.2 + + See qintptr. +*/ + /*! \typedef quintptr \relates @@ -844,9 +863,35 @@ static_assert(sizeof(qint64) == 8, "Internal error, qint64 is misdefined"); Note that quintptr is unsigned. Use qptrdiff for signed values. + In order to print values of this type by using formatted-output + facilities such as \c{printf()}, qDebug(), QString::asprintf() and + so on, you can use the following macros as format specifiers: + + \list + \li \c{PRIuQUINTPTR}: prints the value as a base 10 number. + \li \c{PRIoQUINTPTR}: prints the value as a base 8 number. + \li \c{PRIxQUINTPTR}: prints the value as a base 16 number, using lowercase \c{a-f} letters. + \li \c{PRIXQUINTPTR}: prints the value as a base 16 number, using uppercase \c{A-F} letters. + \endlist + + \code + quintptr p = 123u; + printf("The pointer value is 0x%" PRUXQUINTPTR "\n", p); + \endcode + \sa qptrdiff, quint32, quint64 */ +/*! + \macro PRUoQUINTPTR + \macro PRIuQUINTPTR + \macro PRIxQUINTPTR + \macro PRIXQUINTPTR + \since 6.2 + + See quintptr. +*/ + /*! \typedef qptrdiff \relates @@ -860,9 +905,28 @@ static_assert(sizeof(qint64) == 8, "Internal error, qint64 is misdefined"); Note that qptrdiff is signed. Use quintptr for unsigned values. + In order to print values of this type by using formatted-output + facilities such as \c{printf()}, qDebug(), QString::asprintf() and + so on, you can use the \c{PRIdQPTRDIFF} and \c{PRIiQPTRDIFF} + macros as format specifiers. They will both print the value as a + base 10 number. + + \code + qptrdiff d = 123; + printf("The difference is %" PRIdQPTRDIFF "\n", d); + \endcode + \sa quintptr, qint32, qint64 */ +/*! + \macro PRIdQPTRDIFF + \macro PRIiQPTRDIFF + \since 6.2 + + See qptrdiff. +*/ + /*! \typedef qsizetype \relates @@ -875,9 +939,28 @@ static_assert(sizeof(qint64) == 8, "Internal error, qint64 is misdefined"); Note that qsizetype is signed. Use \c size_t for unsigned values. + In order to print values of this type by using formatted-output + facilities such as \c{printf()}, qDebug(), QString::asprintf() and + so on, you can use the \c{PRIdQSIZETYPE} and \c{PRIiQSIZETYPE} + macros as format specifiers. They will both print the value as a + base 10 number. + + \code + qsizetype s = 123; + printf("The size is %" PRIdQSIZETYPE "\n", s); + \endcode + \sa qptrdiff */ +/*! + \macro PRIdQSIZETYPE + \macro PRIiQSIZETYPE + \since 6.2 + + See qsizetype. +*/ + /*! \enum QtMsgType \relates diff --git a/src/corelib/global/qglobal.h b/src/corelib/global/qglobal.h index c3de245a32..1b92b5e8b6 100644 --- a/src/corelib/global/qglobal.h +++ b/src/corelib/global/qglobal.h @@ -45,6 +45,7 @@ # include # include # include +# include #endif #ifndef __ASSEMBLER__ # include @@ -248,6 +249,20 @@ typedef ptrdiff_t qptrdiff; typedef ptrdiff_t qsizetype; typedef ptrdiff_t qintptr; typedef size_t quintptr; + +#define PRIdQPTRDIFF "td" +#define PRIiQPTRDIFF "ti" + +#define PRIdQSIZETYPE "td" +#define PRIiQSIZETYPE "ti" + +#define PRIdQINTPTR "td" +#define PRIiQINTPTR "ti" + +#define PRIuQUINTPTR "zu" +#define PRIoQUINTPTR "zo" +#define PRIxQUINTPTR "zx" +#define PRIXQUINTPTR "zX" #endif /* @@ -593,7 +608,7 @@ Q_CORE_EXPORT Q_DECL_CONST_FUNCTION const char *qVersion(void) Q_DECL_NOEXCEPT; && sizeof(void *) == sizeof(qptrdiff) size_t and qsizetype are not guaranteed to be the same size as a pointer, but - they usually are. + they usually are. We actually check for that in qglobal.cpp. */ template struct QIntegerForSize; template <> struct QIntegerForSize<1> { typedef quint8 Unsigned; typedef qint8 Signed; }; @@ -611,6 +626,47 @@ typedef QIntegerForSizeof::Signed qptrdiff; typedef qptrdiff qintptr; using qsizetype = QIntegerForSizeof::Signed; +// These custom definitions are necessary as we're not defining our +// datatypes in terms of the language ones, but in terms of integer +// types that have the sime size. For instance, on a 32-bit platform, +// qptrdiff is int, while ptrdiff_t may be aliased to long; therefore +// using %td to print a qptrdiff would be wrong (and raise -Wformat +// warnings), although both int and long have same bit size on that +// platform. +// +// We know that sizeof(size_t) == sizeof(void *) == sizeof(qptrdiff). +#if SIZE_MAX == 4294967295ULL +#define PRIuQUINTPTR "u" +#define PRIoQUINTPTR "o" +#define PRIxQUINTPTR "x" +#define PRIXQUINTPTR "X" + +#define PRIdQPTRDIFF "d" +#define PRIiQPTRDIFF "i" + +#define PRIdQINTPTR "d" +#define PRIiQINTPTR "i" + +#define PRIdQSIZETYPE "d" +#define PRIiQSIZETYPE "i" +#elif SIZE_MAX == 18446744073709551615ULL +#define PRIuQUINTPTR "llu" +#define PRIoQUINTPTR "llo" +#define PRIxQUINTPTR "llx" +#define PRIXQUINTPTR "llX" + +#define PRIdQPTRDIFF "lld" +#define PRIiQPTRDIFF "lli" + +#define PRIdQINTPTR "lld" +#define PRIiQINTPTR "lli" + +#define PRIdQSIZETYPE "lld" +#define PRIiQSIZETYPE "lli" +#else +#error Unsupported platform (unknown value for SIZE_MAX) +#endif + /* moc compats (signals/slots) */ #ifndef QT_MOC_COMPAT # define QT_MOC_COMPAT diff --git a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp index 5b10049144..d2a449bb58 100644 --- a/tests/auto/corelib/global/qglobal/tst_qglobal.cpp +++ b/tests/auto/corelib/global/qglobal/tst_qglobal.cpp @@ -32,6 +32,7 @@ #include #include #include +#include #include @@ -58,6 +59,7 @@ private slots: void qRoundFloats(); void qRoundDoubles_data(); void qRoundDoubles(); + void PRImacros(); }; extern "C" { // functions in qglobal.c @@ -667,5 +669,34 @@ void tst_QGlobal::qRoundDoubles() { QCOMPARE(qRound64(actual), expected); } +void tst_QGlobal::PRImacros() +{ + // none of these calls must generate a -Wformat warning + { + quintptr p = 123u; + (void)QString::asprintf("The value %" PRIuQUINTPTR " is nice", p); + (void)QString::asprintf("The value %" PRIoQUINTPTR " is nice", p); + (void)QString::asprintf("The value %" PRIxQUINTPTR " is nice", p); + (void)QString::asprintf("The value %" PRIXQUINTPTR " is nice", p); + } + + { + qintptr p = 123; + (void)QString::asprintf("The value %" PRIdQINTPTR " is nice", p); + (void)QString::asprintf("The value %" PRIiQINTPTR " is nice", p); + } + + { + qptrdiff d = 123; + (void)QString::asprintf("The value %" PRIdQPTRDIFF " is nice", d); + (void)QString::asprintf("The value %" PRIiQPTRDIFF " is nice", d); + } + { + qsizetype s = 123; + (void)QString::asprintf("The value %" PRIdQSIZETYPE " is nice", s); + (void)QString::asprintf("The value %" PRIiQSIZETYPE " is nice", s); + } +} + QTEST_APPLESS_MAIN(tst_QGlobal) #include "tst_qglobal.moc"