diff options
author | Thiago Macieira <thiago.macieira@nokia.com> | 2010-11-25 21:40:34 (GMT) |
---|---|---|
committer | Thiago Macieira <thiago.macieira@nokia.com> | 2011-04-14 08:52:04 (GMT) |
commit | 0d3044b547614cbd313d90021606af1f81fb10de (patch) | |
tree | 08ac2b69fee1b6aeeb610f3fe5466bdf229d47de | |
parent | 25fe0f83759649af218ea7eecd849dc0a311afbc (diff) | |
download | Qt-0d3044b547614cbd313d90021606af1f81fb10de.zip Qt-0d3044b547614cbd313d90021606af1f81fb10de.tar.gz Qt-0d3044b547614cbd313d90021606af1f81fb10de.tar.bz2 |
Fix strict-alias breaking warnings with GCC.
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
-rw-r--r-- | src/declarative/qml/qdeclarativeobjectscriptclass.cpp | 115 |
1 files 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 <typename T> T &as(); inline void cleanup(); - char data[4 * sizeof(void *)]; int type; bool isObjectType; + char padding[6]; // ensure sizeof(MetaCallArgument) == 8 +}; + +template <typename T> struct TypedMetaCallArgument: public MetaCallArgument +{ + T data; +protected: + TypedMetaCallArgument() {} + ~TypedMetaCallArgument() {} +private: + TypedMetaCallArgument(const TypedMetaCallArgument &); }; + +struct GenericPayload { void *data[4]; }; +struct GenericMetaCallArgument: public TypedMetaCallArgument<GenericPayload> +{ +}; + +template <typename T> T &MetaCallArgument::as() +{ +#ifdef Q_ALIGNOF + // static assert + char dummy_array[Q_ALIGNOF(T) <= sizeof(*this) ? 1 : -1]; Q_UNUSED(dummy_array); +#endif + TypedMetaCallArgument<T> &typed = static_cast<TypedMetaCallArgument<T> &>(*this); + return typed.data; +} + } MetaCallArgument::MetaCallArgument() @@ -664,22 +693,22 @@ MetaCallArgument::~MetaCallArgument() void MetaCallArgument::cleanup() { if (type == QMetaType::QString) { - ((QString *)&data)->~QString(); + as<QString>().~QString(); } else if (type == -1 || type == qMetaTypeId<QVariant>()) { - ((QVariant *)&data)->~QVariant(); + as<QVariant>().~QVariant(); } else if (type == qMetaTypeId<QScriptValue>()) { - ((QScriptValue *)&data)->~QScriptValue(); + as<QScriptValue>().~QScriptValue(); } else if (type == qMetaTypeId<QList<QObject *> >()) { - ((QList<QObject *> *)&data)->~QList<QObject *>(); + as<QList<QObject *> >().~QList<QObject *>(); } } void *MetaCallArgument::dataPtr() { if (type == -1) - return ((QVariant *)data)->data(); + return as<QVariant>().data(); else - return (void *)&data; + return &as<GenericPayload>(); } 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<QScriptValue>()) { - new (&data) QScriptValue(engine->undefinedValue()); + new (&as<QScriptValue>()) 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<QObject *>() = 0; type = callType; } else if (callType == QMetaType::QString) { - new (&data) QString(); + new (&as<QString>()) QString(); type = callType; } else if (callType == qMetaTypeId<QVariant>()) { type = callType; - new (&data) QVariant(); + new (&as<QVariant>()) QVariant(); } else if (callType == qMetaTypeId<QList<QObject *> >()) { type = callType; - new (&data) QList<QObject *>(); + new (&as<QList<QObject *> >()) QList<QObject *>(); } else { type = -1; - new (&data) QVariant(callType, (void *)0); + new (&as<QVariant>()) QVariant(callType, (void *)0); } } @@ -721,37 +750,37 @@ void MetaCallArgument::fromScriptValue(int callType, QDeclarativeEngine *engine, if (type != 0) { cleanup(); type = 0; } if (callType == qMetaTypeId<QScriptValue>()) { - new (&data) QScriptValue(value); + new (&as<QScriptValue>()) QScriptValue(value); type = qMetaTypeId<QScriptValue>(); } else if (callType == QMetaType::Int) { - *((int *)&data) = int(value.toInt32()); + as<int>() = int(value.toInt32()); type = callType; } else if (callType == QMetaType::UInt) { - *((uint *)&data) = uint(value.toUInt32()); + as<uint>() = uint(value.toUInt32()); type = callType; } else if (callType == QMetaType::Bool) { - *((bool *)&data) = value.toBool(); + as<bool>() = value.toBool(); type = callType; } else if (callType == QMetaType::Double) { - *((double *)&data) = double(value.toNumber()); + as<double>() = double(value.toNumber()); type = callType; } else if (callType == QMetaType::Float) { - *((float *)&data) = float(value.toNumber()); + as<float>() = float(value.toNumber()); type = callType; } else if (callType == QMetaType::QString) { if (value.isNull() || value.isUndefined()) - new (&data) QString(); + new (&as<QString>()) QString(); else - new (&data) QString(value.toString()); + new (&as<QString>()) QString(value.toString()); type = callType; } else if (callType == QMetaType::QObjectStar) { - *((QObject **)&data) = value.toQObject(); + as<QObject *>() = value.toQObject(); type = callType; } else if (callType == qMetaTypeId<QVariant>()) { - new (&data) QVariant(QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value)); + new (&as<QVariant>()) QVariant(QDeclarativeEnginePrivate::get(engine)->scriptValueToVariant(value)); type = callType; } else if (callType == qMetaTypeId<QList<QObject*> >()) { - QList<QObject *> *list = new (&data) QList<QObject *>(); + QList<QObject *> *list = new (&as<QList<QObject *> >()) QList<QObject *>(); 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>()) QVariant(); type = -1; QDeclarativeEnginePrivate *priv = QDeclarativeEnginePrivate::get(engine); QVariant v = priv->scriptValueToVariant(value); if (v.userType() == callType) { - *((QVariant *)&data) = v; + as<QVariant>() = v; } else if (v.canConvert((QVariant::Type)callType)) { - *((QVariant *)&data) = v; - ((QVariant *)&data)->convert((QVariant::Type)callType); + as<QVariant>() = v; + as<QVariant>().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>() = QVariant(callType, &obj); } else { - *((QVariant *)&data) = QVariant(callType, (void *)0); + as<QVariant>() = QVariant(callType, (void *)0); } } } @@ -795,27 +824,27 @@ QScriptDeclarativeClass::Value MetaCallArgument::toValue(QDeclarativeEngine *e) QScriptEngine *engine = QDeclarativeEnginePrivate::getScriptEngine(e); if (type == qMetaTypeId<QScriptValue>()) { - return QScriptDeclarativeClass::Value(engine, *((QScriptValue *)&data)); + return QScriptDeclarativeClass::Value(engine, as<QScriptValue>()); } else if (type == QMetaType::Int) { - return QScriptDeclarativeClass::Value(engine, *((int *)&data)); + return QScriptDeclarativeClass::Value(engine, as<int>()); } else if (type == QMetaType::UInt) { - return QScriptDeclarativeClass::Value(engine, *((uint *)&data)); + return QScriptDeclarativeClass::Value(engine, as<uint>()); } else if (type == QMetaType::Bool) { - return QScriptDeclarativeClass::Value(engine, *((bool *)&data)); + return QScriptDeclarativeClass::Value(engine, as<bool>()); } else if (type == QMetaType::Double) { - return QScriptDeclarativeClass::Value(engine, *((double *)&data)); + return QScriptDeclarativeClass::Value(engine, as<double>()); } else if (type == QMetaType::Float) { - return QScriptDeclarativeClass::Value(engine, *((float *)&data)); + return QScriptDeclarativeClass::Value(engine, as<float>()); } else if (type == QMetaType::QString) { - return QScriptDeclarativeClass::Value(engine, *((QString *)&data)); + return QScriptDeclarativeClass::Value(engine, as<QString>()); } else if (type == QMetaType::QObjectStar) { - QObject *object = *((QObject **)&data); + QObject *object = as<QObject *>(); 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<QObject *> >()) { - QList<QObject *> &list = *(QList<QObject *>*)&data; + QList<QObject *> &list = as<QList<QObject *> >(); 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<QVariant>()) { QDeclarativeEnginePrivate *ep = QDeclarativeEnginePrivate::get(e); - QScriptValue rv = ep->scriptValueFromVariant(*((QVariant *)&data)); + QScriptValue rv = ep->scriptValueFromVariant(as<QVariant>()); if (rv.isQObject()) { QObject *object = rv.toQObject(); if (object) @@ -906,7 +935,7 @@ QDeclarativeObjectMethodScriptClass::callMethod(QObject *object, int index, { if (argCount > 0) { - QVarLengthArray<MetaCallArgument, 9> args(argCount + 1); + QVarLengthArray<GenericMetaCallArgument, 9> 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() }; |