Moc: fix generated code for nested enum class corner case
Fixes an issue with generated code where the name of an enclosing namespace is identical to an enum class type, when Q_ENUM_NS is used. Consider: namespace a { Q_NAMESPACE namespace b { enum class b { Key, Key2 }; Q_ENUM_NS(b); } } moc generated code such as: Q_CONSTINIT const QMetaObject a:🅱️:staticMetaObject = { { ... qt_incomplete_metaTypeArray<qt_meta_stringdata_CLASSaSCOPEbENDCLASS_t, // enum 'TestEnum' QtPrivate::TypeAndForceComplete<b::b, std::true_type>, // Q_OBJECT / Q_GADGET QtPrivate::TypeAndForceComplete<void, std::true_type> >, nullptr } }; which confused the compiler: error: ‘b’ is not a member of ‘a:🅱️:b 83 | QtPrivate::TypeAndForceComplete<b::b, std::true_type>, Fixes: QTBUG-112996 Pick-to: 6.6 Change-Id: I37aee83c32efe96cc9d6c2bd0bdb9ba80bb7b8a7 Reviewed-by: Fabian Kosmale <fabian.kosmale@qt.io>
This commit is contained in:
parent
e603661c48
commit
7779400ba6
@ -525,8 +525,7 @@ void Generator::generateCode()
|
||||
// metatypes for enums
|
||||
for (const EnumDef &e : std::as_const(cdef->enumList)) {
|
||||
fprintf(out, "%s\n // enum '%s'\n %s",
|
||||
comma, e.name.constData(),
|
||||
stringForType(cdef->classname % "::" % e.name, true).constData());
|
||||
comma, e.name.constData(), stringForType(e.qualifiedType(cdef), true).constData());
|
||||
comma = ",";
|
||||
}
|
||||
|
||||
|
@ -2187,4 +2187,23 @@ QJsonObject EnumDef::toJson(const ClassDef &cdef) const
|
||||
return def;
|
||||
}
|
||||
|
||||
QByteArray EnumDef::qualifiedType(const ClassDef *cdef) const
|
||||
{
|
||||
if (name == cdef->classname) {
|
||||
// The name of the enclosing namespace is the same as the enum class name
|
||||
if (cdef->qualified.contains("::")) {
|
||||
// QTBUG-112996, fully qualify by using cdef->qualified to disambiguate enum
|
||||
// class name and enclosing namespace, e.g.:
|
||||
// namespace A { namespace B { Q_NAMESPACE; enum class B { }; Q_ENUM_NS(B) } }
|
||||
return cdef->qualified % "::" % name;
|
||||
} else {
|
||||
// Just "B"; otherwise the compiler complains about the type "B::B" inside
|
||||
// "B::staticMetaObject" in the generated code; e.g.:
|
||||
// namespace B { Q_NAMESPACE; enum class B { }; Q_ENUM_NS(B) }
|
||||
return name;
|
||||
}
|
||||
}
|
||||
return cdef->classname % "::" % name;
|
||||
}
|
||||
|
||||
QT_END_NAMESPACE
|
||||
|
@ -48,6 +48,7 @@ struct EnumDef
|
||||
bool isEnumClass; // c++11 enum class
|
||||
EnumDef() : isEnumClass(false) {}
|
||||
QJsonObject toJson(const ClassDef &cdef) const;
|
||||
QByteArray qualifiedType(const ClassDef *cdef) const;
|
||||
};
|
||||
Q_DECLARE_TYPEINFO(EnumDef, Q_RELOCATABLE_TYPE);
|
||||
|
||||
|
@ -203,6 +203,27 @@ namespace TestQNamespace {
|
||||
Q_FLAG_NS(TestFlag2)
|
||||
}
|
||||
|
||||
namespace TestSameEnumNamespace {
|
||||
Q_NAMESPACE
|
||||
|
||||
enum class TestSameEnumNamespace {
|
||||
Key1 = 1,
|
||||
Key2 = 2,
|
||||
};
|
||||
Q_ENUM_NS(TestSameEnumNamespace)
|
||||
}
|
||||
|
||||
namespace TestNestedSameEnumNamespace {
|
||||
namespace a {
|
||||
Q_NAMESPACE
|
||||
// enum class with the same name as the enclosing nested namespace
|
||||
enum class a {
|
||||
Key11 = 11,
|
||||
Key12 = 12,
|
||||
};
|
||||
Q_ENUM_NS(a)
|
||||
}
|
||||
}
|
||||
|
||||
namespace TestExportNamespace {
|
||||
Q_NAMESPACE_EXPORT(TESTEXPORTMACRO)
|
||||
@ -789,6 +810,7 @@ private slots:
|
||||
void optionsFileError_data();
|
||||
void optionsFileError();
|
||||
void testQNamespace();
|
||||
void testNestedQNamespace();
|
||||
void cxx17Namespaces();
|
||||
void cxxAttributes();
|
||||
void mocJsonOutput();
|
||||
@ -4081,6 +4103,28 @@ public:
|
||||
FooNamespace::Enum1 prop() { return FooNamespace::Enum1::Key2; }
|
||||
};
|
||||
|
||||
void tst_Moc::testNestedQNamespace()
|
||||
{
|
||||
QCOMPARE(TestSameEnumNamespace::staticMetaObject.enumeratorCount(), 1);
|
||||
checkEnum(TestSameEnumNamespace::staticMetaObject.enumerator(0), "TestSameEnumNamespace",
|
||||
{{"Key1", 1}, {"Key2", 2}});
|
||||
QMetaEnum meta1 = QMetaEnum::fromType<TestSameEnumNamespace::TestSameEnumNamespace>();
|
||||
QVERIFY(meta1.isValid());
|
||||
QCOMPARE(meta1.name(), "TestSameEnumNamespace");
|
||||
QCOMPARE(meta1.enclosingMetaObject(), &TestSameEnumNamespace::staticMetaObject);
|
||||
QCOMPARE(meta1.keyCount(), 2);
|
||||
|
||||
// QTBUG-112996
|
||||
QCOMPARE(TestNestedSameEnumNamespace::a::staticMetaObject.enumeratorCount(), 1);
|
||||
checkEnum(TestNestedSameEnumNamespace::a::staticMetaObject.enumerator(0), "a",
|
||||
{{"Key11", 11}, {"Key12", 12}});
|
||||
QMetaEnum meta2 = QMetaEnum::fromType<TestNestedSameEnumNamespace::a::a>();
|
||||
QVERIFY(meta2.isValid());
|
||||
QCOMPARE(meta2.name(), "a");
|
||||
QCOMPARE(meta2.enclosingMetaObject(), &TestNestedSameEnumNamespace::a::staticMetaObject);
|
||||
QCOMPARE(meta2.keyCount(), 2);
|
||||
}
|
||||
|
||||
void tst_Moc::testQNamespace()
|
||||
{
|
||||
QCOMPARE(TestQNamespace::staticMetaObject.enumeratorCount(), 5);
|
||||
|
Loading…
Reference in New Issue
Block a user