From 4fe3cf8ee991e6adf3756019ff9d326769f0acf0 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Sat, 29 Oct 2011 19:55:36 +0200 Subject: [PATCH] moc: support c++11 style enums Task-number: QTBUG-21480 Change-Id: Ic116a5a06dd68036823f27146e49511c68cf2de6 Reviewed-by: Simon Hausmann --- src/tools/moc/generator.cpp | 10 +++--- src/tools/moc/moc.cpp | 7 ++++ src/tools/moc/moc.h | 2 ++ tests/auto/tools/moc/cxx11-enums.h | 66 ++++++++++++++++++++++++++++++++++++++ tests/auto/tools/moc/moc.pro | 2 +- tests/auto/tools/moc/tst_moc.cpp | 37 ++++++++++++++++++++- 6 files changed, 118 insertions(+), 6 deletions(-) create mode 100644 tests/auto/tools/moc/cxx11-enums.h diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp index 72fda2d..1ed7de2 100644 --- a/src/tools/moc/generator.cpp +++ b/src/tools/moc/generator.cpp @@ -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()); } } } diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp index 6374a72..8999148 100644 --- a/src/tools/moc/moc.cpp +++ b/src/tools/moc/moc.cpp @@ -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 { diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h index 1bb807c..917cf69 100644 --- a/src/tools/moc/moc.h +++ b/src/tools/moc/moc.h @@ -70,6 +70,8 @@ struct EnumDef { QByteArray name; QList 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 index 0000000..ef98b6a --- /dev/null +++ b/tests/auto/tools/moc/cxx11-enums.h @@ -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 + +#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 diff --git a/tests/auto/tools/moc/moc.pro b/tests/auto/tools/moc/moc.pro index 37e33a1..dfda3c2 100644 --- a/tests/auto/tools/moc/moc.pro +++ b/tests/auto/tools/moc/moc.pro @@ -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 diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp index 1ce6f0c..aad095d 100644 --- a/tests/auto/tools/moc/tst_moc.cpp +++ b/tests/auto/tools/moc/tst_moc.cpp @@ -66,10 +66,10 @@ #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("enumName"); + QTest::addColumn("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" -- 2.7.4