aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2022-04-04 14:07:10 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2022-04-05 14:45:06 +0200
commitc7d0c7c5ce00a37461908dd9329aa563cd146b1e (patch)
tree739b86ef81a884121cd5a6a765db5f3412e62d2b
parent5f836597140d2ae82f235d69561cc7f426e2d7af (diff)
shiboken6: Add attribute "value-check-method" to smart pointers
"value-check-method" (operator bool, std::optional::has_value()), is the opposite of the existing "null-check-method" (QSharedPointer::isNull()) and takes precedence over it. Synthesize these methods for smart pointers as well. As a drive-by, actually generate the value check and null check methods. Add a test for std::shared_ptr. Task-number: PYSIDE-454 Change-Id: Ie3b6f7042883888d23c9e6bed8a1409f0bdb56b9 Reviewed-by: Christian Tismer <tismer@stackless.com> Reviewed-by: Qt CI Bot <qt_ci_bot@qt-project.org>
-rw-r--r--sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp52
-rw-r--r--sources/shiboken6/ApiExtractor/messages.cpp6
-rw-r--r--sources/shiboken6/ApiExtractor/messages.h2
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem.cpp13
-rw-r--r--sources/shiboken6/ApiExtractor/typesystem.h2
-rw-r--r--sources/shiboken6/ApiExtractor/typesystemparser.cpp4
-rw-r--r--sources/shiboken6/doc/typesystem_specifying_types.rst5
-rw-r--r--sources/shiboken6/generator/shiboken/cppgenerator.cpp25
-rw-r--r--sources/shiboken6/tests/smartbinding/std_shared_ptr_test.py9
-rw-r--r--sources/shiboken6/tests/smartbinding/typesystem_smart.xml1
10 files changed, 96 insertions, 23 deletions
diff --git a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
index 84bbc4d9e..4853b0120 100644
--- a/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
+++ b/sources/shiboken6/ApiExtractor/abstractmetabuilder.cpp
@@ -2243,33 +2243,55 @@ const AbstractMetaClass *AbstractMetaBuilderPrivate::resolveTypeSystemTypeDef(co
// internal, compiler-dependent STL implementation headers might not be exposed
// to the parser unless those headers are specified as <system-include>.
+static AbstractMetaFunctionPtr
+ addMethod(AbstractMetaClass *s, const AbstractMetaType &returnType,
+ const QString &name, bool isConst = true)
+{
+ AbstractMetaFunctionPtr function(new AbstractMetaFunction(name));
+ function->setType(returnType);
+ s->addFunction(function);
+ function->setConstant(isConst);
+ qCWarning(lcShiboken, "Synthesizing \"%s\"...",
+ qPrintable(function->classQualifiedSignature()));
+ return function;
+}
+
+static AbstractMetaFunctionPtr
+ addMethod(AbstractMetaClass *s, const QString &returnTypeName,
+ const QString &name, bool isConst = true)
+{
+ auto *typeEntry = TypeDatabase::instance()->findPrimitiveType(returnTypeName);
+ Q_ASSERT(typeEntry);
+ AbstractMetaType returnType(typeEntry);
+ returnType.decideUsagePattern();
+ return addMethod(s, returnType, name, isConst);
+}
+
// 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()));
+ addMethod(s, type, getterName);
}
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()));
+ if (!refCountName.isEmpty() && s->findFunction(refCountName).isNull())
+ addMethod(s, u"int"_qs, refCountName);
+
+ const QString valueCheckMethod = ste->valueCheckMethod();
+ if (!valueCheckMethod.isEmpty() && s->findFunction(valueCheckMethod).isNull()) {
+ auto f = addMethod(s, u"bool"_qs, valueCheckMethod);
+ if (valueCheckMethod == u"operator bool")
+ f->setFunctionType(AbstractMetaFunction::ConversionOperator);
}
+
+ const QString nullCheckMethod = ste->nullCheckMethod();
+ if (!nullCheckMethod.isEmpty() && s->findFunction(nullCheckMethod).isNull())
+ addMethod(s, u"bool"_qs, nullCheckMethod);
}
// Create a missing smart pointer class
diff --git a/sources/shiboken6/ApiExtractor/messages.cpp b/sources/shiboken6/ApiExtractor/messages.cpp
index c074df785..8898a3cf9 100644
--- a/sources/shiboken6/ApiExtractor/messages.cpp
+++ b/sources/shiboken6/ApiExtractor/messages.cpp
@@ -677,10 +677,10 @@ QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntry *te)
+ te->name() + u"\" not found."_qs;
}
-QString msgCannotFindSmartPointerRefCount(const SmartPointerTypeEntry *te)
+QString msgCannotFindSmartPointerMethod(const SmartPointerTypeEntry *te, const QString &m)
{
- return u"Ref count method \""_qs + te->refCountMethodName()
- + u"()\" of smart pointer \""_qs + te->name() + u"\" not found."_qs;
+ return u"Method \""_qs + m + u"()\" of smart pointer \""_qs
+ + te->name() + u"\" not found."_qs;
}
QString msgMethodNotFound(const AbstractMetaClass *klass, const QString &name)
diff --git a/sources/shiboken6/ApiExtractor/messages.h b/sources/shiboken6/ApiExtractor/messages.h
index cdce6788c..45ed3540c 100644
--- a/sources/shiboken6/ApiExtractor/messages.h
+++ b/sources/shiboken6/ApiExtractor/messages.h
@@ -207,7 +207,7 @@ QString msgConversionTypesDiffer(const QString &varType, const QString &conversi
QString msgCannotFindSmartPointerGetter(const SmartPointerTypeEntry *);
-QString msgCannotFindSmartPointerRefCount(const SmartPointerTypeEntry *);
+QString msgCannotFindSmartPointerMethod(const SmartPointerTypeEntry *te, const QString &m);
QString msgMethodNotFound(const AbstractMetaClass *klass, const QString &name);
diff --git a/sources/shiboken6/ApiExtractor/typesystem.cpp b/sources/shiboken6/ApiExtractor/typesystem.cpp
index 21314449e..452fb92aa 100644
--- a/sources/shiboken6/ApiExtractor/typesystem.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystem.cpp
@@ -1741,6 +1741,7 @@ public:
QString m_getterName;
QString m_smartPointerType;
QString m_refCountMethodName;
+ QString m_valueCheckMethod;
QString m_nullCheckMethod;
QString m_resetMethod;
SmartPointerTypeEntry::Instantiations m_instantiations;
@@ -1768,6 +1769,18 @@ QString SmartPointerTypeEntry::refCountMethodName() const
return d->m_refCountMethodName;
}
+QString SmartPointerTypeEntry::valueCheckMethod() const
+{
+ S_D(const SmartPointerTypeEntry);
+ return d->m_valueCheckMethod;
+}
+
+void SmartPointerTypeEntry::setValueCheckMethod(const QString &m)
+{
+ S_D(SmartPointerTypeEntry);
+ d->m_valueCheckMethod = m;
+}
+
QString SmartPointerTypeEntry::nullCheckMethod() const
{
S_D(const SmartPointerTypeEntry);
diff --git a/sources/shiboken6/ApiExtractor/typesystem.h b/sources/shiboken6/ApiExtractor/typesystem.h
index d0894dac1..f1499e612 100644
--- a/sources/shiboken6/ApiExtractor/typesystem.h
+++ b/sources/shiboken6/ApiExtractor/typesystem.h
@@ -722,6 +722,8 @@ public:
QString refCountMethodName() const;
+ QString valueCheckMethod() const;
+ void setValueCheckMethod(const QString &);
QString nullCheckMethod() const;
void setNullCheckMethod(const QString &);
QString resetMethod() const;
diff --git a/sources/shiboken6/ApiExtractor/typesystemparser.cpp b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
index 49cd0970a..4a615420e 100644
--- a/sources/shiboken6/ApiExtractor/typesystemparser.cpp
+++ b/sources/shiboken6/ApiExtractor/typesystemparser.cpp
@@ -1366,6 +1366,7 @@ SmartPointerTypeEntry *
QString smartPointerType;
QString getter;
QString refCountMethodName;
+ QString valueCheckMethod;
QString nullCheckMethod;
QString resetMethod;
QString instantiations;
@@ -1379,6 +1380,8 @@ SmartPointerTypeEntry *
refCountMethodName = attributes->takeAt(i).value().toString();
} else if (name == QLatin1String("instantiations")) {
instantiations = attributes->takeAt(i).value().toString();
+ } else if (name == u"value-check-method") {
+ valueCheckMethod = attributes->takeAt(i).value().toString();
} else if (name == u"null-check-method") {
nullCheckMethod = attributes->takeAt(i).value().toString();
} else if (name == u"reset-method") {
@@ -1420,6 +1423,7 @@ SmartPointerTypeEntry *
return nullptr;
applyComplexTypeAttributes(reader, type, attributes);
type->setNullCheckMethod(nullCheckMethod);
+ type->setValueCheckMethod(valueCheckMethod);
type->setResetMethod(resetMethod);
m_smartPointerInstantiations.insert(type, instantiations);
return type;
diff --git a/sources/shiboken6/doc/typesystem_specifying_types.rst b/sources/shiboken6/doc/typesystem_specifying_types.rst
index ea308554a..e4e9d8bc2 100644
--- a/sources/shiboken6/doc/typesystem_specifying_types.rst
+++ b/sources/shiboken6/doc/typesystem_specifying_types.rst
@@ -577,11 +577,16 @@ smart-pointer-type
type="..."
getter="..."
ref-count-method="..."
+ value-check-method="..."
null-check-method="..."
reset-method="..."
instantiations="..."/>
</typesystem>
+
+ The *optional* attribute **value-check-method** specifies a method
+ that can be used to check whether the pointer has a value.
+
The *optional* attribute **null-check-method** specifies a method
that can be used to check for ``nullptr``.
diff --git a/sources/shiboken6/generator/shiboken/cppgenerator.cpp b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
index ee3bfb542..eeefae010 100644
--- a/sources/shiboken6/generator/shiboken/cppgenerator.cpp
+++ b/sources/shiboken6/generator/shiboken/cppgenerator.cpp
@@ -292,6 +292,15 @@ CppGenerator::BoolCastFunctionOptional
const auto *te = metaClass->typeEntry();
if (te->isSmartPointer()) {
auto *ste = static_cast<const SmartPointerTypeEntry *>(te);
+
+ auto valueCheckMethod = ste->valueCheckMethod();
+ if (!valueCheckMethod.isEmpty()) {
+ const auto func = metaClass->findFunction(valueCheckMethod);
+ if (func.isNull())
+ throw Exception(msgMethodNotFound(metaClass, valueCheckMethod));
+ return BoolCastFunction{func, false};
+ }
+
auto nullCheckMethod = ste->nullCheckMethod();
if (!nullCheckMethod.isEmpty()) {
const auto func = metaClass->findFunction(nullCheckMethod);
@@ -848,11 +857,19 @@ void CppGenerator::generateSmartPointerClass(TextStream &s, const GeneratorConte
writeMethodWrapper(s, md, signatureStream, {getter}, classContext);
}
- const QString refCountMethodName = typeEntry->refCountMethodName();
- if (!refCountMethodName.isEmpty()) { // optional
- auto it = functionGroups.constFind(refCountMethodName);
+ QStringList optionalMethods;
+ if (!typeEntry->refCountMethodName().isEmpty())
+ optionalMethods.append(typeEntry->refCountMethodName());
+ const QString valueCheckMethod = typeEntry->valueCheckMethod();
+ if (!valueCheckMethod.isEmpty() && !valueCheckMethod.startsWith(u"operator"))
+ optionalMethods.append(valueCheckMethod);
+ if (!typeEntry->nullCheckMethod().isEmpty())
+ optionalMethods.append(typeEntry->nullCheckMethod());
+
+ for (const QString &optionalMethod : optionalMethods) {
+ auto it = functionGroups.constFind(optionalMethod);
if (it == functionGroups.cend() || it.value().size() != 1)
- throw Exception(msgCannotFindSmartPointerRefCount(typeEntry));
+ throw Exception(msgCannotFindSmartPointerMethod(typeEntry, optionalMethod));
writeMethodWrapper(s, md, signatureStream, it.value(), classContext);
}
diff --git a/sources/shiboken6/tests/smartbinding/std_shared_ptr_test.py b/sources/shiboken6/tests/smartbinding/std_shared_ptr_test.py
index 1b96569a7..4617f8932 100644
--- a/sources/shiboken6/tests/smartbinding/std_shared_ptr_test.py
+++ b/sources/shiboken6/tests/smartbinding/std_shared_ptr_test.py
@@ -41,12 +41,21 @@ init_paths()
from smart import StdSharedPtrTestBench
+def call_func_on_ptr(ptr):
+ ptr.printInteger()
+
+
class StdSharedPtrTests(unittest.TestCase):
def testIt(self):
p = StdSharedPtrTestBench.createInteger()
StdSharedPtrTestBench.printInteger(p)
+ self.assertTrue(p)
+ call_func_on_ptr(p)
+
np = StdSharedPtrTestBench.createNullInteger()
StdSharedPtrTestBench.printInteger(np)
+ self.assertFalse(np)
+ self.assertRaises(AttributeError, call_func_on_ptr, np)
if __name__ == '__main__':
diff --git a/sources/shiboken6/tests/smartbinding/typesystem_smart.xml b/sources/shiboken6/tests/smartbinding/typesystem_smart.xml
index 8a68bb18d..2bbb1f56a 100644
--- a/sources/shiboken6/tests/smartbinding/typesystem_smart.xml
+++ b/sources/shiboken6/tests/smartbinding/typesystem_smart.xml
@@ -45,6 +45,7 @@
<modify-function signature="^.*$" remove="all"/>
<enum-type name="pointer_safety"/>
<smart-pointer-type name="shared_ptr" type="shared" getter="get"
+ value-check-method="operator bool"
ref-count-method="use_count"
instantiations="Integer">
<include file-name="memory" location="global"/>