qconnectlint is a Clang tool for statically verifying the consistency of signal and slot connections made with Qt's QObject::connect. It can detect the following problems:
- Signals or slots not existing with the expected signature
- Incompatible signal and slot signatures due to types or argument count
- Slots being used as signals
A recent compiler toolchain supporting C++11 is required. GCC 4.7 or Clang 3.1 should be sufficient.
- Download the source for LLVM and Clang 3.2
- Check out qconnectlint as
tools/clang/tools/qconnectlint - Run
./configure --enable-cxx11in the root LLVM directory
--enable-libcppis required on Mac OS X due to the distributed libstdc++ not supporting C++11--disable-assertions --enable-optimizedis recommended for performance reasons. These flags are typically used when building a distribution's version of Clang.--prefixcan be used to install qconnectlint's copy of LLVM and Clang to a non-default location.
- Run the following from LLVM's root directory
$ make install && cd tools/clang/tools/qconnectlint && make installIf a Clang compilation database exists for the project qconnectlint can be invoked with a list of source files to lint.
If no database is present the list of source files must be followed with a delimiting -- and a list of compiler flags exactly as they would be passed to Clang. For example, the following would check the files test1.cpp and test2.cpp with some typical compiler flags:
$ qconnectlint test1.cpp test2.cpp -- -std=c++11 -Wall -I/usr/include/qt4qconnectlint's output mimics Clang's format. This means tools intended to parse the output of Clang should easily handle lint reports. An example Vim compiler plugin is included in the vim directory.
qconnectlint is limited to static analysis using information available at compile time. This has a number of consequences:
- Signals and slots must be referenced using inline
SIGNAL()andSLOT()macros when callingconnect(). For example, passing a signal/slot to a function that indirectly callsconnect()itself won't be checked - Passing a derived class pointer upcast to a base class (typically QObject*) will falsely trigger warnings if the base class doesn't define the referenced signal/slot.
- Signal and slot annotations are lost at the preprocessor stage. As a result qconnectlint can't determine if a given class member has been defined as a signal or slot; it simply checks for the existence of a member with a matching signature.