clazy 1.2 released presenting 5 new Qt compile-time checks

In the previous episode we presented how to uncover 32 Qt best practices at compile time with clazy. Today it’s time to show 5 more and other new goodies present in the freshly released clazy v1.2.

New checks

1. connect-not-normalized

Warns when the content of SIGNAL() , SLOT() , Q_ARG() and Q_RETURN_ARG() is not normalized. Using normalized signatures allows to avoid unneeded memory allocations.

Example:

// warning: Signature is not normalized. Use void mySlot(int) instead of void mySlot(const int) [-Wclazy-connect-not-normalized] o.connect(&o, SIGNAL(mySignal(int, int)), &o, SLOT(void mySlot(const int)));

See QMetaObject::normalizedSignature() for more information.

2. returning-data-from-temporary

Warns when returning the data from a QByteArray that will soon be destroyed. Accessing such data usually results in a crash. For example:

QByteArray b = ...; return b.data();

return funcReturningByteArray().data();

return funcReturningByteArray().constData();

const char * getFoo() { QByteArray b = ...; return b; // QByteArray can implicitly cast to char* }

const char *c1 = getByteArray(); const char *c2 = str.toUtf8().data();

3. install-event-filter

Warns on potential misuse of QObject::installEventFilter() . To install an event filter on obj1 you should call obj1->installEventFilter(this) , but sometimes you’ll write installEventFilter(obj1) by mistake, which compiles fine.

4. qcolor-from-literal

Warns when a QColor is being constructed from a string literal such as “#RRGGBB”. This is less performant than calling the ctor that takes int s, since it creates temporary QString s.

Example:

QColor c("#000000"); // Use QColor c(0, 0, 0) instead c.setNamedColor("#001122"); // Use c = QColor(0, 0x11, 0x22) instead

5. strict-iterators

Warns when iterator objects are implicitly cast to const_iterator . This is mostly equivalent to passing -DQT_STRICT_ITERATORS to the compiler, except that it also works for QString . This prevents detachments but also caches subtle bugs such as:

QHash<int, int> wrong; if (wrong.find(1) == wrong.cend()) { qDebug() << "Not found"; } else { // find() detached the container before cend() was called, so it prints "Found" qDebug() << "Found"; } QHash<int, int> right; if (right.constFind(1) == right.cend()) { // Prints "Not Found". This is correct now ! qDebug() << "Not found"; } else { qDebug() << "Found"; }

New features

1. clazy-standalone

Many people asked for clang-tidy support. This can’t be done due to clang-tidy not supporting plugins yet. Thus, clazy-standalone was born. It works in a similar way as clang-tidy, by operating on a json compilation database instead of being loaded as a compiler plugin. It can be invoked as:

clazy-standalone -checks=level1 -p compile_commands.json myfile.cpp

2. ASTMatchers

If you want to contribute a new check to clazy you can now use the AST Matchers API instead of the low level AST way. AST Matchers are gaining popularity and used in many clang tooling already.

3. Pre-built Windows binaries

Since it’s an hassle to build LLVM on your own on Windows, we’ve made a pre-built ready to use clazy v1.2 package.

The End

That’s all folks. You can get clazy from https://phabricator.kde.org/source/clazy/. Be sure to check the README.md file, it should have answers to most (clazy related) questions.

Please try it and report bugs!