From 28da24d29cfc5137a4cf1940c9fa45d519334e17 Mon Sep 17 00:00:00 2001 From: Renato Filho Date: Thu, 22 Jul 2010 18:01:54 -0300 Subject: Fixed memory leak. Reviewer: Marcelo Lira Luciano Wolf --- abstractmetabuilder.cpp | 57 ++++++++++++++++++++--------- abstractmetabuilder.h | 2 +- abstractmetalang.cpp | 96 ++++++++++++++++++++++++------------------------- abstractmetalang.h | 75 +++++++++++++++++++++++++++----------- tests/testtemplates.cpp | 4 +-- typesystem.cpp | 4 +-- typesystem.h | 8 ++--- 7 files changed, 151 insertions(+), 95 deletions(-) diff --git a/abstractmetabuilder.cpp b/abstractmetabuilder.cpp index 01c9e7619..b02a60fbb 100644 --- a/abstractmetabuilder.cpp +++ b/abstractmetabuilder.cpp @@ -61,7 +61,10 @@ AbstractMetaBuilder::AbstractMetaBuilder() : m_currentClass(0), m_logDirectory(Q AbstractMetaBuilder::~AbstractMetaBuilder() { + qDeleteAll(m_globalEnums); qDeleteAll(m_globalFunctions); + qDeleteAll(m_templates); + qDeleteAll(m_metaClasses); } void AbstractMetaBuilder::checkFunctionModifications() @@ -190,6 +193,7 @@ void AbstractMetaBuilder::traverseOperatorFunction(FunctionModelItem item) baseoperandClass = m_metaClasses.findClass(retType); firstArgumentIsSelf = false; } + delete type; } if (baseoperandClass) { @@ -200,7 +204,8 @@ void AbstractMetaBuilder::traverseOperatorFunction(FunctionModelItem item) // Strip away first argument, since that is the containing object AbstractMetaArgumentList arguments = metaFunction->arguments(); if (firstArgumentIsSelf || unaryOperator) { - arguments.pop_front(); + AbstractMetaArgument *first = arguments.takeFirst(); + delete first; metaFunction->setArguments(arguments); } else { // If the operator method is not unary and the first operator is @@ -208,7 +213,9 @@ void AbstractMetaBuilder::traverseOperatorFunction(FunctionModelItem item) // must be an reverse operator (e.g. CLASS::operator(TYPE, CLASS)). // All operator overloads that operate over a class are already // being added as member functions of that class by the API Extractor. - arguments.pop_back(); + AbstractMetaArgument *last = arguments.takeLast(); + delete last; + metaFunction->setArguments(arguments); metaFunction->setReverseOperator(true); } @@ -244,9 +251,9 @@ void AbstractMetaBuilder::traverseStreamOperator(FunctionModelItem item) // Strip first argument, since that is the containing object AbstractMetaArgumentList arguments = streamFunction->arguments(); if (!streamClass->typeEntry()->generateCode()) - arguments.pop_back(); + delete arguments.takeLast(); else - arguments.pop_front(); + delete arguments.takeFirst(); streamFunction->setArguments(arguments); @@ -275,7 +282,10 @@ void AbstractMetaBuilder::traverseStreamOperator(FunctionModelItem item) funcClass->typeEntry()->addExtraInclude(streamClass->typeEntry()->include()); m_currentClass = oldCurrentClass; + } else if (streamFunction) { + delete streamFunction; } + } } } @@ -420,6 +430,9 @@ bool AbstractMetaBuilder::build(QIODevice* input) } setInclude(funcEntry, func->fileName()); + if (metaFunc->typeEntry()) + delete metaFunc->typeEntry(); + metaFunc->setTypeEntry(funcEntry); m_globalFunctions << metaFunc; } @@ -1285,7 +1298,7 @@ void AbstractMetaBuilder::fixReturnTypeOfConversionOperator(AbstractMetaFunction AbstractMetaType* metaType = createMetaType(); metaType->setTypeEntry(retType); - metaFunction->setType(metaType); + metaFunction->replaceType(metaType); } void AbstractMetaBuilder::traverseFunctions(ScopeModelItem scopeItem, AbstractMetaClass* metaClass) @@ -1362,12 +1375,16 @@ void AbstractMetaBuilder::traverseFunctions(ScopeModelItem scopeItem, AbstractMe fixReturnTypeOfConversionOperator(metaFunction); metaClass->addFunction(metaFunction); + applyFunctionModifications(metaFunction); } else if (metaFunction->isDestructor()) { metaClass->setHasPrivateDestructor(metaFunction->isPrivate()); metaClass->setHasProtectedDestructor(metaFunction->isProtected()); metaClass->setHasVirtualDestructor(metaFunction->isVirtual()); } - applyFunctionModifications(metaFunction); + if (!metaFunction->ownerClass()) { + delete metaFunction; + metaFunction = 0; + } } } @@ -1387,7 +1404,6 @@ void AbstractMetaBuilder::traverseFunctions(ScopeModelItem scopeItem, AbstractMe func->setImplementingClass(metaClass); metaClass->addFunction(func); } - } void AbstractMetaBuilder::applyFunctionModifications(AbstractMetaFunction* func) @@ -1692,6 +1708,7 @@ AbstractMetaFunction* AbstractMetaBuilder::traverseFunction(FunctionModelItem fu AbstractMetaType* type = translateType(functionType, &ok); if (!ok) { + Q_ASSERT(type == 0); ReportHandler::warning(QString("skipping function '%1::%2', unmatched return type '%3'") .arg(className) .arg(functionItem->name()) @@ -1716,7 +1733,7 @@ AbstractMetaFunction* AbstractMetaBuilder::traverseFunction(FunctionModelItem fu ArgumentModelItem arg = arguments.at(0); TypeInfo type = arg->type(); if (type.qualifiedName().first() == "void" && type.indirections() == 0) - arguments.removeFirst(); + delete arguments.takeFirst(); } AbstractMetaArgumentList metaArguments; @@ -1727,7 +1744,8 @@ AbstractMetaFunction* AbstractMetaBuilder::traverseFunction(FunctionModelItem fu bool ok; AbstractMetaType* metaType = translateType(arg->type(), &ok); - if (!metaType || !ok) { + if (!ok) { + Q_ASSERT(metaType == 0); ReportHandler::warning(QString("skipping function '%1::%2', " "unmatched parameter type '%3'") .arg(className) @@ -1806,8 +1824,10 @@ AbstractMetaType* AbstractMetaBuilder::translateType(double vr, const AddedFunct return 0; type = typeDb->findType(typeInfo.name); - if (!type) + if (!type) { type = new TypeEntry(typeInfo.name, TypeEntry::CustomType, vr); + typeDb->addType(type); + } metaType->setTypeEntry(type); metaType->setIndirections(typeInfo.indirections); @@ -1840,6 +1860,7 @@ AbstractMetaType* AbstractMetaBuilder::translateType(const TypeInfo& _typei, boo AbstractMetaType* t = translateType(_typei, &ok, false, resolveScope); if (t && ok) return t; + Q_ASSERT(t == 0); } if (!resolveType) { @@ -2029,7 +2050,7 @@ AbstractMetaType* AbstractMetaBuilder::translateType(const TypeInfo& _typei, boo return 0; } - metaType->addInstantiation(targType); + metaType->addInstantiation(targType, true); } return metaType; @@ -2266,7 +2287,7 @@ bool AbstractMetaBuilder::ancestorHasPrivateCopyConstructor(const AbstractMetaCl } AbstractMetaType* AbstractMetaBuilder::inheritTemplateType(const QList& templateTypes, - AbstractMetaType* metaType, bool* ok) + const AbstractMetaType* metaType, bool* ok) { if (ok) *ok = true; @@ -2299,13 +2320,14 @@ AbstractMetaType* AbstractMetaBuilder::inheritTemplateType(const QListhasInstantiations()) { - QList instantiations = returned->instantiations(); + AbstractMetaTypeList instantiations = returned->instantiations(); for (int i = 0; i < instantiations.count(); ++i) { - instantiations[i] = inheritTemplateType(templateTypes, instantiations.at(i), ok); + AbstractMetaType *type = instantiations[i]; + instantiations[i] = inheritTemplateType(templateTypes, type, ok); if (ok && !(*ok)) return 0; } - returned->setInstantiations(instantiations); + returned->setInstantiations(instantiations, true); } return returned; @@ -2370,7 +2392,7 @@ bool AbstractMetaBuilder::inheritTemplate(AbstractMetaClass* subclass, bool ok = true; AbstractMetaType *ftype = function->type(); - f->setType(inheritTemplateType(templateTypes, ftype, &ok)); + f->replaceType(inheritTemplateType(templateTypes, ftype, &ok)); if (!ok) { delete f; continue; @@ -2380,7 +2402,7 @@ bool AbstractMetaBuilder::inheritTemplate(AbstractMetaClass* subclass, AbstractMetaType* atype = argument->type(); AbstractMetaArgument *arg = argument->copy(); - arg->setType(inheritTemplateType(templateTypes, atype, &ok)); + arg->replaceType(inheritTemplateType(templateTypes, atype, &ok)); if (!ok) break; f->addArgument(arg); @@ -2726,6 +2748,7 @@ AbstractMetaClassList AbstractMetaBuilder::classesTopologicalSorted(const Abstra result << reverseMap[i]; } } + return result; } diff --git a/abstractmetabuilder.h b/abstractmetabuilder.h index 487cadefe..8b2900974 100644 --- a/abstractmetabuilder.h +++ b/abstractmetabuilder.h @@ -167,7 +167,7 @@ public: bool inheritTemplate(AbstractMetaClass *subclass, const AbstractMetaClass *templateClass, const TypeParser::Info &info); - AbstractMetaType *inheritTemplateType(const QList &templateTypes, AbstractMetaType *metaType, bool *ok = 0); + AbstractMetaType *inheritTemplateType(const QList &templateTypes, const AbstractMetaType *metaType, bool *ok = 0); bool isQObject(const QString &qualifiedName); bool isEnum(const QStringList &qualifiedName); diff --git a/abstractmetalang.cpp b/abstractmetalang.cpp index 4c0b27662..ed6278ec7 100644 --- a/abstractmetalang.cpp +++ b/abstractmetalang.cpp @@ -25,9 +25,43 @@ #include "reporthandler.h" #include "typedatabase.h" +/******************************************************************************* + * AbstractMetaVariable + */ + +AbstractMetaVariable::AbstractMetaVariable(const AbstractMetaVariable &other) +{ + m_originalName = other.m_originalName; + m_name = other.m_name; + m_type = other.m_type->copy(); + m_hasName = other.m_hasName; + m_doc = other.m_doc; +} + /******************************************************************************* * AbstractMetaType */ + +AbstractMetaType::AbstractMetaType() + :m_typeEntry(0), + m_arrayElementCount(0), + m_arrayElementType(0), + m_originalTemplateType(0), + m_pattern(InvalidPattern), + m_constant(false), + m_reference(false), + m_cppInstantiation(true), + m_indirections(0), + m_reserved(0) +{ +} + +AbstractMetaType::~AbstractMetaType() +{ + qDeleteAll(m_children); + m_instantiations.clear(); +} + AbstractMetaType *AbstractMetaType::copy() const { AbstractMetaType *cpy = new AbstractMetaType; @@ -58,12 +92,12 @@ QString AbstractMetaType::cppSignature() const s += typeEntry()->qualifiedCppName(); if (hasInstantiationInCpp()) { - QList types = instantiations(); + AbstractMetaTypeList types = instantiations(); s += "<"; for (int i = 0; i < types.count(); ++i) { if (i > 0) s += ", "; - s += types.at(i)->cppSignature(); + s += types[i]->cppSignature(); } s += " >"; } @@ -78,14 +112,13 @@ QString AbstractMetaType::cppSignature() const return s; } + /******************************************************************************* * AbstractMetaArgument */ AbstractMetaArgument *AbstractMetaArgument::copy() const { - AbstractMetaArgument* cpy = new AbstractMetaArgument(*this); - cpy->setType(type()->copy()); - return cpy; + return new AbstractMetaArgument(*this); } /******************************************************************************* @@ -930,6 +963,8 @@ AbstractMetaClass::~AbstractMetaClass() { qDeleteAll(m_functions); qDeleteAll(m_fields); + qDeleteAll(m_enums); + qDeleteAll(m_orphanInterfaces); } /******************************************************************************* @@ -984,6 +1019,7 @@ AbstractMetaClass *AbstractMetaClass::extractInterface() m_extractedInterface = iface; addInterface(iface); + m_orphanInterfaces << iface; } return m_extractedInterface; @@ -1301,6 +1337,8 @@ void AbstractMetaClass::addFunction(AbstractMetaFunction *function) if (!function->isDestructor()) m_functions << function; + else + Q_ASSERT(false); //memory leak m_hasVirtualSlots |= function->isVirtualSlot(); m_hasVirtuals |= !function->isFinal() || function->isVirtualSlot() || hasVirtualDestructor(); @@ -1717,8 +1755,6 @@ AbstractMetaFunctionList AbstractMetaClass::queryFunctions(uint query) const functions << f; } -// qDebug() << "queried" << m_typeEntry->qualifiedCppName() << "got" << functions.size() << "out of" << m_functions.size(); - return functions; } @@ -1865,9 +1901,9 @@ static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractM } if (type->hasInstantiations()) { - QList instantiations = type->instantiations(); - foreach (AbstractMetaType *instantiation, instantiations) - addExtraIncludeForType(metaClass, instantiation); + AbstractMetaTypeList instantiations = type->instantiations(); + foreach (const AbstractMetaType *instantiation, instantiations) + addExtraIncludeForType(metaClass, instantiation); } } @@ -1892,14 +1928,10 @@ void AbstractMetaClass::fixFunctions() AbstractMetaClass *superClass = baseClass(); AbstractMetaFunctionList funcs = functions(); -// printf("fix functions for %s\n", qPrintable(name())); - if (superClass) superClass->fixFunctions(); int iface_idx = 0; while (superClass || iface_idx < interfaces().size()) { -// printf(" - base: %s\n", qPrintable(super_class->name())); - // Since we always traverse the complete hierarchy we are only // interrested in what each super class implements, not what // we may have propagated from their base classes again. @@ -1937,35 +1969,16 @@ void AbstractMetaClass::fixFunctions() uint cmp = f->compareTo(sf); if (cmp & AbstractMetaFunction::EqualModifiedName) { -// printf(" - %s::%s similar to %s::%s %x vs %x\n", -// qPrintable(sf->implementingClass()->typeEntry()->qualifiedCppName()), -// qPrintable(sf->name()), -// qPrintable(f->implementingClass()->typeEntry()->qualifiedCppName()), -// qPrintable(f->name()), -// sf->attributes(), -// f->attributes()); - add = false; if (cmp & AbstractMetaFunction::EqualArguments) { - -// if (!(cmp & AbstractMetaFunction::EqualReturnType)) { -// ReportHandler::warning(QString("%1::%2 and %3::%4 differ in retur type") -// .arg(sf->implementingClass()->name()) -// .arg(sf->name()) -// .arg(f->implementingClass()->name()) -// .arg(f->name())); -// } - // Same function, propegate virtual... if (!(cmp & AbstractMetaFunction::EqualAttributes)) { if (!f->isEmptyFunction()) { if (!sf->isFinalInCpp() && f->isFinalInCpp()) { *f -= AbstractMetaAttributes::FinalInCpp; - // printf(" --- inherit virtual\n"); } if (!sf->isFinalInTargetLang() && f->isFinalInTargetLang()) { *f -= AbstractMetaAttributes::FinalInTargetLang; - // printf(" --- inherit virtual\n"); } #if 0 if (!f->isFinalInTargetLang() && f->isPrivate()) { @@ -1997,7 +2010,6 @@ void AbstractMetaClass::fixFunctions() // But they don't need to be implemented, since they can never be called. if (f->isPrivate()) { f->setFunctionType(AbstractMetaFunction::EmptyFunction); -// f->setVisibility(sf->visibility()); *f += AbstractMetaAttributes::FinalInTargetLang; *f += AbstractMetaAttributes::FinalInCpp; } @@ -2078,8 +2090,6 @@ void AbstractMetaClass::fixFunctions() FunctionModificationList mods = func->modifications(this); foreach (const FunctionModification &mod, mods) { if (mod.isRenameModifier()) { -// qDebug() << name() << func->originalName() << func << " from " -// << func->implementingClass()->name() << "renamed to" << mod.renamedTo(); func->setName(mod.renamedTo()); } } @@ -2118,16 +2128,6 @@ void AbstractMetaClass::fixFunctions() && !f1->isFinalInCpp() && f2->isFinalInCpp()) { *f2 += AbstractMetaAttributes::FinalOverload; -// qDebug() << f2 << f2->implementingClass()->name() << "::" << f2->name() << f2->arguments().size() << " vs " << f1 << f1->implementingClass()->name() << "::" << f1->name() << f1->arguments().size(); -// qDebug() << " " << f2; -// AbstractMetaArgumentList f2Args = f2->arguments(); -// foreach (AbstractMetaArgument *a, f2Args) -// qDebug() << " " << a->type()->name() << a->name(); -// qDebug() << " " << f1; -// AbstractMetaArgumentList f1Args = f1->arguments(); -// foreach (AbstractMetaArgument *a, f1Args) -// qDebug() << " " << a->type()->name() << a->name(); - } } } @@ -2144,12 +2144,12 @@ QString AbstractMetaType::minimalSignature() const minimalSignature += "const "; minimalSignature += typeEntry()->qualifiedCppName(); if (hasInstantiations()) { - QList instantiations = this->instantiations(); + AbstractMetaTypeList instantiations = this->instantiations(); minimalSignature += "< "; for (int i = 0; i < instantiations.size(); ++i) { if (i > 0) minimalSignature += ","; - minimalSignature += instantiations.at(i)->minimalSignature(); + minimalSignature += instantiations[i]->minimalSignature(); } minimalSignature += " >"; } diff --git a/abstractmetalang.h b/abstractmetalang.h index ed7157c83..c502dd16e 100644 --- a/abstractmetalang.h +++ b/abstractmetalang.h @@ -29,6 +29,7 @@ #include #include #include +#include class AbstractMeta; @@ -290,10 +291,11 @@ private: Documentation m_doc; }; - +typedef QList AbstractMetaTypeList; class APIEXTRACTOR_API AbstractMetaType { public: + enum TypeUsagePattern { InvalidPattern, PrimitivePattern, @@ -314,18 +316,8 @@ public: ThreadPattern }; - AbstractMetaType() : - m_typeEntry(0), - m_arrayElementCount(0), - m_arrayElementType(0), - m_originalTemplateType(0), - m_pattern(InvalidPattern), - m_constant(false), - m_reference(false), - m_cppInstantiation(true), - m_indirections(0), - m_reserved(0) - {} + AbstractMetaType(); + ~AbstractMetaType(); QString package() const { @@ -354,18 +346,28 @@ public: { return !m_instantiations.isEmpty(); } - void addInstantiation(AbstractMetaType *inst) + + void addInstantiation(AbstractMetaType* inst, bool owner = false) { + if (owner) + m_children << inst; m_instantiations << inst; } - void setInstantiations(const QList &insts) + + void setInstantiations(const AbstractMetaTypeList &insts, bool owner = false) { m_instantiations = insts; + if (owner) { + m_children.clear(); + m_children = insts; + } } - QList instantiations() const + + AbstractMetaTypeList instantiations() const { return m_instantiations; } + void setInstantiationInCpp(bool incpp) { m_cppInstantiation = incpp; @@ -545,11 +547,11 @@ public: return m_arrayElementCount; } - AbstractMetaType *arrayElementType() const + const AbstractMetaType *arrayElementType() const { return m_arrayElementType; } - void setArrayElementType(AbstractMetaType *t) + void setArrayElementType(const AbstractMetaType *t) { m_arrayElementType = t; } @@ -587,12 +589,12 @@ public: private: const TypeEntry *m_typeEntry; - QList m_instantiations; + AbstractMetaTypeList m_instantiations; QString m_package; QString m_originalTypeDescription; int m_arrayElementCount; - AbstractMetaType *m_arrayElementType; + const AbstractMetaType *m_arrayElementType; const AbstractMetaType *m_originalTemplateType; TypeUsagePattern m_pattern; @@ -601,12 +603,21 @@ private: uint m_cppInstantiation : 1; int m_indirections : 4; uint m_reserved : 25; // unused + AbstractMetaTypeList m_children; + + Q_DISABLE_COPY(AbstractMetaType); }; class APIEXTRACTOR_API AbstractMetaVariable { public: AbstractMetaVariable() : m_type(0), m_hasName(false) {} + AbstractMetaVariable(const AbstractMetaVariable &other); + + virtual ~AbstractMetaVariable() + { + delete m_type; + } AbstractMetaType *type() const { @@ -614,6 +625,13 @@ public: } void setType(AbstractMetaType *type) { + Q_ASSERT(m_type == 0); + m_type = type; + } + void replaceType(AbstractMetaType *type) + { + if (m_type) + delete m_type; m_type = type; } @@ -891,6 +909,14 @@ public: } void setType(AbstractMetaType *type) { + Q_ASSERT(m_type == 0); + m_type = type; + } + + void replaceType(AbstractMetaType *type) + { + if (m_type) + delete m_type; m_type = type; } @@ -1211,6 +1237,10 @@ class AbstractMetaEnum : public AbstractMetaAttributes { public: AbstractMetaEnum() : m_typeEntry(0), m_class(0), m_hasQenumsDeclaration(false) {} + ~AbstractMetaEnum() + { + qDeleteAll(m_enumValues); + } AbstractMetaEnumValueList values() const { @@ -1355,7 +1385,8 @@ public: m_typeEntry(0), //m_qDebugStreamFunction(0) m_stream(false) - {} + { + } virtual ~AbstractMetaClass(); @@ -1865,6 +1896,7 @@ private: AbstractMetaFieldList m_fields; AbstractMetaEnumList m_enums; AbstractMetaClassList m_interfaces; + AbstractMetaClassList m_orphanInterfaces; AbstractMetaClass *m_extractedInterface; AbstractMetaClass *m_primaryInterfaceImplementor; QList m_propertySpecs; @@ -1885,6 +1917,7 @@ private: // FunctionModelItem m_qDebugStreamFunction; bool m_stream; + static int m_count; }; class QPropertySpec diff --git a/tests/testtemplates.cpp b/tests/testtemplates.cpp index d0ea40e3d..4ec550998 100644 --- a/tests/testtemplates.cpp +++ b/tests/testtemplates.cpp @@ -101,11 +101,11 @@ void TestTemplates::testTemplateOnContainers() QCOMPARE(argType->instantiations().count(), 1); QCOMPARE(argType->typeEntry()->qualifiedCppName(), QString("QList")); - AbstractMetaType* instance1 = argType->instantiations().first(); + const AbstractMetaType* instance1 = argType->instantiations().first(); QCOMPARE(instance1->instantiations().count(), 1); QCOMPARE(instance1->typeEntry()->qualifiedCppName(), QString("Namespace::A")); - AbstractMetaType* instance2 = instance1->instantiations().first(); + const AbstractMetaType* instance2 = instance1->instantiations().first(); QCOMPARE(instance2->instantiations().count(), 0); QCOMPARE(instance2->typeEntry()->qualifiedCppName(), QString("Namespace::E1")); } diff --git a/typesystem.cpp b/typesystem.cpp index 82c903eb2..31c4f547e 100644 --- a/typesystem.cpp +++ b/typesystem.cpp @@ -1735,8 +1735,8 @@ QString TemplateInstance::expandCode() const QString CodeSnipAbstract::code() const { QString res; - foreach (CodeSnipFragment *codeFrag, codeList) - res.append(codeFrag->code()); + foreach (CodeSnipFragment codeFrag, codeList) + res.append(codeFrag.code()); return res; } diff --git a/typesystem.h b/typesystem.h index 7c5363e96..a5c954a9c 100644 --- a/typesystem.h +++ b/typesystem.h @@ -114,7 +114,7 @@ struct ArgumentOwner class APIEXTRACTOR_API CodeSnipFragment { private: - const QString m_code; + QString m_code; TemplateInstance *m_instance; public: @@ -135,15 +135,15 @@ public: void addCode(const QString &code) { - codeList.append(new CodeSnipFragment(code)); + codeList.append(CodeSnipFragment(code)); } void addTemplateInstance(TemplateInstance *ti) { - codeList.append(new CodeSnipFragment(ti)); + codeList.append(CodeSnipFragment(ti)); } - QList codeList; + QList codeList; }; class CustomFunction : public CodeSnipAbstract -- cgit v1.2.3