aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2018-09-14 10:51:17 +0200
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2018-09-17 12:22:27 +0000
commit853b637b02b07d502ddb5e84bcf60f6a8a58cf29 (patch)
tree1572e29be67998ef5be7bd77cf11f4b6ef723730 /sources
parent792be5e470107d6d2752fd78e3922427c313b67a (diff)
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 <tismer@stackless.com>
Diffstat (limited to 'sources')
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp2
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp28
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h6
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp28
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.cpp15
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.h6
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel_enums.h7
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testmodifyfunction.cpp34
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testmodifyfunction.h1
9 files changed, 102 insertions, 25 deletions
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(
+<typesystem package="Foo">
+ <primitive-type name='int'/>
+ <object-type name='A'>
+ </object-type>
+</typesystem>)XML";
+ QScopedPointer<AbstractMetaBuilder> 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