Details
-
Bug
-
Resolution: Unresolved
-
P2: Important
-
None
-
5.15.7, 6.4.2
-
None
Description
If you use an include file and macro for auto generating signals, moc may create incorrect signal definitions and cause compiling errors.
Sample code:
// myservice.h // the myservice.cpp is trivial, nothing more than an auto-generated constructor. #ifndef MYSERVICE_H #define MYSERVICE_H #include <QObject> class MyService : public QObject { Q_OBJECT public: explicit MyService(QObject *parent = nullptr); #define MY_PROPERTY(type, name) \ Q_PROPERTY(type name MEMBER m_##name NOTIFY name##Changed) #include "property_list" #undef MY_PROPERTY signals: #define MY_PROPERTY(type, name) \ void name##Changed(type); #include "property_list" #undef MY_PROPERTY private: #define MY_PROPERTY(type, name) \ type m_##name; #include "property_list" #undef MY_PROPERTY }; #endif // MYSERVICE_H
and file "property_list" is:
MY_PROPERTY(QString, value1) MY_PROPERTY(QString, value2)
We'll get following compile errors:
moc_myservice.cpp: In static member function 'static void MyService::qt_static_metacall(QObject*, QMetaObject::Call, int, void**)': moc_myservice.cpp:92:41: error: no matching function for call to 'MyService::value1Changed()' 92 | Q_EMIT _t->value1Changed(); | ~~~~~~~~~~~~~~~~~^~ In file included from moc_myservice.cpp:10: ../qt01/property_list:1:22: note: candidate: 'void MyService::value1Changed(QString)' 1 | MY_PROPERTY(QString, value1) | ^~~~~~ ../qt01/myservice.h:19:10: note: in definition of macro 'MY_PROPERTY' 19 | void name##Changed(type); | ^~~~ ../qt01/property_list:1:22: note: candidate expects 1 argument, 0 provided 1 | MY_PROPERTY(QString, value1) | ^~~~~~ ../qt01/myservice.h:19:10: note: in definition of macro 'MY_PROPERTY' 19 | void name##Changed(type); | ^~~~ moc_myservice.cpp:98:41: error: no matching function for call to 'MyService::value2Changed()' 98 | Q_EMIT _t->value2Changed(); | ~~~~~~~~~~~~~~~~~^~ ../qt01/property_list:2:22: note: candidate: 'void MyService::value2Changed(QString)' 2 | MY_PROPERTY(QString, value2) | ^~~~~~ ../qt01/myservice.h:19:10: note: in definition of macro 'MY_PROPERTY' 19 | void name##Changed(type); | ^~~~ ../qt01/property_list:2:22: note: candidate expects 1 argument, 0 provided 2 | MY_PROPERTY(QString, value2) | ^~~~~~ ../qt01/myservice.h:19:10: note: in definition of macro 'MY_PROPERTY' 19 | void name##Changed(type); | ^~~~ moc_myservice.cpp: In function 'void checkNotifySignalValidity_MyService(MyService*)': moc_myservice.cpp:164:21: error: no matching function for call to 'MyService::value1Changed()' 164 | t->value1Changed(); | ~~~~~~~~~~~~~~~~^~ ../qt01/property_list:1:22: note: candidate: 'void MyService::value1Changed(QString)' 1 | MY_PROPERTY(QString, value1) | ^~~~~~ ../qt01/myservice.h:19:10: note: in definition of macro 'MY_PROPERTY' 19 | void name##Changed(type); | ^~~~ ../qt01/property_list:1:22: note: candidate expects 1 argument, 0 provided 1 | MY_PROPERTY(QString, value1) | ^~~~~~ ../qt01/myservice.h:19:10: note: in definition of macro 'MY_PROPERTY' 19 | void name##Changed(type); | ^~~~ moc_myservice.cpp:165:21: error: no matching function for call to 'MyService::value2Changed()' 165 | t->value2Changed(); | ~~~~~~~~~~~~~~~~^~ ../qt01/property_list:2:22: note: candidate: 'void MyService::value2Changed(QString)' 2 | MY_PROPERTY(QString, value2) | ^~~~~~ ../qt01/myservice.h:19:10: note: in definition of macro 'MY_PROPERTY' 19 | void name##Changed(type); | ^~~~ ../qt01/property_list:2:22: note: candidate expects 1 argument, 0 provided 2 | MY_PROPERTY(QString, value2) | ^~~~~~ ../qt01/myservice.h:19:10: note: in definition of macro 'MY_PROPERTY' 19 | void name##Changed(type); | ^~~~
If we change the signal sector, replace the #include directive with content of file "property_list", this issue will disappear. It looks like moc ran into some problem and generates incorrect code if we're using both macro & include file.