aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2017-04-13 15:29:02 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2017-04-13 15:29:05 +0200
commitdfc22cb270cb94bf28dd0bc0eabae3267418113e (patch)
tree090faff2a10725e99003be9e4a312ce86c98b877
parent60985b97fa181fd897c4d87542943e325493fd6b (diff)
parent3461108126a4a9be1e566e644e9063a8ef44c1cb (diff)
Merge remote-tracking branch 'origin/5.9' into dev
-rw-r--r--ApiExtractor/abstractmetalang.cpp9
-rw-r--r--ApiExtractor/abstractmetalang.h7
-rw-r--r--ApiExtractor/abstractmetalang_typedefs.h3
-rw-r--r--CMakeLists.txt108
-rw-r--r--cmake/Modules/FindPythonInterpWithDebug.cmake57
-rw-r--r--generator/shiboken2/cppgenerator.cpp18
-rw-r--r--generator/shiboken2/shibokengenerator.cpp51
-rw-r--r--generator/shiboken2/shibokengenerator.h21
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.