aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFriedemann Kleint <Friedemann.Kleint@qt.io>2018-03-21 09:29:58 +0100
committerFriedemann Kleint <Friedemann.Kleint@qt.io>2018-04-19 10:36:17 +0000
commit6bb7322e47196186375a3733e9112860817ebb1d (patch)
tree72ad9417342894e4ea76062284c5fcb80c7081ec
parent06fe31fd68823b53bbd0657e4bd63ef06b35137d (diff)
shiboken: Detect class enums by Clang entirely
The Clang function clang_EnumDecl_isScoped() tells whether an enum is a class, so, there is no need to specify that in the typesystem. Use that information to pass it up to the metalang classes and revert the parts of 44cb6c51e6c3b43376f284941454dc8c13b81c3f that added it to the type system. Task-number: PYSIDE-487 Change-Id: Ie10885f74168821d0307e91b6f1f7f3f30dd074b Reviewed-by: Christian Tismer <tismer@stackless.com> Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp3
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.cpp5
-rw-r--r--sources/shiboken2/ApiExtractor/abstractmetalang.h8
-rw-r--r--sources/shiboken2/ApiExtractor/clangparser/clangbuilder.cpp45
-rw-r--r--sources/shiboken2/ApiExtractor/doc/typesystem_specifying_types.rst4
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.cpp22
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel.h13
-rw-r--r--sources/shiboken2/ApiExtractor/parser/codemodel_enums.h6
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.cpp5
-rw-r--r--sources/shiboken2/ApiExtractor/typesystem.h13
-rw-r--r--sources/shiboken2/generator/shiboken2/cppgenerator.cpp8
-rw-r--r--sources/shiboken2/tests/samplebinding/typesystem_sample.xml2
12 files changed, 77 insertions, 57 deletions
diff --git a/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp b/sources/shiboken2/ApiExtractor/abstractmetabuilder.cpp
index 1afc7d13..c38a145b 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 4e507cd3..905504ca 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 45a55e57..c51f7704 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 1ed054d9..0984246c 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 646e7604..322f9bca 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 a35ca314..fbfeaadf 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 2aaea1f7..b300cf24 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 aa8b051d..3115a9a9 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 600536ab..0a47b9b1 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 2f534c93..eae06413 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 18670eae..72da73aa 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 5a12eecc..3cc80860 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">