aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2022-03-22 08:23:57 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2022-03-29 00:06:14 +0200
commit5c6382ee849c769e39d3a017966cfd4deb7dc15e (patch)
tree2044a681ecb44bfad3dd1280b87c315061a2ac1e
parent370e5c712cafb1ff3ca22cc1f9794904f6d7a14a (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.cpp76
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder_p.h2
-rw-r--r--sources/shiboken6/ApiExtractor/messages.cpp23
-rw-r--r--sources/shiboken6/ApiExtractor/messages.h5
-rw-r--r--sources/shiboken6/ApiExtractor/typedatabase.cpp35
-rw-r--r--sources/shiboken6/ApiExtractor/typedatabase.h4
-rw-r--r--sources/shiboken6/ApiExtractor/typedatabase_typedefs.h2
-rw-r--r--sources/shiboken6/doc/typesystem_specifying_types.rst20
-rw-r--r--sources/shiboken6/generator/generator.cpp7
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