From 0d3044b547614cbd313d90021606af1f81fb10de Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 25 Nov 2010 22:40:34 +0100 Subject: Fix strict-alias breaking warnings with GCC. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GCC doesn't like any kind of reinterpret_cast or C-style cast with pointers. So instead do the work with static_cast<>, which it seems to like. Also took the opportunity to change the generic payload type to void*, so the alignment works as expected. I wonder how we haven't had serious crashes so far on ARM... Reviewed-by: Samuel Rødal --- .../qml/qdeclarativeobjectscriptclass.cpp | 115 +++++++++++++-------- 1 file changed, 72 insertions(+), 43 deletions(-) diff --git a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp index dc3ecca..a2411b9 100644 --- a/src/declarative/qml/qdeclarativeobjectscriptclass.cpp +++ b/src/declarative/qml/qdeclarativeobjectscriptclass.cpp @@ -632,7 +632,6 @@ QDeclarativeObjectMethodScriptClass::property(Object *, const Identifier &name) namespace { struct MetaCallArgument { - inline MetaCallArgument(); inline ~MetaCallArgument(); inline void *dataPtr(); @@ -640,15 +639,45 @@ struct MetaCallArgument { void fromScriptValue(int type, QDeclarativeEngine *, const QScriptValue &); inline QScriptDeclarativeClass::Value toValue(QDeclarativeEngine *); +protected: + inline MetaCallArgument(); + private: MetaCallArgument(const MetaCallArgument &); + template T &as(); inline void cleanup(); - char data[4 * sizeof(void *)]; int type; bool isObjectType; + char padding[6]; // ensure sizeof(MetaCallArgument) == 8 +}; + +template struct TypedMetaCallArgument: public MetaCallArgument +{ + T data; +protected: + TypedMetaCallArgument() {} + ~TypedMetaCallArgument() {} +private: + TypedMetaCallArgument(const TypedMetaCallArgument &); }; + +struct GenericPayload { void *data[4]; }; +struct GenericMetaCallArgument: public TypedMetaCallArgument +{ +}; + +template T &MetaCallArgument::as() +{ +#ifdef Q_ALIGNOF + // static assert + char dummy_array[Q_ALIGNOF(T) <= sizeof(*this) ? 1 : -1]; Q_UNUSED(dummy_array); +#endif + TypedMetaCallArgument &typed = static_cast &>(*this); + return typed.data; +} + } MetaCallArgument::MetaCallArgument() @@ -664,22 +693,22 @@ MetaCallArgument::~MetaCallArgument() void MetaCallArgument::cleanup() { if (type == QMetaType::QString) { - ((QString *)&data)->~QString(); + as().~QString(); } else if (type == -1 || type == qMetaTypeId()) { - ((QVariant *)&data)->~QVariant(); + as().~QVariant(); } else if (type == qMetaTypeId()) { - ((QScriptValue *)&data)->~QScriptValue(); + as().~QScriptValue(); } else if (type == qMetaTypeId >()) { - ((QList *)&data)->~QList(); + as >().~QList(); } } void *MetaCallArgument::dataPtr() { if (type == -1) - return ((QVariant *)data)->data(); + return as().data(); else - return (void *)&data; + return &as(); } void MetaCallArgument::initAsType(int callType, QDeclarativeEngine *e) @@ -690,7 +719,7 @@ void MetaCallArgument::initAsType(int callType, QDeclarativeEngine *e) QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(e); if (callType == qMetaTypeId()) { - new (&data) QScriptValue(engine->undefinedValue()); + new (&as()) QScriptValue(engine->undefinedValue()); type = callType; } else if (callType == QMetaType::Int || callType == QMetaType::UInt || @@ -699,20 +728,20 @@ void MetaCallArgument::initAsType(int callType, QDeclarativeEngine *e) callType == QMetaType::Float) { type = callType; } else if (callType == QMetaType::QObjectStar) { - *((QObject **)&data) = 0; + as() = 0; type = callType; } else if (callType == QMetaType::QString) { - new (&data) QString(); + new (&as()) QString(); type = callType; } else if (callType == qMetaTypeId()) { type = callType; - new (&data) QVariant(); + new (&as()) QVariant(); } else if (callType == qMetaTypeId >()) { type = callType; - new (&data) QList(); + new (&as >()) QList(); } else { type = -1; - new (&data) QVariant(callType, (void *)0); + new (&as()) QVariant(callType, (void *)0); } } @@ -721,37 +750,37 @@ void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine, if (type != 0) { cleanup(); type = 0; } if (callType == qMetaTypeId()) { - new (&data) QScriptValue(value); + new (&as()) QScriptValue(value); type = qMetaTypeId(); } else if (callType == QMetaType::Int) { - *((int *)&data) = int(value.toInt32()); + as() = int(value.toInt32()); type = callType; } else if (callType == QMetaType::UInt) { - *((uint *)&data) = uint(value.toUInt32()); + as() = uint(value.toUInt32()); type = callType; } else if (callType == QMetaType::Bool) { - *((bool *)&data) = value.toBool(); + as() = value.toBool(); type = callType; } else if (callType == QMetaType::Double) { - *((double *)&data) = double(value.toNumber()); + as() = double(value.toNumber()); type = callType; } else if (callType == QMetaType::Float) { - *((float *)&data) = float(value.toNumber()); + as() = float(value.toNumber()); type = callType; } else if (callType == QMetaType::QString) { if (value.isNull() || value.isUndefined()) - new (&data) QString(); + new (&as()) QString(); else - new (&data) QString(value.toString()); + new (&as()) QString(value.toString()); type = callType; } else if (callType == QMetaType::QObjectStar) { - *((QObject **)&data) = value.toQObject(); + as() = value.toQObject(); type = callType; } else if (callType == qMetaTypeId()) { - new (&data) QVariant(QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value)); + new (&as()) QVariant(QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value)); type = callType; } else if (callType == qMetaTypeId >()) { - QList *list = new (&data) QList(); + QList *list = new (&as >()) QList(); if (value.isArray()) { int length = value.property(QLatin1String("length")).toInt32(); for (int ii = 0; ii < length; ++ii) { @@ -764,16 +793,16 @@ void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine, } type = callType; } else { - new (&data) QVariant(); + new (&as()) QVariant(); type = -1; QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine); QVariant v = priv->scriptValueToVariant(value); if (v.userType() == callType) { - *((QVariant *)&data) = v; + as() = v; } else if (v.canConvert((QVariant::Type)callType)) { - *((QVariant *)&data) = v; - ((QVariant *)&data)->convert((QVariant::Type)callType); + as() = v; + as().convert((QVariant::Type)callType); } else if (const QMetaObject *mo = priv->rawMetaObjectForType(callType)) { QObject *obj = priv->toQObject(v); @@ -783,9 +812,9 @@ void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine, if (!objMo) obj = 0; } - *((QVariant *)&data) = QVariant(callType, &obj); + as() = QVariant(callType, &obj); } else { - *((QVariant *)&data) = QVariant(callType, (void *)0); + as() = QVariant(callType, (void *)0); } } } @@ -795,27 +824,27 @@ QScriptDeclarativeClass::Value MetaCallArgument::toValue(QDeclarativeEngine *e) QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(e); if (type == qMetaTypeId()) { - return QScriptDeclarativeClass::Value(engine, *((QScriptValue *)&data)); + return QScriptDeclarativeClass::Value(engine, as()); } else if (type == QMetaType::Int) { - return QScriptDeclarativeClass::Value(engine, *((int *)&data)); + return QScriptDeclarativeClass::Value(engine, as()); } else if (type == QMetaType::UInt) { - return QScriptDeclarativeClass::Value(engine, *((uint *)&data)); + return QScriptDeclarativeClass::Value(engine, as()); } else if (type == QMetaType::Bool) { - return QScriptDeclarativeClass::Value(engine, *((bool *)&data)); + return QScriptDeclarativeClass::Value(engine, as()); } else if (type == QMetaType::Double) { - return QScriptDeclarativeClass::Value(engine, *((double *)&data)); + return QScriptDeclarativeClass::Value(engine, as()); } else if (type == QMetaType::Float) { - return QScriptDeclarativeClass::Value(engine, *((float *)&data)); + return QScriptDeclarativeClass::Value(engine, as()); } else if (type == QMetaType::QString) { - return QScriptDeclarativeClass::Value(engine, *((QString *)&data)); + return QScriptDeclarativeClass::Value(engine, as()); } else if (type == QMetaType::QObjectStar) { - QObject *object = *((QObject **)&data); + QObject *object = as(); if (object) QDeclarativeData::get(object, true)->setImplicitDestructible(); QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(e); return QScriptDeclarativeClass::Value(engine, priv->objectClass->newQObject(object)); } else if (type == qMetaTypeId >()) { - QList &list = *(QList*)&data; + QList &list = as >(); QScriptValue rv = engine->newArray(list.count()); QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(e); for (int ii = 0; ii < list.count(); ++ii) { @@ -826,7 +855,7 @@ QScriptDeclarativeClass::Value MetaCallArgument::toValue(QDeclarativeEngine *e) return QScriptDeclarativeClass::Value(engine, rv); } else if (type == -1 || type == qMetaTypeId()) { QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(e); - QScriptValue rv = ep->scriptValueFromVariant(*((QVariant *)&data)); + QScriptValue rv = ep->scriptValueFromVariant(as()); if (rv.isQObject()) { QObject *object = rv.toQObject(); if (object) @@ -906,7 +935,7 @@ QDeclarativeObjectMethodScriptClass::callMethod(QObject *object, int index, { if (argCount > 0) { - QVarLengthArray args(argCount + 1); + QVarLengthArray args(argCount + 1); args[0].initAsType(returnType, engine); for (int ii = 0; ii < argCount; ++ii) @@ -922,7 +951,7 @@ QDeclarativeObjectMethodScriptClass::callMethod(QObject *object, int index, } else if (returnType != 0) { - MetaCallArgument arg; + GenericMetaCallArgument arg; arg.initAsType(returnType, engine); void *args[] = { arg.dataPtr() }; -- cgit v0.12