Nicholas Bishop
Nicholas Bishop

Reputation: 1141

How can I lint C++ code to find all unused return values?

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?

Upvotes: 12

Views: 1335

Answers (3)

Scott McPeak
Scott McPeak

Reputation: 12749

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.

Upvotes: 3

I_Al-thamary
I_Al-thamary

Reputation: 3993

I think there are software can do this like DevExtreme and in social.msdn.microsoft.com in the answer for this question how-to-get-a-warning-for-an-unused-return-value? they mention that Premium and Ultimate versions of visual studio has some tools.

Read this:https://social.msdn.microsoft.com/Forums/vstudio/en-US/4355715a-5af7-4a2b-8aa0-bc2112eaa911/how-to-get-a-warning-for-an-unused-return-value?forum=vclanguage

and this mandatory-error-codes-revisited from: http://www.drdobbs.com/cpp/mandatory-error-codes-revisited/191601612

Upvotes: 0

sbh
sbh

Reputation: 447

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.

Upvotes: 1

Related Questions