From 853b637b02b07d502ddb5e84bcf60f6a8a58cf29 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 14 Sep 2018 10:51:17 +0200 Subject: shiboken: Extend exception specification Change boolean 'noexcept' flag into an enumeration that indicates whether a function throws, is 'noexcept' or the behavior is unknown. This makes it easier to implement an 'auto' mode for exception handling. Task-number: PYSIDE-62 Change-Id: I4e5405863e5af2a54f3528ba5eb5c51d3929703d Reviewed-by: Christian Tismer --- .../shiboken2/ApiExtractor/abstractmetabuilder.cpp | 2 +- .../shiboken2/ApiExtractor/abstractmetalang.cpp | 28 ++++++++++++++---- sources/shiboken2/ApiExtractor/abstractmetalang.h | 6 ++-- .../ApiExtractor/clangparser/clangbuilder.cpp | 28 +++++++++++++----- .../shiboken2/ApiExtractor/parser/codemodel.cpp | 15 ++++++---- sources/shiboken2/ApiExtractor/parser/codemodel.h | 6 ++-- .../ApiExtractor/parser/codemodel_enums.h | 7 +++++ .../ApiExtractor/tests/testmodifyfunction.cpp | 34 ++++++++++++++++++++++ .../ApiExtractor/tests/testmodifyfunction.h | 1 + 9 files changed, 102 insertions(+), 25 deletions(-) (limited to 'sources') diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 979ac010e..f5f5beef4 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -1921,7 +1921,7 @@ AbstractMetaFunction *AbstractMetaBuilderPrivate::traverseFunction(const Functio // Additional check for assignment/move assignment down below metaFunction->setFunctionType(functionTypeFromCodeModel(functionItem->functionType())); metaFunction->setConstant(functionItem->isConstant()); - metaFunction->setNoExcept(functionItem->isNoExcept()); + metaFunction->setExceptionSpecification(functionItem->exceptionSpecification()); if (ReportHandler::isDebug(ReportHandler::MediumDebug)) qCDebug(lcShiboken).noquote().nospace() << " - " << functionName << "()"; diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index c6570059c..22c119c94 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -406,7 +406,6 @@ AbstractMetaFunction::AbstractMetaFunction() m_reverse(false), m_userAdded(false), m_explicit(false), - m_isNoExcept(false), m_pointerOperator(false), m_isCallOperator(false) { @@ -526,7 +525,7 @@ AbstractMetaFunction *AbstractMetaFunction::copy() const if (type()) cpy->setType(type()->copy()); cpy->setConstant(isConstant()); - cpy->setNoExcept(isNoExcept()); + cpy->setExceptionSpecification(m_exceptionSpecification); for (AbstractMetaArgument *arg : m_arguments) cpy->addArgument(arg->copy()); @@ -960,6 +959,16 @@ bool AbstractMetaFunction::isConversionOperator(const QString& funcName) return opRegEx.match(funcName).hasMatch(); } +ExceptionSpecification AbstractMetaFunction::exceptionSpecification() const +{ + return m_exceptionSpecification; +} + +void AbstractMetaFunction::setExceptionSpecification(ExceptionSpecification e) +{ + m_exceptionSpecification = e; +} + bool AbstractMetaFunction::isOperatorOverload(const QString& funcName) { if (isConversionOperator(funcName)) @@ -1133,7 +1142,18 @@ static inline void formatMetaFunctionBrief(QDebug &d, const AbstractMetaFunction void AbstractMetaFunction::formatDebugVerbose(QDebug &d) const { - d << m_functionType << ' ' << m_type << ' ' << m_name << '('; + d << m_functionType << ' ' << m_type << ' ' << m_name; + switch (m_exceptionSpecification) { + case ExceptionSpecification::Unknown: + break; + case ExceptionSpecification::NoExcept: + d << " noexcept"; + break; + case ExceptionSpecification::Throws: + d << " throw(...)"; + break; + } + d << '('; for (int i = 0, count = m_arguments.size(); i < count; ++i) { if (i) d << ", "; @@ -1148,8 +1168,6 @@ void AbstractMetaFunction::formatDebugVerbose(QDebug &d) const d << " [userAdded]"; if (m_explicit) d << " [explicit]"; - if (m_isNoExcept) - d << " [noexcept]"; if (m_pointerOperator) d << " [operator->]"; if (m_isCallOperator) diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 36a125f9d..130a5f46f 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -846,8 +846,8 @@ public: static bool isConversionOperator(const QString& funcName); - bool isNoExcept() const { return m_isNoExcept; } - void setNoExcept(bool n) { m_isNoExcept = n; } + ExceptionSpecification exceptionSpecification() const; + void setExceptionSpecification(ExceptionSpecification e); bool isConversionOperator() const { @@ -1116,10 +1116,10 @@ private: uint m_reverse : 1; uint m_userAdded : 1; uint m_explicit : 1; - uint m_isNoExcept : 1; uint m_pointerOperator : 1; uint m_isCallOperator : 1; mutable int m_cachedAllowThread = -1; + ExceptionSpecification m_exceptionSpecification = ExceptionSpecification::Unknown; }; Q_DECLARE_OPERATORS_FOR_FLAGS(AbstractMetaFunction::CompareResult) diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp index e3e52cdd3..40f915028 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp @@ -257,6 +257,25 @@ bool BuilderPrivate::addClass(const CXCursor &cursor, CodeModel::ClassType t) return true; } +static inline ExceptionSpecification exceptionSpecificationFromClang(int ce) +{ + switch (ce) { + case CXCursor_ExceptionSpecificationKind_BasicNoexcept: + case CXCursor_ExceptionSpecificationKind_ComputedNoexcept: + case CXCursor_ExceptionSpecificationKind_DynamicNone: // throw() + return ExceptionSpecification::NoExcept; + case CXCursor_ExceptionSpecificationKind_Dynamic: // throw(t1..) + case CXCursor_ExceptionSpecificationKind_MSAny: // throw(...) + return ExceptionSpecification::Throws; + default: + // CXCursor_ExceptionSpecificationKind_None, + // CXCursor_ExceptionSpecificationKind_Unevaluated, + // CXCursor_ExceptionSpecificationKind_Uninstantiated + break; + } + return ExceptionSpecification::Unknown; +} + FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor, CodeModel::FunctionType t) const { @@ -270,14 +289,7 @@ FunctionModelItem BuilderPrivate::createFunction(const CXCursor &cursor, result->setFunctionType(t); result->setScope(m_scope); result->setStatic(clang_Cursor_getStorageClass(cursor) == CX_SC_Static); - switch (clang_getCursorExceptionSpecificationType(cursor)) { - case CXCursor_ExceptionSpecificationKind_BasicNoexcept: - case CXCursor_ExceptionSpecificationKind_ComputedNoexcept: - result->setNoExcept(true); - break; - default: - break; - } + result->setExceptionSpecification(exceptionSpecificationFromClang(clang_getCursorExceptionSpecificationType(cursor))); switch (clang_getCursorAvailability(cursor)) { case CXAvailability_Available: break; diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp index c9861b510..173f6dd23 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -1013,12 +1013,17 @@ void _FunctionModelItem::setVariadics(bool isVariadics) bool _FunctionModelItem::isNoExcept() const { - return m_isNoExcept; + return m_exceptionSpecification == ExceptionSpecification::NoExcept; } -void _FunctionModelItem::setNoExcept(bool n) +ExceptionSpecification _FunctionModelItem::exceptionSpecification() const { - m_isNoExcept = n; + return m_exceptionSpecification; +} + +void _FunctionModelItem::setExceptionSpecification(ExceptionSpecification e) +{ + m_exceptionSpecification = e; } bool _FunctionModelItem::isDeleted() const @@ -1116,7 +1121,7 @@ void _FunctionModelItem::setInvokable(bool isInvokable) void _FunctionModelItem::formatDebug(QDebug &d) const { _MemberModelItem::formatDebug(d); - d << ", type=" << m_functionType; + d << ", type=" << m_functionType << ", exspec=" << int(m_exceptionSpecification); if (m_isDeleted) d << " [deleted!]"; if (m_isInline) @@ -1133,8 +1138,6 @@ void _FunctionModelItem::formatDebug(QDebug &d) const d << " [abstract]"; if (m_isExplicit) d << " [explicit]"; - if (m_isNoExcept) - d << " [noexcept]"; if (m_isInvokable) d << " [invokable]"; formatModelItemList(d, ", arguments=", m_arguments); diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h index aad1a8eaa..7bd82bd1d 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -611,7 +611,9 @@ public: bool isSimilar(const FunctionModelItem &other) const; bool isNoExcept() const; - void setNoExcept(bool n); + + ExceptionSpecification exceptionSpecification() const; + void setExceptionSpecification(ExceptionSpecification e); #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; @@ -631,11 +633,11 @@ private: uint m_isAbstract: 1; uint m_isExplicit: 1; uint m_isVariadics: 1; - uint m_isNoExcept : 1; uint m_isInvokable : 1; // Qt }; uint m_flags; }; + ExceptionSpecification m_exceptionSpecification = ExceptionSpecification::Unknown; }; class _VariableModelItem: public _MemberModelItem diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h index 9a3cc0e07..1713ba42f 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h @@ -47,4 +47,11 @@ enum class Indirection ConstPointer // int *const }; +enum class ExceptionSpecification +{ + Unknown, + NoExcept, + Throws +}; + #endif // CODEMODEL_ENUMS_H diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp index 4743b7167..8bb63c6b1 100644 --- a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp @@ -312,4 +312,38 @@ void TestModifyFunction::testGlobalFunctionModification() QCOMPARE(arg->defaultValueExpression(), QLatin1String("A()")); } +void TestModifyFunction::testExceptionSpecification() +{ + const char cppCode[] = R"CPP( +struct A { + void unspecified(); + void nonThrowing() noexcept; + void throwing() throw(int); +}; +)CPP"; + const char xmlCode[] = R"XML( + + + + +)XML"; + QScopedPointer builder(TestUtil::parse(cppCode, xmlCode, false)); + QVERIFY(!builder.isNull()); + + const AbstractMetaClass *classA = AbstractMetaClass::findClass(builder->classes(), QLatin1String("A")); + QVERIFY(classA); + + const AbstractMetaFunction *f = classA->findFunction(QStringLiteral("unspecified")); + QVERIFY(f); + QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::Unknown); + + f = classA->findFunction(QStringLiteral("nonThrowing")); + QVERIFY(f); + QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::NoExcept); + + f = classA->findFunction(QStringLiteral("throwing")); + QVERIFY(f); + QCOMPARE(f->exceptionSpecification(), ExceptionSpecification::Throws); +} + QTEST_APPLESS_MAIN(TestModifyFunction) diff --git a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h index 636b3ef34..494f31991 100644 --- a/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h +++ b/sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h @@ -42,6 +42,7 @@ class TestModifyFunction : public QObject void testRenameArgument(); void invalidateAfterUse(); void testGlobalFunctionModification(); + void testExceptionSpecification(); }; #endif -- cgit v1.2.3