diff options
-rw-r--r-- | abstractmetabuilder.cpp | 5 | ||||
-rw-r--r-- | abstractmetalang.cpp | 26 | ||||
-rw-r--r-- | abstractmetalang.h | 4 | ||||
-rw-r--r-- | tests/testtemplates.cpp | 53 | ||||
-rw-r--r-- | tests/testtemplates.h | 1 |
5 files changed, 84 insertions, 5 deletions
diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp index 41e4abe9e..29a21a051 100644 --- a/abstractmetabuilder.cpp +++ b/abstractmetabuilder.cpp @@ -2564,11 +2564,8 @@ bool AbstractMetaBuilder::inheritTemplate(AbstractMetaClass* subclass, subclass->addFunction(f); } - // Clean up - foreach (AbstractMetaType *type, templateTypes) - delete type; - subclass->setTemplateBaseClass(templateClass); + subclass->setTemplateBaseClassInstantiations(templateTypes); subclass->setInterfaces(templateClass->interfaces()); subclass->setBaseClass(templateClass->baseClass()); diff --git a/abstractmetalang.cpp b/abstractmetalang.cpp index 106aed1a0..5c1641c42 100644 --- a/abstractmetalang.cpp +++ b/abstractmetalang.cpp @@ -1065,6 +1065,10 @@ AbstractMetaClass::~AbstractMetaClass() qDeleteAll(m_fields); qDeleteAll(m_enums); qDeleteAll(m_orphanInterfaces); + if (hasTemplateBaseClassInstantiations()) { + foreach (AbstractMetaType* inst, templateBaseClassInstantiations()) + delete inst; + } } /******************************************************************************* @@ -1544,7 +1548,29 @@ QPropertySpec *AbstractMetaClass::propertySpecForReset(const QString &name) cons return 0; } +typedef QHash<const AbstractMetaClass*, AbstractMetaTypeList> AbstractMetaClassBaseTemplateInstantiationsMap; +Q_GLOBAL_STATIC(AbstractMetaClassBaseTemplateInstantiationsMap, metaClassBaseTemplateInstantiations); + +bool AbstractMetaClass::hasTemplateBaseClassInstantiations() const +{ + if (!templateBaseClass()) + return false; + return metaClassBaseTemplateInstantiations()->contains(this); +} +AbstractMetaTypeList AbstractMetaClass::templateBaseClassInstantiations() const +{ + if (!templateBaseClass()) + return AbstractMetaTypeList(); + return metaClassBaseTemplateInstantiations()->value(this); +} + +void AbstractMetaClass::setTemplateBaseClassInstantiations(AbstractMetaTypeList& instantiations) +{ + if (!templateBaseClass()) + return; + metaClassBaseTemplateInstantiations()->insert(this, instantiations); +} static bool functions_contains(const AbstractMetaFunctionList &l, const AbstractMetaFunction *func) { diff --git a/abstractmetalang.h b/abstractmetalang.h index a3a8def6d..2851d1c70 100644 --- a/abstractmetalang.h +++ b/abstractmetalang.h @@ -1874,6 +1874,10 @@ public: m_templateBaseClass = cls; } + bool hasTemplateBaseClassInstantiations() const; + AbstractMetaTypeList templateBaseClassInstantiations() const; + void setTemplateBaseClassInstantiations(AbstractMetaTypeList& instantiations); + void setTypeAlias(bool typeAlias) { m_isTypeAlias = typeAlias; diff --git a/tests/testtemplates.cpp b/tests/testtemplates.cpp index cd32ac4ac..bfee774d6 100644 --- a/tests/testtemplates.cpp +++ b/tests/testtemplates.cpp @@ -285,7 +285,58 @@ void TestTemplates::testTemplateInheritanceMixedWithNamespaceAndForwardDeclarati QCOMPARE(classB->functions().count(), 3); } +void TestTemplates::testTypedefOfInstantiationOfTemplateClass() +{ + const char cppCode[] = "\ + namespace NSpace {\ + enum ClassType {\ + TypeOne\ + };\ + template<ClassType CLASS_TYPE>\ + struct BaseTemplateClass {\ + inline ClassType getClassType() const { CLASS_TYPE; }\ + };\ + typedef BaseTemplateClass<TypeOne> TypeOneClass;\ + }\ + "; + + const char xmlCode[] = "\ + <typesystem package='Package'>\ + <namespace-type name='NSpace'>\ + <enum-type name='ClassType'/>\ + <object-type name='BaseTemplateClass' generate='no'/>\ + <object-type name='TypeOneClass'/>\ + </namespace-type>\ + </typesystem>\ + "; + + TestUtil t(cppCode, xmlCode, false); + AbstractMetaClassList classes = t.builder()->classes(); + QCOMPARE(classes.count(), 3); + + const AbstractMetaClass* base = classes.findClass("BaseTemplateClass"); + QVERIFY(base); + const AbstractMetaClass* one = classes.findClass("TypeOneClass"); + QVERIFY(one); + QCOMPARE(one->templateBaseClass(), base); + QCOMPARE(one->functions().count(), base->functions().count()); + QVERIFY(one->isTypeAlias()); + const ComplexTypeEntry* oneType = one->typeEntry(); + const ComplexTypeEntry* baseType = base->typeEntry(); + QCOMPARE(oneType->baseContainerType(), baseType); + QCOMPARE(one->baseClassNames(), QStringList("BaseTemplateClass<TypeOne>")); + + QVERIFY(one->hasTemplateBaseClassInstantiations()); + AbstractMetaTypeList instantiations = one->templateBaseClassInstantiations(); + QCOMPARE(instantiations.count(), 1); + const AbstractMetaType* inst = instantiations.first(); + QVERIFY(inst); + QVERIFY(!inst->isEnum()); + QVERIFY(!inst->typeEntry()->isEnum()); + QVERIFY(inst->typeEntry()->isEnumValue()); + QCOMPARE(inst->cppSignature(), QString("NSpace::TypeOne")); +} + QTEST_APPLESS_MAIN(TestTemplates) #include "testtemplates.moc" - diff --git a/tests/testtemplates.h b/tests/testtemplates.h index a06a388b5..1b7267af4 100644 --- a/tests/testtemplates.h +++ b/tests/testtemplates.h @@ -38,6 +38,7 @@ private slots: void testInheritanceFromContainterTemplate(); void testTemplateInheritanceMixedWithForwardDeclaration(); void testTemplateInheritanceMixedWithNamespaceAndForwardDeclaration(); + void testTypedefOfInstantiationOfTemplateClass(); }; #endif |