strreg(f.normalizedType);
strreg(f.tag);
- for (int j = 0; j < f.arguments.count(); ++j) {
+ int argsCount = f.arguments.count() - (f.isPrivateSignal ? 1 : 0);
+ for (int j = 0; j < argsCount; ++j) {
const ArgumentDef &a = f.arguments.at(j);
if (!isBuiltinType(a.normalizedType))
strreg(a.normalizedType);
if (f.revision > 0)
flags |= MethodRevisioned;
- int argc = f.arguments.count();
+ int argc = f.arguments.count() - (f.isPrivateSignal ? 1 : 0);
fprintf(out, " %4d, %4d, %4d, %4d, 0x%02x,\n",
stridx(f.name), argc, paramsIndex, stridx(f.tag), flags);
fprintf(out, " ");
// Types
- for (int j = -1; j < f.arguments.count(); ++j) {
+ int argsCount = f.arguments.count() - (f.isPrivateSignal ? 1 : 0);
+ for (int j = -1; j < argsCount; ++j) {
if (j > -1)
fputc(' ', out);
const QByteArray &typeName = (j < 0) ? f.normalizedType : f.arguments.at(j).normalizedType;
}
// Parameter names
- for (int j = 0; j < f.arguments.count(); ++j) {
+ for (int j = 0; j < argsCount; ++j) {
const ArgumentDef &arg = f.arguments.at(j);
fprintf(out, " %4d,", stridx(arg.name));
}
cdef->classname.constData(), cdef->classname.constData());
const FunctionDef &f = cdef->constructorList.at(ctorindex);
int offset = 1;
- for (int j = 0; j < f.arguments.count(); ++j) {
+
+ int argsCount = f.arguments.count() - (f.isPrivateSignal ? 1 : 0);
+ for (int j = 0; j < argsCount; ++j) {
const ArgumentDef &a = f.arguments.at(j);
if (j)
fprintf(out, ",");
fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))", a.typeNameForCast.constData(), offset++);
}
+ if (f.isPrivateSignal) {
+ if (argsCount > 0)
+ fprintf(out, ", ");
+ fprintf(out, "%s", QByteArray(f.arguments.last().normalizedType + "()").constData());
+ }
fprintf(out, ");\n");
fprintf(out, " if (_a[0]) *reinterpret_cast<QObject**>(_a[0]) = _r; } break;\n");
}
fprintf(out, "%s->", f.inPrivateClass.constData());
fprintf(out, "%s(", f.name.constData());
int offset = 1;
- for (int j = 0; j < f.arguments.count(); ++j) {
+
+ int argsCount = f.arguments.count() - (f.isPrivateSignal ? 1 : 0);
+ for (int j = 0; j < argsCount; ++j) {
const ArgumentDef &a = f.arguments.at(j);
if (j)
fprintf(out, ",");
fprintf(out, "(*reinterpret_cast< %s>(_a[%d]))",a.typeNameForCast.constData(), offset++);
isUsed_a = true;
}
+ if (f.isPrivateSignal) {
+ if (argsCount > 0)
+ fprintf(out, ", ");
+ fprintf(out, "%s", QByteArray(f.arguments.last().normalizedType + "()").constData());
+ }
fprintf(out, ");");
if (f.normalizedType != "void") {
fprintf(out, "\n if (_a[0]) *reinterpret_cast< %s*>(_a[0]) = _r; } ",
anythingUsed = true;
fprintf(out, " {\n");
fprintf(out, " typedef %s (%s::*_t)(",f.type.rawName.constData() , cdef->classname.constData());
- for (int j = 0; j < f.arguments.count(); ++j) {
+
+ int argsCount = f.arguments.count() - (f.isPrivateSignal ? 1 : 0);
+ for (int j = 0; j < argsCount; ++j) {
const ArgumentDef &a = f.arguments.at(j);
if (j)
fprintf(out, ", ");
fprintf(out, "%s", QByteArray(a.type.name + ' ' + a.rightType).constData());
}
+ if (f.isPrivateSignal) {
+ if (argsCount > 0)
+ fprintf(out, ", ");
+ fprintf(out, "%s", f.arguments.last().normalizedType.constData());
+ }
if (f.isConst)
fprintf(out, ") const;\n");
else
void cxx11Enums();
void returnRefs();
+ void privateSignalConnection();
+
signals:
void sigWithUnsignedArg(unsigned foo);
void sigWithSignedArg(signed foo);
// they used to cause miscompilation of the moc generated file.
}
+class SignalConnectionTester : public QObject
+{
+ Q_OBJECT
+public:
+ SignalConnectionTester(QObject *parent = 0)
+ : QObject(parent), testPassed(false)
+ {
+
+ }
+
+public Q_SLOTS:
+ void testSlot()
+ {
+ testPassed = true;
+ }
+ void testSlotWith1Arg(int i)
+ {
+ testPassed = i == 42;
+ }
+ void testSlotWith2Args(int i, const QString &s)
+ {
+ testPassed = i == 42 && s == "Hello";
+ }
+
+public:
+ bool testPassed;
+};
+
+class ClassWithPrivateSignals : public QObject
+{
+ Q_OBJECT
+public:
+ ClassWithPrivateSignals(QObject *parent = 0)
+ : QObject(parent)
+ {
+
+ }
+
+ void emitPrivateSignals()
+ {
+ emit privateSignal1(QPrivateSignal());
+ emit privateSignalWith1Arg(42, QPrivateSignal());
+ emit privateSignalWith2Args(42, "Hello", QPrivateSignal());
+ }
+
+Q_SIGNALS:
+ void privateSignal1(QPrivateSignal);
+ void privateSignalWith1Arg(int arg1, QPrivateSignal);
+ void privateSignalWith2Args(int arg1, const QString &arg2, QPrivateSignal);
+};
+
+class SubClassFromPrivateSignals : public ClassWithPrivateSignals
+{
+ Q_OBJECT
+public:
+ SubClassFromPrivateSignals(QObject *parent = 0)
+ : ClassWithPrivateSignals(parent)
+ {
+
+ }
+
+ void emitProtectedSignals()
+ {
+ // Compile test: All of this intentionally does not compile:
+// emit privateSignal1();
+// emit privateSignalWith1Arg(42);
+// emit privateSignalWith2Args(42, "Hello");
+//
+// emit privateSignal1(QPrivateSignal());
+// emit privateSignalWith1Arg(42, QPrivateSignal());
+// emit privateSignalWith2Args(42, "Hello", QPrivateSignal());
+//
+// emit privateSignal1(ClassWithPrivateSignals::QPrivateSignal());
+// emit privateSignalWith1Arg(42, ClassWithPrivateSignals::QPrivateSignal());
+// emit privateSignalWith2Args(42, "Hello", ClassWithPrivateSignals::QPrivateSignal());
+ }
+};
+
+void tst_Moc::privateSignalConnection()
+{
+ // Function pointer connects. Matching signals and slots
+ {
+ ClassWithPrivateSignals classWithPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&classWithPrivateSignals, &ClassWithPrivateSignals::privateSignal1, &tester, &SignalConnectionTester::testSlot);
+
+ QVERIFY(!tester.testPassed);
+
+ classWithPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ tester.testPassed = false;
+ QMetaObject::invokeMethod(&classWithPrivateSignals, "privateSignal1");
+ QVERIFY(tester.testPassed);
+ }
+ {
+ SubClassFromPrivateSignals subClassFromPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&subClassFromPrivateSignals, &ClassWithPrivateSignals::privateSignal1, &tester, &SignalConnectionTester::testSlot);
+
+ QVERIFY(!tester.testPassed);
+
+ subClassFromPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ tester.testPassed = false;
+ QMetaObject::invokeMethod(&subClassFromPrivateSignals, "privateSignal1");
+ QVERIFY(tester.testPassed);
+ }
+ {
+ ClassWithPrivateSignals classWithPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&classWithPrivateSignals, &ClassWithPrivateSignals::privateSignalWith1Arg, &tester, &SignalConnectionTester::testSlotWith1Arg);
+
+ QVERIFY(!tester.testPassed);
+
+ classWithPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ tester.testPassed = false;
+ QMetaObject::invokeMethod(&classWithPrivateSignals, "privateSignalWith1Arg", Q_ARG(int, 42));
+ QVERIFY(tester.testPassed);
+ }
+ {
+ SubClassFromPrivateSignals subClassFromPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&subClassFromPrivateSignals, &ClassWithPrivateSignals::privateSignalWith1Arg, &tester, &SignalConnectionTester::testSlotWith1Arg);
+
+ QVERIFY(!tester.testPassed);
+
+ subClassFromPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ tester.testPassed = false;
+ QMetaObject::invokeMethod(&subClassFromPrivateSignals, "privateSignalWith1Arg", Q_ARG(int, 42));
+ QVERIFY(tester.testPassed);
+ }
+ {
+ ClassWithPrivateSignals classWithPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&classWithPrivateSignals, &ClassWithPrivateSignals::privateSignalWith2Args, &tester, &SignalConnectionTester::testSlotWith2Args);
+
+ QVERIFY(!tester.testPassed);
+
+ classWithPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ tester.testPassed = false;
+ QMetaObject::invokeMethod(&classWithPrivateSignals, "privateSignalWith2Args", Q_ARG(int, 42), Q_ARG(QString, "Hello"));
+ QVERIFY(tester.testPassed);
+ }
+ {
+ SubClassFromPrivateSignals subClassFromPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&subClassFromPrivateSignals, &ClassWithPrivateSignals::privateSignalWith2Args, &tester, &SignalConnectionTester::testSlotWith2Args);
+
+ QVERIFY(!tester.testPassed);
+
+ subClassFromPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ tester.testPassed = false;
+ QMetaObject::invokeMethod(&subClassFromPrivateSignals, "privateSignalWith2Args", Q_ARG(int, 42), Q_ARG(QString, "Hello"));
+ QVERIFY(tester.testPassed);
+ }
+
+
+ // String based connects. Matching signals and slots
+ {
+ ClassWithPrivateSignals classWithPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&classWithPrivateSignals, SIGNAL(privateSignal1()), &tester, SLOT(testSlot()));
+
+ QVERIFY(!tester.testPassed);
+
+ classWithPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ SubClassFromPrivateSignals subClassFromPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&subClassFromPrivateSignals, SIGNAL(privateSignal1()), &tester, SLOT(testSlot()));
+
+ QVERIFY(!tester.testPassed);
+
+ subClassFromPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ ClassWithPrivateSignals classWithPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&classWithPrivateSignals, SIGNAL(privateSignalWith1Arg(int)), &tester, SLOT(testSlotWith1Arg(int)));
+
+ QVERIFY(!tester.testPassed);
+
+ classWithPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ SubClassFromPrivateSignals subClassFromPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&subClassFromPrivateSignals, SIGNAL(privateSignalWith1Arg(int)), &tester, SLOT(testSlotWith1Arg(int)));
+
+ QVERIFY(!tester.testPassed);
+
+ subClassFromPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ ClassWithPrivateSignals classWithPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&classWithPrivateSignals, SIGNAL(privateSignalWith2Args(int,QString)), &tester, SLOT(testSlotWith2Args(int,QString)));
+ QVERIFY(!tester.testPassed);
+
+ classWithPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ SubClassFromPrivateSignals subClassFromPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&subClassFromPrivateSignals, SIGNAL(privateSignalWith2Args(int,QString)), &tester, SLOT(testSlotWith2Args(int,QString)));
+
+ QVERIFY(!tester.testPassed);
+
+ subClassFromPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+
+ // Function pointer connects. Decayed slot arguments
+ {
+ ClassWithPrivateSignals classWithPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&classWithPrivateSignals, &ClassWithPrivateSignals::privateSignalWith1Arg, &tester, &SignalConnectionTester::testSlot);
+
+ QVERIFY(!tester.testPassed);
+
+ classWithPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ SubClassFromPrivateSignals subClassFromPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&subClassFromPrivateSignals, &ClassWithPrivateSignals::privateSignalWith1Arg, &tester, &SignalConnectionTester::testSlot);
+
+ QVERIFY(!tester.testPassed);
+
+ subClassFromPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ ClassWithPrivateSignals classWithPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&classWithPrivateSignals, &ClassWithPrivateSignals::privateSignalWith1Arg, &tester, &SignalConnectionTester::testSlotWith1Arg);
+ QVERIFY(!tester.testPassed);
+
+ classWithPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ SubClassFromPrivateSignals subClassFromPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&subClassFromPrivateSignals, &ClassWithPrivateSignals::privateSignalWith1Arg, &tester, &SignalConnectionTester::testSlotWith1Arg);
+
+ QVERIFY(!tester.testPassed);
+
+ subClassFromPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ ClassWithPrivateSignals classWithPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&classWithPrivateSignals, &ClassWithPrivateSignals::privateSignalWith1Arg, &tester, &SignalConnectionTester::testSlot);
+ QVERIFY(!tester.testPassed);
+
+ classWithPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ SubClassFromPrivateSignals subClassFromPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&subClassFromPrivateSignals, &ClassWithPrivateSignals::privateSignalWith1Arg, &tester, &SignalConnectionTester::testSlot);
+
+ QVERIFY(!tester.testPassed);
+
+ subClassFromPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+
+ // String based connects. Decayed slot arguments
+ {
+ ClassWithPrivateSignals classWithPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&classWithPrivateSignals, SIGNAL(privateSignalWith1Arg(int)), &tester, SLOT(testSlot()));
+
+ QVERIFY(!tester.testPassed);
+
+ classWithPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ SubClassFromPrivateSignals subClassFromPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&subClassFromPrivateSignals, SIGNAL(privateSignalWith1Arg(int)), &tester, SLOT(testSlot()));
+
+ QVERIFY(!tester.testPassed);
+
+ subClassFromPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ ClassWithPrivateSignals classWithPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&classWithPrivateSignals, SIGNAL(privateSignalWith2Args(int,QString)), &tester, SLOT(testSlotWith1Arg(int)));
+ QVERIFY(!tester.testPassed);
+
+ classWithPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ SubClassFromPrivateSignals subClassFromPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&subClassFromPrivateSignals, SIGNAL(privateSignalWith2Args(int,QString)), &tester, SLOT(testSlotWith1Arg(int)));
+
+ QVERIFY(!tester.testPassed);
+
+ subClassFromPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ ClassWithPrivateSignals classWithPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&classWithPrivateSignals, SIGNAL(privateSignalWith2Args(int,QString)), &tester, SLOT(testSlot()));
+ QVERIFY(!tester.testPassed);
+
+ classWithPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+ {
+ SubClassFromPrivateSignals subClassFromPrivateSignals;
+ SignalConnectionTester tester;
+ QObject::connect(&subClassFromPrivateSignals, SIGNAL(privateSignalWith2Args(int,QString)), &tester, SLOT(testSlot()));
+
+ QVERIFY(!tester.testPassed);
+
+ subClassFromPrivateSignals.emitPrivateSignals();
+
+ QVERIFY(tester.testPassed);
+ }
+}
+
+
QTEST_MAIN(tst_Moc)
#include "tst_moc.moc"