summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMilian Wolff <milian.wolff@kdab.com>2019-04-12 13:21:44 +0200
committerMilian Wolff <milian.wolff@kdab.com>2019-12-12 13:02:52 +0100
commit656d6f2a9b221dbd5adfc46262cb243e696d8d62 (patch)
treee1fc6f21e2cc1999ef18be3e97a8f09ebb5b1e47
parent83818431e15e36ad9c8484cee33475ba00731d6f (diff)
Support Q_GADGET QMetaObject super class hierarchies across templates
This patch fixes the QMetaObject::superClass hierarchy for Q_GADGETs that inherit from a template which in turn inherits another Q_GADGET. One common scenario where this is applied is for the CRTP. Without this patch, moc would stop at the template and then sets the superClass QMetaObject to a nullptr. For QObjects this works, since there moc knows that every child must by definition inherit QObject. In order to support this for Q_GADGETs too, we defer the judgment about the availability of a staticMetaObject in the base class to compile time through the existing QtPrivate::MetaObjectForType<Base>::value() helper. [ChangeLog][QtCore][moc] Moc now correctly sets a non-null QMetaObject::superClass for Q_GADGETs that inherit from a template which inherits another Q_GADGET. Change-Id: I103b5efd74ed24172dffce477ca2ed6d0f374d44 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
-rw-r--r--src/tools/moc/generator.cpp4
-rw-r--r--tests/auto/tools/moc/allmocs_baseline_in.json11
-rw-r--r--tests/auto/tools/moc/grand-parent-gadget-class.h3
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp1
4 files changed, 17 insertions, 2 deletions
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index 553e16d472..9029bf9008 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -541,8 +541,10 @@ void Generator::generateCode()
if (isQObject)
fprintf(out, " nullptr,\n");
- else if (cdef->superclassList.size() && (!cdef->hasQGadget || knownGadgets.contains(purestSuperClass)))
+ else if (cdef->superclassList.size() && !cdef->hasQGadget) // for qobject, we know the super class must have a static metaobject
fprintf(out, " QMetaObject::SuperData::link<%s::staticMetaObject>(),\n", purestSuperClass.constData());
+ else if (cdef->superclassList.size()) // for gadgets we need to query at compile time for it
+ fprintf(out, " QtPrivate::MetaObjectForType<%s>::value(),\n", purestSuperClass.constData());
else
fprintf(out, " nullptr,\n");
fprintf(out, " qt_meta_stringdata_%s.data,\n"
diff --git a/tests/auto/tools/moc/allmocs_baseline_in.json b/tests/auto/tools/moc/allmocs_baseline_in.json
index bde5a1c52b..8cb397190c 100644
--- a/tests/auto/tools/moc/allmocs_baseline_in.json
+++ b/tests/auto/tools/moc/allmocs_baseline_in.json
@@ -2061,6 +2061,17 @@
"name": "Derived"
}
]
+ },
+ {
+ "className": "CRTPDerivedGadget",
+ "gadget": true,
+ "qualifiedClassName": "GrandParentGadget::CRTPDerivedGadget",
+ "superClasses": [
+ {
+ "access": "public",
+ "name": "CRTP<CRTPDerivedGadget>"
+ }
+ ]
}
],
"inputFile": "grand-parent-gadget-class.h",
diff --git a/tests/auto/tools/moc/grand-parent-gadget-class.h b/tests/auto/tools/moc/grand-parent-gadget-class.h
index 7ffd636ca1..c7720a1ab9 100644
--- a/tests/auto/tools/moc/grand-parent-gadget-class.h
+++ b/tests/auto/tools/moc/grand-parent-gadget-class.h
@@ -36,7 +36,8 @@ namespace GrandParentGadget {
struct BaseGadget { Q_GADGET };
struct Derived : BaseGadget {};
struct DerivedGadget : Derived { Q_GADGET };
-
+template<typename T> struct CRTP : BaseGadget {};
+struct CRTPDerivedGadget : CRTP<CRTPDerivedGadget> { Q_GADGET };
}
#endif // GRANDPARENTGADGETCLASS_H
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
index 9fc00288fe..6b202f79a6 100644
--- a/tests/auto/tools/moc/tst_moc.cpp
+++ b/tests/auto/tools/moc/tst_moc.cpp
@@ -3836,6 +3836,7 @@ void tst_Moc::gadgetHierarchy()
{
QCOMPARE(NonGadgetParent::Derived::staticMetaObject.superClass(), static_cast<const QMetaObject*>(nullptr));
QCOMPARE(GrandParentGadget::DerivedGadget::staticMetaObject.superClass(), &GrandParentGadget::BaseGadget::staticMetaObject);
+ QCOMPARE(GrandParentGadget::CRTPDerivedGadget::staticMetaObject.superClass(), &GrandParentGadget::BaseGadget::staticMetaObject);
}
void tst_Moc::optionsFileError_data()