summaryrefslogtreecommitdiffstats
path: root/src/tools/moc
diff options
context:
space:
mode:
Diffstat (limited to 'src/tools/moc')
-rw-r--r--src/tools/moc/generator.cpp306
-rw-r--r--src/tools/moc/preprocessor.cpp59
-rw-r--r--src/tools/moc/preprocessor.h4
3 files changed, 222 insertions, 147 deletions
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 6c5e772e8c..912fa995fa 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -359,7 +359,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 +431,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();
//
@@ -513,7 +521,7 @@ void Generator::generateCode()
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, ");
@@ -919,10 +927,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 +934,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,
- " _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, "else ");
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 +1046,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 +1129,14 @@ 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, " switch (_id) {\n");
for (int methodindex = 0; methodindex < methodList.size(); ++methodindex) {
const FunctionDef &f = methodList.at(methodindex);
@@ -1377,6 +1264,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");
diff --git a/src/tools/moc/preprocessor.cpp b/src/tools/moc/preprocessor.cpp
index c5d6b58412..687c4f8474 100644
--- a/src/tools/moc/preprocessor.cpp
+++ b/src/tools/moc/preprocessor.cpp
@@ -52,11 +52,12 @@ static QByteArray cleaned(const QByteArray &input)
QByteArray result;
result.reserve(input.size());
const char *data = input.constData();
+ const char *end = input.constData() + input.size();
char *output = result.data();
int newlines = 0;
- while (*data) {
- while (*data && is_space(*data))
+ while (data != end) {
+ while (data != end && is_space(*data))
++data;
bool takeLine = (*data == '#');
if (*data == '%' && *(data+1) == ':') {
@@ -66,15 +67,15 @@ static QByteArray cleaned(const QByteArray &input)
if (takeLine) {
*output = '#';
++output;
- do ++data; while (*data && is_space(*data));
+ do ++data; while (data != end && is_space(*data));
}
- while (*data) {
+ while (data != end) {
// handle \\\n, \\\r\n and \\\r
if (*data == '\\') {
if (*(data + 1) == '\r') {
++data;
}
- if (*data && (*(data + 1) == '\n' || (*data) == '\r')) {
+ if (data != end && (*(data + 1) == '\n' || (*data) == '\r')) {
++newlines;
data += 1;
if (*data != '\r')
@@ -201,7 +202,7 @@ Symbols Preprocessor::tokenize(const QByteArray& input, int lineNum, Preprocesso
data = skipQuote(data);
token = STRING_LITERAL;
// concatenate multi-line strings for easier
- // STRING_LITERAAL handling in moc
+ // STRING_LITERAL handling in moc
if (!Preprocessor::preprocessOnly
&& !symbols.isEmpty()
&& symbols.last().token == STRING_LITERAL) {
@@ -964,6 +965,43 @@ int Preprocessor::evaluateCondition()
return expression.value();
}
+static QByteArray readOrMapFile(QFile *file)
+{
+ const qint64 size = file->size();
+ char *rawInput = reinterpret_cast<char*>(file->map(0, size));
+ return rawInput ? QByteArray::fromRawData(rawInput, size) : file->readAll();
+}
+
+static void mergeStringLiterals(Symbols *_symbols)
+{
+ Symbols &symbols = *_symbols;
+ for (Symbols::iterator i = symbols.begin(); i != symbols.end(); ++i) {
+ if (i->token == STRING_LITERAL) {
+ Symbols::Iterator mergeSymbol = i;
+ int literalsLength = mergeSymbol->len;
+ while (++i != symbols.end() && i->token == STRING_LITERAL)
+ literalsLength += i->len - 2; // no quotes
+
+ if (literalsLength != mergeSymbol->len) {
+ QByteArray mergeSymbolOriginalLexem = mergeSymbol->unquotedLexem();
+ QByteArray &mergeSymbolLexem = mergeSymbol->lex;
+ mergeSymbolLexem.resize(0);
+ mergeSymbolLexem.reserve(literalsLength);
+ mergeSymbolLexem.append('"');
+ mergeSymbolLexem.append(mergeSymbolOriginalLexem);
+ for (Symbols::const_iterator j = mergeSymbol + 1; j != i; ++j)
+ mergeSymbolLexem.append(j->lex.constData() + j->from + 1, j->len - 2); // append j->unquotedLexem()
+ mergeSymbolLexem.append('"');
+ mergeSymbol->len = mergeSymbol->lex.length();
+ mergeSymbol->from = 0;
+ i = symbols.erase(mergeSymbol + 1, i);
+ }
+ if (i == symbols.end())
+ break;
+ }
+ }
+}
+
void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
{
currentFilenames.push(filename);
@@ -1020,7 +1058,8 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
if (!file.open(QFile::ReadOnly))
continue;
- QByteArray input = file.readAll();
+ QByteArray input = readOrMapFile(&file);
+
file.close();
if (input.isEmpty())
continue;
@@ -1153,9 +1192,10 @@ void Preprocessor::preprocess(const QByteArray &filename, Symbols &preprocessed)
currentFilenames.pop();
}
-Symbols Preprocessor::preprocessed(const QByteArray &filename, QIODevice *file)
+Symbols Preprocessor::preprocessed(const QByteArray &filename, QFile *file)
{
- QByteArray input = file->readAll();
+ QByteArray input = readOrMapFile(file);
+
if (input.isEmpty())
return symbols;
@@ -1176,6 +1216,7 @@ Symbols Preprocessor::preprocessed(const QByteArray &filename, QIODevice *file)
// phase 3: preprocess conditions and substitute macros
Symbols result;
preprocess(filename, result);
+ mergeStringLiterals(&result);
#if 0
for (int j = 0; j < result.size(); ++j)
diff --git a/src/tools/moc/preprocessor.h b/src/tools/moc/preprocessor.h
index fc86781be8..77f3a30ac0 100644
--- a/src/tools/moc/preprocessor.h
+++ b/src/tools/moc/preprocessor.h
@@ -57,7 +57,7 @@ typedef SubArray MacroName;
#endif
typedef QHash<MacroName, Macro> Macros;
-class QIODevice;
+class QFile;
class Preprocessor : public Parser
{
@@ -67,7 +67,7 @@ public:
QList<QByteArray> frameworks;
QSet<QByteArray> preprocessedIncludes;
Macros macros;
- Symbols preprocessed(const QByteArray &filename, QIODevice *device);
+ Symbols preprocessed(const QByteArray &filename, QFile *device);
void parseDefineArguments(Macro *m);