diff options
author | Marcelo Lira <marcelo.lira@openbossa.org> | 2011-08-07 14:01:53 -0300 |
---|---|---|
committer | Hugo Parente Lima <hugo.pl@gmail.com> | 2012-03-09 19:10:18 -0300 |
commit | c956f7307362d8ea2f0c2658b5954264fbf2bc05 (patch) | |
tree | 442566271a03f8a28c647b10cf3a512bf512aefe | |
parent | 389dab874764823c7a4b7a0b8a257f001d83ec02 (diff) |
AbstractMetaClasses now hold the instantiation types for the templates they implement.
AbstractMetaClasses that are typedefs for template class instantiations
use to keep the template from where they derive, but didn't keep the
values used for the derivation. Now this is fixed, and with an unit test.
Reviewed by Luciano Wolf <luciano.wolf@openbossa.org>
Reviewed by Renato Araújo <renato.filho@openbossa.org>
-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 41e4abe..29a21a0 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 106aed1..5c1641c 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 a3a8def..2851d1c 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 cd32ac4..bfee774 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 a06a388..1b7267a 100644 --- a/tests/testtemplates.h +++ b/tests/testtemplates.h @@ -38,6 +38,7 @@ private slots: void testInheritanceFromContainterTemplate(); void testTemplateInheritanceMixedWithForwardDeclaration(); void testTemplateInheritanceMixedWithNamespaceAndForwardDeclaration(); + void testTypedefOfInstantiationOfTemplateClass(); }; #endif |