I would like to statically inspect all calls to non-void functions where the return value is not used.
In effect this would be like applying __attribute__ ((warn_unused_result))
to all non-void functions, but of course for a large project that is not practical to do.
Is there any static analysis tool that can provide this information?
This can be done using clang-query
. Here is a shell script that invokes clang-query
to find calls that return a value that is not used:
#!/bin/sh
# cmd.sh: Run clang-query to report unused return values.
# When --dump, print the AST of matching syntax.
if [ "x$1" = "x--dump" ]; then
dump="set output dump"
shift
fi
query='m
callExpr(
isExpansionInMainFile(),
hasParent(anyOf(
compoundStmt(),
ifStmt(hasCondition(expr().bind("cond"))),
whileStmt(hasCondition(expr().bind("cond"))),
doStmt(hasCondition(expr().bind("cond")))
)),
unless(hasType(voidType())),
unless(isTypeDependent()),
unless(cxxOperatorCallExpr()),
unless(callee(namedDecl(anyOf(
hasName("memset"),
hasName("setlength"),
hasName("flags"),
hasName("width"),
hasName("__builtin_memcpy")
)))),
unless(equalsBoundNode("cond")))'
clang-query -c="$dump" -c="$query" "$@"
To run this on, say, test1.cc
:
$ ./cmd.sh test1.cc --
The basic idea of the query is to look for call expressions whose immediate parent is a compound statement. That is expanded to handle an immediate parent that is a control flow statement, being careful not to report when the call appears as the conditional expression.
Some other complications the query deals with:
This only reports in the main file of a translation unit in order to eliminate the voluminous noise from headers. Remove the isExpansionInMainFile
filter to drink from the fire hose.
In C++ templates, we might not know what the type is, so suppress reporting all calls with dependent types.
Some functions like memset
have useless or only rarely useful return values. They have to be filtered out to see any useful signal. The list of function names in the query is just the tip of that iceberg.
C++ overloaded operators, including operator<<
and operator=
, usually return a value, but that value is most often ignored. So suppress reports for all overloaded operators.
I've tested this lightly (with clang-query
from clang+llvm-8.0.1) on some files in a utility library of mine, which is how I found some of the things that need to be filtered out for this to be useful. There are probably many more things that need filtering, depending on your application.
The query language is described at https://clang.llvm.org/docs/LibASTMatchersReference.html . See this answer of mine for some more links and information about clang-query
.
Cppcheck is a command-line tool that tries to detect bugs that your C/C++ compiler doesn't see, it also includes a web based report generator.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With