diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-10-01 07:59:26 +0200 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2020-10-01 07:59:26 +0200 |
commit | 2ec2127b9f4bcd62975b175e77cd0502580d9de7 (patch) | |
tree | a63b666c1289604311338ecf59d9ea91c353a3c6 | |
parent | 0f922f604297a2022527f04a696da121396ddc0a (diff) | |
parent | 26e4ba3639bac57b0481bd6bb3964b1afa340ab9 (diff) |
Merge remote-tracking branch 'origin/5.15' into dev
Change-Id: Idaf124ad5e1d6a41d52918cecba47499be5e7324
11 files changed, 137 insertions, 62 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index edb449b04..f705994f2 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -808,6 +808,12 @@ bool AbstractMetaFunction::argumentRemoved(int key) const return false; } +const AbstractMetaClass *AbstractMetaFunction::targetLangOwner() const +{ + return m_class && m_class->isInvisibleNamespace() + ? m_class->targetLangEnclosingClass() : m_class; +} + bool AbstractMetaFunction::isDeprecated() const { const FunctionModificationList &modifications = this->modifications(declaringClass()); @@ -1638,6 +1644,14 @@ bool AbstractMetaClass::isNamespace() const return m_typeEntry->isNamespace(); } +// Is an invisible namespaces whose functions/enums +// should be mapped to the global space. +bool AbstractMetaClass::isInvisibleNamespace() const +{ + return m_typeEntry->isNamespace() && m_typeEntry->generateCode() + && !NamespaceTypeEntry::isVisibleScope(m_typeEntry); +} + static bool qObjectPredicate(const AbstractMetaClass *c) { return c->qualifiedCppName() == QLatin1String("QObject"); @@ -2129,6 +2143,31 @@ AbstractMetaEnumValue *AbstractMetaClass::findEnumValue(const QString &enumValue return nullptr; } +void AbstractMetaClass::getEnumsToBeGenerated(AbstractMetaEnumList *enumList) const +{ + for (AbstractMetaEnum *metaEnum : m_enums) { + if (!metaEnum->isPrivate() && metaEnum->typeEntry()->generateCode()) + enumList->append(metaEnum); + } +} + +void AbstractMetaClass::getEnumsFromInvisibleNamespacesToBeGenerated(AbstractMetaEnumList *enumList) const +{ + if (isNamespace()) { + invisibleNamespaceRecursion([enumList](AbstractMetaClass *c) { + c->getEnumsToBeGenerated(enumList); + }); + } +} + +void AbstractMetaClass::getFunctionsFromInvisibleNamespacesToBeGenerated(AbstractMetaFunctionList *funcList) const +{ + if (isNamespace()) { + invisibleNamespaceRecursion([funcList](AbstractMetaClass *c) { + funcList->append(c->functions()); + }); + } +} static void addExtraIncludeForType(AbstractMetaClass *metaClass, const AbstractMetaType *type) { diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 0e187fbcf..df9790a3d 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -913,6 +913,9 @@ public: m_class = cls; } + // Owner excluding invisible namespaces + const AbstractMetaClass *targetLangOwner() const; + // The first class in a hierarchy that declares the function const AbstractMetaClass *declaringClass() const { @@ -1432,6 +1435,10 @@ public: AbstractMetaEnum *findEnum(const QString &enumName); AbstractMetaEnumValue *findEnumValue(const QString &enumName); + void getEnumsToBeGenerated(AbstractMetaEnumList *enumList) const; + void getEnumsFromInvisibleNamespacesToBeGenerated(AbstractMetaEnumList *enumList) const; + + void getFunctionsFromInvisibleNamespacesToBeGenerated(AbstractMetaFunctionList *funcList) const; QString fullName() const { @@ -1482,6 +1489,7 @@ public: QString package() const; bool isNamespace() const; + bool isInvisibleNamespace() const; bool isQObject() const; @@ -1678,6 +1686,9 @@ public: SourceLocation sourceLocation() const; void setSourceLocation(const SourceLocation &sourceLocation); + template <class Function> + void invisibleNamespaceRecursion(Function f) const; + private: #ifndef QT_NO_DEBUG_STREAM void format(QDebug &d) const; @@ -1725,4 +1736,15 @@ private: Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::FunctionQueryOptions) Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaClass::OperatorQueryOptions) +template <class Function> +void AbstractMetaClass::invisibleNamespaceRecursion(Function f) const +{ + for (auto ic : m_innerClasses) { + if (ic->isInvisibleNamespace()) { + f(ic); + ic->invisibleNamespaceRecursion(f); + } + } +} + #endif // ABSTRACTMETALANG_H diff --git a/sources/shiboken2/generator/generator.cpp b/sources/shiboken2/generator/generator.cpp index 5fa462bef..487715a3c 100644 --- a/sources/shiboken2/generator/generator.cpp +++ b/sources/shiboken2/generator/generator.cpp @@ -168,7 +168,7 @@ struct Generator::GeneratorPrivate QStringList instantiatedContainersNames; QVector<const AbstractMetaType *> instantiatedContainers; QVector<const AbstractMetaType *> instantiatedSmartPointers; - + AbstractMetaClassList m_invisibleTopNamespaces; }; Generator::Generator() : m_d(new GeneratorPrivate) @@ -191,6 +191,15 @@ bool Generator::setup(const ApiExtractor &extractor) collectInstantiatedContainersAndSmartPointers(); + for (auto c : classes()) { + if (c->enclosingClass() == nullptr && c->isInvisibleNamespace()) { + m_d->m_invisibleTopNamespaces.append(c); + c->invisibleNamespaceRecursion([&](AbstractMetaClass *ic) { + m_d->m_invisibleTopNamespaces.append(ic); + }); + } + } + return doSetup(); } @@ -344,6 +353,11 @@ const AbstractMetaClassList &Generator::classes() const return m_d->apiextractor->classes(); } +const AbstractMetaClassList &Generator::invisibleTopNamespaces() const +{ + return m_d->m_invisibleTopNamespaces; +} + AbstractMetaClassList Generator::classesTopologicalSorted(const Dependencies &additionalDependencies) const { return m_d->apiextractor->classesTopologicalSorted(additionalDependencies); diff --git a/sources/shiboken2/generator/generator.h b/sources/shiboken2/generator/generator.h index 324bb8474..cf6df528f 100644 --- a/sources/shiboken2/generator/generator.h +++ b/sources/shiboken2/generator/generator.h @@ -218,6 +218,9 @@ public: /// Returns the classes used to generate the binding code. const AbstractMetaClassList &classes() const; + /// Returns the top namespace made invisible + const AbstractMetaClassList &invisibleTopNamespaces() const; + /// Returns the output directory QString outputDirectory() const; diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 89e97093b..388358249 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -390,8 +390,7 @@ void CppGenerator::generateClass(QTextStream &s, const GeneratorContext &classCo } AbstractMetaEnumList classEnums = metaClass->enums(); - for (AbstractMetaClass *innerClass : innerClasses) - lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); + metaClass->getEnumsFromInvisibleNamespacesToBeGenerated(&classEnums); //Extra includes s << "\n// Extra includes\n"; @@ -1386,9 +1385,7 @@ void CppGenerator::writeConverterFunctions(QTextStream &s, const AbstractMetaCla s << "// Type conversion functions.\n\n"; AbstractMetaEnumList classEnums = metaClass->enums(); - const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); - for (AbstractMetaClass *innerClass : innerClasses) - lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); + metaClass->getEnumsFromInvisibleNamespacesToBeGenerated(&classEnums); if (!classEnums.isEmpty()) s << "// Python to C++ enum conversion.\n"; for (const AbstractMetaEnum *metaEnum : qAsConst(classEnums)) @@ -1738,7 +1735,7 @@ void CppGenerator::writeMethodWrapperPreamble(QTextStream &s, OverloadData &over const GeneratorContext &context) { const AbstractMetaFunction *rfunc = overloadData.referenceFunction(); - const AbstractMetaClass *ownerClass = rfunc->ownerClass(); + const AbstractMetaClass *ownerClass = rfunc->targetLangOwner(); Q_ASSERT(ownerClass == context.metaClass()); int minArgs = overloadData.minArgs(); int maxArgs = overloadData.maxArgs(); @@ -4770,8 +4767,14 @@ void CppGenerator::writeMethodDefinitionEntry(QTextStream &s, const AbstractMeta if (overloadData.hasArgumentWithDefaultValue()) s << "|METH_KEYWORDS"; } - if (func->ownerClass() && overloadData.hasStaticFunction()) + // METH_STATIC causes a crash when used for global functions (also from + // invisible namespaces). + auto ownerClass = func->ownerClass(); + if (ownerClass + && !invisibleTopNamespaces().contains(const_cast<AbstractMetaClass *>(ownerClass)) + && overloadData.hasStaticFunction()) { s << "|METH_STATIC"; + } } void CppGenerator::writeMethodDefinition(QTextStream &s, const AbstractMetaFunctionList &overloads) @@ -5051,13 +5054,13 @@ void CppGenerator::writeFlagsNumberMethodsDefinition(QTextStream &s, const Abstr QString cpythonName = cpythonEnumName(cppEnum); s << "static PyType_Slot " << cpythonName << "_number_slots[] = {\n"; - s << INDENT << "{Py_nb_bool, (void *)" << cpythonName << "__nonzero},\n"; - s << INDENT << "{Py_nb_invert, (void *)" << cpythonName << "___invert__},\n"; - s << INDENT << "{Py_nb_and, (void *)" << cpythonName << "___and__},\n"; - s << INDENT << "{Py_nb_xor, (void *)" << cpythonName << "___xor__},\n"; - s << INDENT << "{Py_nb_or, (void *)" << cpythonName << "___or__},\n"; - s << INDENT << "{Py_nb_int, (void *)" << cpythonName << "_long},\n"; - s << INDENT << "{Py_nb_index, (void *)" << cpythonName << "_long},\n"; + s << INDENT << "{Py_nb_bool, reinterpret_cast<void *>(" << cpythonName << "__nonzero)},\n"; + s << INDENT << "{Py_nb_invert, reinterpret_cast<void *>(" << cpythonName << "___invert__)},\n"; + s << INDENT << "{Py_nb_and, reinterpret_cast<void *>(" << cpythonName << "___and__)},\n"; + s << INDENT << "{Py_nb_xor, reinterpret_cast<void *>(" << cpythonName << "___xor__)},\n"; + s << INDENT << "{Py_nb_or, reinterpret_cast<void *>(" << cpythonName << "___or__)},\n"; + s << INDENT << "{Py_nb_int, reinterpret_cast<void *>(" << cpythonName << "_long)},\n"; + s << INDENT << "{Py_nb_index, reinterpret_cast<void *>(" << cpythonName << "_long)},\n"; s << INDENT << "{0, " << NULL_PTR << "} // sentinel\n"; s << "};\n\n"; } @@ -5068,7 +5071,7 @@ void CppGenerator::writeFlagsBinaryOperator(QTextStream &s, const AbstractMetaEn FlagsTypeEntry *flagsEntry = cppEnum->typeEntry()->flags(); Q_ASSERT(flagsEntry); - s << "PyObject * " << cpythonEnumName(cppEnum) << "___" << pyOpName + s << "PyObject *" << cpythonEnumName(cppEnum) << "___" << pyOpName << "__(PyObject *self, PyObject *" << PYTHON_ARG << ")\n{\n"; AbstractMetaType *flagsType = buildAbstractMetaTypeFromTypeEntry(flagsEntry); @@ -5310,9 +5313,7 @@ void CppGenerator::writeClassRegister(QTextStream &s, } AbstractMetaEnumList classEnums = metaClass->enums(); - const AbstractMetaClassList &innerClasses = metaClass->innerClasses(); - for (AbstractMetaClass *innerClass : innerClasses) - lookForEnumsInClassesNotToBeGenerated(classEnums, innerClass); + metaClass->getEnumsFromInvisibleNamespacesToBeGenerated(&classEnums); ErrorCode errorCode(QString::fromLatin1("")); writeEnumsInitialization(s, classEnums); @@ -5819,11 +5820,8 @@ bool CppGenerator::finishGeneration() // Global enums AbstractMetaEnumList globalEnums = this->globalEnums(); - for (const AbstractMetaClass *metaClass : classes()) { - const AbstractMetaClass *encClass = metaClass->enclosingClass(); - if (!encClass || !NamespaceTypeEntry::isVisibleScope(encClass->typeEntry())) - lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); - } + for (const AbstractMetaClass *nsp : invisibleTopNamespaces()) + nsp->getEnumsToBeGenerated(&globalEnums); TypeDatabase *typeDb = TypeDatabase::instance(); const TypeSystemTypeEntry *moduleEntry = typeDb->defaultTypeSystemType(); diff --git a/sources/shiboken2/generator/shiboken2/headergenerator.cpp b/sources/shiboken2/generator/shiboken2/headergenerator.cpp index 1fdd89af8..1d3a20447 100644 --- a/sources/shiboken2/generator/shiboken2/headergenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/headergenerator.cpp @@ -340,14 +340,15 @@ void HeaderGenerator::writeTypeIndexValueLine(QTextStream &s, const TypeEntry *t void HeaderGenerator::writeTypeIndexValueLines(QTextStream &s, const AbstractMetaClass *metaClass) { auto typeEntry = metaClass->typeEntry(); - if (!typeEntry->generateCode() || !NamespaceTypeEntry::isVisibleScope(typeEntry)) + if (!typeEntry->generateCode()) return; - writeTypeIndexValueLine(s, metaClass->typeEntry()); + // enum indices are required for invisible namespaces as well. for (const AbstractMetaEnum *metaEnum : metaClass->enums()) { - if (metaEnum->isPrivate()) - continue; - writeTypeIndexValueLine(s, metaEnum->typeEntry()); + if (!metaEnum->isPrivate()) + writeTypeIndexValueLine(s, metaEnum->typeEntry()); } + if (NamespaceTypeEntry::isVisibleScope(typeEntry)) + writeTypeIndexValueLine(s, metaClass->typeEntry()); } // Format the typedefs for the typedef entries to be generated @@ -399,19 +400,16 @@ bool HeaderGenerator::finishGeneration() Indentation indent(INDENT); macrosStream << "// Type indices\nenum : int {\n"; - AbstractMetaEnumList globalEnums = this->globalEnums(); AbstractMetaClassList classList = classes(); std::sort(classList.begin(), classList.end(), [](AbstractMetaClass *a, AbstractMetaClass *b) { return a->typeEntry()->sbkIndex() < b->typeEntry()->sbkIndex(); }); - for (const AbstractMetaClass *metaClass : classList) { + for (const AbstractMetaClass *metaClass : classList) writeTypeIndexValueLines(macrosStream, metaClass); - lookForEnumsInClassesNotToBeGenerated(globalEnums, metaClass); - } - for (const AbstractMetaEnum *metaEnum : qAsConst(globalEnums)) + for (const AbstractMetaEnum *metaEnum : globalEnums()) writeTypeIndexValueLine(macrosStream, metaEnum->typeEntry()); // Write the smart pointer define indexes. @@ -486,12 +484,11 @@ bool HeaderGenerator::finishGeneration() typeFunctions << "QT_WARNING_PUSH\n"; typeFunctions << "QT_WARNING_DISABLE_DEPRECATED\n"; } - for (const AbstractMetaEnum *cppEnum : qAsConst(globalEnums)) { - if (cppEnum->isAnonymous() || cppEnum->isPrivate()) - continue; - includes << cppEnum->typeEntry()->include(); - writeProtectedEnumSurrogate(protEnumsSurrogates, cppEnum); - writeSbkTypeFunction(typeFunctions, cppEnum); + for (const AbstractMetaEnum *cppEnum : globalEnums()) { + if (!cppEnum->isAnonymous()) { + includes << cppEnum->typeEntry()->include(); + writeSbkTypeFunction(typeFunctions, cppEnum); + } } for (AbstractMetaClass *metaClass : classList) { diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp index 1f91609bd..a6a175999 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.cpp @@ -334,20 +334,6 @@ bool ShibokenGenerator::shouldWriteVirtualMethodNative(const AbstractMetaFunctio && (func->attributes() & AbstractMetaAttributes::FinalCppMethod) == 0); } -void ShibokenGenerator::lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList &enumList, const AbstractMetaClass *metaClass) -{ - Q_ASSERT(metaClass); - // if a scope is not to be generated, collect its enums into the parent scope - if (!NamespaceTypeEntry::isVisibleScope(metaClass->typeEntry())) { - for (AbstractMetaEnum *metaEnum : metaClass->enums()) { - if (!metaEnum->isPrivate() && metaEnum->typeEntry()->generateCode() - && !enumList.contains(metaEnum)) { - enumList.append(metaEnum); - } - } - } -} - QString ShibokenGenerator::wrapperName(const AbstractMetaClass *metaClass) const { Q_ASSERT(shouldGenerateCppWrapper(metaClass)); @@ -2471,14 +2457,21 @@ static bool isGroupable(const AbstractMetaFunction *func) return true; } -ShibokenGenerator::FunctionGroups ShibokenGenerator::getGlobalFunctionGroups() const +static void insertIntoFunctionGroups(const AbstractMetaFunctionList &lst, + ShibokenGenerator::FunctionGroups *results) { - const AbstractMetaFunctionList &lst = globalFunctions(); - FunctionGroups results; for (AbstractMetaFunction *func : lst) { if (isGroupable(func)) - results[func->name()].append(func); + (*results)[func->name()].append(func); } +} + +ShibokenGenerator::FunctionGroups ShibokenGenerator::getGlobalFunctionGroups() const +{ + FunctionGroups results; + insertIntoFunctionGroups(globalFunctions(), &results); + for (auto nsp : invisibleTopNamespaces()) + insertIntoFunctionGroups(nsp->functions(), &results); return results; } @@ -2502,7 +2495,8 @@ ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroups(const Abs ShibokenGenerator::FunctionGroups ShibokenGenerator::getFunctionGroupsImpl(const AbstractMetaClass *scope) { - const AbstractMetaFunctionList &lst = scope->functions(); + AbstractMetaFunctionList lst = scope->functions(); + scope->getFunctionsFromInvisibleNamespacesToBeGenerated(&lst); FunctionGroups results; for (AbstractMetaFunction *func : lst) { diff --git a/sources/shiboken2/generator/shiboken2/shibokengenerator.h b/sources/shiboken2/generator/shiboken2/shibokengenerator.h index 83e7cf5b9..33da01a3a 100644 --- a/sources/shiboken2/generator/shiboken2/shibokengenerator.h +++ b/sources/shiboken2/generator/shiboken2/shibokengenerator.h @@ -228,9 +228,6 @@ protected: /// Condition to call WriteVirtualMethodNative. Was extracted because also used to count these calls. bool shouldWriteVirtualMethodNative(const AbstractMetaFunction *func); - /// Adds enums eligible for generation from classes/namespaces marked not to be generated. - static void lookForEnumsInClassesNotToBeGenerated(AbstractMetaEnumList &enumList, const AbstractMetaClass *metaClass); - QString wrapperName(const AbstractMetaClass *metaClass) const; QString fullPythonClassName(const AbstractMetaClass *metaClass); diff --git a/sources/shiboken2/tests/libsample/removednamespaces.h b/sources/shiboken2/tests/libsample/removednamespaces.h index 9ad798bf7..47c18c049 100644 --- a/sources/shiboken2/tests/libsample/removednamespaces.h +++ b/sources/shiboken2/tests/libsample/removednamespaces.h @@ -39,6 +39,8 @@ enum RemovedNamespace1_Enum { RemovedNamespace1_Enum_Value0 = 0, enum { RemovedNamespace1_AnonymousEnum_Value0 }; +inline int mathSum(int x, int y) { return x + y; } + struct ObjectOnInvisibleNamespace { bool exists() const { return true; } @@ -63,6 +65,8 @@ namespace RemovedNamespace3 enum { RemovedNamespace3_AnonymousEnum_Value0 }; + inline int nestedMathSum(int x, int y) { return x + y; } + } // namespace RemovedNamespace3 } // namespace UnremovedNamespace diff --git a/sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py b/sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py index 168a609dc..fc1da5d8a 100644 --- a/sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py +++ b/sources/shiboken2/tests/samplebinding/enumfromremovednamespace_test.py @@ -65,12 +65,18 @@ class TestEnumFromRemovedNamespace(unittest.TestCase): self.assertEqual(objectFullname(signature.parameters['other'].annotation), "sample.ObjectOnInvisibleNamespace") + def testGlobalFunctionFromRemovedNamespace(self): + self.assertEqual(sample.mathSum(1, 2), 3) + def testEnumPromotedToUpperNamespace(self): sample.UnremovedNamespace sample.UnremovedNamespace.RemovedNamespace3_Enum sample.UnremovedNamespace.RemovedNamespace3_Enum_Value0 sample.UnremovedNamespace.RemovedNamespace3_AnonymousEnum_Value0 + def testNestedFunctionFromRemovedNamespace(self): + self.assertEqual(sample.UnremovedNamespace.nestedMathSum(1, 2), 3) + if __name__ == '__main__': unittest.main() diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml index 66ae6d0a1..6a52dae7a 100644 --- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml @@ -599,6 +599,7 @@ <namespace-type name="RemovedNamespace1" visible='false'> <enum-type name="RemovedNamespace1_Enum" /> + <function signature="mathSum(int,int)"/> <value-type name="ObjectOnInvisibleNamespace" /> <namespace-type name="RemovedNamespace2" visible='false'> <enum-type name="RemovedNamespace2_Enum" /> |