diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-03-01 08:19:26 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2019-03-01 08:19:26 +0100 |
commit | 639c5df6ad397ba98ca727c744278372087b2d46 (patch) | |
tree | 31e84eab330cb8a0a1f1236c85c8fad968918ceb /sources/shiboken2/ApiExtractor/abstractmetalang.cpp | |
parent | b97ccab8c268d260f704e11b33d64fa31f74e258 (diff) | |
parent | 099f3f46ca9ec1362f211278df4b3e4949b0a339 (diff) |
Merge remote-tracking branch 'origin/5.12' into dev
Change-Id: I0f3c2de6195b863dc60ecbb988e4e14182e3ad03
Diffstat (limited to 'sources/shiboken2/ApiExtractor/abstractmetalang.cpp')
-rw-r--r-- | sources/shiboken2/ApiExtractor/abstractmetalang.cpp | 124 |
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) |