summaryrefslogtreecommitdiffstats
path: root/src/tools
diff options
context:
space:
mode:
authorFabian Kosmale <fabian.kosmale@qt.io>2020-03-19 10:47:29 +0100
committerFabian Kosmale <fabian.kosmale@qt.io>2020-06-02 22:42:15 +0200
commitfa987d44417528856d5e80ed7b48ba99e19fa307 (patch)
tree50cd74c1a9dd3c2197f7de2ac0d431a5b16b0a42 /src/tools
parent5306fdabc1ceb09875f791526553b3665017f7ce (diff)
MetaObject: Store the QMetaType of the methods
This does the analog of 46f407126ef3e94d59254012cdc34d6a4ad2faf2 for the methods we care about (signals, slots, Q_INVOKABLEs). In addition to the actual QMetaType, we store an array with offsets so that we later can do a mapping from methodIndex to metatype. The newly added QMetaMethod::{return,parameter}MetaType methods can then be used to retrieve the metatypes. This does however require that all involved types are complete. This is unfortunately not a feasible requirement. Thus, we only populate the metatype array on a best effort basis. For any incomplete type, we store QMetaType::Unknown. Then, when accessing the metatype, we fall back to the old string based code base if it's Unknown. Squashes "moc: support incomplete types" and "Fix compile failures after QMetaMethod change" Fixes: QTBUG-82932 Change-Id: I6b7a587cc364b7cad0c158d6de54e8a204289ad4 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
Diffstat (limited to 'src/tools')
-rw-r--r--src/tools/moc/generator.cpp67
-rw-r--r--src/tools/moc/generator.h5
-rw-r--r--src/tools/moc/main.cpp6
-rw-r--r--src/tools/moc/moc.cpp2
-rw-r--r--src/tools/moc/moc.h3
5 files changed, 65 insertions, 18 deletions
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 976d49ad20..849e25b76d 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -80,9 +80,9 @@ QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
return nullptr;
}
-Generator::Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile)
+Generator::Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile, bool requireCompleteTypes)
: out(outfile), cdef(classDef), metaTypes(metaTypes), knownQObjectClasses(knownQObjectClasses)
- , knownGadgets(knownGadgets)
+ , knownGadgets(knownGadgets), requireCompleteTypes(requireCompleteTypes)
{
if (cdef->superclassList.size())
purestSuperClass = cdef->superclassList.constFirst().first;
@@ -350,7 +350,7 @@ void Generator::generateCode()
int methodCount = cdef->signalList.count() + cdef->slotList.count() + cdef->methodList.count();
fprintf(out, " %4d, %4d, // methods\n", methodCount, methodCount ? index : 0);
- index += methodCount * 5;
+ index += methodCount * QMetaObjectPrivate::IntsPerMethod;
if (cdef->revisionedMethods)
index += methodCount;
int paramsIndex = index;
@@ -391,20 +391,22 @@ void Generator::generateCode()
//
generateClassInfos();
+ int initialMetaTypeOffset = cdef->propertyList.count();
+
//
// Build signals array first, otherwise the signal indices would be wrong
//
- generateFunctions(cdef->signalList, "signal", MethodSignal, paramsIndex);
+ generateFunctions(cdef->signalList, "signal", MethodSignal, paramsIndex, initialMetaTypeOffset);
//
// Build slots array
//
- generateFunctions(cdef->slotList, "slot", MethodSlot, paramsIndex);
+ generateFunctions(cdef->slotList, "slot", MethodSlot, paramsIndex, initialMetaTypeOffset);
//
// Build method array
//
- generateFunctions(cdef->methodList, "method", MethodMethod, paramsIndex);
+ generateFunctions(cdef->methodList, "method", MethodMethod, paramsIndex, initialMetaTypeOffset);
//
// Build method version arrays
@@ -438,7 +440,7 @@ void Generator::generateCode()
// Build constructors array
//
if (isConstructible)
- generateFunctions(cdef->constructorList, "constructor", MethodConstructor, paramsIndex);
+ generateFunctions(cdef->constructorList, "constructor", MethodConstructor, paramsIndex, initialMetaTypeOffset);
//
// Terminate data array
@@ -553,14 +555,48 @@ void Generator::generateCode()
else
fprintf(out, " qt_meta_extradata_%s,\n", qualifiedClassNameIdentifier.constData());
- if (cdef->propertyList.isEmpty()) {
+ bool constructorListContainsArgument = false;
+ for (int i = 0; i< cdef->constructorList.count(); ++i) {
+ const FunctionDef& fdef = cdef->constructorList.at(i);
+ if (fdef.arguments.count()) {
+ constructorListContainsArgument = true;
+ break;
+ }
+ }
+ if (cdef->propertyList.isEmpty() && cdef->signalList.isEmpty() && cdef->slotList.isEmpty() && cdef->methodList.isEmpty() && !constructorListContainsArgument) {
fprintf(out, " nullptr,\n");
} else {
- fprintf(out, "qt_metaTypeArray<\n");
+ bool needsComma = false;
+ if (!requireCompleteTypes) {
+ fprintf(out, "qt_incomplete_metaTypeArray<qt_meta_stringdata_%s_t\n", qualifiedClassNameIdentifier.constData());
+ needsComma = true;
+ } else {
+ fprintf(out, "qt_metaTypeArray<\n");
+ }
for (int i = 0; i < cdef->propertyList.count(); ++i) {
const PropertyDef &p = cdef->propertyList.at(i);
- fprintf(out, "%s%s", i == 0 ? "" : ", ", p.type.data());
+ fprintf(out, "%s%s", needsComma ? ", " : "", p.type.data());
+ needsComma = true;
+ }
+ for (const QVector<FunctionDef> &methodContainer: {cdef->signalList, cdef->slotList, cdef->methodList} ) {
+ for (int i = 0; i< methodContainer.count(); ++i) {
+ const FunctionDef& fdef = methodContainer.at(i);
+ fprintf(out, "%s%s", needsComma ? ", " : "", fdef.type.name.data());
+ needsComma = true;
+ for (const auto &argument: fdef.arguments) {
+ fprintf(out, ", %s", argument.type.name.data());
+ }
+ }
+ fprintf(out, "\n");
+ }
+ for (int i = 0; i< cdef->constructorList.count(); ++i) {
+ const FunctionDef& fdef = cdef->constructorList.at(i);
+ for (const auto &argument: fdef.arguments) {
+ fprintf(out, "%s%s", needsComma ? ", " : "", argument.type.name.data());
+ needsComma = true;
+ }
}
+ fprintf(out, "\n");
fprintf(out, ">,\n");
}
@@ -572,6 +608,7 @@ void Generator::generateCode()
fprintf(out, "\nconst QMetaObject *%s::metaObject() const\n{\n return QObject::d_ptr->metaObject ? QObject::d_ptr->dynamicMetaObject() : &staticMetaObject;\n}\n",
cdef->qualified.constData());
+
//
// Generate smart cast function
//
@@ -688,11 +725,11 @@ void Generator::registerByteArrayVector(const QVector<QByteArray> &list)
strreg(ba);
}
-void Generator::generateFunctions(const QVector<FunctionDef>& list, const char *functype, int type, int &paramsIndex)
+void Generator::generateFunctions(const QVector<FunctionDef>& list, const char *functype, int type, int &paramsIndex, int &initialMetatypeOffset)
{
if (list.isEmpty())
return;
- fprintf(out, "\n // %ss: name, argc, parameters, tag, flags\n", functype);
+ fprintf(out, "\n // %ss: name, argc, parameters, tag, flags, initial metatype offsets\n", functype);
for (int i = 0; i < list.count(); ++i) {
const FunctionDef &f = list.at(i);
@@ -727,10 +764,12 @@ void Generator::generateFunctions(const QVector<FunctionDef>& list, const char *
}
int argc = f.arguments.count();
- fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x /* %s */,\n",
- stridx(f.name), argc, paramsIndex, stridx(f.tag), flags, comment.constData());
+ fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x, %4d /* %s */,\n",
+ stridx(f.name), argc, paramsIndex, stridx(f.tag), flags, initialMetatypeOffset, comment.constData());
paramsIndex += 1 + argc * 2;
+ // constructors don't have a return type
+ initialMetatypeOffset += (f.isConstructor ? 0 : 1) + argc;
}
}
diff --git a/src/tools/moc/generator.h b/src/tools/moc/generator.h
index e92b9d1208..f3d3b40349 100644
--- a/src/tools/moc/generator.h
+++ b/src/tools/moc/generator.h
@@ -39,7 +39,7 @@ class Generator
ClassDef *cdef;
QVector<uint> meta_data;
public:
- Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = nullptr);
+ Generator(ClassDef *classDef, const QVector<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = nullptr, bool requireCompleteTypes = false);
void generateCode();
private:
bool registerableMetaType(const QByteArray &propertyType);
@@ -47,7 +47,7 @@ private:
void generateClassInfos();
void registerFunctionStrings(const QVector<FunctionDef> &list);
void registerByteArrayVector(const QVector<QByteArray> &list);
- void generateFunctions(const QVector<FunctionDef> &list, const char *functype, int type, int &paramsIndex);
+ void generateFunctions(const QVector<FunctionDef> &list, const char *functype, int type, int &paramsIndex, int &initialMetatypeOffset);
void generateFunctionRevisions(const QVector<FunctionDef> &list, const char *functype);
void generateFunctionParameters(const QVector<FunctionDef> &list, const char *functype);
void generateTypeInfo(const QByteArray &typeName, bool allowEmptyName = false);
@@ -70,6 +70,7 @@ private:
QVector<QByteArray> metaTypes;
QHash<QByteArray, QByteArray> knownQObjectClasses;
QHash<QByteArray, QByteArray> knownGadgets;
+ bool requireCompleteTypes;
};
QT_END_NAMESPACE
diff --git a/src/tools/moc/main.cpp b/src/tools/moc/main.cpp
index b8c2d7f594..61f3666b16 100644
--- a/src/tools/moc/main.cpp
+++ b/src/tools/moc/main.cpp
@@ -367,6 +367,10 @@ int runMoc(int argc, char **argv)
depFileRuleNameOption.setValueName(QStringLiteral("rule name"));
parser.addOption(depFileRuleNameOption);
+ QCommandLineOption requireCompleTypesOption(QStringLiteral("require-complete-types"));
+ requireCompleTypesOption.setDescription(QStringLiteral("Require complete types for better performance"));
+ parser.addOption(requireCompleTypesOption);
+
parser.addPositionalArgument(QStringLiteral("[header-file]"),
QStringLiteral("Header file to read from, otherwise stdin."));
parser.addPositionalArgument(QStringLiteral("[@option-file]"),
@@ -398,6 +402,8 @@ int runMoc(int argc, char **argv)
moc.noInclude = true;
autoInclude = false;
}
+ if (parser.isSet(requireCompleTypesOption))
+ moc.requireCompleteTypes = true;
if (!ignoreConflictingOptions) {
if (parser.isSet(forceIncludeOption)) {
moc.noInclude = false;
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index f04f4c5d0d..0ffbe7bb13 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -1125,7 +1125,7 @@ void Moc::generate(FILE *out, FILE *jsonOutput)
fputs("", out);
for (i = 0; i < classList.size(); ++i) {
- Generator generator(&classList[i], metaTypes, knownQObjectClasses, knownGadgets, out);
+ Generator generator(&classList[i], metaTypes, knownQObjectClasses, knownGadgets, out, requireCompleteTypes);
generator.generateCode();
}
fputs("", out);
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index 486d033049..84ddf47a89 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -224,13 +224,14 @@ class Moc : public Parser
{
public:
Moc()
- : noInclude(false), mustIncludeQPluginH(false)
+ : noInclude(false), mustIncludeQPluginH(false), requireCompleteTypes(false)
{}
QByteArray filename;
bool noInclude;
bool mustIncludeQPluginH;
+ bool requireCompleteTypes;
QByteArray includePath;
QVector<QByteArray> includeFiles;
QVector<ClassDef> classList;