moc: support c++11 style enums
authorOlivier Goffart <ogoffart@kde.org>
Sat, 29 Oct 2011 17:55:36 +0000 (19:55 +0200)
committerQt by Nokia <qt-info@nokia.com>
Sat, 29 Oct 2011 19:18:45 +0000 (21:18 +0200)
Task-number: QTBUG-21480

Change-Id: Ic116a5a06dd68036823f27146e49511c68cf2de6
Reviewed-by: Simon Hausmann <simon.hausmann@nokia.com>
src/tools/moc/generator.cpp
src/tools/moc/moc.cpp
src/tools/moc/moc.h
tests/auto/tools/moc/cxx11-enums.h [new file with mode: 0644]
tests/auto/tools/moc/moc.pro
tests/auto/tools/moc/tst_moc.cpp

index 72fda2d..1ed7de2 100644 (file)
@@ -622,10 +622,12 @@ void Generator::generateEnums(int index)
         const EnumDef &e = cdef->enumList.at(i);
         for (int j = 0; j < e.values.count(); ++j) {
             const QByteArray &val = e.values.at(j);
-            fprintf(out, "    %4d, uint(%s::%s),\n",
-                    strreg(val),
-                    cdef->qualified.constData(),
-                    val.constData());
+            QByteArray code = cdef->qualified.constData();
+            if (e.isEnumClass)
+                code += "::" + e.name;
+            code += "::" + val;
+            fprintf(out, "    %4d, uint(%s),\n",
+                    strreg(val), code.constData());
         }
     }
 }
