NOV
15
2015

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

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

Since then it has moved to an official KDE repo http://anongit.kde.org/clazy, 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!

Comments

i get this error message when i run clazy:
/usr/lib/llvm-3.7/bin/clang: symbol lookup error: /usr/lib/x86_64-linux-gnu/ClangLazy.so: undefined symbol: _ZNK5clang15DeclarationName11getAsStringEv

note that i used clang for CC and clazy for CXX


By shaforostoff at Mon, 11/16/2015 - 14:01

That's due to mixing old ABI and new C++11 ABI.
Your llvm was probably built with new ABI, but you compiled the plugin with old ABI.
Did you compile the plugin with clang ? clang doesn't support the new ABI yet ( https://llvm.org/bugs/show_bug.cgi?id=23529), try building it with gcc or try a distro that hasn't moved to the new ABI.


By sergio.martins at Mon, 11/16/2015 - 19:56

"Did you compile the plugin with clang?"

yes, that seemed logical to me ;)


By shaforostoff at Tue, 11/17/2015 - 10:27