diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2017-04-13 15:29:02 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2017-04-13 15:29:05 +0200 |
commit | dfc22cb270cb94bf28dd0bc0eabae3267418113e (patch) | |
tree | 090faff2a10725e99003be9e4a312ce86c98b877 | |
parent | 60985b97fa181fd897c4d87542943e325493fd6b (diff) | |
parent | 3461108126a4a9be1e566e644e9063a8ef44c1cb (diff) |
Merge remote-tracking branch 'origin/5.9' into dev
Change-Id: Ib3be5d174442af28a36b51a715c347c245706264
-rw-r--r-- | ApiExtractor/abstractmetalang.cpp | 9 | ||||
-rw-r--r-- | ApiExtractor/abstractmetalang.h | 7 | ||||
-rw-r--r-- | ApiExtractor/abstractmetalang_typedefs.h | 3 | ||||
-rw-r--r-- | CMakeLists.txt | 108 | ||||
-rw-r--r-- | cmake/Modules/FindPythonInterpWithDebug.cmake | 57 | ||||
-rw-r--r-- | generator/shiboken2/cppgenerator.cpp | 18 | ||||
-rw-r--r-- | generator/shiboken2/shibokengenerator.cpp | 51 | ||||
-rw-r--r-- | generator/shiboken2/shibokengenerator.h | 21 |
8 files changed, 152 insertions, 122 deletions
diff --git a/ApiExtractor/abstractmetalang.cpp b/ApiExtractor/abstractmetalang.cpp index a309088..4fa009f 100644 --- a/ApiExtractor/abstractmetalang.cpp +++ b/ApiExtractor/abstractmetalang.cpp @@ -2647,15 +2647,6 @@ AbstractMetaEnum *AbstractMetaClass::findEnum(const AbstractMetaClassList &class return metaClass->findEnum(enumName); } -AbstractMetaEnumValue *AbstractMetaEnumValueList::find(const QString &name) const -{ - for (int i = 0; i < size(); ++i) { - if (name == at(i)->name()) - return at(i); - } - return 0; -} - AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const AbstractMetaClassList &classes, const QString &name) { diff --git a/ApiExtractor/abstractmetalang.h b/ApiExtractor/abstractmetalang.h index 082e55c..4d6d5fb 100644 --- a/ApiExtractor/abstractmetalang.h +++ b/ApiExtractor/abstractmetalang.h @@ -1293,13 +1293,6 @@ private: Documentation m_doc; }; - -class AbstractMetaEnumValueList : public QVector<AbstractMetaEnumValue *> -{ -public: - AbstractMetaEnumValue *find(const QString &name) const; -}; - class AbstractMetaEnum : public AbstractMetaAttributes { public: diff --git a/ApiExtractor/abstractmetalang_typedefs.h b/ApiExtractor/abstractmetalang_typedefs.h index 1081902..da83698 100644 --- a/ApiExtractor/abstractmetalang_typedefs.h +++ b/ApiExtractor/abstractmetalang_typedefs.h @@ -35,13 +35,14 @@ class AbstractMetaClass; class AbstractMetaField; class AbstractMetaArgument; class AbstractMetaEnum; -class AbstractMetaEnumValueList; +class AbstractMetaEnumValue; class AbstractMetaFunction; class AbstractMetaType; typedef QVector<AbstractMetaArgument *> AbstractMetaArgumentList; typedef QVector<AbstractMetaClass *> AbstractMetaClassList; typedef QVector<AbstractMetaEnum *> AbstractMetaEnumList; +typedef QVector<AbstractMetaEnumValue *> AbstractMetaEnumValueList; typedef QVector<AbstractMetaField *> AbstractMetaFieldList; typedef QVector<AbstractMetaFunction *> AbstractMetaFunctionList; typedef QVector<AbstractMetaType *> AbstractMetaTypeList; diff --git a/CMakeLists.txt b/CMakeLists.txt index 496210e..dae9999 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -50,50 +50,94 @@ set(CLANG_EXTRA_INCLUDES ${CLANG_DIR}/include) set(CLANG_EXTRA_LIBRARIES ${CLANG_LIBRARY}) ## For debugging the PYTHON* variables -#message("PYTHONLIBS_FOUND: " ${PYTHONLIBS_FOUND}) -#message("PYTHON_LIBRARIES: " ${PYTHON_LIBRARIES}) -#message("PYTHON_INCLUDE_DIRS: " ${PYTHON_INCLUDE_DIRS}) -#message("PYTHON_DEBUG_LIBRARIES: " ${PYTHON_DEBUG_LIBRARIES}) -#message("PYTHONINTERP_FOUND: " ${PYTHONINTERP_FOUND}) -#message("PYTHON_EXECUTABLE: " ${PYTHON_EXECUTABLE}) -#message("PYTHON_VERSION_MAJOR: " ${PYTHON_VERSION_MAJOR}) -#message("PYTHON_VERSION_MINOR: " ${PYTHON_VERSION_MINOR}) -#message("PYTHON_VERSION_PATCH: " ${PYTHON_VERSION_PATCH}) +message("PYTHONLIBS_FOUND: " ${PYTHONLIBS_FOUND}) +message("PYTHON_LIBRARIES: " ${PYTHON_LIBRARIES}) +message("PYTHON_INCLUDE_DIRS: " ${PYTHON_INCLUDE_DIRS}) +message("PYTHON_DEBUG_LIBRARIES: " ${PYTHON_DEBUG_LIBRARIES}) +message("PYTHONINTERP_FOUND: " ${PYTHONINTERP_FOUND}) +message("PYTHON_EXECUTABLE: " ${PYTHON_EXECUTABLE}) +message("PYTHON_VERSION: " ${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.${PYTHON_VERSION_PATCH}) + +# Queries the python sysconfig for the abi flags which need to be inserted into extension suffixes. +# Only present starting with Python 3.2. +# Corresponding configure switches to single letter flags: +# --with-pymalloc -> m +# --with-pydebug -> d +# --with-unicode -> u (rare) +macro(get_python3_abi_flags) + if (NOT PYTHON_ABI_FLAGS) + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "if True: + import sysconfig + print(sysconfig.get_config_var('abiflags')) + " + OUTPUT_VARIABLE PYTHON_ABI_FLAGS + OUTPUT_STRIP_TRAILING_WHITESPACE) + endif() + message("PYTHON_ABI_FLAGS: " ${PYTHON_ABI_FLAGS}) +endmacro() -if (UNIX AND NOT APPLE) - # TODO: This part needs more testing first to be available on OSX and WIN - # Also note the quirk that UNIX includes Apple! +macro(get_python_multi_arch_suffix) + # TODO: This part needs testing to check if it is available on Windows. + # It is present on macOS, but is not used yet. + # Result is something like 'x86_64-linux-gnu'. if (NOT PYTHON_MULTIARCH_SUFFIX) execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "if True: - import sysconfig - print(sysconfig.get_config_var('MULTIARCH')) - " - OUTPUT_VARIABLE PYTHON_MULTIARCH_SUFFIX - OUTPUT_STRIP_TRAILING_WHITESPACE) + COMMAND ${PYTHON_EXECUTABLE} -c "if True: + import sysconfig + print(sysconfig.get_config_var('MULTIARCH')) + " + OUTPUT_VARIABLE PYTHON_MULTIARCH_SUFFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) endif() - + message("PYTHON_MULTIARCH_SUFFIX: " ${PYTHON_MULTIARCH_SUFFIX}) +endmacro() + +macro(get_python2_release_suffix) + # Result of imp.get_suffixes() is something like: + # [('_d.so', 'rb', 3), ('module_d.so', 'rb', 3), ('.x86_64-linux-gnu_d.so', 'rb', 3)] + # or alternatively the same but withut the '_d' part. + # The list comprehension is used to choose which suffix to include in library names. + execute_process( + COMMAND ${PYTHON_EXECUTABLE} -c "if True: + import imp + print('_d' if any([tup[0].endswith('_d.so') for tup in imp.get_suffixes()]) else '') + " + OUTPUT_VARIABLE PYTHON_MODULE_RELEASE_SUFFIX + OUTPUT_STRIP_TRAILING_WHITESPACE) + message("PYTHON_MODULE_RELEASE_SUFFIX: " ${PYTHON_MODULE_RELEASE_SUFFIX}) +endmacro() + +# Note the quirk that UNIX includes Apple! +if (UNIX AND NOT APPLE) if (NOT PYTHON_EXTENSION_SUFFIX) + get_python_multi_arch_suffix() + # The suffix added to .so libraries should be differenet between Python 2 and 3. + # The position of the multiarch suffix is different, and the way the debug flag is set + # computed differently. + # In Python 2 there is no standard way to query if the python interpeter was built in debug or + # release build (sysconfig.get_config_var('Py_Debug') can have a different value than you would + # expect if you do a custom Python build). The solution is to query for the import + # suffixes and check if _d is present there. It is present on Linux distribution + # packages of Python, but not in custom built Python builds, because the distros apply their + # custom patches too append the '_d's. + # In Python 3 (starting with 3.2) there is a standard way to check if '_d' needs to be added, + # as well as any other letters, by querying the abiflags sysconfig variable. if (PYTHON_VERSION_MAJOR EQUAL 2) - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(PYTHON_RELEASE_SUFFIX "-dbg") - else() - set(PYTHON_RELEASE_SUFFIX "") + get_python2_release_suffix() + if(PYTHON_MULTIARCH_SUFFIX) + set(PYTHON_EXTENSION_SUFFIX ".${PYTHON_MULTIARCH_SUFFIX}") endif() - set(PYTHON_EXTENSION_SUFFIX "-python${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}${PYTHON_RELEASE_SUFFIX}") + set(PYTHON_EXTENSION_SUFFIX "${PYTHON_EXTENSION_SUFFIX}${PYTHON_MODULE_RELEASE_SUFFIX}") elseif (PYTHON_VERSION_MAJOR EQUAL 3) - if(CMAKE_BUILD_TYPE STREQUAL "Debug") - set(PYTHON_RELEASE_SUFFIX "dm") - else() - set(PYTHON_RELEASE_SUFFIX "m") + get_python3_abi_flags() + set(PYTHON_EXTENSION_SUFFIX ".cpython-${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}${PYTHON_ABI_FLAGS}") + if(PYTHON_MULTIARCH_SUFFIX) + set(PYTHON_EXTENSION_SUFFIX "${PYTHON_EXTENSION_SUFFIX}-${PYTHON_MULTIARCH_SUFFIX}") endif() - set(PYTHON_EXTENSION_SUFFIX ".cpython-${PYTHON_VERSION_MAJOR}${PYTHON_VERSION_MINOR}${PYTHON_RELEASE_SUFFIX}") else() message(FATAL_ERROR "Unsupported PYTHON_VERSION=${PYTHON_VERSION_MAJOR}.${PYTHON_VERSION_MINOR}.${PYTHON_VERSION_PATCH}!") endif() - if(PYTHON_MULTIARCH_SUFFIX) - set(PYTHON_EXTENSION_SUFFIX "${PYTHON_EXTENSION_SUFFIX}-${PYTHON_MULTIARCH_SUFFIX}") - endif() endif() message(STATUS "PYTHON_EXTENSION_SUFFIX: ${PYTHON_EXTENSION_SUFFIX}") endif () diff --git a/cmake/Modules/FindPythonInterpWithDebug.cmake b/cmake/Modules/FindPythonInterpWithDebug.cmake deleted file mode 100644 index df01366..0000000 --- a/cmake/Modules/FindPythonInterpWithDebug.cmake +++ /dev/null @@ -1,57 +0,0 @@ -find_program(PYTHON_EXECUTABLE NAMES python3.6 python3.5 python3.4 python3.3 python3.2 python2.7 python2.6 python2.5) - -if (NOT PYTHON_EXECUTABLE) - find_package(PythonInterp REQUIRED) -else() - set(PYTHONINTERP_FOUND 1) -endif() - -if (PYTHONINTERP_FOUND AND UNIX AND CMAKE_BUILD_TYPE STREQUAL "Debug") - # This is for Debian - set(PYTHON_EXECUTABLE_TMP "${PYTHON_EXECUTABLE}-dbg") - - if (NOT EXISTS "${PYTHON_EXECUTABLE_TMP}") - # On Fedora we usually have the suffix as debug. As we didn't - # find python interpreter with the suffix dbg we'll fall back - # to the suffix as debug. - set(PYTHON_EXECUTABLE_TMP "${PYTHON_EXECUTABLE}-debug") - endif() - # Falling back to the standard interpreter. - if (NOT EXISTS "${PYTHON_EXECUTABLE_TMP}") - set(PYTHON_EXECUTABLE_TMP "${PYTHON_EXECUTABLE}") - endif() - - set(PYTHON_EXECUTABLE "${PYTHON_EXECUTABLE_TMP}") -endif() - -# Detect if the python libs were compiled in debug mode -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "if True: - from distutils import sysconfig - print(bool(sysconfig.get_config_var('Py_DEBUG'))) - " - OUTPUT_VARIABLE PYTHON_WITH_DEBUG - OUTPUT_STRIP_TRAILING_WHITESPACE) - -execute_process( - COMMAND ${PYTHON_EXECUTABLE} -c "if True: - import sys - from distutils import sysconfig - vr = sys.version_info - suffix = '-dbg' if bool(sysconfig.get_config_var('Py_DEBUG')) else '' - print('-python%d.%d%s' % (vr[0], vr[1], suffix)) - " - OUTPUT_VARIABLE PYTHON_SUFFIX - OUTPUT_STRIP_TRAILING_WHITESPACE) - -# Fix missing variable on UNIX env -if (NOT PYTHON_DEBUG_LIBRARIES AND UNIX) - string(REPLACE "-dbg" "" PYTHON_NAME_TMP ${PYTHON_SUFFIX}) - string(REPLACE "-python" "python" PYTHON_NAME ${PYTHON_NAME_TMP}) - find_library(LIBRARY_FOUND ${PYTHON_NAME}_d) - if (LIBRARY_FOUND) - set(PYTHON_DEBUG_LIBRARIES "${LIBRARY_FOUND}") - else() - set(PYTHON_DEBUG_LIBRARIES "${PYTHON_LIBRARIES}") - endif() -endif() diff --git a/generator/shiboken2/cppgenerator.cpp b/generator/shiboken2/cppgenerator.cpp index 85829ab..28a0e4b 100644 --- a/generator/shiboken2/cppgenerator.cpp +++ b/generator/shiboken2/cppgenerator.cpp @@ -368,6 +368,7 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) const FunctionGroupMap &functionGroups = getFunctionGroups(metaClass); for (FunctionGroupMapIt it = functionGroups.cbegin(), end = functionGroups.cend(); it != end; ++it) { AbstractMetaFunctionList overloads; + QSet<QString> seenSignatures; for (AbstractMetaFunction *func : it.value()) { if (!func->isAssignmentOperator() && !func->usesRValueReferences() @@ -375,8 +376,12 @@ void CppGenerator::generateClass(QTextStream &s, GeneratorContext &classContext) && !func->isModifiedRemoved() && (!func->isPrivate() || func->functionType() == AbstractMetaFunction::EmptyFunction) && func->ownerClass() == func->implementingClass() - && (func->name() != QLatin1String("qt_metacall"))) - overloads.append(func); + && (func->name() != QLatin1String("qt_metacall"))) { + // PYSIDE-331: Inheritance works correctly when there are disjoint functions. + // But when a function is both in a class and inherited in a subclass, + // then we need to search through all subclasses and collect the new signatures. + overloads << getFunctionAndInheritedOverloads(func, &seenSignatures); + } } if (overloads.isEmpty()) @@ -3160,6 +3165,9 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f if (func->isStatic()) { mc << "::" << methodCallClassName << "::"; } else { + const QString selfVarCast = func->ownerClass() == func->implementingClass() + ? QLatin1String(CPP_SELF_VAR) + : QLatin1String("reinterpret_cast<") + methodCallClassName + QLatin1String(" *>(" CPP_SELF_VAR ")"); if (func->isConstant()) { if (avoidProtectedHack()) { mc << "const_cast<const ::"; @@ -3167,13 +3175,13 @@ void CppGenerator::writeMethodCall(QTextStream &s, const AbstractMetaFunction *f mc << wrapperName(func->ownerClass()); else mc << methodCallClassName; - mc << "*>(" CPP_SELF_VAR ")->"; + mc << "*>(" << selfVarCast << ")->"; } else { mc << "const_cast<const ::" << methodCallClassName; - mc << "*>(" CPP_SELF_VAR ")->"; + mc << "*>(" << selfVarCast << ")->"; } } else { - mc << CPP_SELF_VAR "->"; + mc << selfVarCast << "->"; } } diff --git a/generator/shiboken2/shibokengenerator.cpp b/generator/shiboken2/shibokengenerator.cpp index 1437e17..ffce283 100644 --- a/generator/shiboken2/shibokengenerator.cpp +++ b/generator/shiboken2/shibokengenerator.cpp @@ -354,8 +354,10 @@ QString ShibokenGenerator::cpythonFunctionName(const AbstractMetaFunction* func) { QString result; - if (func->ownerClass()) { - result = cpythonBaseName(func->ownerClass()->typeEntry()); + // PYSIDE-331: For inherited functions, we need to find the same labels. + // Therefore we use the implementing class. + if (func->implementingClass()) { + result = cpythonBaseName(func->implementingClass()->typeEntry()); if (func->isConstructor()) { result += QLatin1String("_Init"); } else { @@ -426,8 +428,11 @@ static QString searchForEnumScope(const AbstractMetaClass* metaClass, const QStr return metaClass->qualifiedCppName(); } } - - return searchForEnumScope(metaClass->enclosingClass(), enumValueName); + // PYSIDE-331: We need to also search the base classes. + QString ret = searchForEnumScope(metaClass->enclosingClass(), enumValueName); + if (ret.isEmpty()) + ret = searchForEnumScope(metaClass->baseClass(), enumValueName); + return ret; } /* @@ -787,12 +792,12 @@ QString ShibokenGenerator::converterObject(const TypeEntry* type) return QString::fromLatin1("Shiboken::Conversions::PrimitiveTypeConverter<%1>()").arg(type->qualifiedCppName()); if (isWrapperType(type) || type->isEnum() || type->isFlags()) return QString::fromLatin1("SBK_CONVERTER(%1)").arg(cpythonTypeNameExt(type)); - + if (type->isArray()) { qDebug() << "Warning: no idea how to handle the Qt5 type " << type->qualifiedCppName(); return QString::null; } - + /* the typedef'd primitive types case */ const PrimitiveTypeEntry* pte = dynamic_cast<const PrimitiveTypeEntry*>(type); if (!pte) { @@ -2368,19 +2373,47 @@ QMap< QString, AbstractMetaFunctionList > ShibokenGenerator::getFunctionGroups(c return results; } +AbstractMetaFunctionList ShibokenGenerator::getInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen) +{ + AbstractMetaFunctionList results; + AbstractMetaClass* basis; + if (func->ownerClass() && (basis = func->ownerClass()->baseClass(), basis)) { + for (; basis; basis = basis->baseClass()) { + const AbstractMetaFunction* inFunc = basis->findFunction(func->name()); + if (inFunc && !seen->contains(inFunc->minimalSignature())) { + seen->insert(inFunc->minimalSignature()); + AbstractMetaFunction* newFunc = inFunc->copy(); + newFunc->setImplementingClass(func->implementingClass()); + results << newFunc; + } + } + } + return results; +} + +AbstractMetaFunctionList ShibokenGenerator::getFunctionAndInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen) +{ + AbstractMetaFunctionList results; + seen->insert(func->minimalSignature()); + results << const_cast<AbstractMetaFunction *>(func) << getInheritedOverloads(func, seen); + return results; +} + AbstractMetaFunctionList ShibokenGenerator::getFunctionOverloads(const AbstractMetaClass* scope, const QString& functionName) { AbstractMetaFunctionList lst = scope ? scope->functions() : globalFunctions(); AbstractMetaFunctionList results; + QSet<QString> seenSignatures; for (AbstractMetaFunction *func : qAsConst(lst)) { if (func->name() != functionName) continue; - if (isGroupable(func)) - results << func; + if (isGroupable(func)) { + // PYSIDE-331: look also into base classes. + results << getFunctionAndInheritedOverloads(func, &seenSignatures); + } } return results; - } QPair< int, int > ShibokenGenerator::getMinMaxArguments(const AbstractMetaFunction* metaFunction) diff --git a/generator/shiboken2/shibokengenerator.h b/generator/shiboken2/shibokengenerator.h index 649d384..cf2af04 100644 --- a/generator/shiboken2/shibokengenerator.h +++ b/generator/shiboken2/shibokengenerator.h @@ -80,10 +80,27 @@ public: /** * Returns a map with all functions grouped, the function name is used as key. - * Example ofg return value: { "foo" -> ["foo(int)", "foo(int, long)], "bar" -> "bar(double)"} - * \param scope Where to search for functions, null means all global functions. + * Example of return value: { "foo" -> ["foo(int)", "foo(int, long)], "bar" -> "bar(double)"} + * \param scope Where to search for functions, null means all global functions. */ QMap<QString, AbstractMetaFunctionList> getFunctionGroups(const AbstractMetaClass* scope = 0); + + /** + * Returns all different inherited overloads of func. + * The function can be called multiple times without duplication. + * \param func the metafunction to be searched in subclasses. + * \param seen the function's minimal signatures already seen. + */ + AbstractMetaFunctionList getInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen); + + /** + * Returns all different inherited overloads of func, and includes func as well. + * The function can be called multiple times without duplication. + * \param func the metafunction to be searched in subclasses. + * \param seen the function's minimal signatures already seen. + */ + AbstractMetaFunctionList getFunctionAndInheritedOverloads(const AbstractMetaFunction *func, QSet<QString> *seen); + /** * Returns all overloads for a function named \p functionName. * \param scope scope used to search for overloads. |