aboutsummaryrefslogtreecommitdiffstats
path: root/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2019-03-01 08:19:26 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2019-03-01 08:19:26 +0100
commit639c5df6ad397ba98ca727c744278372087b2d46 (patch)
tree31e84eab330cb8a0a1f1236c85c8fad968918ceb /sources/shiboken2/ApiExtractor/abstractmetalang.cpp
parentb97ccab8c268d260f704e11b33d64fa31f74e258 (diff)
parent099f3f46ca9ec1362f211278df4b3e4949b0a339 (diff)
Merge remote-tracking branch 'origin/5.12' into dev
Diffstat (limited to 'sources/shiboken2/ApiExtractor/abstractmetalang.cpp')
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp124
1 files changed, 102 insertions, 22 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
index 73f1bf621..a10a15b08 100644
--- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
+++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp
@@ -72,6 +72,26 @@ MetaClass *findByName(QVector<MetaClass *> haystack, QStringView needle)
return nullptr;
}
+// Helper for recursing the base classes of an AbstractMetaClass.
+// Returns the class for which the predicate is true.
+template <class Predicate>
+const AbstractMetaClass *recurseClassHierarchy(const AbstractMetaClass *klass,
+ Predicate pred)
+{
+ if (pred(klass))
+ return klass;
+ if (auto base = klass->baseClass()) {
+ if (auto r = recurseClassHierarchy(base, pred))
+ return r;
+ }
+ const auto interfaces = klass->interfaces();
+ for (auto i : interfaces) {
+ if (auto r = recurseClassHierarchy(i, pred))
+ return r;
+ }
+ return nullptr;
+}
+
/*******************************************************************************
* AbstractMetaVariable
*/
@@ -411,8 +431,7 @@ AbstractMetaFunction::AbstractMetaFunction()
m_userAdded(false),
m_explicit(false),
m_pointerOperator(false),
- m_isCallOperator(false),
- m_generateExceptionHandling(false)
+ m_isCallOperator(false)
{
}
@@ -531,7 +550,8 @@ AbstractMetaFunction *AbstractMetaFunction::copy() const
cpy->setType(type()->copy());
cpy->setConstant(isConstant());
cpy->setExceptionSpecification(m_exceptionSpecification);
- cpy->setGenerateExceptionHandling(m_generateExceptionHandling);
+ cpy->setAllowThreadModification(m_allowThreadModification);
+ cpy->setExceptionHandlingModification(m_exceptionHandlingModification);
for (AbstractMetaArgument *arg : m_arguments)
cpy->addArgument(arg->copy());
@@ -754,28 +774,40 @@ bool AbstractMetaFunction::autoDetectAllowThread() const
return !maybeGetter;
}
-bool AbstractMetaFunction::allowThread() const
+static inline TypeSystem::AllowThread allowThreadMod(const AbstractMetaClass *klass)
{
- using AllowThread = TypeSystem::AllowThread;
+ return klass->typeEntry()->allowThread();
+}
- if (m_cachedAllowThread < 0) {
- AllowThread allowThread = AllowThread::Auto;
- // Find a modification that specifies allowThread
- const FunctionModificationList &modifications = this->modifications(declaringClass());
- for (const FunctionModification &modification : modifications) {
- if (modification.allowThread() != AllowThread::Unspecified) {
- allowThread = modification.allowThread();
- break;
- }
- }
+static inline bool hasAllowThreadMod(const AbstractMetaClass *klass)
+{
+ return allowThreadMod(klass) != TypeSystem::AllowThread::Unspecified;
+}
- m_cachedAllowThread = allowThread == AllowThread::Allow
- || (allowThread == AllowThread::Auto && autoDetectAllowThread()) ? 1 : 0;
+bool AbstractMetaFunction::allowThread() const
+{
+ auto allowThreadModification = m_allowThreadModification;
+ // If there is no modification on the function, check for a base class.
+ if (m_class && allowThreadModification == TypeSystem::AllowThread::Unspecified) {
+ if (auto base = recurseClassHierarchy(m_class, hasAllowThreadMod))
+ allowThreadModification = allowThreadMod(base);
+ }
- if (m_cachedAllowThread == 0)
- qCDebug(lcShiboken).noquote() << msgDisallowThread(this);
+ bool result = true;
+ switch (allowThreadModification) {
+ case TypeSystem::AllowThread::Disallow:
+ result = false;
+ break;
+ case TypeSystem::AllowThread::Allow:
+ break;
+ case TypeSystem::AllowThread::Auto:
+ case TypeSystem::AllowThread::Unspecified:
+ result = autoDetectAllowThread();
+ break;
}
- return m_cachedAllowThread > 0;
+ if (!result)
+ qCDebug(lcShiboken).noquote() << msgDisallowThread(this);
+ return result;
}
TypeSystem::Ownership AbstractMetaFunction::ownership(const AbstractMetaClass *cls, TypeSystem::Language language, int key) const
@@ -975,6 +1007,54 @@ void AbstractMetaFunction::setExceptionSpecification(ExceptionSpecification e)
m_exceptionSpecification = e;
}
+static inline TypeSystem::ExceptionHandling exceptionMod(const AbstractMetaClass *klass)
+{
+ return klass->typeEntry()->exceptionHandling();
+}
+
+static inline bool hasExceptionMod(const AbstractMetaClass *klass)
+{
+ return exceptionMod(klass) != TypeSystem::ExceptionHandling::Unspecified;
+}
+
+bool AbstractMetaFunction::generateExceptionHandling() const
+{
+ switch (m_functionType) {
+ case AbstractMetaFunction::CopyConstructorFunction:
+ case AbstractMetaFunction::MoveConstructorFunction:
+ case AbstractMetaFunction::AssignmentOperatorFunction:
+ case AbstractMetaFunction::MoveAssignmentOperatorFunction:
+ case AbstractMetaFunction::DestructorFunction:
+ return false;
+ default:
+ break;
+ }
+
+ auto exceptionHandlingModification = m_exceptionHandlingModification;
+ // If there is no modification on the function, check for a base class.
+ if (m_class && exceptionHandlingModification == TypeSystem::ExceptionHandling::Unspecified) {
+ if (auto base = recurseClassHierarchy(m_class, hasExceptionMod))
+ exceptionHandlingModification = exceptionMod(base);
+ }
+
+ bool result = false;
+ switch (exceptionHandlingModification) {
+ case TypeSystem::ExceptionHandling::On:
+ result = true;
+ break;
+ case TypeSystem::ExceptionHandling::AutoDefaultToOn:
+ result = m_exceptionSpecification != ExceptionSpecification::NoExcept;
+ break;
+ case TypeSystem::ExceptionHandling::AutoDefaultToOff:
+ result = m_exceptionSpecification == ExceptionSpecification::Throws;
+ break;
+ case TypeSystem::ExceptionHandling::Unspecified:
+ case TypeSystem::ExceptionHandling::Off:
+ break;
+ }
+ return result;
+}
+
bool AbstractMetaFunction::isOperatorOverload(const QString& funcName)
{
if (isConversionOperator(funcName))
@@ -1159,8 +1239,8 @@ void AbstractMetaFunction::formatDebugVerbose(QDebug &d) const
d << " throw(...)";
break;
}
- if (m_generateExceptionHandling)
- d << "[generate-exception-handling]";
+ if (m_exceptionHandlingModification != TypeSystem::ExceptionHandling::Unspecified)
+ d << " exeption-mod " << int(m_exceptionHandlingModification);
d << '(';
for (int i = 0, count = m_arguments.size(); i < count; ++i) {
if (i)