From 714ddb6c74b4db4853ca2e34bb50f2888e75ec8d Mon Sep 17 00:00:00 2001 From: Marcelo Lira Date: Sat, 6 Aug 2011 17:28:00 -0300 Subject: The type checking now pays attention to the tag. An unit test was also added for it. --- generator/cppgenerator.cpp | 16 +++++++++++----- generator/cppgenerator.h | 2 +- generator/shibokengenerator.cpp | 19 +++++++++++++++++++ generator/shibokengenerator.h | 3 +++ tests/libsample/modifications.cpp | 6 ++++++ tests/libsample/modifications.h | 4 ++++ tests/samplebinding/modifications_test.py | 5 +++++ tests/samplebinding/typesystem_sample.xml | 5 +++++ 8 files changed, 54 insertions(+), 6 deletions(-) diff --git a/generator/cppgenerator.cpp b/generator/cppgenerator.cpp index 44d62f4f6..70290253d 100644 --- a/generator/cppgenerator.cpp +++ b/generator/cppgenerator.cpp @@ -1469,7 +1469,7 @@ void CppGenerator::writeInvalidPyObjectCheck(QTextStream& s, const QString& pyOb s << INDENT << "return " << m_currentErrorCode << ';' << endl; } -void CppGenerator::writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber, QString customType) +void CppGenerator::writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber, QString customType, bool rejectNull) { AbstractMetaType* metaType; std::auto_ptr metaType_autoptr; @@ -1482,12 +1482,17 @@ void CppGenerator::writeTypeCheck(QTextStream& s, const AbstractMetaType* argTyp } } + QString typeCheck; if (customCheck.isEmpty()) - s << cpythonIsConvertibleFunction(argType, argType->isEnum() ? false : isNumber); + typeCheck = cpythonIsConvertibleFunction(argType, argType->isEnum() ? false : isNumber); else - s << customCheck; + typeCheck = customCheck; + typeCheck.append(QString("(%1)").arg(argumentName)); - s << '(' << argumentName << ')'; + if (rejectNull) + typeCheck = QString("(%1 != Py_None && %2)").arg(argumentName).arg(typeCheck); + + s << typeCheck; } void CppGenerator::writeTypeCheck(QTextStream& s, const OverloadData* overloadData, QString argumentName) @@ -1510,7 +1515,8 @@ void CppGenerator::writeTypeCheck(QTextStream& s, const OverloadData* overloadDa const AbstractMetaType* argType = overloadData->argType(); bool numberType = numericTypes.count() == 1 || ShibokenGenerator::isPyInt(argType); QString customType = (overloadData->hasArgumentTypeReplace() ? overloadData->argumentTypeReplaced() : ""); - writeTypeCheck(s, argType, argumentName, numberType, customType); + bool rejectNull = shouldRejectNullPointerArgument(overloadData->referenceFunction(), overloadData->argPos()); + writeTypeCheck(s, argType, argumentName, numberType, customType, rejectNull); } void CppGenerator::writeArgumentConversion(QTextStream& s, diff --git a/generator/cppgenerator.h b/generator/cppgenerator.h index 4dea57bd2..f0548931e 100644 --- a/generator/cppgenerator.h +++ b/generator/cppgenerator.h @@ -65,7 +65,7 @@ private: /// Writes the check section for the validity of wrapped C++ objects. void writeInvalidPyObjectCheck(QTextStream& s, const QString& pyObj); - void writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber = false, QString customType = ""); + void writeTypeCheck(QTextStream& s, const AbstractMetaType* argType, QString argumentName, bool isNumber = false, QString customType = "", bool rejectNull = false); void writeTypeCheck(QTextStream& s, const OverloadData* overloadData, QString argumentName); void writeTypeDiscoveryFunction(QTextStream& s, const AbstractMetaClass* metaClass); diff --git a/generator/shibokengenerator.cpp b/generator/shibokengenerator.cpp index 17cd31a91..54e5b2a2e 100644 --- a/generator/shibokengenerator.cpp +++ b/generator/shibokengenerator.cpp @@ -595,6 +595,25 @@ void ShibokenGenerator::writeToCppConversion(QTextStream& s, const AbstractMetaT s << "toCpp(" << argumentName << ')'; } +bool ShibokenGenerator::shouldRejectNullPointerArgument(const AbstractMetaFunction* func, int argIndex) +{ + if (argIndex < 0 || argIndex >= func->arguments().count()) + return false; + // Argument type is not a pointer, a None rejection should not be + // necessary because the type checking would handle that already. + if (!isPointer(func->arguments().at(argIndex)->type())) + return false; + if (func->argumentRemoved(argIndex + 1)) + return false; + foreach (FunctionModification funcMod, func->modifications()) { + foreach (ArgumentModification argMod, funcMod.argument_mods) { + if (argMod.index == argIndex + 1 && argMod.noNullPointers) + return true; + } + } + return false; +} + QString ShibokenGenerator::getFormatUnitString(const AbstractMetaFunction* func, bool incRef) const { QString result; diff --git a/generator/shibokengenerator.h b/generator/shibokengenerator.h index 729dc0bc0..3139399e3 100644 --- a/generator/shibokengenerator.h +++ b/generator/shibokengenerator.h @@ -234,6 +234,9 @@ public: const AbstractMetaClass* context, const QString& argumentName, Options options = NoOption); void writeToCppConversion(QTextStream& s, const AbstractMetaClass* metaClass, const QString& argumentName); + /// Returns true if the argument is a pointer that rejects NULL values. + static bool shouldRejectNullPointerArgument(const AbstractMetaFunction* func, int argIndex); + /// Verifies if the class should have a C++ wrapper generated for it, instead of only a Python wrapper. bool shouldGenerateCppWrapper(const AbstractMetaClass* metaClass) const; diff --git a/tests/libsample/modifications.cpp b/tests/libsample/modifications.cpp index 72c3f40ed..739ca5c74 100644 --- a/tests/libsample/modifications.cpp +++ b/tests/libsample/modifications.cpp @@ -103,3 +103,9 @@ Modifications::getSize(const void* data, int size) (void)data; return size; } + +int +Modifications::sumPointCoordinates(const Point* point) +{ + return point->x() + point->y(); +} diff --git a/tests/libsample/modifications.h b/tests/libsample/modifications.h index 1b6fb8240..c7a7748c6 100644 --- a/tests/libsample/modifications.h +++ b/tests/libsample/modifications.h @@ -98,6 +98,10 @@ public: // Replace 'const void*' by 'ByteArray&'. int getSize(const void* data, int size); + + // Mark the argument with a tag; + // the test implementation must expect point never to be null. + int sumPointCoordinates(const Point* point); }; class LIBSAMPLE_API AbstractModifications : public Modifications diff --git a/tests/samplebinding/modifications_test.py b/tests/samplebinding/modifications_test.py index b37d74635..344801015 100644 --- a/tests/samplebinding/modifications_test.py +++ b/tests/samplebinding/modifications_test.py @@ -143,5 +143,10 @@ class ModificationsTest(unittest.TestCase): self.assertEqual(self.mods.getSize(ba), len(ba)) self.assertEqual(self.mods.getSize(ba, 20), 20) + def testNoNulPointerTag(self): + point = Point(12, 34) + self.assertEqual(self.mods.sumPointCoordinates(point), 12 + 34) + self.assertRaises(TypeError, self.mods.sumPointCoordinates, None) + if __name__ == '__main__': unittest.main() diff --git a/tests/samplebinding/typesystem_sample.xml b/tests/samplebinding/typesystem_sample.xml index add18c289..3e910ccc6 100644 --- a/tests/samplebinding/typesystem_sample.xml +++ b/tests/samplebinding/typesystem_sample.xml @@ -714,6 +714,11 @@ %PYARG_0 = %CONVERTTOPYTHON[%RETURN_TYPE](%0); + + + + + -- cgit v1.2.3