diff options
author | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2018-03-19 17:24:00 +0100 |
---|---|---|
committer | Friedemann Kleint <Friedemann.Kleint@qt.io> | 2018-04-19 12:51:14 +0000 |
commit | fb7386c18c15ca83aebe8f973c1b018d016baaa9 (patch) | |
tree | 91f0c2988af2e4133a2fdc702fccce69a623b9bf /sources | |
parent | a89690409972501741c846ac8ad4a499f2982809 (diff) |
shiboken: Use enum values from Clang
Remove a lot of ugly value parsing code in favor of
clang_getEnumConstantDeclValue() and
clang_getEnumConstantDeclUnsignedValue() depending on the
type.
Introduce a class EnumValue containing a union of qint64 and quint64 values
to represent signed/unsigned values correctly and use that in the code model
and meta language classes.
Change-Id: If2efb7cfd560237907678b8f6fdfb0bc689c0c93
Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'sources')
13 files changed, 277 insertions, 264 deletions
diff --git a/sources/shiboken2/ApiExtractor/CMakeLists.txt b/sources/shiboken2/ApiExtractor/CMakeLists.txt index 4355e32ef..20d1d9a89 100644 --- a/sources/shiboken2/ApiExtractor/CMakeLists.txt +++ b/sources/shiboken2/ApiExtractor/CMakeLists.txt @@ -55,6 +55,7 @@ clangparser/clangdebugutils.cpp clangparser/clangutils.cpp # Old parser parser/codemodel.cpp +parser/enumvalue.cpp ) set(APIEXTRACTOR_EXTRA_INCLUDES ${CLANG_EXTRA_INCLUDES}) diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index c38a145bd..739e32896 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -508,8 +508,6 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) addAbstractMetaClass(cls); } - figureOutEnumValues(); - for (const ClassModelItem &item : typeValues) traverseClassMembers(item); @@ -684,7 +682,6 @@ void AbstractMetaBuilderPrivate::traverseDom(const FileModelItem &dom) traverseStreamOperator(item); } - figureOutDefaultEnumArguments(); checkFunctionModifications(); // sort all classes topologically @@ -839,207 +836,6 @@ AbstractMetaClass *AbstractMetaBuilderPrivate::traverseNamespace(const FileModel return metaClass; } -struct Operator -{ - enum Type { Complement, Plus, ShiftRight, ShiftLeft, None }; - - Operator() : type(None) {} - - int calculate(int x) - { - switch (type) { - case Complement: return ~value; - case Plus: return x + value; - case ShiftRight: return x >> value; - case ShiftLeft: return x << value; - case None: return x; - } - return x; - } - - Type type; - int value; -}; - - - -Operator findOperator(QString* s) -{ - const char *names[] = { - "~", - "+", - ">>", - "<<" - }; - - for (int i = 0; i < Operator::None; ++i) { - QString name = QLatin1String(names[i]); - QString str = *s; - int splitPoint = str.indexOf(name); - if (splitPoint > -1) { - bool ok; - QString right = str.mid(splitPoint + name.length()); - Operator op; - - op.value = right.toInt(&ok); - if (!ok && right.length() > 0 && right.at(right.length() - 1).toLower() == QLatin1Char('u')) - op.value = right.left(right.length() - 1).toUInt(&ok, 0); - - if (ok) { - op.type = Operator::Type(i); - if (splitPoint > 0) - *s = str.left(splitPoint).trimmed(); - else - *s = QString(); - return op; - } - } - } - return Operator(); -} - -int AbstractMetaBuilderPrivate::figureOutEnumValue(const QString &stringValue, - int oldValuevalue, - AbstractMetaEnum *metaEnum, - AbstractMetaFunction *metaFunction) -{ - if (stringValue.isEmpty()) - return oldValuevalue; - - QStringList stringValues = stringValue.split(QLatin1Char('|')); - - int returnValue = 0; - - bool matched = false; - - for (int i = 0; i < stringValues.size(); ++i) { - QString s = stringValues.at(i).trimmed(); - - bool ok; - int v; - - Operator op = findOperator(&s); - - if (s.length() > 0 && s.at(0) == QLatin1Char('0')) - v = s.toUInt(&ok, 0); - else if (s.length() > 0 && s.at(s.length() - 1).toLower() == QLatin1Char('u')) - v = s.left(s.length() - 1).toUInt(&ok, 0); - else - v = s.toInt(&ok); - - if (ok || s.isEmpty()) { - matched = true; - } else if (m_enumValues.contains(s)) { - v = m_enumValues[s]->value(); - matched = true; - } else { - if (metaEnum) { - v = findOutValueFromString(s, matched); - if (!matched) { - QString enclosingClass = QString(metaEnum->enclosingClass() ? metaEnum->enclosingClass()->name() + colonColon() : QString()); - qCWarning(lcShiboken).noquote().nospace() - << "unhandled enum value: " << s << " in " - << enclosingClass << metaEnum->name() << " from header '" - << metaEnum->typeEntry()->include().name() << '\''; - } - } else { - qCWarning(lcShiboken) << "unhandled enum value: Unknown enum"; - } - } - - if (matched) - returnValue |= op.calculate(v); - } - - if (!matched) { - QString warn = QStringLiteral("unmatched enum %1").arg(stringValue); - - if (metaFunction) { - warn += QStringLiteral(" when parsing default value of '%1' in class '%2'") - .arg(metaFunction->name(), metaFunction->implementingClass()->name()); - } - warn += QLatin1String(" from header '") + metaEnum->typeEntry()->include().name() - + QLatin1Char('\''); - - qCWarning(lcShiboken).noquote().nospace() << warn; - returnValue = oldValuevalue; - } - - return returnValue; -} - -void AbstractMetaBuilderPrivate::figureOutEnumValuesForClass(AbstractMetaClass *metaClass, - QSet<AbstractMetaClass *> *classes) -{ - AbstractMetaClass* base = metaClass->baseClass(); - - if (base && !classes->contains(base)) - figureOutEnumValuesForClass(base, classes); - - if (classes->contains(metaClass)) - return; - - const AbstractMetaEnumList &enums = metaClass->enums(); - for (AbstractMetaEnum* e : enums) { - if (!e) { - qCWarning(lcShiboken).noquote().nospace() << "bad enum in class " << metaClass->name(); - continue; - } - AbstractMetaEnumValueList lst = e->values(); - int value = 0; - for (int i = 0; i < lst.size(); ++i) { - value = figureOutEnumValue(lst.at(i)->stringValue(), value, e); - lst.at(i)->setValue(value); - value++; - } - } - - *classes += metaClass; -} - - -void AbstractMetaBuilderPrivate::figureOutEnumValues() -{ - // Keep a set of classes that we already traversed. We use this to - // enforce that we traverse base classes prior to subclasses. - QSet<AbstractMetaClass*> classes; - for (AbstractMetaClass *c : qAsConst(m_metaClasses)) - figureOutEnumValuesForClass(c, &classes); - - for (AbstractMetaEnum* metaEnum : qAsConst(m_globalEnums)) { - AbstractMetaEnumValueList enumValues = metaEnum->values(); - int value = 0; - for (int i = 0; i < enumValues.size(); ++i) { - value = figureOutEnumValue(enumValues.at(i)->stringValue(), value, metaEnum); - enumValues.at(i)->setValue(value); - value++; - } - } -} - -void AbstractMetaBuilderPrivate::figureOutDefaultEnumArguments() -{ - for (AbstractMetaClass* metaClass : qAsConst(m_metaClasses)) { - const AbstractMetaFunctionList &functions = metaClass->functions(); - for (AbstractMetaFunction* metaFunction : functions) { - const AbstractMetaArgumentList &arguments = metaFunction->arguments(); - for (AbstractMetaArgument *arg : arguments) { - QString expr = arg->defaultValueExpression(); - if (expr.isEmpty()) - continue; - - if (!metaFunction->replacedDefaultExpression(metaFunction->implementingClass(), - arg->argumentIndex() + 1).isEmpty()) { - continue; - } - - arg->setDefaultValueExpression(expr); - } - } - } -} - - AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumItem, AbstractMetaClass *enclosing, const QSet<QString> &enumsDeclarations) @@ -1097,12 +893,14 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte AbstractMetaEnum *metaEnum = new AbstractMetaEnum; metaEnum->setEnumKind(enumItem->enumKind()); + metaEnum->setSigned(enumItem->isSigned()); if (enumsDeclarations.contains(qualifiedName) || enumsDeclarations.contains(enumName)) { metaEnum->setHasQEnumsDeclaration(true); } - metaEnum->setTypeEntry((EnumTypeEntry*) typeEntry); + EnumTypeEntry *enumTypeEntry = static_cast<EnumTypeEntry *>(typeEntry); + metaEnum->setTypeEntry(enumTypeEntry); switch (enumItem->accessPolicy()) { case CodeModel::Public: *metaEnum += AbstractMetaAttributes::Public; @@ -1128,7 +926,8 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte metaEnumValue->setName(value->name()); // Deciding the enum value... - metaEnumValue->setStringValue(value->value()); + metaEnumValue->setStringValue(value->stringValue()); + metaEnumValue->setValue(value->value()); metaEnum->addEnumValue(metaEnumValue); if (ReportHandler::isDebug(ReportHandler::FullDebug)) { @@ -1159,7 +958,9 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte name += colonColon(); } name += e->name(); - EnumValueTypeEntry* enumValue = new EnumValueTypeEntry(name, e->value(), static_cast<EnumTypeEntry*>(typeEntry), typeEntry->version()); + EnumValueTypeEntry *enumValue = + new EnumValueTypeEntry(name, e->stringValue(), + enumTypeEntry, enumTypeEntry->version()); TypeDatabase::instance()->addType(enumValue); } @@ -2571,9 +2372,9 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ arrayType->setArrayElementType(elementType); if (!typeInfo.arrays.at(i).isEmpty()) { bool _ok; - const int elems = findOutValueFromString(typeInfo.arrays.at(i), _ok); + const qint64 elems = findOutValueFromString(typeInfo.arrays.at(i), _ok); if (_ok) - arrayType->setArrayElementCount(elems); + arrayType->setArrayElementCount(int(elems)); } arrayType->setTypeEntry(new ArrayTypeEntry(elementType->typeEntry() , elementType->typeEntry()->version())); decideUsagePattern(arrayType); @@ -2713,9 +2514,9 @@ AbstractMetaType *AbstractMetaBuilderPrivate::translateType(const TypeInfo &_typ } -int AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringValue, bool &ok) +qint64 AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringValue, bool &ok) { - int value = stringValue.toInt(&ok); + qint64 value = stringValue.toLongLong(&ok); if (ok) return value; @@ -2736,13 +2537,13 @@ int AbstractMetaBuilderPrivate::findOutValueFromString(const QString &stringValu AbstractMetaEnumValue *enumValue = AbstractMetaClass::findEnumValue(m_metaClasses, stringValue); if (enumValue) { ok = true; - return enumValue->value(); + return enumValue->value().value(); } for (AbstractMetaEnum *metaEnum : qAsConst(m_globalEnums)) { if (const AbstractMetaEnumValue *ev = metaEnum->findEnumValue(stringValue)) { ok = true; - return ev->value(); + return ev->value().value(); } } diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h index 7a2565914..7f5e866ab 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h @@ -60,11 +60,6 @@ public: AbstractMetaClass *argumentToClass(ArgumentModelItem); - void figureOutEnumValuesForClass(AbstractMetaClass *metaClass, QSet<AbstractMetaClass *> *classes); - int figureOutEnumValue(const QString &name, int value, AbstractMetaEnum *meta_enum, AbstractMetaFunction *metaFunction = 0); - void figureOutEnumValues(); - void figureOutDefaultEnumArguments(); - void addAbstractMetaClass(AbstractMetaClass *cls); AbstractMetaClass *traverseTypeDef(const FileModelItem &dom, const TypeDefModelItem &typeDef); @@ -129,7 +124,7 @@ public: bool resolveType = true, bool resolveScope = true); - int findOutValueFromString(const QString &stringValue, bool &ok); + qint64 findOutValueFromString(const QString &stringValue, bool &ok); void decideUsagePattern(AbstractMetaType *type); diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index 905504ca3..235413165 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -1700,7 +1700,10 @@ QDebug operator<<(QDebug d, const AbstractMetaEnum *ae) d.nospace(); d << "AbstractMetaEnum("; if (ae) { - d << ae->fullName() << '['; + d << ae->fullName(); + if (!ae->isSigned()) + d << " (unsigned) "; + d << '['; const AbstractMetaEnumValueList &values = ae->values(); for (int i = 0, count = values.size(); i < count; ++i) { if (i) @@ -2411,7 +2414,7 @@ QDebug operator<<(QDebug d, const AbstractMetaClass *ac) */ AbstractMetaEnum::AbstractMetaEnum() : - m_hasQenumsDeclaration(false) + m_hasQenumsDeclaration(false), m_signed(true) { } diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index c51f7704b..7e0bfa322 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -34,6 +34,7 @@ #include "typesystem_typedefs.h" #include "parser/codemodel_enums.h" +#include "parser/enumvalue.h" #include <QtCore/qobjectdefs.h> #include <QtCore/QStringList> @@ -1090,12 +1091,12 @@ class AbstractMetaEnumValue public: AbstractMetaEnumValue() {} - int value() const + EnumValue value() const { return m_value; } - void setValue(int value) + void setValue(EnumValue value) { m_value = value; } @@ -1134,7 +1135,7 @@ private: QString m_name; QString m_stringValue; - int m_value = 0; + EnumValue m_value; Documentation m_doc; }; @@ -1204,6 +1205,9 @@ public: m_class = c; } + bool isSigned() const { return m_signed; } + void setSigned(bool s) { m_signed = s; } + private: AbstractMetaEnumValueList m_enumValues; EnumTypeEntry *m_typeEntry = nullptr; @@ -1211,6 +1215,7 @@ private: EnumKind m_enumKind = CEnum; uint m_hasQenumsDeclaration : 1; + uint m_signed : 1; }; #ifndef QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp index 0984246c8..b57ef2f43 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp @@ -124,6 +124,24 @@ static void setFileName(const CXCursor &cursor, _CodeModelItem *item) } } +static bool isSigned(CXTypeKind kind) +{ + switch (kind) { + case CXType_UChar: + case CXType_Char16: + case CXType_Char32: + case CXType_UShort: + case CXType_UInt: + case CXType_ULong: + case CXType_ULongLong: + case CXType_UInt128: + return false; + default: + break; + } + return true; +} + class BuilderPrivate { public: typedef QHash<CXCursor, ClassModelItem> CursorClassHash; @@ -687,6 +705,7 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) setFileName(cursor, d->m_currentEnum.data()); d->m_currentEnum->setScope(d->m_scope); d->m_currentEnum->setEnumKind(kind); + d->m_currentEnum->setSigned(isSigned(clang_getEnumDeclIntegerType(cursor).kind)); if (!qSharedPointerDynamicCast<_ClassModelItem>(d->m_scopeStack.back()).isNull()) d->m_currentEnum->setAccessPolicy(accessPolicy(clang_getCXXAccessSpecifier(cursor))); d->m_scopeStack.back()->addEnum(d->m_currentEnum); @@ -700,8 +719,14 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) appendDiagnostic(d); return Error; } + EnumValue enumValue; + if (d->m_currentEnum->isSigned()) + enumValue.setValue(clang_getEnumConstantDeclValue(cursor)); + else + enumValue.setUnsignedValue(clang_getEnumConstantDeclUnsignedValue(cursor)); EnumeratorModelItem enumConstant(new _EnumeratorModelItem(d->m_model, name)); - enumConstant->setValue(d->cursorValueExpression(this, cursor)); + enumConstant->setStringValue(d->cursorValueExpression(this, cursor)); + enumConstant->setValue(enumValue); d->m_currentEnum->addEnumerator(enumConstant); } break; diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp index fbfeaadf7..1262f5901 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -1014,6 +1014,16 @@ void _EnumModelItem::addEnumerator(EnumeratorModelItem item) m_enumerators.append(item); } +bool _EnumModelItem::isSigned() const +{ + return m_signed; +} + +void _EnumModelItem::setSigned(bool s) +{ + m_signed = s; +} + #ifndef QT_NO_DEBUG_STREAM void _EnumModelItem::formatDebug(QDebug &d) const { @@ -1028,6 +1038,8 @@ void _EnumModelItem::formatDebug(QDebug &d) const d << " (class)"; break; } + if (!m_signed) + d << " (unsigned)"; formatModelItemList(d, ", enumerators=", m_enumerators); } #endif // !QT_NO_DEBUG_STREAM @@ -1037,22 +1049,21 @@ _EnumeratorModelItem::~_EnumeratorModelItem() { } -QString _EnumeratorModelItem::value() const +QString _EnumeratorModelItem::stringValue() const { - return m_value; + return m_stringValue; } -void _EnumeratorModelItem::setValue(const QString &value) +void _EnumeratorModelItem::setStringValue(const QString &value) { - m_value = value; + m_stringValue = value; } #ifndef QT_NO_DEBUG_STREAM void _EnumeratorModelItem::formatDebug(QDebug &d) const { _CodeModelItem::formatDebug(d); - if (!m_value.isEmpty()) - d << ", value=\"" << m_value << '"'; + d << ", value=" << m_value << ", stringValue=\"" << m_stringValue << '"'; } #endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h index b300cf249..ed0eedf7d 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -33,6 +33,7 @@ #include "codemodel_fwd.h" #include "codemodel_enums.h" +#include "enumvalue.h" #include <QtCore/QHash> #include <QtCore/QSet> @@ -633,6 +634,8 @@ public: explicit _EnumModelItem(CodeModel *model, const QString &name, int kind = __node_kind) : _CodeModelItem(model, name, kind) {} + explicit _EnumModelItem(CodeModel *model, int kind = __node_kind) + : _CodeModelItem(model, kind) {} ~_EnumModelItem(); CodeModel::AccessPolicy accessPolicy() const; @@ -648,10 +651,14 @@ public: void formatDebug(QDebug &d) const override; #endif + bool isSigned() const; + void setSigned(bool s); + private: CodeModel::AccessPolicy m_accessPolicy = CodeModel::Public; EnumeratorList m_enumerators; EnumKind m_enumKind = CEnum; + bool m_signed = true; }; class _EnumeratorModelItem: public _CodeModelItem @@ -665,15 +672,19 @@ public: : _CodeModelItem(model, name, kind) {} ~_EnumeratorModelItem(); - QString value() const; - void setValue(const QString &value); + QString stringValue() const; + void setStringValue(const QString &stringValue); + + EnumValue value() const { return m_value; } + void setValue(EnumValue v) { m_value = v; } #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; #endif private: - QString m_value; + QString m_stringValue; + EnumValue m_value; }; class _TemplateParameterModelItem: public _CodeModelItem diff --git a/sources/shiboken2/ApiExtractor/parser/enumvalue.cpp b/sources/shiboken2/ApiExtractor/parser/enumvalue.cpp new file mode 100644 index 000000000..84723eb14 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/parser/enumvalue.cpp @@ -0,0 +1,76 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include "enumvalue.h" + +#include <QtCore/QDebug> +#include <QtCore/QString> +#include <QtCore/QTextStream> + +QString EnumValue::toString() const +{ + return m_type == EnumValue::Signed + ? QString::number(m_value) : QString::number(m_unsignedValue); +} + +void EnumValue::setValue(qint64 v) +{ + m_value = v; + m_type = Signed; +} + +void EnumValue::setUnsignedValue(quint64 v) +{ + m_unsignedValue = v; + m_type = Unsigned; +} + +#ifndef QT_NO_DEBUG_STREAM +QDebug operator<<(QDebug d,const EnumValue &v) +{ + QDebugStateSaver saver(d); + d.nospace(); + d.noquote(); + d << "EnumValue("; + if (v.m_type == EnumValue::Signed) + d << v.m_value; + else + d << v.m_unsignedValue << 'u'; + d << ')'; + return d; +} +#endif // !QT_NO_DEBUG_STREAM + +QTextStream &operator<<(QTextStream &s, const EnumValue &v) +{ + if (v.m_type == EnumValue::Signed) + s << v.m_value; + else + s << v.m_unsignedValue; + return s; +} diff --git a/sources/shiboken2/ApiExtractor/parser/enumvalue.h b/sources/shiboken2/ApiExtractor/parser/enumvalue.h new file mode 100644 index 000000000..2e2070306 --- /dev/null +++ b/sources/shiboken2/ApiExtractor/parser/enumvalue.h @@ -0,0 +1,70 @@ +/**************************************************************************** +** +** Copyright (C) 2018 The Qt Company Ltd. +** Contact: https://www.qt.io/licensing/ +** +** This file is part of PySide2. +** +** $QT_BEGIN_LICENSE:GPL-EXCEPT$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see https://www.qt.io/terms-conditions. For further +** information use the contact form at https://www.qt.io/contact-us. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 3 as published by the Free Software +** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT +** included in the packaging of this file. Please review the following +** information to ensure the GNU General Public License requirements will +** be met: https://www.gnu.org/licenses/gpl-3.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#ifndef ENUMVALUE_H +#define ENUMVALUE_H + +#include <QtCore/QtGlobal> + +QT_FORWARD_DECLARE_CLASS(QDebug) +QT_FORWARD_DECLARE_CLASS(QString) +QT_FORWARD_DECLARE_CLASS(QTextStream) + +class EnumValue +{ +public: + enum Type + { + Signed, + Unsigned + }; + + QString toString() const; + + Type type() { return m_type; } + qint64 value() const { return m_value; } + quint64 unsignedValue() const { return m_unsignedValue; } + + void setValue(qint64 v); + void setUnsignedValue(quint64 v); + +private: +#ifndef QT_NO_DEBUG_STREAM + friend QDebug operator<<(QDebug, const EnumValue &); +#endif + friend QTextStream &operator<<(QTextStream &, const EnumValue &); + + union + { + qint64 m_value = 0; + quint64 m_unsignedValue; + }; + Type m_type = Signed; +}; + +#endif // ENUMVALUE_H diff --git a/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp b/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp index cbeb216c9..eb10fc8a0 100644 --- a/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp @@ -133,7 +133,7 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValue() const AbstractMetaArgument* arg = classA->functions().last()->arguments().first(); QVERIFY(arg->type()->isArray()); - QCOMPARE(arg->type()->arrayElementCount(), nvalues->value()); + QCOMPARE(arg->type()->arrayElementCount(), nvalues->value().value()); QCOMPARE(arg->type()->arrayElementType()->name(), QLatin1String("double")); }; @@ -164,7 +164,7 @@ void TestArrayArgument::testArrayArgumentWithSizeDefinedByEnumValueFromGlobalEnu const AbstractMetaArgument* arg = classA->functions().last()->arguments().first(); QVERIFY(arg->type()->isArray()); - QCOMPARE(arg->type()->arrayElementCount(), nvalues->value()); + QCOMPARE(arg->type()->arrayElementCount(), nvalues->value().value()); QCOMPARE(arg->type()->arrayElementType()->name(), QLatin1String("double")); }; diff --git a/sources/shiboken2/ApiExtractor/tests/testenum.cpp b/sources/shiboken2/ApiExtractor/tests/testenum.cpp index 55c098840..970f6d00c 100644 --- a/sources/shiboken2/ApiExtractor/tests/testenum.cpp +++ b/sources/shiboken2/ApiExtractor/tests/testenum.cpp @@ -149,12 +149,12 @@ void TestEnum::testAnonymousEnum() AbstractMetaEnumValue* enumValueA0 = anonEnumA1->values().first(); QCOMPARE(enumValueA0->name(), QLatin1String("A0")); - QCOMPARE(enumValueA0->value(), 0); + QCOMPARE(enumValueA0->value().value(), 0); QCOMPARE(enumValueA0->stringValue(), QString()); AbstractMetaEnumValue* enumValueA1 = anonEnumA1->values().last(); QCOMPARE(enumValueA1->name(), QLatin1String("A1")); - QCOMPARE(enumValueA1->value(), 1); + QCOMPARE(enumValueA1->value().value(), 1); QCOMPARE(enumValueA1->stringValue(), QString()); AbstractMetaEnum* anonEnumIsThis = classes[0]->findEnum(QLatin1String("isThis")); @@ -164,12 +164,12 @@ void TestEnum::testAnonymousEnum() AbstractMetaEnumValue* enumValueIsThis = anonEnumIsThis->values().first(); QCOMPARE(enumValueIsThis->name(), QLatin1String("isThis")); - QCOMPARE(enumValueIsThis->value(), static_cast<int>(true)); + QCOMPARE(enumValueIsThis->value().value(), static_cast<int>(true)); QCOMPARE(enumValueIsThis->stringValue(), QLatin1String("true")); AbstractMetaEnumValue* enumValueIsThat = anonEnumIsThis->values().last(); QCOMPARE(enumValueIsThat->name(), QLatin1String("isThat")); - QCOMPARE(enumValueIsThat->value(), static_cast<int>(false)); + QCOMPARE(enumValueIsThat->value().value(), static_cast<int>(false)); QCOMPARE(enumValueIsThat->stringValue(), QLatin1String("false")); } @@ -195,12 +195,12 @@ void TestEnum::testGlobalEnums() AbstractMetaEnumValue* enumValueA0 = enumA->values().first(); QCOMPARE(enumValueA0->name(), QLatin1String("A0")); - QCOMPARE(enumValueA0->value(), 0); + QCOMPARE(enumValueA0->value().value(), 0); QCOMPARE(enumValueA0->stringValue(), QString()); AbstractMetaEnumValue* enumValueA1 = enumA->values().last(); QCOMPARE(enumValueA1->name(), QLatin1String("A1")); - QCOMPARE(enumValueA1->value(), 1); + QCOMPARE(enumValueA1->value().value(), 1); QCOMPARE(enumValueA1->stringValue(), QString()); AbstractMetaEnum* enumB = globalEnums.last(); @@ -208,12 +208,12 @@ void TestEnum::testGlobalEnums() AbstractMetaEnumValue* enumValueB0 = enumB->values().first(); QCOMPARE(enumValueB0->name(), QLatin1String("B0")); - QCOMPARE(enumValueB0->value(), 2); + QCOMPARE(enumValueB0->value().value(), 2); QCOMPARE(enumValueB0->stringValue(), QLatin1String("2")); AbstractMetaEnumValue* enumValueB1 = enumB->values().last(); QCOMPARE(enumValueB1->name(), QLatin1String("B1")); - QCOMPARE(enumValueB1->value(), 4); + QCOMPARE(enumValueB1->value().value(), 4); QCOMPARE(enumValueB1->stringValue(), QLatin1String("0x4")); } @@ -245,12 +245,12 @@ void TestEnum::testEnumValueFromNeighbourEnum() AbstractMetaEnumValue* enumValueA0 = enumA->values().first(); QCOMPARE(enumValueA0->name(), QLatin1String("ValueA0")); - QCOMPARE(enumValueA0->value(), 0); + QCOMPARE(enumValueA0->value().value(), 0); QCOMPARE(enumValueA0->stringValue(), QString()); AbstractMetaEnumValue* enumValueA1 = enumA->values().last(); QCOMPARE(enumValueA1->name(), QLatin1String("ValueA1")); - QCOMPARE(enumValueA1->value(), 1); + QCOMPARE(enumValueA1->value().value(), 1); QCOMPARE(enumValueA1->stringValue(), QString()); AbstractMetaEnum* enumB = classes[0]->findEnum(QLatin1String("EnumB")); @@ -259,12 +259,12 @@ void TestEnum::testEnumValueFromNeighbourEnum() AbstractMetaEnumValue* enumValueB0 = enumB->values().first(); QCOMPARE(enumValueB0->name(), QLatin1String("ValueB0")); - QCOMPARE(enumValueB0->value(), 1); + QCOMPARE(enumValueB0->value().value(), 1); QCOMPARE(enumValueB0->stringValue(), QLatin1String("A::ValueA1")); AbstractMetaEnumValue* enumValueB1 = enumB->values().last(); QCOMPARE(enumValueB1->name(), QLatin1String("ValueB1")); - QCOMPARE(enumValueB1->value(), 0); + QCOMPARE(enumValueB1->value().value(), 0); QCOMPARE(enumValueB1->stringValue(), QLatin1String("ValueA0")); } @@ -272,21 +272,25 @@ void TestEnum::testEnumValueFromExpression() { const char* cppCode ="\ struct A {\n\ - enum EnumA {\n\ + enum EnumA : unsigned {\n\ ValueA0 = 3u,\n\ ValueA1 = ~3u,\n\ - ValueA2 = ~3,\n\ + ValueA2 = 0xffffffff,\n\ ValueA3 = 0xf0,\n\ ValueA4 = 8 |ValueA3,\n\ ValueA5 = ValueA3|32,\n\ ValueA6 = ValueA3 >> 1,\n\ ValueA7 = ValueA3 << 1\n\ };\n\ + enum EnumB : int {\n\ + ValueB0 = ~3,\n\ + };\n\ };\n"; const char* xmlCode = "\ <typesystem package=\"Foo\">\n\ <value-type name='A'>\n\ <enum-type name='EnumA'/>\n\ + <enum-type name='EnumB'/>\n\ </value-type>\n\ </typesystem>\n"; @@ -298,47 +302,58 @@ void TestEnum::testEnumValueFromExpression() AbstractMetaEnum* enumA = classA->findEnum(QLatin1String("EnumA")); QVERIFY(enumA); + QVERIFY(!enumA->isSigned()); QCOMPARE(enumA->typeEntry()->qualifiedCppName(), QLatin1String("A::EnumA")); AbstractMetaEnumValue* valueA0 = enumA->values().at(0); QCOMPARE(valueA0->name(), QLatin1String("ValueA0")); QCOMPARE(valueA0->stringValue(), QLatin1String("3u")); - QCOMPARE(valueA0->value(), (int) 3u); + QCOMPARE(valueA0->value().unsignedValue(), 3u); AbstractMetaEnumValue* valueA1 = enumA->values().at(1); QCOMPARE(valueA1->name(), QLatin1String("ValueA1")); QCOMPARE(valueA1->stringValue(), QLatin1String("~3u")); - QCOMPARE(valueA1->value(), (int) ~3u); + QCOMPARE(valueA1->value().unsignedValue(), ~3u); AbstractMetaEnumValue* valueA2 = enumA->values().at(2); QCOMPARE(valueA2->name(), QLatin1String("ValueA2")); - QCOMPARE(valueA2->stringValue(), QLatin1String("~3")); - QCOMPARE(valueA2->value(), ~3); + QCOMPARE(valueA2->stringValue(), QLatin1String("0xffffffff")); + QCOMPARE(valueA2->value().unsignedValue(), 0xffffffffu); AbstractMetaEnumValue* valueA3 = enumA->values().at(3); QCOMPARE(valueA3->name(), QLatin1String("ValueA3")); QCOMPARE(valueA3->stringValue(), QLatin1String("0xf0")); - QCOMPARE(valueA3->value(), 0xf0); + QCOMPARE(valueA3->value().unsignedValue(), 0xf0u); AbstractMetaEnumValue* valueA4 = enumA->values().at(4); QCOMPARE(valueA4->name(), QLatin1String("ValueA4")); QCOMPARE(valueA4->stringValue(), QLatin1String("8 |ValueA3")); - QCOMPARE(valueA4->value(), 8|0xf0); + QCOMPARE(valueA4->value().unsignedValue(), 8|0xf0u); AbstractMetaEnumValue* valueA5 = enumA->values().at(5); QCOMPARE(valueA5->name(), QLatin1String("ValueA5")); QCOMPARE(valueA5->stringValue(), QLatin1String("ValueA3|32")); - QCOMPARE(valueA5->value(), 0xf0|32); + QCOMPARE(valueA5->value().unsignedValue(), 0xf0u|32); AbstractMetaEnumValue* valueA6 = enumA->values().at(6); QCOMPARE(valueA6->name(), QLatin1String("ValueA6")); QCOMPARE(valueA6->stringValue(), QLatin1String("ValueA3 >> 1")); - QCOMPARE(valueA6->value(), 0xf0 >> 1); + QCOMPARE(valueA6->value().unsignedValue(), 0xf0u >> 1); AbstractMetaEnumValue* valueA7 = enumA->values().at(7); QCOMPARE(valueA7->name(), QLatin1String("ValueA7")); QCOMPARE(valueA7->stringValue(), QLatin1String("ValueA3 << 1")); - QCOMPARE(valueA7->value(), 0xf0 << 1); + QCOMPARE(valueA7->value().unsignedValue(), 0xf0u << 1); + + const AbstractMetaEnum *enumB = classA->findEnum(QLatin1String("EnumB")); + QVERIFY(enumB); + QVERIFY(enumB->isSigned()); + QCOMPARE(enumB->typeEntry()->qualifiedCppName(), QLatin1String("A::EnumB")); + QCOMPARE(enumB->values().size(), 1); + const AbstractMetaEnumValue *valueB0 = enumB->values().at(0); + QCOMPARE(valueB0->name(), QLatin1String("ValueB0")); + QCOMPARE(valueB0->stringValue(), QLatin1String("~3")); + QCOMPARE(valueB0->value().value(), ~3); } void TestEnum::testPrivateEnum() @@ -375,12 +390,12 @@ void TestEnum::testPrivateEnum() AbstractMetaEnumValue* pub0 = publicEnum->values().first(); QCOMPARE(pub0->name(), QLatin1String("Pub0")); - QCOMPARE(pub0->value(), 0x0f); + QCOMPARE(pub0->value().value(), 0x0f); QCOMPARE(pub0->stringValue(), QLatin1String("Priv0")); AbstractMetaEnumValue* pub1 = publicEnum->values().last(); QCOMPARE(pub1->name(), QLatin1String("Pub1")); - QCOMPARE(pub1->value(), 0xf0); + QCOMPARE(pub1->value().value(), 0xf0); QCOMPARE(pub1->stringValue(), QLatin1String("A::Priv1")); } @@ -408,12 +423,12 @@ void TestEnum::testTypedefEnum() AbstractMetaEnumValue* enumValueA0 = enumA->values().first(); QCOMPARE(enumValueA0->name(), QLatin1String("A0")); - QCOMPARE(enumValueA0->value(), 0); + QCOMPARE(enumValueA0->value().value(), 0); QCOMPARE(enumValueA0->stringValue(), QLatin1String("")); AbstractMetaEnumValue* enumValueA1 = enumA->values().last(); QCOMPARE(enumValueA1->name(), QLatin1String("A1")); - QCOMPARE(enumValueA1->value(), 1); + QCOMPARE(enumValueA1->value().value(), 1); QCOMPARE(enumValueA1->stringValue(), QString()); } diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 72da73aa4..8d4c146c1 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -4529,7 +4529,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu enumValueText += cppEnum->name() + QLatin1String("::"); enumValueText += enumValue->name(); } else { - enumValueText += QString::number(enumValue->value()); + enumValueText += enumValue->value().toString(); } switch (cppEnum->enumKind()) { |