aboutsummaryrefslogtreecommitdiffstats
path: root/ApiExtractor
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2017-02-27 14:56:28 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2017-02-28 07:10:52 +0000
commita0f5f68f02b97e8eb8f2b2de1fa57354f9f2c711 (patch)
tree5fcdfb17d00ca0de9fc2d60be7514ead99cea241 /ApiExtractor
parent107cfc1677587bb9e21621af9b96168b3ff8dc0e (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.cpp74
-rw-r--r--ApiExtractor/abstractmetalang.cpp25
-rw-r--r--ApiExtractor/abstractmetalang.h10
-rw-r--r--ApiExtractor/tests/testabstractmetaclass.cpp44
-rw-r--r--ApiExtractor/tests/testabstractmetaclass.h1
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();