diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2017-02-27 14:56:28 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2017-02-28 07:10:52 +0000 |
commit | a0f5f68f02b97e8eb8f2b2de1fa57354f9f2c711 (patch) | |
tree | 5fcdfb17d00ca0de9fc2d60be7514ead99cea241 /ApiExtractor | |
parent | 107cfc1677587bb9e21621af9b96168b3ff8dc0e (diff) |
AbstractMetaFunction: Make FunctionType enumeration more fine-grained
Add CopyConstructorFunction, MoveConstructorFunction,
AssignmentOperatorFunction and MoveAssignmentOperatorFunction.
Add code to determine the type at the bottom of
AbstractMetaBuilderPrivate::traverseFunction().
This prevents those special functions from appearing in the list
of conversions and operators, causing cyclic dependencies.
Task-number: PYSIDE-323
Change-Id: I57c24024cb949dfed96341172f85b67f9f82a17c
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'ApiExtractor')
-rw-r--r-- | ApiExtractor/abstractmetabuilder.cpp | 74 | ||||
-rw-r--r-- | ApiExtractor/abstractmetalang.cpp | 25 | ||||
-rw-r--r-- | ApiExtractor/abstractmetalang.h | 10 | ||||
-rw-r--r-- | ApiExtractor/tests/testabstractmetaclass.cpp | 44 | ||||
-rw-r--r-- | ApiExtractor/tests/testabstractmetaclass.h | 1 |
5 files changed, 109 insertions, 45 deletions
diff --git a/ApiExtractor/abstractmetabuilder.cpp b/ApiExtractor/abstractmetabuilder.cpp index 14e6b36..fbf62d3 100644 --- a/ApiExtractor/abstractmetabuilder.cpp +++ b/ApiExtractor/abstractmetabuilder.cpp @@ -1615,20 +1615,10 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, } } - // Can not use metaFunction->isCopyConstructor() because - // the function wasn't assigned to its owner class yet. - bool isCopyCtor = false; - if (metaFunction->isConstructor() && metaFunction->arguments().size() == 1) { - const AbstractMetaType* argType = metaFunction->arguments().first()->type(); - isCopyCtor = argType->isConstant() - && argType->referenceType() == LValueReference - && argType->typeEntry()->name() == metaFunction->name(); - } - - bool isInvalidDestructor = metaFunction->isDestructor() && metaFunction->isPrivate(); - bool isInvalidConstructor = metaFunction->isConstructor() - && ((metaFunction->isPrivate() && !isCopyCtor) || metaFunction->isInvalid()); - + const bool isInvalidDestructor = metaFunction->isDestructor() && metaFunction->isPrivate(); + const bool isInvalidConstructor = metaFunction->isConstructor() + && ((metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction) + || metaFunction->isInvalid()); if ((isInvalidDestructor || isInvalidConstructor) && !metaClass->hasNonPrivateConstructor()) { *metaClass += AbstractMetaAttributes::Final; @@ -1644,7 +1634,7 @@ void AbstractMetaBuilderPrivate::traverseFunctions(ScopeModelItem scopeItem, if (!metaFunction->isDestructor() && !metaFunction->isInvalid() - && !(metaFunction->isPrivate() && metaFunction->isConstructor() && !isCopyCtor)) { + && !(metaFunction->isPrivate() && metaFunction->functionType() == AbstractMetaFunction::ConstructorFunction)) { setupFunctionDefaults(metaFunction, metaClass); @@ -1923,8 +1913,13 @@ AbstractMetaFunction* AbstractMetaBuilderPrivate::traverseFunction(const AddedFu *metaFunction += AbstractMetaFunction::Static; if (metaFunction->name() == metaClass->name()) { metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction); - if (fargs.size() == 1 && fargs.first()->type()->typeEntry()->isCustom()) - metaFunction->setExplicit(true); + if (fargs.size() == 1) { + const TypeEntry *te = fargs.first()->type()->typeEntry(); + if (te->isCustom()) + metaFunction->setExplicit(true); + if (te->name() == metaFunction->name()) + metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); + } } else { metaFunction->setFunctionType(AbstractMetaFunction::NormalFunction); } @@ -2053,6 +2048,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel metaFunction->setInvalid(true); } else if (stripTemplateArgs(functionName) == strippedClassName) { metaFunction->setFunctionType(AbstractMetaFunction::ConstructorFunction); + // Check for Copy/Move down below metaFunction->setExplicit(functionItem->isExplicit()); metaFunction->setName(m_currentClass->name()); } else { @@ -2179,6 +2175,40 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(FunctionModel } fixArgumentNames(metaFunction); + + // Determine class special functions + if (m_currentClass && metaFunction->arguments().size() == 1) { + const AbstractMetaType *argType = metaFunction->arguments().first()->type(); + if (argType->typeEntry() == m_currentClass->typeEntry() && argType->indirections() == 0) { + if (metaFunction->isConstructor()) { + switch (argType->referenceType()) { + case NoReference: + metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); + break; + case LValueReference: + if (argType->isConstant()) + metaFunction->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); + break; + case RValueReference: + metaFunction->setFunctionType(AbstractMetaFunction::MoveConstructorFunction); + break; + } + } else if (metaFunction->name() == QLatin1String("operator=")) { + switch (argType->referenceType()) { + case NoReference: + metaFunction->setFunctionType(AbstractMetaFunction::AssignmentOperatorFunction); + break; + case LValueReference: + if (argType->isConstant()) + metaFunction->setFunctionType(AbstractMetaFunction::AssignmentOperatorFunction); + break; + case RValueReference: + metaFunction->setFunctionType(AbstractMetaFunction::MoveAssignmentOperatorFunction); + break; + } + } + } + } return metaFunction; } @@ -2975,13 +3005,9 @@ static AbstractMetaFunction* findCopyCtor(AbstractMetaClass* cls) functions << cls->queryFunctions(AbstractMetaClass::Visible); foreach (AbstractMetaFunction* f, functions) { - if (f->isConstructor() || f->name() == QLatin1String("operator=")) { - AbstractMetaArgumentList arguments = f->arguments(); - if (arguments.size() == 1) { - if (cls->typeEntry()->qualifiedCppName() == arguments.at(0)->type()->typeEntry()->qualifiedCppName()) - return f; - } - } + const AbstractMetaFunction::FunctionType t = f->functionType(); + if (t == AbstractMetaFunction::CopyConstructorFunction || t == AbstractMetaFunction::AssignmentOperatorFunction) + return f; } return 0; } diff --git a/ApiExtractor/abstractmetalang.cpp b/ApiExtractor/abstractmetalang.cpp index b1b7580..9a5b315 100644 --- a/ApiExtractor/abstractmetalang.cpp +++ b/ApiExtractor/abstractmetalang.cpp @@ -1062,10 +1062,8 @@ bool AbstractMetaFunction::isSubscriptOperator() const bool AbstractMetaFunction::isAssignmentOperator() const { - if (!isOperatorOverload()) - return false; - - return originalName() == QLatin1String("operator="); + return m_functionType == AssignmentOperatorFunction + || m_functionType == MoveAssignmentOperatorFunction; } bool AbstractMetaFunction::isOtherOperator() const @@ -1117,16 +1115,6 @@ bool AbstractMetaFunction::isVirtual() const return !isFinal() && !isSignal() && !isStatic() && !isFinalInCpp() && !isConstructor(); } -bool AbstractMetaFunction::isCopyConstructor() const -{ - if (!ownerClass() || !isConstructor() || arguments().count() != 1) - return false; - - const AbstractMetaType* type = arguments().first()->type(); - return type->typeEntry() == ownerClass()->typeEntry() && - type->isConstant() && type->referenceType() == LValueReference; -} - QString AbstractMetaFunction::modifiedName() const { if (m_cachedModifiedName.isEmpty()) { @@ -1425,7 +1413,8 @@ AbstractMetaFunctionList AbstractMetaClass::implicitConversions() const foreach (AbstractMetaFunction *f, list) { if ((f->actualMinimumArgumentCount() == 1 || f->arguments().size() == 1 || f->isConversionOperator()) && !f->isExplicit() - && !f->isCopyConstructor() + && f->functionType() != AbstractMetaFunction::CopyConstructorFunction + && f->functionType() != AbstractMetaFunction::MoveConstructorFunction && !f->isModifiedRemoved() && (f->originalAttributes() & Public)) { returned += f; @@ -2016,7 +2005,7 @@ bool AbstractMetaClass::hasConstructors() const bool AbstractMetaClass::hasCopyConstructor() const { foreach (const AbstractMetaFunction* ctor, queryFunctions(Constructors)) { - if (ctor->isCopyConstructor()) + if (ctor->functionType() == AbstractMetaFunction::CopyConstructorFunction) return true; } return false; @@ -2025,7 +2014,7 @@ bool AbstractMetaClass::hasCopyConstructor() const bool AbstractMetaClass::hasPrivateCopyConstructor() const { foreach (const AbstractMetaFunction* ctor, queryFunctions(Constructors)) { - if (ctor->isCopyConstructor() && ctor->isPrivate()) + if (ctor->functionType() == AbstractMetaFunction::CopyConstructorFunction && ctor->isPrivate()) return true; } return false; @@ -2058,7 +2047,7 @@ void AbstractMetaClass::addDefaultCopyConstructor(bool isPrivate) f->setOriginalName(name()); f->setName(name()); f->setOwnerClass(this); - f->setFunctionType(AbstractMetaFunction::ConstructorFunction); + f->setFunctionType(AbstractMetaFunction::CopyConstructorFunction); f->setDeclaringClass(this); AbstractMetaType* argType = new AbstractMetaType; diff --git a/ApiExtractor/abstractmetalang.h b/ApiExtractor/abstractmetalang.h index c54982d..1eba4be 100644 --- a/ApiExtractor/abstractmetalang.h +++ b/ApiExtractor/abstractmetalang.h @@ -791,6 +791,10 @@ class AbstractMetaFunction : public AbstractMetaAttributes public: enum FunctionType { ConstructorFunction, + CopyConstructorFunction, + MoveConstructorFunction, + AssignmentOperatorFunction, + MoveAssignmentOperatorFunction, DestructorFunction, NormalFunction, SignalFunction, @@ -914,7 +918,7 @@ public: bool isComparisonOperator() const; bool isLogicalOperator() const; bool isSubscriptOperator() const; - bool isAssignmentOperator() const; + bool isAssignmentOperator() const; // Assignment or move assignment bool isOtherOperator() const; /** @@ -930,7 +934,6 @@ public: // TODO: ths function *should* know if it is virtual // instead of asking to your implementing class. bool isVirtual() const; - bool isCopyConstructor() const; bool isThread() const; bool allowThread() const; QString modifiedName() const; @@ -1031,7 +1034,8 @@ public: } bool isConstructor() const { - return functionType() == ConstructorFunction; + return m_functionType == ConstructorFunction || m_functionType == CopyConstructorFunction + || m_functionType == MoveConstructorFunction; } bool isNormal() const { diff --git a/ApiExtractor/tests/testabstractmetaclass.cpp b/ApiExtractor/tests/testabstractmetaclass.cpp index ae9c8ea..ef02c4d 100644 --- a/ApiExtractor/tests/testabstractmetaclass.cpp +++ b/ApiExtractor/tests/testabstractmetaclass.cpp @@ -232,6 +232,50 @@ void TestAbstractMetaClass::testInnerClassOfAPolymorphicOne() QVERIFY(!classB->isPolymorphic()); } +void TestAbstractMetaClass::testSpecialFunctions() +{ + const char cppCode[] ="\ + struct A {\n\ + A();\n\ + A(const A&);\n\ + A &operator=(const A&);\n\ + };\n\ + struct B {\n\ + B();\n\ + B(B);\n\ + B &operator=(B);\n\ + };\n"; + const char xmlCode[] = "\ + <typesystem package=\"Foo\">\n\ + <object-type name='A'/>\n\ + <object-type name='B'/>\n\ + </typesystem>\n"; + + TestUtil t(cppCode, xmlCode); + AbstractMetaClassList classes = t.builder()->classes(); + QCOMPARE(classes.count(), 2); + + const AbstractMetaClass *classA = classes.findClass(QLatin1String("A")); + QVERIFY(classA); + AbstractMetaFunctionList ctors = classA->queryFunctions(AbstractMetaClass::Constructors); + QCOMPARE(ctors.size(), 2); + QCOMPARE(ctors.first()->functionType(), AbstractMetaFunction::ConstructorFunction); + QCOMPARE(ctors.at(1)->functionType(), AbstractMetaFunction::CopyConstructorFunction); + AbstractMetaFunctionList assigmentOps = classA->queryFunctionsByName(QLatin1String("operator=")); + QCOMPARE(assigmentOps.size(), 1); + QCOMPARE(assigmentOps.first()->functionType(), AbstractMetaFunction::AssignmentOperatorFunction); + + const AbstractMetaClass *classB = classes.findClass(QLatin1String("B")); + QVERIFY(classB); + ctors = classB->queryFunctions(AbstractMetaClass::Constructors); + QCOMPARE(ctors.size(), 2); + QCOMPARE(ctors.first()->functionType(), AbstractMetaFunction::ConstructorFunction); + QCOMPARE(ctors.at(1)->functionType(), AbstractMetaFunction::CopyConstructorFunction); + assigmentOps = classA->queryFunctionsByName(QLatin1String("operator=")); + QCOMPARE(assigmentOps.size(), 1); + QCOMPARE(assigmentOps.first()->functionType(), AbstractMetaFunction::AssignmentOperatorFunction); +} + void TestAbstractMetaClass::testClassDefaultConstructors() { const char* cppCode ="\ diff --git a/ApiExtractor/tests/testabstractmetaclass.h b/ApiExtractor/tests/testabstractmetaclass.h index 1f12739..089347f 100644 --- a/ApiExtractor/tests/testabstractmetaclass.h +++ b/ApiExtractor/tests/testabstractmetaclass.h @@ -43,6 +43,7 @@ private slots: void testDefaultValues(); void testModifiedDefaultValues(); void testInnerClassOfAPolymorphicOne(); + void testSpecialFunctions(); void testClassDefaultConstructors(); void testClassInheritedDefaultConstructors(); void testAbstractClassDefaultConstructors(); |