summaryrefslogtreecommitdiffstats
path: root/src/tools/moc/generator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/moc/generator.cpp')
-rw-r--r--src/tools/moc/generator.cpp345
1 files changed, 198 insertions, 147 deletions
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 6c5e772e8c..f27c155da5 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -1,6 +1,6 @@
/****************************************************************************
**
-** Copyright (C) 2014 Digia Plc and/or its subsidiary(-ies).
+** Copyright (C) 2015 Digia Plc and/or its subsidiary(-ies).
** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
** Contact: http://www.qt-project.org/legal
**
@@ -230,13 +230,23 @@ void Generator::generateCode()
//
// Build stringdata struct
//
+ const int constCharArraySizeLimit = 65535;
fprintf(out, "struct qt_meta_stringdata_%s_t {\n", qualifiedClassNameIdentifier.constData());
fprintf(out, " QByteArrayData data[%d];\n", strings.size());
{
- int len = 0;
- for (int i = 0; i < strings.size(); ++i)
- len += strings.at(i).length() + 1;
- fprintf(out, " char stringdata[%d];\n", len);
+ int stringDataLength = 0;
+ int stringDataCounter = 0;
+ for (int i = 0; i < strings.size(); ++i) {
+ int thisLength = strings.at(i).length() + 1;
+ stringDataLength += thisLength;
+ if (stringDataLength / constCharArraySizeLimit) {
+ // save previous stringdata and start computing the next one.
+ fprintf(out, " char stringdata%d[%d];\n", stringDataCounter++, stringDataLength - thisLength);
+ stringDataLength = thisLength;
+ }
+ }
+ fprintf(out, " char stringdata%d[%d];\n", stringDataCounter, stringDataLength);
+
}
fprintf(out, "};\n");
@@ -247,7 +257,7 @@ void Generator::generateCode()
// QByteArrayData::data() implementation returning simply "this + offset".
fprintf(out, "#define QT_MOC_LITERAL(idx, ofs, len) \\\n"
" Q_STATIC_BYTE_ARRAY_DATA_HEADER_INITIALIZER_WITH_OFFSET(len, \\\n"
- " qptrdiff(offsetof(qt_meta_stringdata_%s_t, stringdata) + ofs \\\n"
+ " qptrdiff(offsetof(qt_meta_stringdata_%s_t, stringdata0) + ofs \\\n"
" - idx * sizeof(QByteArrayData)) \\\n"
" )\n",
qualifiedClassNameIdentifier.constData());
@@ -282,9 +292,18 @@ void Generator::generateCode()
fprintf(out, " \"");
int col = 0;
int len = 0;
+ int stringDataLength = 0;
for (int i = 0; i < strings.size(); ++i) {
QByteArray s = strings.at(i);
len = s.length();
+ stringDataLength += len + 1;
+ if (stringDataLength >= constCharArraySizeLimit) {
+ fprintf(out, "\",\n \"");
+ stringDataLength = len + 1;
+ col = 0;
+ } else if (i)
+ fputs("\\0", out); // add \0 at the end of each string
+
if (col && col + len >= 72) {
fprintf(out, "\"\n \"");
col = 0;
@@ -309,9 +328,6 @@ void Generator::generateCode()
idx += spanLen;
col += spanLen;
}
-
- if (i != strings.size() - 1) // skip the last \0 the c++ will add it for us
- fputs("\\0", out);
col += len + 2;
}
@@ -359,7 +375,13 @@ void Generator::generateCode()
fprintf(out, " %4d, %4d, // constructors\n", isConstructible ? cdef->constructorList.count() : 0,
isConstructible ? index : 0);
- fprintf(out, " %4d, // flags\n", 0);
+ int flags = 0;
+ if (cdef->hasQGadget) {
+ // Ideally, all the classes could have that flag. But this broke classes generated
+ // by qdbusxml2cpp which generate code that require that we call qt_metacall for properties
+ flags |= PropertyAccessInStaticMetaCall;
+ }
+ fprintf(out, " %4d, // flags\n", flags);
fprintf(out, " %4d, // signalCount\n", cdef->signalList.count());
@@ -425,7 +447,9 @@ void Generator::generateCode()
//
// Generate internal qt_static_metacall() function
//
- if (cdef->hasQObject && !isQt)
+ const bool hasStaticMetaCall = !isQt &&
+ (cdef->hasQObject || !cdef->methodList.isEmpty() || !cdef->propertyList.isEmpty());
+ if (hasStaticMetaCall)
generateStaticMetacall();
//
@@ -506,14 +530,14 @@ void Generator::generateCode()
if (isQObject)
fprintf(out, " { Q_NULLPTR, ");
- else if (cdef->superclassList.size())
+ else if (cdef->superclassList.size() && (!cdef->hasQGadget || knownGadgets.contains(purestSuperClass)))
fprintf(out, " { &%s::staticMetaObject, ", purestSuperClass.constData());
else
fprintf(out, " { Q_NULLPTR, ");
fprintf(out, "qt_meta_stringdata_%s.data,\n"
" qt_meta_data_%s, ", qualifiedClassNameIdentifier.constData(),
qualifiedClassNameIdentifier.constData());
- if (cdef->hasQObject && !isQt)
+ if (hasStaticMetaCall)
fprintf(out, " qt_static_metacall, ");
else
fprintf(out, " Q_NULLPTR, ");
@@ -538,7 +562,7 @@ void Generator::generateCode()
//
fprintf(out, "\nvoid *%s::qt_metacast(const char *_clname)\n{\n", cdef->qualified.constData());
fprintf(out, " if (!_clname) return Q_NULLPTR;\n");
- fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s.stringdata))\n"
+ fprintf(out, " if (!strcmp(_clname, qt_meta_stringdata_%s.stringdata0))\n"
" return static_cast<void*>(const_cast< %s*>(this));\n",
qualifiedClassNameIdentifier.constData(), cdef->classname.constData());
for (int i = 1; i < cdef->superclassList.size(); ++i) { // for all superclasses but the first one
@@ -919,10 +943,6 @@ void Generator::generateMetacall()
}
if (cdef->propertyList.size()) {
- bool needGet = false;
- bool needTempVarForGet = false;
- bool needSet = false;
- bool needReset = false;
bool needDesignable = false;
bool needScriptable = false;
bool needStored = false;
@@ -930,132 +950,21 @@ void Generator::generateMetacall()
bool needUser = false;
for (int i = 0; i < cdef->propertyList.size(); ++i) {
const PropertyDef &p = cdef->propertyList.at(i);
- needGet |= !p.read.isEmpty() || !p.member.isEmpty();
- if (!p.read.isEmpty() || !p.member.isEmpty())
- needTempVarForGet |= (p.gspec != PropertyDef::PointerSpec
- && p.gspec != PropertyDef::ReferenceSpec);
-
- needSet |= !p.write.isEmpty() || (!p.member.isEmpty() && !p.constant);
- needReset |= !p.reset.isEmpty();
needDesignable |= p.designable.endsWith(')');
needScriptable |= p.scriptable.endsWith(')');
needStored |= p.stored.endsWith(')');
needEditable |= p.editable.endsWith(')');
needUser |= p.user.endsWith(')');
}
- fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
+ fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
if (needElse)
- fprintf(out, " else ");
- fprintf(out, "if (_c == QMetaObject::ReadProperty) {\n");
- if (needGet) {
- if (needTempVarForGet)
- fprintf(out, " void *_v = _a[0];\n");
- fprintf(out, " switch (_id) {\n");
- for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
- const PropertyDef &p = cdef->propertyList.at(propindex);
- if (p.read.isEmpty() && p.member.isEmpty())
- continue;
- QByteArray prefix;
- if (p.inPrivateClass.size()) {
- prefix = p.inPrivateClass;
- prefix.append("->");
- }
- if (p.gspec == PropertyDef::PointerSpec)
- fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(%s%s())); break;\n",
- propindex, prefix.constData(), p.read.constData());
- else if (p.gspec == PropertyDef::ReferenceSpec)
- fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(&%s%s())); break;\n",
- propindex, prefix.constData(), p.read.constData());
- else if (cdef->enumDeclarations.value(p.type, false))
- fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s%s()); break;\n",
- propindex, prefix.constData(), p.read.constData());
- else if (!p.read.isEmpty())
- fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n",
- propindex, p.type.constData(), prefix.constData(), p.read.constData());
- else
- fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s; break;\n",
- propindex, p.type.constData(), prefix.constData(), p.member.constData());
- }
- fprintf(out, " default: break;\n");
- fprintf(out, " }\n");
- }
-
- fprintf(out,
- " _id -= %d;\n"
- " }", cdef->propertyList.count());
-
- fprintf(out, " else ");
- fprintf(out, "if (_c == QMetaObject::WriteProperty) {\n");
-
- if (needSet) {
- fprintf(out, " void *_v = _a[0];\n");
- fprintf(out, " switch (_id) {\n");
- for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
- const PropertyDef &p = cdef->propertyList.at(propindex);
- if (p.constant)
- continue;
- if (p.write.isEmpty() && p.member.isEmpty())
- continue;
- QByteArray prefix;
- if (p.inPrivateClass.size()) {
- prefix = p.inPrivateClass;
- prefix.append("->");
- }
- if (cdef->enumDeclarations.value(p.type, false)) {
- fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
- propindex, prefix.constData(), p.write.constData());
- } else if (!p.write.isEmpty()) {
- fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n",
- propindex, prefix.constData(), p.write.constData(), p.type.constData());
- } else {
- fprintf(out, " case %d:\n", propindex);
- fprintf(out, " if (%s%s != *reinterpret_cast< %s*>(_v)) {\n",
- prefix.constData(), p.member.constData(), p.type.constData());
- fprintf(out, " %s%s = *reinterpret_cast< %s*>(_v);\n",
- prefix.constData(), p.member.constData(), p.type.constData());
- if (!p.notify.isEmpty() && p.notifyId != -1) {
- const FunctionDef &f = cdef->signalList.at(p.notifyId);
- if (f.arguments.size() == 0)
- fprintf(out, " Q_EMIT %s();\n", p.notify.constData());
- else if (f.arguments.size() == 1 && f.arguments.at(0).normalizedType == p.type)
- fprintf(out, " Q_EMIT %s(%s%s);\n",
- p.notify.constData(), prefix.constData(), p.member.constData());
- }
- fprintf(out, " }\n");
- fprintf(out, " break;\n");
- }
- }
- fprintf(out, " default: break;\n");
- fprintf(out, " }\n");
- }
-
+ fprintf(out, "else ");
fprintf(out,
- " _id -= %d;\n"
- " }", cdef->propertyList.count());
-
- fprintf(out, " else ");
- fprintf(out, "if (_c == QMetaObject::ResetProperty) {\n");
- if (needReset) {
- fprintf(out, " switch (_id) {\n");
- for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
- const PropertyDef &p = cdef->propertyList.at(propindex);
- if (!p.reset.endsWith(')'))
- continue;
- QByteArray prefix;
- if (p.inPrivateClass.size()) {
- prefix = p.inPrivateClass;
- prefix.append("->");
- }
- fprintf(out, " case %d: %s%s; break;\n",
- propindex, prefix.constData(), p.reset.constData());
- }
- fprintf(out, " default: break;\n");
- fprintf(out, " }\n");
- }
- fprintf(out,
- " _id -= %d;\n"
- " }", cdef->propertyList.count());
+ "if (_c == QMetaObject::ReadProperty || _c == QMetaObject::WriteProperty\n"
+ " || _c == QMetaObject::ResetProperty || _c == QMetaObject::RegisterPropertyMetaType) {\n"
+ " qt_static_metacall(this, _c, _id, _a);\n"
+ " _id -= %d;\n }", cdef->propertyList.count());
fprintf(out, " else ");
fprintf(out, "if (_c == QMetaObject::QueryPropertyDesignable) {\n");
@@ -1153,16 +1062,6 @@ void Generator::generateMetacall()
" _id -= %d;\n"
" }", cdef->propertyList.count());
- fprintf(out, " else ");
- fprintf(out, "if (_c == QMetaObject::RegisterPropertyMetaType) {\n");
- fprintf(out, " if (_id < %d)\n", cdef->propertyList.size());
-
- if (automaticPropertyMetaTypesHelper().isEmpty())
- fprintf(out, " *reinterpret_cast<int*>(_a[0]) = -1;\n");
- else
- fprintf(out, " qt_static_metacall(this, _c, _id, _a);\n");
- fprintf(out, " _id -= %d;\n }", cdef->propertyList.size());
-
fprintf(out, "\n#endif // QT_NO_PROPERTIES");
}
if (methodList.size() || cdef->signalList.size() || cdef->propertyList.size())
@@ -1246,10 +1145,15 @@ void Generator::generateStaticMetacall()
else
fprintf(out, " ");
fprintf(out, "if (_c == QMetaObject::InvokeMetaMethod) {\n");
+ if (cdef->hasQObject) {
#ifndef QT_NO_DEBUG
- fprintf(out, " Q_ASSERT(staticMetaObject.cast(_o));\n");
+ fprintf(out, " Q_ASSERT(staticMetaObject.cast(_o));\n");
#endif
- fprintf(out, " %s *_t = static_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
+ fprintf(out, " %s *_t = static_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
+ } else {
+ fprintf(out, " %s *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
+ }
+ fprintf(out, " Q_UNUSED(_t)\n");
fprintf(out, " switch (_id) {\n");
for (int methodindex = 0; methodindex < methodList.size(); ++methodindex) {
const FunctionDef &f = methodList.at(methodindex);
@@ -1377,6 +1281,153 @@ void Generator::generateStaticMetacall()
needElse = true;
}
+ if (!cdef->propertyList.empty()) {
+ bool needGet = false;
+ bool needTempVarForGet = false;
+ bool needSet = false;
+ bool needReset = false;
+ for (int i = 0; i < cdef->propertyList.size(); ++i) {
+ const PropertyDef &p = cdef->propertyList.at(i);
+ needGet |= !p.read.isEmpty() || !p.member.isEmpty();
+ if (!p.read.isEmpty() || !p.member.isEmpty())
+ needTempVarForGet |= (p.gspec != PropertyDef::PointerSpec
+ && p.gspec != PropertyDef::ReferenceSpec);
+
+ needSet |= !p.write.isEmpty() || (!p.member.isEmpty() && !p.constant);
+ needReset |= !p.reset.isEmpty();
+ }
+ fprintf(out, "\n#ifndef QT_NO_PROPERTIES\n ");
+
+ if (needElse)
+ fprintf(out, "else ");
+ fprintf(out, "if (_c == QMetaObject::ReadProperty) {\n");
+ if (needGet) {
+ if (cdef->hasQObject) {
+#ifndef QT_NO_DEBUG
+ fprintf(out, " Q_ASSERT(staticMetaObject.cast(_o));\n");
+#endif
+ fprintf(out, " %s *_t = static_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
+ } else {
+ fprintf(out, " %s *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
+ }
+ if (needTempVarForGet)
+ fprintf(out, " void *_v = _a[0];\n");
+ fprintf(out, " switch (_id) {\n");
+ for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ const PropertyDef &p = cdef->propertyList.at(propindex);
+ if (p.read.isEmpty() && p.member.isEmpty())
+ continue;
+ QByteArray prefix = "_t->";
+ if (p.inPrivateClass.size()) {
+ prefix += p.inPrivateClass + "->";
+ }
+ if (p.gspec == PropertyDef::PointerSpec)
+ fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(%s%s())); break;\n",
+ propindex, prefix.constData(), p.read.constData());
+ else if (p.gspec == PropertyDef::ReferenceSpec)
+ fprintf(out, " case %d: _a[0] = const_cast<void*>(reinterpret_cast<const void*>(&%s%s())); break;\n",
+ propindex, prefix.constData(), p.read.constData());
+ else if (cdef->enumDeclarations.value(p.type, false))
+ fprintf(out, " case %d: *reinterpret_cast<int*>(_v) = QFlag(%s%s()); break;\n",
+ propindex, prefix.constData(), p.read.constData());
+ else if (!p.read.isEmpty())
+ fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s(); break;\n",
+ propindex, p.type.constData(), prefix.constData(), p.read.constData());
+ else
+ fprintf(out, " case %d: *reinterpret_cast< %s*>(_v) = %s%s; break;\n",
+ propindex, p.type.constData(), prefix.constData(), p.member.constData());
+ }
+ fprintf(out, " default: break;\n");
+ fprintf(out, " }\n");
+ }
+
+ fprintf(out, " }");
+
+ fprintf(out, " else ");
+ fprintf(out, "if (_c == QMetaObject::WriteProperty) {\n");
+
+ if (needSet) {
+ if (cdef->hasQObject) {
+#ifndef QT_NO_DEBUG
+ fprintf(out, " Q_ASSERT(staticMetaObject.cast(_o));\n");
+#endif
+ fprintf(out, " %s *_t = static_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
+ } else {
+ fprintf(out, " %s *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
+ }
+ fprintf(out, " void *_v = _a[0];\n");
+ fprintf(out, " switch (_id) {\n");
+ for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ const PropertyDef &p = cdef->propertyList.at(propindex);
+ if (p.constant)
+ continue;
+ if (p.write.isEmpty() && p.member.isEmpty())
+ continue;
+ QByteArray prefix = "_t->";
+ if (p.inPrivateClass.size()) {
+ prefix += p.inPrivateClass + "->";
+ }
+ if (cdef->enumDeclarations.value(p.type, false)) {
+ fprintf(out, " case %d: %s%s(QFlag(*reinterpret_cast<int*>(_v))); break;\n",
+ propindex, prefix.constData(), p.write.constData());
+ } else if (!p.write.isEmpty()) {
+ fprintf(out, " case %d: %s%s(*reinterpret_cast< %s*>(_v)); break;\n",
+ propindex, prefix.constData(), p.write.constData(), p.type.constData());
+ } else {
+ fprintf(out, " case %d:\n", propindex);
+ fprintf(out, " if (%s%s != *reinterpret_cast< %s*>(_v)) {\n",
+ prefix.constData(), p.member.constData(), p.type.constData());
+ fprintf(out, " %s%s = *reinterpret_cast< %s*>(_v);\n",
+ prefix.constData(), p.member.constData(), p.type.constData());
+ if (!p.notify.isEmpty() && p.notifyId != -1) {
+ const FunctionDef &f = cdef->signalList.at(p.notifyId);
+ if (f.arguments.size() == 0)
+ fprintf(out, " Q_EMIT _t->%s();\n", p.notify.constData());
+ else if (f.arguments.size() == 1 && f.arguments.at(0).normalizedType == p.type)
+ fprintf(out, " Q_EMIT _t->%s(%s%s);\n",
+ p.notify.constData(), prefix.constData(), p.member.constData());
+ }
+ fprintf(out, " }\n");
+ fprintf(out, " break;\n");
+ }
+ }
+ fprintf(out, " default: break;\n");
+ fprintf(out, " }\n");
+ }
+
+ fprintf(out, " }");
+
+ fprintf(out, " else ");
+ fprintf(out, "if (_c == QMetaObject::ResetProperty) {\n");
+ if (needReset) {
+ if (cdef->hasQObject) {
+#ifndef QT_NO_DEBUG
+ fprintf(out, " Q_ASSERT(staticMetaObject.cast(_o));\n");
+#endif
+ fprintf(out, " %s *_t = static_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
+ } else {
+ fprintf(out, " %s *_t = reinterpret_cast<%s *>(_o);\n", cdef->classname.constData(), cdef->classname.constData());
+ }
+ fprintf(out, " switch (_id) {\n");
+ for (int propindex = 0; propindex < cdef->propertyList.size(); ++propindex) {
+ const PropertyDef &p = cdef->propertyList.at(propindex);
+ if (!p.reset.endsWith(')'))
+ continue;
+ QByteArray prefix = "_t->";
+ if (p.inPrivateClass.size()) {
+ prefix += p.inPrivateClass + "->";
+ }
+ fprintf(out, " case %d: %s%s; break;\n",
+ propindex, prefix.constData(), p.reset.constData());
+ }
+ fprintf(out, " default: break;\n");
+ fprintf(out, " }\n");
+ }
+ fprintf(out, " }");
+ fprintf(out, "\n#endif // QT_NO_PROPERTIES");
+ needElse = true;
+ }
+
if (needElse)
fprintf(out, "\n");