From 99c59f82575695163e45e3848a5338f2d4fadaae Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Mon, 20 Jun 2022 08:25:31 +0200 Subject: dumpcpp: Completely specify enums from referenced typelibs Forward-declaring enums causes problems with the moc-generated code. Introduce a variable to qaxbase storing the preformatted value string. Task-number: QTBUG-100145 Pick-to: 6.4 6.3 Change-Id: I500353d9788e3ea20bf1cc64172ca1b640976e5e Reviewed-by: Volker Hilsheimer --- src/activeqt/container/qaxbase.cpp | 101 ++++++++++++++++++++++++++----------- tools/dumpcpp/main.cpp | 27 ++++------ 2 files changed, 83 insertions(+), 45 deletions(-) diff --git a/src/activeqt/container/qaxbase.cpp b/src/activeqt/container/qaxbase.cpp index 664e406..e1cb0c8 100644 --- a/src/activeqt/container/qaxbase.cpp +++ b/src/activeqt/container/qaxbase.cpp @@ -1756,6 +1756,63 @@ MetaObjectGenerator::~MetaObjectGenerator() bool qax_dispatchEqualsIDispatch = true; QByteArrayList qax_qualified_usertypes; +// Value strings for enums +QHash qax_enum_values; + +// Read enum values +QList > qax_readEnumValues(ITypeLib *typelib, UINT index) +{ + QList > result; + + // Get the type information for the enum + ITypeInfo *enuminfo = nullptr; + typelib->GetTypeInfo(index, &enuminfo); + if (!enuminfo) + return result; + + // Get the attributes of the enum type + TYPEATTR *typeattr = nullptr; + enuminfo->GetTypeAttr(&typeattr); + if (typeattr == nullptr) { + enuminfo->Release(); + return result; + } + + // Get all values of the enumeration + result.reserve(typeattr->cVars); + for (UINT vd = 0; vd < typeattr->cVars; ++vd) { + VARDESC *vardesc = nullptr; + enuminfo->GetVarDesc(vd, &vardesc); + if (vardesc != nullptr) { + if (vardesc->varkind == VAR_CONST) { + const int value = vardesc->lpvarValue->lVal; + QByteArray valueName = qaxTypeInfoName(enuminfo, vardesc->memid); + result.append({valueName, value}); + } + enuminfo->ReleaseVarDesc(vardesc); + } + } + enuminfo->ReleaseTypeAttr(typeattr); + enuminfo->Release(); + return result; +} + +// Format enum values into a string v1=1, v2=2,... +static QByteArray enumValueString(ITypeLib *typelib, UINT index) +{ + QByteArray result; + const auto enumValues = qax_readEnumValues(typelib, index); + const auto last = enumValues.size() - 1; + for (qsizetype i = 0; i <= last; ++i) { + const auto &enumValue = enumValues.at(i); + result += " " + enumValue.first + '=' + + QByteArray::number(enumValue.second); + if (i < last) + result += ','; + result += '\n'; + } + return result; +} QByteArray MetaObjectGenerator::usertypeToString(const TYPEDESC &tdesc, ITypeInfo *info, const QByteArray &function) { @@ -1812,8 +1869,11 @@ QByteArray MetaObjectGenerator::usertypeToString(const TYPEDESC &tdesc, ITypeInf } break; case TKIND_ENUM: - if (typeLibName != current_typelib) + if (typeLibName != current_typelib) { userTypeName.prepend(typeLibName + "::"); + // For dumpcpp + qax_enum_values.insert(userTypeName, enumValueString(usertypelib, index)); + } if (!qax_qualified_usertypes.contains("enum " + userTypeName)) qax_qualified_usertypes << "enum " + userTypeName; break; @@ -2166,10 +2226,9 @@ void MetaObjectGenerator::readEnumInfo() TYPEKIND typekind; typelib->GetTypeInfoType(i, &typekind); if (typekind == TKIND_ENUM) { - // Get the type information for the enum - ITypeInfo *enuminfo = nullptr; - typelib->GetTypeInfo(i, &enuminfo); - if (!enuminfo) + // Get the values of the enum + const auto values = qax_readEnumValues(typelib, i); + if (values.isEmpty()) continue; // Get the name of the enumeration @@ -2183,31 +2242,15 @@ void MetaObjectGenerator::readEnumInfo() } // Get the attributes of the enum type - TYPEATTR *typeattr = nullptr; - enuminfo->GetTypeAttr(&typeattr); - if (typeattr) { - // Get all values of the enumeration - for (UINT vd = 0; vd < typeattr->cVars; ++vd) { - VARDESC *vardesc = nullptr; - enuminfo->GetVarDesc(vd, &vardesc); - if (vardesc && vardesc->varkind == VAR_CONST) { - int value = vardesc->lpvarValue->lVal; - int memid = vardesc->memid; - // Get the name of the value - QByteArray valueName = qaxTypeInfoName(enuminfo, memid); - if (valueName.isEmpty()) - valueName = "value" + QByteArray::number(valueindex++); - if (clashCheck.contains(QString::fromLatin1(valueName))) - valueName += QByteArray::number(++clashIndex); - - clashCheck.insert(QString::fromLatin1(valueName)); - addEnumValue(enumName, valueName, value); - } - enuminfo->ReleaseVarDesc(vardesc); - } + for (const auto &value : values) { + QByteArray valueName = value.first; + if (valueName.isEmpty()) + valueName = "value" + QByteArray::number(valueindex++); + if (clashCheck.contains(QString::fromLatin1(valueName))) + valueName += QByteArray::number(++clashIndex); + clashCheck.insert(QString::fromLatin1(valueName)); + addEnumValue(enumName, valueName, value.second); } - enuminfo->ReleaseTypeAttr(typeattr); - enuminfo->Release(); } } diff --git a/tools/dumpcpp/main.cpp b/tools/dumpcpp/main.cpp index 58e58ef..9471fcf 100644 --- a/tools/dumpcpp/main.cpp +++ b/tools/dumpcpp/main.cpp @@ -50,6 +50,7 @@ extern QMetaObject *qax_readEnumInfo(ITypeLib *typeLib, const QMetaObject *paren extern QMetaObject *qax_readClassInfo(ITypeLib *typeLib, ITypeInfo *typeInfo, const QMetaObject *parentObject); extern QMetaObject *qax_readInterfaceInfo(ITypeLib *typeLib, ITypeInfo *typeInfo, const QMetaObject *parentObject); extern QByteArrayList qax_qualified_usertypes; +extern QHash qax_enum_values; extern QString qax_docuFromName(ITypeInfo *typeInfo, const QString &name); extern bool qax_dispatchEqualsIDispatch; extern void qax_deleteMetaObject(QMetaObject *mo); @@ -596,19 +597,6 @@ static QByteArrayList vTableOnlyStubsFromTypeLib(ITypeLib *typelib, const QStrin return result; } -static void writeForwardDeclaration(QTextStream &declOut, const QByteArray &className) -{ - if (className.startsWith("enum ")) { - declOut << "#ifndef Q_CC_MINGW\n" - << " " << className << ';' << Qt::endl // Only MSVC accepts this - << "#else\n" - << " " << className << " {};" << Qt::endl - << "#endif\n"; - } else { - declOut << " " << className << ';' << Qt::endl; - } -} - static const QMetaObject *baseMetaObject(ObjectCategories c) { return c.testFlag(ActiveX) @@ -782,9 +770,16 @@ bool generateTypeLibrary(QString typeLibFile, QString outname, if (libName != QLatin1String(nspace)) { declOut << "namespace " << nspace << " {" << Qt::endl; for (const auto &className : it.value()) { - if (className.contains(' ')) { - writeForwardDeclaration(declOut, className); - namespaceForType.insert(className.mid(className.indexOf(' ') + 1), nspace); + const auto spacePos = className.indexOf(' '); + if (spacePos != -1) { + const QByteArray name = className.mid(spacePos + 1); + if (className.startsWith("enum ")) { + declOut << " " << className << " {\n" + << qax_enum_values.value(nspace + "::" + name) << " };\n"; + } else { + declOut << " " << className << ";\n"; + } + namespaceForType.insert(name, nspace); } else { declOut << " class " << className << ';' << Qt::endl; opaquePointerTypes.append(nspace + "::" + className); -- cgit v1.2.3