Fix regression in property handling with enums from gadgets

When declaring a Q_PROPERTY(SomeType::SomeEnum foo ...) and SomeType is not a
QObject but a gadget, then we must still include SomeType's meta object in the
list of related meta objects.

Task-number: QTBUG-35657
Change-Id: I46195140cb5d180c4f03bb1fe06a876e3fe11267
Reviewed-by: Olivier Goffart <ogoffart@woboq.com>
This commit is contained in:
Simon Hausmann 2013-12-23 15:16:08 +01:00 committed by The Qt Project
parent d776937df9
commit 2b287c7c21
8 changed files with 143 additions and 12 deletions

View File

@ -87,8 +87,9 @@ QT_FOR_EACH_STATIC_TYPE(RETURN_METATYPENAME_STRING)
return 0; return 0;
} }
Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, FILE *outfile) Generator::Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile)
: out(outfile), cdef(classDef), metaTypes(metaTypes), knownQObjectClasses(knownQObjectClasses) : out(outfile), cdef(classDef), metaTypes(metaTypes), knownQObjectClasses(knownQObjectClasses)
, knownGadgets(knownGadgets)
{ {
if (cdef->superclassList.size()) if (cdef->superclassList.size())
purestSuperClass = cdef->superclassList.first().first; purestSuperClass = cdef->superclassList.first().first;
@ -452,8 +453,11 @@ void Generator::generateCode()
// The scope may be a namespace for example, so it's only safe to include scopes that are known QObjects (QTBUG-2151) // The scope may be a namespace for example, so it's only safe to include scopes that are known QObjects (QTBUG-2151)
QHash<QByteArray, QByteArray>::ConstIterator scopeIt = knownQObjectClasses.find(unqualifiedScope); QHash<QByteArray, QByteArray>::ConstIterator scopeIt = knownQObjectClasses.find(unqualifiedScope);
if (scopeIt == knownQObjectClasses.constEnd()) if (scopeIt == knownQObjectClasses.constEnd()) {
continue; scopeIt = knownGadgets.find(unqualifiedScope);
if (scopeIt == knownGadgets.constEnd())
continue;
}
const QByteArray &scope = *scopeIt; const QByteArray &scope = *scopeIt;
if (scope == "Qt") if (scope == "Qt")

View File

@ -52,7 +52,7 @@ class Generator
ClassDef *cdef; ClassDef *cdef;
QVector<uint> meta_data; QVector<uint> meta_data;
public: public:
Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, FILE *outfile = 0); Generator(ClassDef *classDef, const QList<QByteArray> &metaTypes, const QHash<QByteArray, QByteArray> &knownQObjectClasses, const QHash<QByteArray, QByteArray> &knownGadgets, FILE *outfile = 0);
void generateCode(); void generateCode();
private: private:
bool registerableMetaType(const QByteArray &propertyType); bool registerableMetaType(const QByteArray &propertyType);
@ -80,6 +80,7 @@ private:
QByteArray purestSuperClass; QByteArray purestSuperClass;
QList<QByteArray> metaTypes; QList<QByteArray> metaTypes;
QHash<QByteArray, QByteArray> knownQObjectClasses; QHash<QByteArray, QByteArray> knownQObjectClasses;
QHash<QByteArray, QByteArray> knownGadgets;
}; };
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -608,21 +608,27 @@ void Moc::parse()
continue; continue;
while (inClass(&def) && hasNext()) { while (inClass(&def) && hasNext()) {
if (next() == Q_OBJECT_TOKEN) { switch (next()) {
case Q_OBJECT_TOKEN:
def.hasQObject = true; def.hasQObject = true;
break; break;
case Q_GADGET_TOKEN:
def.hasQGadget = true;
break;
default: break;
} }
} }
if (!def.hasQObject) if (!def.hasQObject && !def.hasQGadget)
continue; continue;
for (int i = namespaceList.size() - 1; i >= 0; --i) for (int i = namespaceList.size() - 1; i >= 0; --i)
if (inNamespace(&namespaceList.at(i))) if (inNamespace(&namespaceList.at(i)))
def.qualified.prepend(namespaceList.at(i).name + "::"); def.qualified.prepend(namespaceList.at(i).name + "::");
knownQObjectClasses.insert(def.classname, def.qualified); QHash<QByteArray, QByteArray> &classHash = def.hasQObject ? knownQObjectClasses : knownGadgets;
knownQObjectClasses.insert(def.qualified, def.qualified); classHash.insert(def.classname, def.qualified);
classHash.insert(def.qualified, def.qualified);
continue; } continue; }
default: break; default: break;
@ -795,8 +801,9 @@ void Moc::parse()
checkProperties(&def); checkProperties(&def);
classList += def; classList += def;
knownQObjectClasses.insert(def.classname, def.qualified); QHash<QByteArray, QByteArray> &classHash = def.hasQObject ? knownQObjectClasses : knownGadgets;
knownQObjectClasses.insert(def.qualified, def.qualified); classHash.insert(def.classname, def.qualified);
classHash.insert(def.qualified, def.qualified);
} }
} }
} }
@ -896,7 +903,7 @@ void Moc::generate(FILE *out)
fprintf(out, "QT_BEGIN_MOC_NAMESPACE\n"); fprintf(out, "QT_BEGIN_MOC_NAMESPACE\n");
for (i = 0; i < classList.size(); ++i) { for (i = 0; i < classList.size(); ++i) {
Generator generator(&classList[i], metaTypes, knownQObjectClasses, out); Generator generator(&classList[i], metaTypes, knownQObjectClasses, knownGadgets, out);
generator.generateCode(); generator.generateCode();
} }

