summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/corelib/kernel/qobjectdefs.h3
-rw-r--r--src/tools/moc/generator.cpp37
-rw-r--r--src/tools/moc/moc.cpp4
-rw-r--r--src/tools/moc/moc.h3
-rw-r--r--tests/auto/tools/moc/tst_moc.cpp370
5 files changed, 408 insertions, 9 deletions
diff --git a/src/corelib/kernel/qobjectdefs.h b/src/corelib/kernel/qobjectdefs.h
index e840706021..ba348b5245 100644
--- a/src/corelib/kernel/qobjectdefs.h
+++ b/src/corelib/kernel/qobjectdefs.h
@@ -154,7 +154,8 @@ public: \
QT_TR_FUNCTIONS \
virtual int qt_metacall(QMetaObject::Call, int, void **); \
private: \
- Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **);
+ Q_DECL_HIDDEN_STATIC_METACALL static void qt_static_metacall(QObject *, QMetaObject::Call, int, void **); \
+ struct QPrivateSignal {};
/* qmake ignore Q_OBJECT */
#define Q_OBJECT_FAKE Q_OBJECT
diff --git a/src/tools/moc/generator.cpp b/src/tools/moc/generator.cpp
index bcf70cbe91..09a4603753 100644
--- a/src/tools/moc/generator.cpp
+++ b/src/tools/moc/generator.cpp
@@ -540,7 +540,8 @@ void Generator::registerFunctionStrings(const QList<FunctionDef>& list)
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);
@@ -580,7 +581,7 @@ void Generator::generateFunctions(const QList<FunctionDef>& list, const char *fu
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);
@@ -608,7 +609,8 @@ void Generator::generateFunctionParameters(const QList<FunctionDef>& list, const
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;
@@ -617,7 +619,7 @@ void Generator::generateFunctionParameters(const QList<FunctionDef>& list, const
}
// 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));
}
@@ -1056,12 +1058,19 @@ void Generator::generateStaticMetacall()
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");
}
@@ -1098,13 +1107,20 @@ void Generator::generateStaticMetacall()
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; } ",
@@ -1131,12 +1147,19 @@ void Generator::generateStaticMetacall()
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
diff --git a/src/tools/moc/moc.cpp b/src/tools/moc/moc.cpp
index c35f27deaf..0caa124e79 100644
--- a/src/tools/moc/moc.cpp
+++ b/src/tools/moc/moc.cpp
@@ -309,6 +309,10 @@ void Moc::parseFunctionArguments(FunctionDef *def)
if (!until(COMMA))
break;
}
+
+ if (!def->arguments.isEmpty()
+ && def->arguments.last().normalizedType == "QPrivateSignal")
+ def->isPrivateSignal = true;
}
bool Moc::testFunctionAttribute(FunctionDef *def)
diff --git a/src/tools/moc/moc.h b/src/tools/moc/moc.h
index e20e29acb8..66cc942a9f 100644
--- a/src/tools/moc/moc.h
+++ b/src/tools/moc/moc.h
@@ -92,7 +92,7 @@ struct FunctionDef
{
FunctionDef(): returnTypeIsVolatile(false), access(Private), isConst(false), isVirtual(false), isStatic(false),
inlineCode(false), wasCloned(false), isCompat(false), isInvokable(false),
- isScriptable(false), isSlot(false), isSignal(false),
+ isScriptable(false), isSlot(false), isSignal(false), isPrivateSignal(false),
isConstructor(false), isDestructor(false), isAbstract(false), revision(0) {}
Type type;
QByteArray normalizedType;
@@ -116,6 +116,7 @@ struct FunctionDef
bool isScriptable;
bool isSlot;
bool isSignal;
+ bool isPrivateSignal;
bool isConstructor;
bool isDestructor;
bool isAbstract;
diff --git a/tests/auto/tools/moc/tst_moc.cpp b/tests/auto/tools/moc/tst_moc.cpp
index d4602a6e77..a79a5f604b 100644
--- a/tests/auto/tools/moc/tst_moc.cpp
+++ b/tests/auto/tools/moc/tst_moc.cpp
@@ -543,6 +543,8 @@ private slots:
void cxx11Enums();
void returnRefs();
+ void privateSignalConnection();
+
signals:
void sigWithUnsignedArg(unsigned foo);
void sigWithSignedArg(signed foo);
@@ -1768,6 +1770,374 @@ void tst_Moc::returnRefs()
// 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"