aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarcelo Lira <marcelo.lira@openbossa.org>2011-08-07 14:01:53 -0300
committerHugo Parente Lima <hugo.pl@gmail.com>2012-03-09 19:10:18 -0300
commitc956f7307362d8ea2f0c2658b5954264fbf2bc05 (patch)
tree442566271a03f8a28c647b10cf3a512bf512aefe
parent389dab874764823c7a4b7a0b8a257f001d83ec02 (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.cpp5
-rw-r--r--abstractmetalang.cpp26
-rw-r--r--abstractmetalang.h4
-rw-r--r--tests/testtemplates.cpp53
-rw-r--r--tests/testtemplates.h1
5 files changed, 84 insertions, 5 deletions
diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp
index 41e4abe9..29a21a05 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 106aed1a..5c1641c4 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 a3a8def6..2851d1c7 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 cd32ac4a..bfee774d 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 a06a388b..1b7267af 100644
--- a/tests/testtemplates.h
+++ b/tests/testtemplates.h
@@ -38,6 +38,7 @@ private slots:
void testInheritanceFromContainterTemplate();
void testTemplateInheritanceMixedWithForwardDeclaration();
void testTemplateInheritanceMixedWithNamespaceAndForwardDeclaration();
+ void testTypedefOfInstantiationOfTemplateClass();
};
#endif