View File

@ -217,6 +217,7 @@ public:
QList<QByteArray> metaTypes; QList<QByteArray> metaTypes;
// map from class name to fully qualified name // map from class name to fully qualified name
QHash<QByteArray, QByteArray> knownQObjectClasses; QHash<QByteArray, QByteArray> knownQObjectClasses;
QHash<QByteArray, QByteArray> knownGadgets;
QMap<QString, QJsonArray> metaArgs; QMap<QString, QJsonArray> metaArgs;
void parse(); void parse();

View File

@ -25,7 +25,9 @@ HEADERS += using-namespaces.h no-keywords.h task87883.h c-comments.h backslash-n
function-with-attributes.h \ function-with-attributes.h \
plugin_metadata.h \ plugin_metadata.h \
single-quote-digit-separator-n3781.h \ single-quote-digit-separator-n3781.h \
related-metaobjects-in-namespaces.h related-metaobjects-in-namespaces.h \
qtbug-35657-gadget.h \
related-metaobjects-in-gadget.h
if(*-g++*|*-icc*|*-clang*|*-llvm):!irix-*:!win32-*: HEADERS += os9-newlines.h win-newlines.h if(*-g++*|*-icc*|*-clang*|*-llvm):!irix-*:!win32-*: HEADERS += os9-newlines.h win-newlines.h

View File

@ -0,0 +1,51 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, 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, Digia gives you certain additional
** rights. These rights are described in the Digia 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.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QObject>
namespace QTBUG_35657 {
class A {
Q_GADGET
Q_ENUMS(SomeEnum)
public:
enum SomeEnum { SomeEnumValue = 0 };
};
}

View File

@ -0,0 +1,54 @@
/****************************************************************************
**
** Copyright (C) 2013 Digia Plc and/or its subsidiary(-ies).
** Contact: http://www.qt-project.org/legal
**
** This file is part of the test suite of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** Commercial License Usage
** Licensees holding valid commercial Qt licenses may use this file in
** accordance with the commercial license agreement provided with the
** Software or, alternatively, in accordance with the terms contained in
** a written agreement between you and Digia. For licensing terms and
** conditions see http://qt.digia.com/licensing. For further information
** use the contact form at http://qt.digia.com/contact-us.
**
** GNU Lesser General Public License Usage
** Alternatively, 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, Digia gives you certain additional
** rights. These rights are described in the Digia 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.
**
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include <QObject>
#include "qtbug-35657-gadget.h"
namespace QTBUG_35657 {
class B : public QObject
{
Q_OBJECT
Q_PROPERTY(A::SomeEnum blah READ blah)
public:
A::SomeEnum blah() const { return A::SomeEnumValue; }
};
}

View File

@ -77,6 +77,7 @@
#include "parse-defines.h" #include "parse-defines.h"
#include "related-metaobjects-in-namespaces.h" #include "related-metaobjects-in-namespaces.h"
#include "related-metaobjects-in-gadget.h"
QT_USE_NAMESPACE QT_USE_NAMESPACE
@ -571,6 +572,7 @@ private slots:
void QTBUG32933_relatedObjectsDontIncludeItself(); void QTBUG32933_relatedObjectsDontIncludeItself();
void writeEnumFromUnrelatedClass(); void writeEnumFromUnrelatedClass();
void relatedMetaObjectsWithinNamespaces(); void relatedMetaObjectsWithinNamespaces();
void relatedMetaObjectsInGadget();
signals: signals:
void sigWithUnsignedArg(unsigned foo); void sigWithUnsignedArg(unsigned foo);
@ -3162,6 +3164,15 @@ void tst_Moc::relatedMetaObjectsWithinNamespaces()
QVERIFY(testMo->d.relatedMetaObjects[0] == relatedMo); QVERIFY(testMo->d.relatedMetaObjects[0] == relatedMo);
} }
void tst_Moc::relatedMetaObjectsInGadget()
{
const QMetaObject *relatedMo = &QTBUG_35657::A::staticMetaObject;
const QMetaObject *testMo = &QTBUG_35657::B::staticMetaObject;
QVERIFY(testMo->d.relatedMetaObjects);
QVERIFY(testMo->d.relatedMetaObjects[0] == relatedMo);
}
QTEST_MAIN(tst_Moc) QTEST_MAIN(tst_Moc)
// the generated code must compile with QT_NO_KEYWORDS // the generated code must compile with QT_NO_KEYWORDS