summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@nokia.com>2010-11-25 21:40:34 (GMT)
committerThiago Macieira <thiago.macieira@nokia.com>2011-04-14 08:52:04 (GMT)
commit0d3044b547614cbd313d90021606af1f81fb10de (patch)
tree08ac2b69fee1b6aeeb610f3fe5466bdf229d47de
parent25fe0f83759649af218ea7eecd849dc0a311afbc (diff)
downloadQt-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.cpp115
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() };