From fed603fde515339ec520accefded211ac6f69982 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Wed, 4 Jan 2012 14:30:42 +0100 Subject: Ensure shared_null(s) are statically initialized on VS 2010 This removes const qualification on data members of QConst*Data, which was subjecting QString's and QByteArray's shared_null to the "order of static initialization fiasco", with up-to-date VS 2010. Furthermore, the const qualification in the places where it was removed had little meaning and no value. It was unnecessary. As such, "Const" was removed from the struct's names and "Static" used in its place, to imply their usefulness in supporting statically-initialized fixed-size (string and byte) containers. A test case was added to QArrayData as that is meant to replace both QStringData and QByteArrayData in the near future. VS issue reported at: https://connect.microsoft.com/VisualStudio/feedback/details/716461 Change-Id: I3d86f2a387a68f359bb3d8f4d10cf3da51c6ecf7 Reviewed-by: Thiago Macieira Reviewed-by: Olivier Goffart Reviewed-by: Bradley T. Hughes --- src/corelib/tools/qbytearray.cpp | 4 +-- src/corelib/tools/qbytearray.h | 28 +++++++-------- src/corelib/tools/qstring.cpp | 4 +-- src/corelib/tools/qstring.h | 42 +++++++++++----------- src/corelib/tools/qstringbuilder.h | 8 ++--- .../corelib/tools/qarraydata/tst_qarraydata.cpp | 17 +++++++++ 6 files changed, 60 insertions(+), 43 deletions(-) diff --git a/src/corelib/tools/qbytearray.cpp b/src/corelib/tools/qbytearray.cpp index 09cc6d2f97..e56e4fc8ff 100644 --- a/src/corelib/tools/qbytearray.cpp +++ b/src/corelib/tools/qbytearray.cpp @@ -614,9 +614,9 @@ static inline char qToLower(char c) return c; } -const QConstByteArrayData<1> QByteArray::shared_null = { { Q_REFCOUNT_INITIALIZE_STATIC, +const QStaticByteArrayData<1> QByteArray::shared_null = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, { 0 } }, { 0 } }; -const QConstByteArrayData<1> QByteArray::shared_empty = { { Q_REFCOUNT_INITIALIZE_STATIC, +const QStaticByteArrayData<1> QByteArray::shared_empty = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, { 0 } }, { 0 } }; /*! diff --git a/src/corelib/tools/qbytearray.h b/src/corelib/tools/qbytearray.h index 932998cb4c..dcaa6153f9 100644 --- a/src/corelib/tools/qbytearray.h +++ b/src/corelib/tools/qbytearray.h @@ -133,24 +133,24 @@ struct QByteArrayData inline const char *data() const { return d + sizeof(qptrdiff) + offset; } }; -template struct QConstByteArrayData +template struct QStaticByteArrayData { - const QByteArrayData ba; - const char data[N + 1]; + QByteArrayData ba; + char data[N + 1]; }; -template struct QConstByteArrayDataPtr +template struct QStaticByteArrayDataPtr { - const QConstByteArrayData *ptr; + const QStaticByteArrayData *ptr; }; #if defined(Q_COMPILER_LAMBDA) -# define QByteArrayLiteral(str) ([]() -> QConstByteArrayDataPtr { \ +# define QByteArrayLiteral(str) ([]() -> QStaticByteArrayDataPtr { \ enum { Size = sizeof(str) - 1 }; \ - static const QConstByteArrayData qbytearray_literal = \ + static const QStaticByteArrayData qbytearray_literal = \ { { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, str }; \ - QConstByteArrayDataPtr holder = { &qbytearray_literal }; \ + QStaticByteArrayDataPtr holder = { &qbytearray_literal }; \ return holder; }()) #elif defined(Q_CC_GNU) @@ -161,9 +161,9 @@ template struct QConstByteArrayDataPtr # define QByteArrayLiteral(str) \ __extension__ ({ \ enum { Size = sizeof(str) - 1 }; \ - static const QConstByteArrayData qbytearray_literal = \ + static const QStaticByteArrayData qbytearray_literal = \ { { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, str }; \ - QConstByteArrayDataPtr holder = { &qbytearray_literal }; \ + QStaticByteArrayDataPtr holder = { &qbytearray_literal }; \ holder; }) #endif @@ -378,16 +378,16 @@ public: bool isNull() const; template - inline QByteArray(const QConstByteArrayData &dd) + inline QByteArray(const QStaticByteArrayData &dd) : d(const_cast(&dd.str)) {} template - Q_DECL_CONSTEXPR inline QByteArray(QConstByteArrayDataPtr dd) + Q_DECL_CONSTEXPR inline QByteArray(QStaticByteArrayDataPtr dd) : d(const_cast(&dd.ptr->ba)) {} private: operator QNoImplicitBoolCast() const; - static const QConstByteArrayData<1> shared_null; - static const QConstByteArrayData<1> shared_empty; + static const QStaticByteArrayData<1> shared_null; + static const QStaticByteArrayData<1> shared_empty; Data *d; QByteArray(Data *dd, int /*dummy*/, int /*dummy*/) : d(dd) {} void realloc(int alloc); diff --git a/src/corelib/tools/qstring.cpp b/src/corelib/tools/qstring.cpp index 16bf26721e..d57adbe731 100644 --- a/src/corelib/tools/qstring.cpp +++ b/src/corelib/tools/qstring.cpp @@ -798,8 +798,8 @@ const QString::Null QString::null = { }; \sa split() */ -const QConstStringData<1> QString::shared_null = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, { 0 } }, { 0 } }; -const QConstStringData<1> QString::shared_empty = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, { 0 } }, { 0 } }; +const QStaticStringData<1> QString::shared_null = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, { 0 } }, { 0 } }; +const QStaticStringData<1> QString::shared_empty = { { Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, false, { 0 } }, { 0 } }; int QString::grow(int size) { diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index ba3407e1cc..898c80ce35 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -90,27 +90,27 @@ struct QStringData { inline const ushort *data() const { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; } }; -template struct QConstStringData; -template struct QConstStringDataPtr +template struct QStaticStringData; +template struct QStaticStringDataPtr { - const QConstStringData *ptr; + const QStaticStringData *ptr; }; #if defined(Q_COMPILER_UNICODE_STRINGS) -template struct QConstStringData +template struct QStaticStringData { - const QStringData str; - const char16_t data[N + 1]; + QStringData str; + char16_t data[N + 1]; }; #define QT_UNICODE_LITERAL_II(str) u"" str #elif defined(Q_OS_WIN) || (defined(__SIZEOF_WCHAR_T__) && __SIZEOF_WCHAR_T__ == 2) || defined(WCHAR_MAX) && (WCHAR_MAX - 0 < 65536) // wchar_t is 2 bytes -template struct QConstStringData +template struct QStaticStringData { - const QStringData str; - const wchar_t data[N + 1]; + QStringData str; + wchar_t data[N + 1]; }; #if defined(Q_CC_MSVC) @@ -120,21 +120,21 @@ template struct QConstStringData #endif #else -template struct QConstStringData +template struct QStaticStringData { - const QStringData str; - const ushort data[N + 1]; + QStringData str; + ushort data[N + 1]; }; #endif #if defined(QT_UNICODE_LITERAL_II) # define QT_UNICODE_LITERAL(str) QT_UNICODE_LITERAL_II(str) # if defined(Q_COMPILER_LAMBDA) -# define QStringLiteral(str) ([]() -> QConstStringDataPtr { \ +# define QStringLiteral(str) ([]() -> QStaticStringDataPtr { \ enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \ - static const QConstStringData qstring_literal = \ + static const QStaticStringData qstring_literal = \ { { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \ - QConstStringDataPtr holder = { &qstring_literal }; \ + QStaticStringDataPtr holder = { &qstring_literal }; \ return holder; }()) # elif defined(Q_CC_GNU) @@ -145,9 +145,9 @@ template struct QConstStringData # define QStringLiteral(str) \ __extension__ ({ \ enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \ - static const QConstStringData qstring_literal = \ + static const QStaticStringData qstring_literal = \ { { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \ - QConstStringDataPtr holder = { &qstring_literal }; \ + QStaticStringDataPtr holder = { &qstring_literal }; \ holder; }) # endif #endif @@ -586,9 +586,9 @@ public: QString(int size, Qt::Initialization); template - inline QString(const QConstStringData &dd) : d(const_cast(&dd.str)) {} + inline QString(const QStaticStringData &dd) : d(const_cast(&dd.str)) {} template - Q_DECL_CONSTEXPR inline QString(QConstStringDataPtr dd) : d(const_cast(&dd.ptr->str)) {} + Q_DECL_CONSTEXPR inline QString(QStaticStringDataPtr dd) : d(const_cast(&dd.ptr->str)) {} private: #if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED) @@ -600,8 +600,8 @@ private: QString &operator=(const QByteArray &a); #endif - static const QConstStringData<1> shared_null; - static const QConstStringData<1> shared_empty; + static const QStaticStringData<1> shared_null; + static const QStaticStringData<1> shared_empty; Data *d; inline QString(Data *dd, int /*dummy*/) : d(dd) {} diff --git a/src/corelib/tools/qstringbuilder.h b/src/corelib/tools/qstringbuilder.h index 30b81c42f4..de6b655e95 100644 --- a/src/corelib/tools/qstringbuilder.h +++ b/src/corelib/tools/qstringbuilder.h @@ -249,9 +249,9 @@ template <> struct QConcatenable : private QAbstractConcatenable #endif }; -template struct QConcatenable > : private QAbstractConcatenable +template struct QConcatenable > : private QAbstractConcatenable { - typedef QConstStringDataPtr type; + typedef QStaticStringDataPtr type; typedef QString ConvertTo; enum { ExactSize = true }; static int size(const type &) { return N; } @@ -363,9 +363,9 @@ template <> struct QConcatenable : private QAbstractConcatenable } }; -template struct QConcatenable > : private QAbstractConcatenable +template struct QConcatenable > : private QAbstractConcatenable { - typedef QConstByteArrayDataPtr type; + typedef QStaticByteArrayDataPtr type; typedef QByteArray ConvertTo; enum { ExactSize = false }; static int size(const type &) { return N; } diff --git a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp index 89a1f8bc75..63a26ed926 100644 --- a/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp +++ b/tests/auto/corelib/tools/qarraydata/tst_qarraydata.cpp @@ -46,6 +46,23 @@ #include "simplevector.h" +struct SharedNullVerifier +{ + SharedNullVerifier() + { + Q_ASSERT(QArrayData::shared_null.ref.isStatic()); + Q_ASSERT(QArrayData::shared_null.ref.isShared()); + Q_ASSERT(QArrayData::shared_null.ref.isSharable()); + } +}; + +// This is meant to verify/ensure that shared_null is not being dynamically +// initialized and stays away from the order-of-static-initialization fiasco. +// +// Of course, if this was to fail, qmake and the build should have crashed and +// burned before we ever got to this point :-) +SharedNullVerifier globalInit; + class tst_QArrayData : public QObject { Q_OBJECT -- cgit v1.2.3