diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 4e255ea0053..a5d2220e596 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -883,6 +883,7 @@ void Moc::parse() if (test(Q_SIGNALS_TOKEN)) error("Signals cannot have access specifier"); break; + case STRUCT: case CLASS: { ClassDef nestedDef; if (parseClassHead(&nestedDef)) { diff --git a/src/tools/moc/token.h b/src/tools/moc/token.h index a70808370dd..34c6dfafa50 100644 --- a/src/tools/moc/token.h +++ b/src/tools/moc/token.h @@ -127,6 +127,7 @@ QT_BEGIN_NAMESPACE F(SIGNALS) \ F(SLOTS) \ F(RETURN) \ + F(Q_META_TOKEN_BEGIN) \ F(Q_OBJECT_TOKEN) \ F(Q_GADGET_TOKEN) \ F(Q_GADGET_EXPORT_TOKEN) \ @@ -141,7 +142,6 @@ QT_BEGIN_NAMESPACE F(Q_FLAGS_TOKEN) \ F(Q_FLAG_TOKEN) \ F(Q_FLAG_NS_TOKEN) \ - F(Q_DECLARE_FLAGS_TOKEN) \ F(Q_DECLARE_INTERFACE_TOKEN) \ F(Q_DECLARE_METATYPE_TOKEN) \ F(Q_CLASSINFO_TOKEN) \ @@ -158,6 +158,8 @@ QT_BEGIN_NAMESPACE F(QT_ANONYMOUS_PRIVATE_PROPERTY_TOKEN) \ F(Q_REVISION_TOKEN) \ F(Q_MOC_INCLUDE_TOKEN) \ + F(Q_META_TOKEN_END) \ + F(Q_DECLARE_FLAGS_TOKEN) \ F(SPECIAL_TREATMENT_MARK) \ F(MOC_INCLUDE_BEGIN) \ F(MOC_INCLUDE_END) \ @@ -238,8 +240,6 @@ enum Token { PP_STRING_LITERAL = STRING_LITERAL, PP_TILDE = TILDE, PP_WHITESPACE = WHITESPACE, - Q_META_TOKEN_BEGIN = Q_OBJECT_TOKEN, - Q_META_TOKEN_END = SPECIAL_TREATMENT_MARK }; // for debugging only diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index eefcd28e589..8ff7b267752 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -548,6 +548,18 @@ class TestClass : public MyNamespace::TestSuperClass, public DONT_CONFUSE_MOC(My public: inline TestClass() {} + // These two here test that Q_DECLARE_FLAGS is permitted in a class or + // struct nested inside of a Q_OBJECT and defined within the body of the + // class. A Q_OBJECT is not allowed here (see privateClass()). + struct NestedStruct { + enum E {}; + Q_DECLARE_FLAGS(Flags, E) + }; + class NestedClass { + enum E {}; + Q_DECLARE_FLAGS(Flags, E) + }; + private slots: inline void dummy1() MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES {} inline void dummy2() MACRO_WITH_POSSIBLE_COMPILER_SPECIFIC_ATTRIBUTES const {} @@ -2494,6 +2506,29 @@ void tst_Moc::warnings_data() << QString() << QString("standard input:2:1: error: Plugin Metadata file \".\" could not be opened: file to open is a directory"); #endif + + static const char *tags[] = { "class", "struct" }; + static const char *metaKeywords[] = { "Q_OBJECT", "Q_GADGET" }; + for (size_t i = 0; i < std::size(tags) * 2 * std::size(metaKeywords) * 2; ++i) { + const char *tag1 = tags[i & 1]; + const char *tag2 = tags[(i >> 1) & 1]; + const char *meta1 = metaKeywords[(i >> 2) & 1]; + const char *meta2 = metaKeywords[(i >> 3) & 1]; + QByteArray input = tag1; + input += " X : public Base {\n "; + input += meta1; + input += "\n "; + input += tag2; + input += " Nested : public Base {\n "; + input += meta2; + input += " };\n};\n"; + QTest::addRow("nested-%s-%s-%s-%s", tag1, meta1, tag2, meta2) + << input + << QStringList() + << 1 + << QString() + << "standard input:4:1: error: Meta object features not supported for nested classes"; + } } void tst_Moc::warnings()