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 <thiago.macieira@intel.com> Reviewed-by: Olivier Goffart <ogoffart@woboq.com> Reviewed-by: Bradley T. Hughes <bradley.hughes@nokia.com>
This commit is contained in:
parent
9a890a519e
commit
fed603fde5
@ -614,9 +614,9 @@ static inline char qToLower(char c)
|
|||||||
return 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 } };
|
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 } };
|
0, 0, 0, { 0 } }, { 0 } };
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -133,24 +133,24 @@ struct QByteArrayData
|
|||||||
inline const char *data() const { return d + sizeof(qptrdiff) + offset; }
|
inline const char *data() const { return d + sizeof(qptrdiff) + offset; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<int N> struct QConstByteArrayData
|
template<int N> struct QStaticByteArrayData
|
||||||
{
|
{
|
||||||
const QByteArrayData ba;
|
QByteArrayData ba;
|
||||||
const char data[N + 1];
|
char data[N + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
template<int N> struct QConstByteArrayDataPtr
|
template<int N> struct QStaticByteArrayDataPtr
|
||||||
{
|
{
|
||||||
const QConstByteArrayData<N> *ptr;
|
const QStaticByteArrayData<N> *ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
||||||
#if defined(Q_COMPILER_LAMBDA)
|
#if defined(Q_COMPILER_LAMBDA)
|
||||||
# define QByteArrayLiteral(str) ([]() -> QConstByteArrayDataPtr<sizeof(str) - 1> { \
|
# define QByteArrayLiteral(str) ([]() -> QStaticByteArrayDataPtr<sizeof(str) - 1> { \
|
||||||
enum { Size = sizeof(str) - 1 }; \
|
enum { Size = sizeof(str) - 1 }; \
|
||||||
static const QConstByteArrayData<Size> qbytearray_literal = \
|
static const QStaticByteArrayData<Size> qbytearray_literal = \
|
||||||
{ { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, str }; \
|
{ { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, str }; \
|
||||||
QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
|
QStaticByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
|
||||||
return holder; }())
|
return holder; }())
|
||||||
|
|
||||||
#elif defined(Q_CC_GNU)
|
#elif defined(Q_CC_GNU)
|
||||||
@ -161,9 +161,9 @@ template<int N> struct QConstByteArrayDataPtr
|
|||||||
# define QByteArrayLiteral(str) \
|
# define QByteArrayLiteral(str) \
|
||||||
__extension__ ({ \
|
__extension__ ({ \
|
||||||
enum { Size = sizeof(str) - 1 }; \
|
enum { Size = sizeof(str) - 1 }; \
|
||||||
static const QConstByteArrayData<Size> qbytearray_literal = \
|
static const QStaticByteArrayData<Size> qbytearray_literal = \
|
||||||
{ { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, str }; \
|
{ { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, str }; \
|
||||||
QConstByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
|
QStaticByteArrayDataPtr<Size> holder = { &qbytearray_literal }; \
|
||||||
holder; })
|
holder; })
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@ -378,16 +378,16 @@ public:
|
|||||||
bool isNull() const;
|
bool isNull() const;
|
||||||
|
|
||||||
template <int n>
|
template <int n>
|
||||||
inline QByteArray(const QConstByteArrayData<n> &dd)
|
inline QByteArray(const QStaticByteArrayData<n> &dd)
|
||||||
: d(const_cast<QByteArrayData *>(&dd.str)) {}
|
: d(const_cast<QByteArrayData *>(&dd.str)) {}
|
||||||
template <int N>
|
template <int N>
|
||||||
Q_DECL_CONSTEXPR inline QByteArray(QConstByteArrayDataPtr<N> dd)
|
Q_DECL_CONSTEXPR inline QByteArray(QStaticByteArrayDataPtr<N> dd)
|
||||||
: d(const_cast<QByteArrayData *>(&dd.ptr->ba)) {}
|
: d(const_cast<QByteArrayData *>(&dd.ptr->ba)) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
operator QNoImplicitBoolCast() const;
|
operator QNoImplicitBoolCast() const;
|
||||||
static const QConstByteArrayData<1> shared_null;
|
static const QStaticByteArrayData<1> shared_null;
|
||||||
static const QConstByteArrayData<1> shared_empty;
|
static const QStaticByteArrayData<1> shared_empty;
|
||||||
Data *d;
|
Data *d;
|
||||||
QByteArray(Data *dd, int /*dummy*/, int /*dummy*/) : d(dd) {}
|
QByteArray(Data *dd, int /*dummy*/, int /*dummy*/) : d(dd) {}
|
||||||
void realloc(int alloc);
|
void realloc(int alloc);
|
||||||
|
@ -798,8 +798,8 @@ const QString::Null QString::null = { };
|
|||||||
\sa split()
|
\sa split()
|
||||||
*/
|
*/
|
||||||
|
|
||||||
const QConstStringData<1> QString::shared_null = { { 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 QConstStringData<1> QString::shared_empty = { { 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)
|
int QString::grow(int size)
|
||||||
{
|
{
|
||||||
|
@ -90,27 +90,27 @@ struct QStringData {
|
|||||||
inline const ushort *data() const { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; }
|
inline const ushort *data() const { return d + sizeof(qptrdiff)/sizeof(ushort) + offset; }
|
||||||
};
|
};
|
||||||
|
|
||||||
template<int N> struct QConstStringData;
|
template<int N> struct QStaticStringData;
|
||||||
template<int N> struct QConstStringDataPtr
|
template<int N> struct QStaticStringDataPtr
|
||||||
{
|
{
|
||||||
const QConstStringData<N> *ptr;
|
const QStaticStringData<N> *ptr;
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(Q_COMPILER_UNICODE_STRINGS)
|
#if defined(Q_COMPILER_UNICODE_STRINGS)
|
||||||
template<int N> struct QConstStringData
|
template<int N> struct QStaticStringData
|
||||||
{
|
{
|
||||||
const QStringData str;
|
QStringData str;
|
||||||
const char16_t data[N + 1];
|
char16_t data[N + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
#define QT_UNICODE_LITERAL_II(str) u"" str
|
#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)
|
#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
|
// wchar_t is 2 bytes
|
||||||
template<int N> struct QConstStringData
|
template<int N> struct QStaticStringData
|
||||||
{
|
{
|
||||||
const QStringData str;
|
QStringData str;
|
||||||
const wchar_t data[N + 1];
|
wchar_t data[N + 1];
|
||||||
};
|
};
|
||||||
|
|
||||||
#if defined(Q_CC_MSVC)
|
#if defined(Q_CC_MSVC)
|
||||||
@ -120,21 +120,21 @@ template<int N> struct QConstStringData
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
#else
|
#else
|
||||||
template<int N> struct QConstStringData
|
template<int N> struct QStaticStringData
|
||||||
{
|
{
|
||||||
const QStringData str;
|
QStringData str;
|
||||||
const ushort data[N + 1];
|
ushort data[N + 1];
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if defined(QT_UNICODE_LITERAL_II)
|
#if defined(QT_UNICODE_LITERAL_II)
|
||||||
# define QT_UNICODE_LITERAL(str) QT_UNICODE_LITERAL_II(str)
|
# define QT_UNICODE_LITERAL(str) QT_UNICODE_LITERAL_II(str)
|
||||||
# if defined(Q_COMPILER_LAMBDA)
|
# if defined(Q_COMPILER_LAMBDA)
|
||||||
# define QStringLiteral(str) ([]() -> QConstStringDataPtr<sizeof(QT_UNICODE_LITERAL(str))/2 - 1> { \
|
# define QStringLiteral(str) ([]() -> QStaticStringDataPtr<sizeof(QT_UNICODE_LITERAL(str))/2 - 1> { \
|
||||||
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
||||||
static const QConstStringData<Size> qstring_literal = \
|
static const QStaticStringData<Size> qstring_literal = \
|
||||||
{ { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \
|
{ { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \
|
||||||
QConstStringDataPtr<Size> holder = { &qstring_literal }; \
|
QStaticStringDataPtr<Size> holder = { &qstring_literal }; \
|
||||||
return holder; }())
|
return holder; }())
|
||||||
|
|
||||||
# elif defined(Q_CC_GNU)
|
# elif defined(Q_CC_GNU)
|
||||||
@ -145,9 +145,9 @@ template<int N> struct QConstStringData
|
|||||||
# define QStringLiteral(str) \
|
# define QStringLiteral(str) \
|
||||||
__extension__ ({ \
|
__extension__ ({ \
|
||||||
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
enum { Size = sizeof(QT_UNICODE_LITERAL(str))/2 - 1 }; \
|
||||||
static const QConstStringData<Size> qstring_literal = \
|
static const QStaticStringData<Size> qstring_literal = \
|
||||||
{ { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \
|
{ { Q_REFCOUNT_INITIALIZE_STATIC, Size, 0, 0, { 0 } }, QT_UNICODE_LITERAL(str) }; \
|
||||||
QConstStringDataPtr<Size> holder = { &qstring_literal }; \
|
QStaticStringDataPtr<Size> holder = { &qstring_literal }; \
|
||||||
holder; })
|
holder; })
|
||||||
# endif
|
# endif
|
||||||
#endif
|
#endif
|
||||||
@ -586,9 +586,9 @@ public:
|
|||||||
|
|
||||||
QString(int size, Qt::Initialization);
|
QString(int size, Qt::Initialization);
|
||||||
template <int n>
|
template <int n>
|
||||||
inline QString(const QConstStringData<n> &dd) : d(const_cast<QStringData *>(&dd.str)) {}
|
inline QString(const QStaticStringData<n> &dd) : d(const_cast<QStringData *>(&dd.str)) {}
|
||||||
template <int N>
|
template <int N>
|
||||||
Q_DECL_CONSTEXPR inline QString(QConstStringDataPtr<N> dd) : d(const_cast<QStringData *>(&dd.ptr->str)) {}
|
Q_DECL_CONSTEXPR inline QString(QStaticStringDataPtr<N> dd) : d(const_cast<QStringData *>(&dd.ptr->str)) {}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
#if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED)
|
#if defined(QT_NO_CAST_FROM_ASCII) && !defined(Q_NO_DECLARED_NOT_DEFINED)
|
||||||
@ -600,8 +600,8 @@ private:
|
|||||||
QString &operator=(const QByteArray &a);
|
QString &operator=(const QByteArray &a);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static const QConstStringData<1> shared_null;
|
static const QStaticStringData<1> shared_null;
|
||||||
static const QConstStringData<1> shared_empty;
|
static const QStaticStringData<1> shared_empty;
|
||||||
Data *d;
|
Data *d;
|
||||||
inline QString(Data *dd, int /*dummy*/) : d(dd) {}
|
inline QString(Data *dd, int /*dummy*/) : d(dd) {}
|
||||||
|
|
||||||
|
@ -249,9 +249,9 @@ template <> struct QConcatenable<QString> : private QAbstractConcatenable
|
|||||||
#endif
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int N> struct QConcatenable<QConstStringDataPtr<N> > : private QAbstractConcatenable
|
template <int N> struct QConcatenable<QStaticStringDataPtr<N> > : private QAbstractConcatenable
|
||||||
{
|
{
|
||||||
typedef QConstStringDataPtr<N> type;
|
typedef QStaticStringDataPtr<N> type;
|
||||||
typedef QString ConvertTo;
|
typedef QString ConvertTo;
|
||||||
enum { ExactSize = true };
|
enum { ExactSize = true };
|
||||||
static int size(const type &) { return N; }
|
static int size(const type &) { return N; }
|
||||||
@ -363,9 +363,9 @@ template <> struct QConcatenable<QByteArray> : private QAbstractConcatenable
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
template <int N> struct QConcatenable<QConstByteArrayDataPtr<N> > : private QAbstractConcatenable
|
template <int N> struct QConcatenable<QStaticByteArrayDataPtr<N> > : private QAbstractConcatenable
|
||||||
{
|
{
|
||||||
typedef QConstByteArrayDataPtr<N> type;
|
typedef QStaticByteArrayDataPtr<N> type;
|
||||||
typedef QByteArray ConvertTo;
|
typedef QByteArray ConvertTo;
|
||||||
enum { ExactSize = false };
|
enum { ExactSize = false };
|
||||||
static int size(const type &) { return N; }
|
static int size(const type &) { return N; }
|
||||||
|
@ -46,6 +46,23 @@
|
|||||||
|
|
||||||
#include "simplevector.h"
|
#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
|
class tst_QArrayData : public QObject
|
||||||
{
|
{
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
Loading…
x
Reference in New Issue
Block a user