Skip to content

New C++/Qt code checks in clazy static analyzer

Sunday, 15 November 2015  |  sergio.martins

About two months ago I blogged about clazy, a Qt oriented static analyser.

Since then it has moved to an official KDE repo, got an IRC channel (#kde-clazy @ freenode) and also many fun new checks.

Here's a quick dump of the new features (be sure to see the README for the old checks too):

**** Performance related checks ****

qstring-arg: (saves allocations) s5 = QString("%1 %2 %3 %4").arg(s).arg(s1).arg(s3, s4); main.cpp: warning: Use multi-arg instead [-Wclazy-qstring-arg]

qstring-ref: (saves allocations, fixit included) int n = str.mid(1, 1).toInt(&ok); main.cpp: warning: Use midRef() instead [-Wclazy-qstring-ref]

qdatetime-utc: (saves allocations) QDateTime::currentDateTime().toUTC(); main.cpp: warning: Use QDateTime::currentDateTimeUtc() instead [-Wclazy-qdatetime-utc]

qgetenv (saves allocations): qgetenv("Foo").isEmpty(); main.cpp: warning: qgetenv().isEmpty() allocates. Use qEnvironmentVariableIsEmpty() instead [-Wclazy-qgetenv]

range-loop: for (int i : getQtList()) { range-loop.cpp warning: c++11 range-loop might detach Qt container [-Wclazy-foreach]

foreach: foreach (int i, v) { main.cpp: warning: foreach with STL container causes deep-copy [-Wclazy-foreach]

old-style-connect: connect(ptr, SIGNAL(signal1()), SLOT(slot1())); main.cpp: warning: Old Style Connect [-Wclazy-old-style-connect]

qDeleteAll: qDeleteAll(s.values()); main.cpp: warning: Calling qDeleteAll with QSet::values, call qDeleteAll on the container itself [-Wclazy-qdeleteall]

**** Crash related checks ****

temporary-iterator: for (auto it = getList().begin(); it != getList().end(); ++it) {} main.cpp: warning: Don't call QList::end() on temporary [-Wclazy-temporary-iterator]

auto-unexpected-qstringbuilder: const auto s1 = "tests/" + QString::fromLatin1("foo"); main.cpp: warning: auto deduced to be QStringBuilder instead of QString. Possible crash. [-Wclazy-auto-unexpected-qstringbuilder]

**** Misc related checks ****

writing-to-temporary: widget->sizePolicy().setVerticalStretch(1); main.cpp: warning: Call to temporary is a no-op: QSizePolicy::setVerticalStretch [-Wclazy-writing-to-temporary]

implicit-casts: explicit ComposerLineEdit(bool useCompletion, QWidget *parent = Q_NULLPTR); RecipientLineEdit::RecipientLineEdit(QWidget *parent) : ComposerLineEdit(parent) <-- oops, passing pointer as firt argument, which is a bool main.cpp warning: Implicit pointer to bool cast (argument 1) [-Wclazy-implicit-casts]

Also, old-style-connect and qstring-ref checks got fixits, so you can fix your code just by recompiling it with clazy.

Big thanks to everyone who contributed ideas and even code!

Please report bugs at b.k.o, happy hacking!