Page MenuHomePhabricator

[analyzer] Add new checker for unchecked return value.
Needs ReviewPublic

Authored by balazske on Nov 3 2020, 8:53 AM.



Add a checker that checks if a function is used without examining
its return value. The set of functions is taken from CERT rule
ERR33-C "Detect and handle standard library errors". This is a
simplified check for the problem.

Diff Detail

Unit TestsFailed

400 mslinux > HWAddressSanitizer-x86_64.TestCases::sizes.cpp
Script: -- : 'RUN: at line 3'; /mnt/disks/ssd0/agent/llvm-project/build/./bin/clang --driver-mode=g++ -m64 -gline-tables-only -fsanitize=hwaddress -fuse-ld=lld -mcmodel=large -mllvm -hwasan-globals -mllvm -hwasan-use-short-granules -mllvm -hwasan-instrument-landing-pads=0 -mllvm -hwasan-instrument-personality-functions /mnt/disks/ssd0/agent/llvm-project/compiler-rt/test/hwasan/TestCases/sizes.cpp -nostdlib++ -lstdc++ -o /mnt/disks/ssd0/agent/llvm-project/build/projects/compiler-rt/test/hwasan/X86_64/TestCases/Output/sizes.cpp.tmp

Event Timeline

balazske created this revision.Nov 3 2020, 8:53 AM
balazske requested review of this revision.Nov 3 2020, 8:53 AM

This is a very simplified form of the check that is implemented in D72705 but still may be useful in practical cases. This check could be a clang-tidy check but it is planned that the checker takes use of the planned new attributes to determine if a function should be checked.


Please note that the CallExpr does not necessarily stands alone. It may be wrapped into an ExprWithCleanUps. We should consider these CallExprs as unchecked too.


Hmm, why StringMap<>? Why not CallDescriptionMap<>?


Please use some valid format here. E.g. scanf("%*c");


Please add such simple test case for all the functions we try to check. (One call is enough for every such function, either in std:: or on the top namespace.)

balazske updated this revision to Diff 303444.Nov 6 2020, 7:07 AM

Small fixes in test.

balazske marked 2 inline comments as done.Nov 6 2020, 7:09 AM
balazske added inline comments.

It looks like that the matcher finds these occurrences too. A test was added for it.


CallDescriptionMap is only usable with CallEvent that is not used in this checker. Or it can be extended with lookup from FunctionDecl?

balazske marked an inline comment as done.Nov 11 2020, 5:46 AM

Maybe it is better to have this check for every system function that has non-void return value (except specific functions)? This check is applicable to CERT rule ERR33-C, POS54-C and EXP12-C too (it is restricted but can find a part of the problems).

Looks like a neat checker! I guess the only question is the function matching, and I don't dislike it in its current state. @martong, do you have any thoughts on this?

On another note, have you checked this on some projects yet? I expect that we might need to tone down on some of the functions if this ends up being too noisy.


I suppose we need this to compensate for the fact that we can't reliably match on standard C functions. Unfortunately, using CallDescription wouldn't necessarily solve this: D81745.


Good point. @martong, you have used FunctionDecl based checking, do you have any thoughts here?

Great job!
I'd like to see more tests with the following cases:

  • more expressions with function calls - ternary expression, arithmetic, array literals, initializer lists, etc.
  • using/not using it in if statement with initializer
  • using/not using it in different parts of GNU statement expressions
  • calls in different parts of exception handling (both C++ and Obj-C)
  • calls in lambdas/blocks/coroutines
  • calls in different parts of C++ range-for loop
  • calls in different parts of Obj-C for loop over collections
  • calls under labels
  • calls in attributed statements (e.g. [[clang::nomerge]] foo())
  • calls in goto statements
  • calls in Obj-C @synchronized and @autoreleasepool statements
NoQ added a comment.Feb 11 2021, 7:06 AM

but it is planned that the checker takes use of the planned new attributes to determine if a function should be checked

This is literally __attribute__((warn_unused_result)) for which there already is a compiler warning.

There is a clang-tidy check bugprone-unused-return-value that may be confusing in relation to this checker. It does similar job for a selected set of functions and with different reason.