diff options
12 files changed, 77 insertions, 57 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp index 1afc7d135..c38a145bd 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp @@ -1055,7 +1055,7 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte nspace = QStringList(names.mid(0, names.size() - 1)).join(colonColon()); typeEntry = new EnumTypeEntry(nspace, enumName, QVersionNumber(0, 0)); TypeDatabase::instance()->addType(typeEntry); - } else if (!enumItem->isAnonymous()) { + } else if (enumItem->enumKind() != AnonymousEnum) { typeEntry = TypeDatabase::instance()->findType(qualifiedName); } else { QStringList tmpQualifiedName = enumItem->qualifiedName(); @@ -1096,6 +1096,7 @@ AbstractMetaEnum *AbstractMetaBuilderPrivate::traverseEnum(EnumModelItem enumIte } AbstractMetaEnum *metaEnum = new AbstractMetaEnum; + metaEnum->setEnumKind(enumItem->enumKind()); if (enumsDeclarations.contains(qualifiedName) || enumsDeclarations.contains(enumName)) { metaEnum->setHasQEnumsDeclaration(true); diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp index 4e507cd38..905504ca3 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.cpp +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.cpp @@ -2457,8 +2457,3 @@ QString AbstractMetaEnum::package() const { return m_typeEntry->targetLangPackage(); } - -bool AbstractMetaEnum::isAnonymous() const -{ - return m_typeEntry->isAnonymous(); -} diff --git a/sources/shiboken2/ApiExtractor/abstractmetalang.h b/sources/shiboken2/ApiExtractor/abstractmetalang.h index 45a55e570..c51f7704b 100644 --- a/sources/shiboken2/ApiExtractor/abstractmetalang.h +++ b/sources/shiboken2/ApiExtractor/abstractmetalang.h @@ -1168,6 +1168,11 @@ public: return package() + QLatin1Char('.') + qualifier() + QLatin1Char('.') + name(); } + EnumKind enumKind() const { return m_enumKind; } + void setEnumKind(EnumKind kind) { m_enumKind = kind; } + + bool isAnonymous() const { return m_enumKind == AnonymousEnum; } + // Has the enum been declared inside a Q_ENUMS() macro in its enclosing class? void setHasQEnumsDeclaration(bool on) { @@ -1199,13 +1204,12 @@ public: m_class = c; } - bool isAnonymous() const; - private: AbstractMetaEnumValueList m_enumValues; EnumTypeEntry *m_typeEntry = nullptr; AbstractMetaClass *m_class = nullptr; + EnumKind m_enumKind = CEnum; uint m_hasQenumsDeclaration : 1; }; diff --git a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp index 1ed054d91..0984246c8 100644 --- a/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp +++ b/sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp @@ -41,6 +41,7 @@ #include <QtCore/QVector> #include <string.h> +#include <ctype.h> #if QT_VERSION < 0x050800 # define Q_FALLTHROUGH() (void)0 @@ -437,6 +438,36 @@ QString BuilderPrivate::cursorValueExpression(BaseVisitor *bv, const CXCursor &c return QString::fromLocal8Bit(equalSign, int(snippet.second - equalSign)).trimmed(); } +// A hacky reimplementation of clang_EnumDecl_isScoped() for Clang < 5.0 +// which simply checks for a blank-delimited " class " keyword in the enum snippet. + +#define CLANG_NO_ENUMDECL_ISSCOPED \ + (CINDEX_VERSION_MAJOR == 0 && CINDEX_VERSION_MINOR < 43) + +#if CLANG_NO_ENUMDECL_ISSCOPED +static const char *indexOf(const BaseVisitor::CodeSnippet &snippet, const char *needle) +{ + const size_t snippetLength = snippet.first ? size_t(snippet.second - snippet.first) : 0; + const size_t needleLength = strlen(needle); + if (needleLength > snippetLength) + return nullptr; + for (const char *c = snippet.first, *end = snippet.second - needleLength; c < end; ++c) { + if (memcmp(c, needle, needleLength) == 0) + return c; + } + return nullptr; +} + +long clang_EnumDecl_isScoped4(BaseVisitor *bv, const CXCursor &cursor) +{ + BaseVisitor::CodeSnippet snippet = bv->getCodeSnippet(cursor); + const char *classSpec = indexOf(snippet, "class"); + const bool isClass = classSpec && classSpec > snippet.first + && isspace(*(classSpec - 1)) && isspace(*(classSpec + 5)); + return isClass ? 1 : 0; +} +#endif // CLANG_NO_ENUMDECL_ISSCOPED + // Add a base class to the current class from CXCursor_CXXBaseSpecifier void BuilderPrivate::addBaseClass(const CXCursor &cursor) { @@ -641,13 +672,21 @@ BaseVisitor::StartTokenResult Builder::startToken(const CXCursor &cursor) break; case CXCursor_EnumDecl: { QString name = getCursorSpelling(cursor); - const bool anonymous = name.isEmpty(); - if (anonymous) + EnumKind kind = CEnum; + if (name.isEmpty()) { + kind = AnonymousEnum; name = QStringLiteral("enum_") + QString::number(++d->m_anonymousEnumCount); +#if !CLANG_NO_ENUMDECL_ISSCOPED + } else if (clang_EnumDecl_isScoped(cursor) != 0) { +#else + } else if (clang_EnumDecl_isScoped4(this, cursor) != 0) { +#endif + kind = EnumClass; + } d->m_currentEnum.reset(new _EnumModelItem(d->m_model, name)); setFileName(cursor, d->m_currentEnum.data()); d->m_currentEnum->setScope(d->m_scope); - d->m_currentEnum->setAnonymous(anonymous); + d->m_currentEnum->setEnumKind(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); diff --git a/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst b/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst index 646e76043..322f9bca6 100644 --- a/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst +++ b/sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst @@ -180,10 +180,6 @@ enum-type Notice that the **enum-type** tag can either have **name** or **identified-by-value** but not both. - The *optional* boolean attribute **class** specifies whether the underlying - enumeration is a C++ 11 enumeration class. In that case, the enumeration values - need to be qualified by the enumeration name to match the C++ Syntax. - The **revision** attribute can be used to specify a revision for each type, easing the production of ABI compatible bindings. diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp index a35ca314b..fbfeaadf7 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.cpp +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.cpp @@ -1014,22 +1014,20 @@ void _EnumModelItem::addEnumerator(EnumeratorModelItem item) m_enumerators.append(item); } -bool _EnumModelItem::isAnonymous() const -{ - return m_anonymous; -} - -void _EnumModelItem::setAnonymous(bool anonymous) -{ - m_anonymous = anonymous; -} - #ifndef QT_NO_DEBUG_STREAM void _EnumModelItem::formatDebug(QDebug &d) const { _CodeModelItem::formatDebug(d); - if (m_anonymous) - d << " (anonymous)"; + switch (m_enumKind) { + case CEnum: + break; + case AnonymousEnum: + d << " (anonymous)"; + break; + case EnumClass: + d << " (class)"; + break; + } formatModelItemList(d, ", enumerators=", m_enumerators); } #endif // !QT_NO_DEBUG_STREAM diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel.h b/sources/shiboken2/ApiExtractor/parser/codemodel.h index 2aaea1f78..b300cf249 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel.h @@ -631,10 +631,8 @@ class _EnumModelItem: public _CodeModelItem public: DECLARE_MODEL_NODE(Enum) - explicit _EnumModelItem(CodeModel *model, int kind = __node_kind) - : _CodeModelItem(model, kind), m_accessPolicy(CodeModel::Public), m_anonymous(false) {} explicit _EnumModelItem(CodeModel *model, const QString &name, int kind = __node_kind) - : _CodeModelItem(model, name, kind), m_accessPolicy(CodeModel::Public), m_anonymous(false) {} + : _CodeModelItem(model, name, kind) {} ~_EnumModelItem(); CodeModel::AccessPolicy accessPolicy() const; @@ -642,17 +640,18 @@ public: EnumeratorList enumerators() const; void addEnumerator(EnumeratorModelItem item); - bool isAnonymous() const; - void setAnonymous(bool anonymous); + + EnumKind enumKind() const { return m_enumKind; } + void setEnumKind(EnumKind kind) { m_enumKind = kind; } #ifndef QT_NO_DEBUG_STREAM void formatDebug(QDebug &d) const override; #endif private: - CodeModel::AccessPolicy m_accessPolicy; + CodeModel::AccessPolicy m_accessPolicy = CodeModel::Public; EnumeratorList m_enumerators; - bool m_anonymous; + EnumKind m_enumKind = CEnum; }; class _EnumeratorModelItem: public _CodeModelItem diff --git a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h index aa8b051d8..3115a9a94 100644 --- a/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h +++ b/sources/shiboken2/ApiExtractor/parser/codemodel_enums.h @@ -35,4 +35,10 @@ enum ReferenceType { RValueReference }; +enum EnumKind { + CEnum, // Standard C: enum Foo { value1, value2 } + AnonymousEnum, // enum { value1, value2 } + EnumClass // C++ 11 : enum class Foo { value1, value2 } +}; + #endif // CODEMODEL_ENUMS_H diff --git a/sources/shiboken2/ApiExtractor/typesystem.cpp b/sources/shiboken2/ApiExtractor/typesystem.cpp index 600536aba..0a47b9b17 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.cpp +++ b/sources/shiboken2/ApiExtractor/typesystem.cpp @@ -963,11 +963,6 @@ bool Handler::startElement(const QStringRef &n, const QXmlStreamAttributes &atts m_currentEnum = new EnumTypeEntry(QStringList(names.mid(0, names.size() - 1)).join(colonColon()), names.constLast(), since); - if (!attributes.value(enumIdentifiedByValueAttribute()).isEmpty()) { - m_currentEnum->setEnumKind(EnumTypeEntry::AnonymousEnum); - } else if (convertBoolean(attributes.value(classAttribute()), classAttribute(), false)) { - m_currentEnum->setEnumKind(EnumTypeEntry::EnumClass); - } element->entry = m_currentEnum; m_currentEnum->setCodeGeneration(m_generate); m_currentEnum->setTargetLangPackage(m_defaultPackage); diff --git a/sources/shiboken2/ApiExtractor/typesystem.h b/sources/shiboken2/ApiExtractor/typesystem.h index 2f534c93d..eae064134 100644 --- a/sources/shiboken2/ApiExtractor/typesystem.h +++ b/sources/shiboken2/ApiExtractor/typesystem.h @@ -1041,12 +1041,6 @@ private: class EnumTypeEntry : public TypeEntry { public: - enum EnumKind { - CEnum, // Standard C: enum Foo { value1, value2 } - AnonymousEnum, // enum { value1, value2 } - EnumClass // C++ 11 : enum class Foo { value1, value2 } - }; - explicit EnumTypeEntry(const QString &nspace, const QString &enumName, const QVersionNumber &vr); @@ -1068,9 +1062,6 @@ public: m_qualifier = q; } - EnumKind enumKind() const { return m_enumKind; } - void setEnumKind(EnumKind kind) { m_enumKind = kind; } - bool preferredConversion() const override; bool isBoundsChecked() const @@ -1136,8 +1127,6 @@ public: m_forceInteger = force; } - bool isAnonymous() const { return m_enumKind == AnonymousEnum; } - private: QString m_packageName; QString m_qualifier; @@ -1150,8 +1139,6 @@ private: FlagsTypeEntry *m_flags = nullptr; - EnumKind m_enumKind = CEnum; - bool m_extensible = false; bool m_forceInteger = false; }; diff --git a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp index 18670eae6..72da73aa4 100644 --- a/sources/shiboken2/generator/shiboken2/cppgenerator.cpp +++ b/sources/shiboken2/generator/shiboken2/cppgenerator.cpp @@ -4532,8 +4532,8 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu enumValueText += QString::number(enumValue->value()); } - switch (enumTypeEntry->enumKind()) { - case EnumTypeEntry::AnonymousEnum: + switch (cppEnum->enumKind()) { + case AnonymousEnum: if (enclosingClass || hasUpperEnclosingClass) { s << INDENT << '{' << endl; { @@ -4557,7 +4557,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu } } break; - case EnumTypeEntry::CEnum: { + case CEnum: { s << INDENT << "if (!Shiboken::Enum::"; s << ((enclosingClass || hasUpperEnclosingClass) ? "createScopedEnumItem" : "createGlobalEnumItem"); s << '(' << enumVarTypeObj << ',' << endl; @@ -4567,7 +4567,7 @@ void CppGenerator::writeEnumInitialization(QTextStream& s, const AbstractMetaEnu s << INDENT << "return " << m_currentErrorCode << ';' << endl; } break; - case EnumTypeEntry::EnumClass: { + case EnumClass: { s << INDENT << "if (!Shiboken::Enum::createScopedEnumItem(" << enumVarTypeObj << ',' << endl; Indentation indent(INDENT); diff --git a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml index 5a12eeccd..3cc80860d 100644 --- a/sources/shiboken2/tests/samplebinding/typesystem_sample.xml +++ b/sources/shiboken2/tests/samplebinding/typesystem_sample.xml @@ -798,7 +798,7 @@ <value-type name="Event"> <enum-type name="EventType"/> - <enum-type name="EventTypeClass" class="yes"/> + <enum-type name="EventTypeClass"/> </value-type> <value-type name="BlackBox"> |