diff options
| author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-03-22 08:23:57 +0100 |
|---|---|---|
| committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2022-03-29 00:06:14 +0200 |
| commit | 5c6382ee849c769e39d3a017966cfd4deb7dc15e (patch) | |
| tree | 2044a681ecb44bfad3dd1280b87c315061a2ac1e | |
| parent | 370e5c712cafb1ff3ca22cc1f9794904f6d7a14a (diff) | |
shiboken6: Synthesize missing smart pointer functions and classes
Add a function to create the smart pointer classes and their relevant
member functions in case they are not in the code model due to being
in some unspecified helper base class.
[ChangeLog][shiboken6] Using std::shared_ptr has been simplified; it
no longer requires specifying all implementation headers for the class
declaration to be fully visible.
Task-number: PYSIDE-454
Change-Id: I870ec59e55e947fa13f875c4af8756246651c466
Reviewed-by: Christian Tismer <tismer@stackless.com>
| -rw-r--r-- | sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp | 76 | ||||
| -rw-r--r-- | sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h | 2 | ||||
| -rw-r--r-- | sources/shiboken6/ApiExtractor/messages.cpp | 23 | ||||
| -rw-r--r-- | sources/shiboken6/ApiExtractor/messages.h | 5 | ||||
| -rw-r--r-- | sources/shiboken6/ApiExtractor/typedatabase.cpp | 35 | ||||
| -rw-r--r-- | sources/shiboken6/ApiExtractor/typedatabase.h | 4 | ||||
| -rw-r--r-- | sources/shiboken6/ApiExtractor/typedatabase_typedefs.h | 2 | ||||
| -rw-r--r-- | sources/shiboken6/doc/typesystem_specifying_types.rst | 20 | ||||
| -rw-r--r-- | sources/shiboken6/generator/generator.cpp | 7 |
9 files changed, 133 insertions, 41 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp index 903cde198..84bbc4d9e 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp @@ -642,6 +642,8 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom, cls->setInnerClasses(classesTopologicalSorted(cls->innerClasses())); } + fixSmartPointers(); + dumpLog(); sortLists(); @@ -2235,6 +2237,80 @@ const AbstractMetaClass *AbstractMetaBuilderPrivate::resolveTypeSystemTypeDef(co return nullptr; } +// The below helpers and AbstractMetaBuilderPrivate::fixSmartPointers() +// synthesize missing smart pointer functions and classes. For example for +// std::shared_ptr, the full class declaration or base classes from +// internal, compiler-dependent STL implementation headers might not be exposed +// to the parser unless those headers are specified as <system-include>. + +// Add the relevant missing smart pointer functions. +static void fixSmartPointerClass(AbstractMetaClass *s, const SmartPointerTypeEntry *ste) +{ + const QString getterName = ste->getter(); + if (s->findFunction(getterName).isNull()) { + AbstractMetaFunctionPtr getter(new AbstractMetaFunction(getterName)); + AbstractMetaType type(s->templateArguments().constFirst()); + type.addIndirection(); + type.decideUsagePattern(); + getter->setType(type); + s->addFunction(getter); + qCWarning(lcShiboken, "Synthesizing \"%s\"...", + qPrintable(getter->classQualifiedSignature())); + } + + const QString refCountName = ste->refCountMethodName(); + if (!refCountName.isEmpty() && s->findFunction(refCountName).isNull()) { + AbstractMetaFunctionPtr refCount(new AbstractMetaFunction(refCountName)); + auto *intTypeEntry = TypeDatabase::instance()->findPrimitiveType(u"int"_qs); + Q_ASSERT(intTypeEntry); + AbstractMetaType intType(intTypeEntry); + intType.decideUsagePattern(); + refCount->setType(intType); + s->addFunction(refCount); + qCWarning(lcShiboken, "Synthesizing \"%s\"...", + qPrintable(refCount->classQualifiedSignature())); + } +} + +// Create a missing smart pointer class +static AbstractMetaClass *createSmartPointerClass(const SmartPointerTypeEntry *ste, + const AbstractMetaClassList &allClasses) +{ + auto *result = new AbstractMetaClass(); + result->setTypeEntry(const_cast<SmartPointerTypeEntry *>(ste)); + auto *templateArg = new TemplateArgumentEntry(u"T"_qs, ste->version(), + ste->typeSystemTypeEntry()); + result->setTemplateArguments({templateArg}); + fixSmartPointerClass(result, ste); + auto *enclosingTe = ste->parent(); + if (!enclosingTe->isTypeSystem()) { + auto *enclosing = AbstractMetaClass::findClass(allClasses, enclosingTe); + if (enclosing == nullptr) + throw Exception(msgEnclosingClassNotFound(ste)); + result->setEnclosingClass(enclosing); + auto inner = enclosing->innerClasses(); + inner.append(result); + enclosing->setInnerClasses(inner); + } + return result; +} + +void AbstractMetaBuilderPrivate::fixSmartPointers() +{ + const auto smartPointerTypes = TypeDatabase::instance()->smartPointerTypes(); + for (auto *ste : smartPointerTypes) { + const AbstractMetaClass *smartPointerClass = + AbstractMetaClass::findClass(m_smartPointers, ste); + if (smartPointerClass) { + fixSmartPointerClass(const_cast<AbstractMetaClass *>(smartPointerClass), ste); + } else { + qCWarning(lcShiboken, "Synthesizing smart pointer \"%s\"...", + qPrintable(ste->qualifiedCppName())); + m_smartPointers.append(createSmartPointerClass(ste, m_metaClasses)); + } + } +} + std::optional<AbstractMetaType> AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typei, const AbstractMetaClass *currentClass, diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h index 031eb926e..e028e058f 100644 --- a/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h @@ -209,6 +209,8 @@ public: void fillAddedFunctions(AbstractMetaClass *metaClass); const AbstractMetaClass *resolveTypeSystemTypeDef(const AbstractMetaType &t) const; + void fixSmartPointers(); + AbstractMetaBuilder *q; AbstractMetaClassList m_metaClasses; AbstractMetaClassList m_templates; diff --git a/sources/shiboken6/ApiExtractor/messages.cpp b/sources/shiboken6/ApiExtractor/messages.cpp index 235f03ab9..c074df785 100644 --- a/sources/shiboken6/ApiExtractor/messages.cpp +++ b/sources/shiboken6/ApiExtractor/messages.cpp @@ -671,20 +671,6 @@ QString msgConversionTypesDiffer(const QString &varType, const QString &conversi return result; } -QString msgCannotFindSmartPointer(const QString &instantiationType, - const AbstractMetaClassCList &pointers) -{ - QString result; - QTextStream str(&result); - str << "Unable to find smart pointer type for " << instantiationType << " (known types:"; - for (auto t : pointers) { - auto typeEntry = t->typeEntry(); - str << ' ' << typeEntry->targetLangName() << '/' << typeEntry->qualifiedCppName(); - } - str << ")."; - return result; -} - QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntry *te) { return u"Getter \""_qs + te->getter() + u"()\" of smart pointer \""_qs @@ -759,6 +745,15 @@ QString msgClassNotFound(const TypeEntry *t) + QLatin1String("\" in the code model. Maybe it is forward declared?"); } +QString msgEnclosingClassNotFound(const TypeEntry *t) +{ + QString result; + QTextStream str(&result); + str << "Warning: Enclosing class \"" << t->parent()->name() + << "\" of class \"" << t->name() << "\" not found."; + return result; +} + QString msgUnknownOperator(const AbstractMetaFunction* func) { QString result = QLatin1String("Unknown operator: \"") + func->originalName() diff --git a/sources/shiboken6/ApiExtractor/messages.h b/sources/shiboken6/ApiExtractor/messages.h index d2a7474b9..cdce6788c 100644 --- a/sources/shiboken6/ApiExtractor/messages.h +++ b/sources/shiboken6/ApiExtractor/messages.h @@ -205,9 +205,6 @@ QString msgCannotUseEnumAsInt(const QString &name); QString msgConversionTypesDiffer(const QString &varType, const QString &conversionType); -QString msgCannotFindSmartPointer(const QString &instantiationType, - const AbstractMetaClassCList &pointers); - QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntry *); QString msgCannotFindSmartPointerRefCount(const SmartPointerTypeEntry *); @@ -239,6 +236,8 @@ QString msgCyclicDependency(const QString &funcName, const QString &graphName, QString msgClassNotFound(const TypeEntry *t); +QString msgEnclosingClassNotFound(const TypeEntry *t); + QString msgUnknownOperator(const AbstractMetaFunction* func); QString msgWrongIndex(const char *varName, const QString &capture, diff --git a/sources/shiboken6/ApiExtractor/typedatabase.cpp b/sources/shiboken6/ApiExtractor/typedatabase.cpp index 015769cfa..098100ef9 100644 --- a/sources/shiboken6/ApiExtractor/typedatabase.cpp +++ b/sources/shiboken6/ApiExtractor/typedatabase.cpp @@ -369,6 +369,17 @@ TypeEntries TypeDatabase::findTypesHelper(const QString &name, Predicate pred) c return result; } +template<class Type, class Predicate> +QList<const Type *> TypeDatabase::findTypesByTypeHelper(Predicate pred) const +{ + QList<const Type *> result; + for (auto *entry : m_entries) { + if (pred(entry)) + result.append(static_cast<const Type *>(entry)); + } + return result; +} + TypeEntries TypeDatabase::findTypes(const QString &name) const { return findTypesHelper(name, useType); @@ -411,24 +422,20 @@ TypeEntryMultiMapConstIteratorRange TypeDatabase::findTypeRange(const QString &n PrimitiveTypeEntryList TypeDatabase::primitiveTypes() const { - PrimitiveTypeEntryList returned; - for (auto it = m_entries.cbegin(), end = m_entries.cend(); it != end; ++it) { - TypeEntry *typeEntry = it.value(); - if (typeEntry->isPrimitive()) - returned.append(static_cast<PrimitiveTypeEntry *>(typeEntry)); - } - return returned; + auto pred = [](const TypeEntry *t) { return t->isPrimitive(); }; + return findTypesByTypeHelper<PrimitiveTypeEntry>(pred); } ContainerTypeEntryList TypeDatabase::containerTypes() const { - ContainerTypeEntryList returned; - for (auto it = m_entries.cbegin(), end = m_entries.cend(); it != end; ++it) { - TypeEntry *typeEntry = it.value(); - if (typeEntry->isContainer()) - returned.append(static_cast<ContainerTypeEntry *>(typeEntry)); - } - return returned; + auto pred = [](const TypeEntry *t) { return t->isContainer(); }; + return findTypesByTypeHelper<ContainerTypeEntry>(pred); +} + +SmartPointerTypeEntryList TypeDatabase::smartPointerTypes() const +{ + auto pred = [](const TypeEntry *t) { return t->isSmartPointer(); }; + return findTypesByTypeHelper<SmartPointerTypeEntry>(pred); } #ifndef QT_NO_DEBUG_STREAM diff --git a/sources/shiboken6/ApiExtractor/typedatabase.h b/sources/shiboken6/ApiExtractor/typedatabase.h index cfd6a2228..ba1e90f00 100644 --- a/sources/shiboken6/ApiExtractor/typedatabase.h +++ b/sources/shiboken6/ApiExtractor/typedatabase.h @@ -148,6 +148,8 @@ public: ContainerTypeEntryList containerTypes() const; + SmartPointerTypeEntryList smartPointerTypes() const; + void addRejection(const TypeRejection &); bool isClassRejected(const QString &className, QString *reason = nullptr) const; bool isFunctionRejected(const QString &className, const QString &functionName, @@ -229,6 +231,8 @@ private: TypeEntryMultiMapConstIteratorRange findTypeRange(const QString &name) const; template <class Predicate> TypeEntries findTypesHelper(const QString &name, Predicate pred) const; + template <class Type, class Predicate> + QList<const Type *> findTypesByTypeHelper(Predicate pred) const; TypeEntry *resolveTypeDefEntry(TypedefEntry *typedefEntry, QString *errorMessage); template <class String> bool isSuppressedWarningHelper(const String &s) const; diff --git a/sources/shiboken6/ApiExtractor/typedatabase_typedefs.h b/sources/shiboken6/ApiExtractor/typedatabase_typedefs.h index 03ad90463..859642c80 100644 --- a/sources/shiboken6/ApiExtractor/typedatabase_typedefs.h +++ b/sources/shiboken6/ApiExtractor/typedatabase_typedefs.h @@ -37,6 +37,7 @@ class ConstantValueTypeEntry; class ContainerTypeEntry; class NamespaceTypeEntry; class PrimitiveTypeEntry; +class SmartPointerTypeEntry; class TemplateEntry; class TypeEntry; class TypedefEntry; @@ -65,5 +66,6 @@ using TypedefEntryMap = QMap<QString, TypedefEntry *>; using ContainerTypeEntryList = QList<const ContainerTypeEntry *>; using NamespaceTypeEntryList = QList<NamespaceTypeEntry *>; using PrimitiveTypeEntryList = QList<const PrimitiveTypeEntry *>; +using SmartPointerTypeEntryList = QList<const SmartPointerTypeEntry *>; #endif // TYPEDATABASE_TYPEDEFS_H diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst index 329300680..ea308554a 100644 --- a/sources/shiboken6/doc/typesystem_specifying_types.rst +++ b/sources/shiboken6/doc/typesystem_specifying_types.rst @@ -588,17 +588,29 @@ smart-pointer-type The *optional* attribute **reset-method** specifies a method that can be used to clear the pointer. - The example below shows an entry for a ``std::shared_ptr`` found in - the standard library of ``g++`` version 9: + The example below shows an entry for a ``std::shared_ptr``: .. code-block:: xml <system-include file-name="memory"/> - <system-include file-name="shared_ptr.h"/> <namespace-type name="std"> <include file-name="memory" location="global"/> - <custom-type name="__shared_ptr"/> + <modify-function signature="^.*$" remove="all"/> + <enum-type name="pointer_safety"/> + <smart-pointer-type name="shared_ptr" type="shared" getter="get" + ref-count-method="use_count" + instantiations="Integer"> + <include file-name="memory" location="global"/> + </smart-pointer-type> + </namespace-type> + + If the smart pointer is the only relevant class from namespace ``std``, + it can also be hidden: + + .. code-block:: xml + + <namespace-type name="std" visible="no"> <smart-pointer-type name="shared_ptr" type="shared" getter="get" ref-count-method="use_count" instantiations="Integer"> diff --git a/sources/shiboken6/generator/generator.cpp b/sources/shiboken6/generator/generator.cpp index 55465087b..739b2de65 100644 --- a/sources/shiboken6/generator/generator.cpp +++ b/sources/shiboken6/generator/generator.cpp @@ -549,12 +549,7 @@ bool Generator::generate() for (const AbstractMetaType &type : qAsConst(m_d->instantiatedSmartPointers)) { const AbstractMetaClass *smartPointerClass = AbstractMetaClass::findClass(smartPointers, type.typeEntry()); - if (!smartPointerClass) { - qCWarning(lcShiboken, "%s", - qPrintable(msgCannotFindSmartPointer(type.cppSignature(), - smartPointers))); - return false; - } + Q_ASSERT(smartPointerClass); const AbstractMetaClass *pointeeClass = nullptr; const auto *instantiatedType = type.instantiations().constFirst().typeEntry(); if (instantiatedType->isComplex()) // not a C++ primitive |
