Fix source incompatibility while connecting signals with forward declared arguments

QObject::connect tries to determine if the arguments are registered
metatypes. This used to work even for arguments that were forward
declared. But now, the metatype system tries to call
QtPrivate::IsQEnumHelper<T>::Value to know if it is registered.
That fails on gcc if T is forward declared.

Apparently gcc needs to know the full type of T to pass it in the
ellipsis function, even within a sizeof expression.

So change the ellipsis expression to a template one.

Task-number: QTBUG-44496
Change-Id: I7fa07bd3cde470b134c2ec53b0d581333d16a6f1
Reviewed-by: Thiago Macieira <thiago.macieira@intel.com>
This commit is contained in:
Olivier Goffart 2015-02-22 10:02:08 +01:00 committed by Olivier Goffart (Woboq GmbH)
parent 59c4024171
commit 7c77013c7f
2 changed files with 24 additions and 5 deletions

View File

@ -1364,15 +1364,15 @@ namespace QtPrivate
enum { Value = sizeof(checkType(static_cast<T*>(0))) == sizeof(void*) };
};
char qt_getEnumMetaObject(...);
char qt_getEnumMetaObject(); // Workaround bugs in MSVC.
template<typename T> char qt_getEnumMetaObject(const T&);
template<typename T>
struct IsQEnumHelper {
static const T &declval();
// If the type was declared with Q_ENUM, the friend qt_getEnumMetaObject(T) declared in the
// If the type was declared with Q_ENUM, the friend qt_getEnumMetaObject() declared in the
// Q_ENUM macro will be chosen by ADL, and the return type will be QMetaObject*.
// Otherwise the chosen overload will be qt_getEnumMetaObject(...) which returne 'char'
// Otherwise the chosen overload will be the catch all template function
// qt_getEnumMetaObject(T) which returns 'char'
enum { Value = sizeof(qt_getEnumMetaObject(declval())) == sizeof(QMetaObject*) };
};

View File

@ -1,7 +1,7 @@
/****************************************************************************
**
** Copyright (C) 2015 The Qt Company Ltd.
** Copyright (C) 2013 Olivier Goffart <ogoffart@woboq.com>
** Copyright (C) 2015 Olivier Goffart <ogoffart@woboq.com>
** Contact: http://www.qt.io/licensing/
**
** This file is part of the test suite of the Qt Toolkit.
@ -127,6 +127,7 @@ private slots:
void connectConvert();
void connectWithReference();
void connectManyArguments();
void connectForwardDeclare();
void returnValue_data();
void returnValue();
void returnValue2_data();
@ -5208,6 +5209,24 @@ void tst_QObject::connectManyArguments()
QCOMPARE(ManyArgumentNamespace::count, 12);
}
class ForwardDeclared;
class ForwardDeclareArguments : public QObject
{
Q_OBJECT
signals:
void mySignal(const ForwardDeclared&);
public slots:
void mySlot(const ForwardDeclared&) {}
};
void tst_QObject::connectForwardDeclare()
{
ForwardDeclareArguments ob;
// it should compile
QVERIFY(connect(&ob, &ForwardDeclareArguments::mySignal, &ob, &ForwardDeclareArguments::mySlot, Qt::QueuedConnection));
}
class ReturnValue : public QObject {
friend class tst_QObject;
Q_OBJECT