aboutsummaryrefslogtreecommitdiffstats
path: root/sources
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2018-03-19 17:24:00 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2018-04-19 12:51:14 +0000
commitfb7386c18c15ca83aebe8f973c1b018d016baaa9 (patch)
tree91f0c2988af2e4133a2fdc702fccce69a623b9bf /sources
parenta89690409972501741c846ac8ad4a499f2982809 (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')
-rw-r--r--sources/shiboken2/ApiExtractor/CMakeLists.txt1
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp227
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder_p.h7
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp7
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h11
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp27
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.cpp23
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.h17
-rw-r--r--sources/shiboken2/ApiExtractor/parser/enumvalue.cpp76
-rw-r--r--sources/shiboken2/ApiExtractor/parser/enumvalue.h70
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testarrayargument.cpp4
-rw-r--r--sources/shiboken2/ApiExtractor/tests/testenum.cpp69
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp2
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()) {