index 6374a72..8999148 100644 (file)
@@ -251,6 +251,9 @@ bool Moc::parseEnum(EnumDef *def)
 {
     bool isTypdefEnum = false; // typedef enum { ... } Foo;
 
+    if (test(CLASS))
+        def->isEnumClass = true;
+
     if (test(IDENTIFIER)) {
         def->name = lexem();
     } else {
@@ -258,6 +261,10 @@ bool Moc::parseEnum(EnumDef *def)
             return false; // anonymous enum
         isTypdefEnum = true;
     }
+    if (test(COLON)) { // C++11 strongly typed enum
+        // enum Foo : unsigned long { ... };
+        parseType(); //ignore the result
+    }
     if (!test(LBRACE))
         return false;
     do {
index 1bb807c..917cf69 100644 (file)
@@ -70,6 +70,8 @@ struct EnumDef
 {
     QByteArray name;
     QList<QByteArray> values;
+    bool isEnumClass; // c++11 enum class
+    EnumDef() : isEnumClass(false) {}
 };
 
 struct ArgumentDef
diff --git a/tests/auto/tools/moc/cxx11-enums.h b/tests/auto/tools/moc/cxx11-enums.h
new file mode 100644 (file)
index 0000000..ef98b6a
--- /dev/null
@@ -0,0 +1,66 @@
+/****************************************************************************
+**
+** Copyright (C) 2011 Olivier Goffart.
+** All rights reserved.
+** Contact: Nokia Corporation (qt-info@nokia.com)
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:LGPL$
+** GNU Lesser General Public License Usage
+** This file may be used under the terms of the GNU Lesser General Public
+** License version 2.1 as published by the Free Software Foundation and
+** appearing in the file LICENSE.LGPL included in the packaging of this
+** file. Please review the following information to ensure the GNU Lesser
+** General Public License version 2.1 requirements will be met:
+** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html.
+**
+** In addition, as a special exception, Nokia gives you certain additional
+** rights. These rights are described in the Nokia Qt LGPL Exception
+** version 1.1, included in the file LGPL_EXCEPTION.txt in this package.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU General
+** Public License version 3.0 as published by the Free Software Foundation
+** and appearing in the file LICENSE.GPL included in the packaging of this
+** file. Please review the following information to ensure the GNU General
+** Public License version 3.0 requirements will be met:
+** http://www.gnu.org/copyleft/gpl.html.
+**
+** Other Usage
+** Alternatively, this file may be used in accordance with the terms and
+** conditions contained in a signed written agreement between you and Nokia.
+**
+**
+**
+**
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+#include <QtCore/QObject>
+
+#if defined(Q_COMPILER_CLASS_ENUM) || defined(Q_MOC_RUN)
+class CXX11Enums
+{
+    Q_GADGET
+public:
+    Q_ENUMS(EnumClass TypedEnum TypedEnumClass NormalEnum)
+    enum class EnumClass { A0, A1, A2, A3 };
+    enum TypedEnum : char { B0, B1 , B2, B3 };
+    enum class TypedEnumClass : char { C0, C1, C2, C3 };
+    enum NormalEnum { D2 = 2, D3, D0 =0 , D1 };
+};
+
+#else
+//workaround to get the moc compiled code to compile
+class CXX11Enums
+{
+    Q_GADGET
+public:
+    struct EnumClass { enum { A0, A1, A2, A3 }; };
+    struct TypedEnumClass { enum { C0, C1, C2, C3 }; };
+    enum NormalEnum { D2 = 2, D3, D0 =0 , D1 };
+    enum TypedEnum { B0, B1 , B2, B3 };
+};
+#endif
index 37e33a1..dfda3c2 100644 (file)
@@ -17,7 +17,7 @@ HEADERS += using-namespaces.h no-keywords.h task87883.h c-comments.h backslash-n
            slots-with-void-template.h qinvokable.h namespaced-flags.h trigraphs.h \
            escapes-in-string-literals.h cstyle-enums.h qprivateslots.h gadgetwithnoenums.h \
            dir-in-include-path.h single_function_keyword.h task192552.h task189996.h \
-           task234909.h task240368.h pure-virtual-signals.h
+           task234909.h task240368.h pure-virtual-signals.h cxx11-enums.h
 if(*-g++*|*-icc*|*-clang|*-llvm):!irix-*:!win32-*: HEADERS += os9-newlines.h win-newlines.h
 SOURCES += tst_moc.cpp
 
index 1ce6f0c..aad095d 100644 (file)
 #include "escapes-in-string-literals.h"
 #include "cstyle-enums.h"
 
-
 #if defined(PARSE_BOOST)
 #include "parse-boost.h"
 #endif
+#include "cxx11-enums.h"
 
 QT_USE_NAMESPACE
 
@@ -511,6 +511,8 @@ private slots:
     void warnings();
 #endif
     void privateClass();
+    void cxx11Enums_data();
+    void cxx11Enums();
 
 signals:
     void sigWithUnsignedArg(unsigned foo);
@@ -1630,6 +1632,39 @@ void tst_Moc::privateClass()
     QVERIFY(PrivateClass::staticMetaObject.indexOfSignal("someSignal()") > 0);
 }
 
+void tst_Moc::cxx11Enums_data()
+{
+    QTest::addColumn<QByteArray>("enumName");
+    QTest::addColumn<char>("prefix");
+
+    QTest::newRow("EnumClass") << QByteArray("EnumClass") << 'A';
+    QTest::newRow("TypedEnum") << QByteArray("TypedEnum") << 'B';
+    QTest::newRow("TypedEnumClass") << QByteArray("TypedEnumClass") << 'C';
+    QTest::newRow("NormalEnum") << QByteArray("NormalEnum") << 'D';
+}
+
+
+void tst_Moc::cxx11Enums()
+{
+    const QMetaObject *meta = &CXX11Enums::staticMetaObject;
+    QCOMPARE(meta->enumeratorOffset(), 0);
+
+    QFETCH(QByteArray, enumName);
+    QFETCH(char, prefix);
+
+    int idx;
+    idx = meta->indexOfEnumerator(enumName);
+    QVERIFY(idx != -1);
+    QCOMPARE(meta->enumerator(idx).enclosingMetaObject(), meta);
+    QCOMPARE(meta->enumerator(idx).isValid(), true);
+    QCOMPARE(meta->enumerator(idx).keyCount(), 4);
+    QCOMPARE(meta->enumerator(idx).name(), enumName.constData());
+    for (int i = 0; i < 4; i++) {
+        QByteArray v = prefix + QByteArray::number(i);
+        QCOMPARE(meta->enumerator(idx).keyToValue(v), i);
+        QCOMPARE(meta->enumerator(idx).valueToKey(i), v.constData());
+    }
+}
 
 QTEST_APPLESS_MAIN(tst_Moc)
 #include "tst_moc.moc"