aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRenato Filho <renato.filho@openbossa.org>2010-04-20 19:56:45 -0300
committerRenato Filho <renato.filho@openbossa.org>2010-04-22 18:20:04 -0300
commitb24af354ea6f05253150179467aa77e7c999611e (patch)
treede838af180926b7bdfd9e912d515842410b06491
parentf0f1aa01139a073430eb2c5feb767dedc45d3b4f (diff)
Fixed argument policy propagate.
Reviewer: Hugo Parente Lima <hugo.lima@openbossa.org>, Luciano Wolf <luciano.wolf@openbossa.org>
-rw-r--r--cppgenerator.cpp106
-rw-r--r--cppgenerator.h3
-rw-r--r--tests/libsample/objecttype.h2
-rw-r--r--tests/libsample/objecttypelayout.h2
-rwxr-xr-xtests/samplebinding/objecttypelayout_test.py12
5 files changed, 77 insertions, 48 deletions
diff --git a/cppgenerator.cpp b/cppgenerator.cpp
index 68222adbe..1ec1e44e4 100644
--- a/cppgenerator.cpp
+++ b/cppgenerator.cpp
@@ -587,16 +587,9 @@ void CppGenerator::writeVirtualMethodNative(QTextStream &s, const AbstractMetaFu
writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::NativeCode, func, lastArg);
}
- // write ownership rules
- TypeSystem::Ownership ownership = func->ownership(func->ownerClass(), TypeSystem::TargetLangCode, 0);
- if (ownership == TypeSystem::CppOwnership) {
- s << INDENT << "// Return value ownership transference" << endl;
- s << INDENT << "SbkBaseWrapper_setOwnership("PYTHON_RETURN_VAR".object(), 0);" << endl;
- } else
- writeReturnValueHeuristics(s, func, "BindingManager::instance().retrieveWrapper(this)");
-
if (type)
s << INDENT << "return "CPP_RETURN_VAR";" << endl;
+
s << '}' << endl << endl;
}
@@ -1606,7 +1599,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
writeCodeSnips(s, snips, CodeSnip::End, TypeSystem::TargetLangCode, func, lastArg);
}
- writeParentChildManagement(s, func);
+ bool hasReturnPolicy = false;
// Ownership transference between C++ and Python.
QList<ArgumentModification> ownership_mods;
@@ -1631,6 +1624,9 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
break;
}
+ if (arg_mod.index == 0)
+ hasReturnPolicy = true;
+
// The default ownership does nothing. This is useful to avoid automatic heuristically
// based generation of code defining parenting.
if (arg_mod.ownerships[TypeSystem::TargetLangCode] == TypeSystem::DefaultOwnership)
@@ -1665,6 +1661,7 @@ void CppGenerator::writeMethodCall(QTextStream& s, const AbstractMetaFunction* f
s << func->minimalSignature() << arg_mod.index << "\", " << pyArgName << ");" << endl;
}
}
+ writeParentChildManagement(s, func, !hasReturnPolicy);
}
QStringList CppGenerator::getAncestorMultipleInheritance(const AbstractMetaClass* metaClass)
@@ -3067,58 +3064,78 @@ void CppGenerator::finishGeneration()
}
}
-void CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func)
+bool CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool useHeuristicPolicy)
{
const int numArgs = func->arguments().count();
const AbstractMetaClass* cppClass = func->ownerClass();
- bool ctorHeuristicEnabled = func->isConstructor() && useCtorHeuristic();
+ const AbstractMetaClass* dClass = func->declaringClass();
+ bool ctorHeuristicEnabled = func->isConstructor() && useCtorHeuristic() && useHeuristicPolicy;
- // -1 = return value
- // 0 = self
- // 1..n = func. args.
- for (int i = -1; i <= numArgs; ++i) {
- QString parentVariable;
- QString childVariable;
- ArgumentOwner argOwner = func->argumentOwner(cppClass, i);
- bool usePyArgs = getMinMaxArguments(func).second > 1 || func->isConstructor();
-
- ArgumentOwner::Action action = argOwner.action;
- int parentIndex = argOwner.index;
- int childIndex = i;
- if (ctorHeuristicEnabled && i > 0 && numArgs) {
- AbstractMetaArgument* arg = func->arguments().at(i-1);
- if (arg->argumentName() == "parent" && (arg->type()->isObject() || arg->type()->isQObject())) {
- action = ArgumentOwner::Add;
- parentIndex = i;
- childIndex = -1;
- }
+ QString parentVariable;
+ QString childVariable;
+ ArgumentOwner argOwner = func->argumentOwner(cppClass, argIndex);
+
+ if (argOwner.index == -2) //invalid
+ argOwner = func->argumentOwner(dClass, argIndex);
+
+ bool usePyArgs = getMinMaxArguments(func).second > 1 || func->isConstructor();
+
+ ArgumentOwner::Action action = argOwner.action;
+ int parentIndex = argOwner.index;
+ int childIndex = argIndex;
+ if (ctorHeuristicEnabled && argIndex > 0 && numArgs) {
+ AbstractMetaArgument* arg = func->arguments().at(argIndex-1);
+ if (arg->argumentName() == "parent" && (arg->type()->isObject() || arg->type()->isQObject())) {
+ action = ArgumentOwner::Add;
+ parentIndex = argIndex;
+ childIndex = -1;
}
+ }
- if (action != ArgumentOwner::Invalid) {
- if (!usePyArgs && i > 1)
- ReportHandler::warning("Argument index for parent tag out of bounds: "+func->signature());
+ if (action != ArgumentOwner::Invalid) {
+ if (!usePyArgs && argIndex > 1)
+ ReportHandler::warning("Argument index for parent tag out of bounds: "+func->signature());
+ if (action == ArgumentOwner::Remove) {
+ parentVariable = "Py_None";
+ } else {
if (parentIndex == 0)
parentVariable = PYTHON_RETURN_VAR;
else if (parentIndex == -1)
parentVariable = "self";
else
parentVariable = usePyArgs ? "pyargs["+QString::number(parentIndex-1)+"]" : "arg";
+ }
- if (argOwner.action == ArgumentOwner::Remove)
- childVariable = "0";
- else if (childIndex == 0)
- childVariable = PYTHON_RETURN_VAR;
- else if (childIndex == -1)
- childVariable = "self";
- else
- childVariable = usePyArgs ? "pyargs["+QString::number(childIndex-1)+"]" : "arg";
+ if (childIndex == 0)
+ childVariable = PYTHON_RETURN_VAR;
+ else if (childIndex == -1)
+ childVariable = "self";
+ else
+ childVariable = usePyArgs ? "pyargs["+QString::number(childIndex-1)+"]" : "arg";
- s << INDENT << "Shiboken::setParent(" << parentVariable << ", " << childVariable << ");\n";
+ s << INDENT << "Shiboken::setParent(" << parentVariable << ", " << childVariable << ");\n";
- }
+ return true;
+ }
+
+ if (argIndex == 0 && useHeuristicPolicy)
+ writeReturnValueHeuristics(s, func);
+
+ return false;
+}
+
+void CppGenerator::writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool useHeuristicForReturn)
+{
+ const int numArgs = func->arguments().count();
+ s << INDENT << "//CppGenerator::writeParentChildManagement" << endl;
+
+ // -1 = return value
+ // 0 = self
+ // 1..n = func. args.
+ for (int i = -1; i <= numArgs; ++i) {
+ writeParentChildManagement(s, func, i, i == 0 ? useHeuristicForReturn : true);
}
- writeReturnValueHeuristics(s, func);
}
void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self)
@@ -3126,7 +3143,6 @@ void CppGenerator::writeReturnValueHeuristics(QTextStream& s, const AbstractMeta
AbstractMetaType *type = func->type();
if (!useReturnValueHeuristic()
|| !func->ownerClass()
- || func->ownership(func->ownerClass(), TypeSystem::TargetLangCode, 0) != TypeSystem::InvalidOwnership
|| !type
|| func->isStatic()
|| !func->typeReplaced(0).isEmpty()) {
diff --git a/cppgenerator.h b/cppgenerator.h
index c9d24d246..b0a9e143e 100644
--- a/cppgenerator.h
+++ b/cppgenerator.h
@@ -153,7 +153,8 @@ private:
void writeExtendedToCppFunction(QTextStream& s, const TypeEntry* externalType, const QList<const AbstractMetaClass*>& conversions);
void writeExtendedConverterInitialization(QTextStream& s, const TypeEntry* externalType, const QList<const AbstractMetaClass*>& conversions);
- void writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func);
+ void writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, bool userHeuristicForReturn);
+ bool writeParentChildManagement(QTextStream& s, const AbstractMetaFunction* func, int argIndex, bool userHeuristicPolicy);
void writeReturnValueHeuristics(QTextStream& s, const AbstractMetaFunction* func, const QString& self = "self");
/**
* Returns the multiple inheritance initializer function for the given class.
diff --git a/tests/libsample/objecttype.h b/tests/libsample/objecttype.h
index b606dd818..0515ecc98 100644
--- a/tests/libsample/objecttype.h
+++ b/tests/libsample/objecttype.h
@@ -75,7 +75,7 @@ public:
void killChild(const Str& name);
void removeChild(ObjectType* child);
ObjectType* takeChild(ObjectType* child);
- ObjectType* takeChild(const Str& name);
+ virtual ObjectType* takeChild(const Str& name);
ObjectType* findChild(const Str& name);
Str objectName() const;
diff --git a/tests/libsample/objecttypelayout.h b/tests/libsample/objecttypelayout.h
index 5662ac339..1f05b7495 100644
--- a/tests/libsample/objecttypelayout.h
+++ b/tests/libsample/objecttypelayout.h
@@ -49,6 +49,8 @@ public:
virtual bool isLayoutType() { return true; }
static ObjectTypeLayout* create() { return new ObjectTypeLayout(); }
+
+ virtual ObjectType* takeChild(const Str& name) { return ObjectType::takeChild(name); }
private:
std::list<ObjectType*> m_objects;
diff --git a/tests/samplebinding/objecttypelayout_test.py b/tests/samplebinding/objecttypelayout_test.py
index 444ee8b5d..1e14e5a4a 100755
--- a/tests/samplebinding/objecttypelayout_test.py
+++ b/tests/samplebinding/objecttypelayout_test.py
@@ -35,6 +35,17 @@ from sample import *
class ObjectTypeLayoutTest(unittest.TestCase):
'''Test cases for ObjectTypeLayout class.'''
+ def testOwnershipOverride(self):
+ l = ObjectTypeLayout()
+
+ o1 = ObjectType(l)
+ o1.setObjectName('o1')
+
+ self.assertEqual(sys.getrefcount(o1), 3)
+ l.takeChild('o1')
+ self.assertEqual(sys.getrefcount(o1), 2)
+
+
def testSetNullLayout(self):
'''ObjectType.setLayout(0).'''
o2 = ObjectType()
@@ -281,7 +292,6 @@ class ObjectTypeLayoutTest(unittest.TestCase):
self.assertRaises(RuntimeError, l1.objectName)
self.assertRaises(RuntimeError, l2.objectName)
-
if __name__ == '__main__':
unittest.main()