This is an archive of the discontinued LLVM Phabricator instance.

[analyzer] Export coverage information from the analyzer.
Needs ReviewPublic

Authored by xazax.hun on Oct 26 2016, 7:18 AM.

Details

Summary

This patch adds a new option to export an optimistic basic block coverage from the static analyzer.

Example usage:

clang++ --analyze -Xclang -analyzer-config -Xclang record-coverage=gcovfiles foo.cpp

Example output:

-:0:Source:foo.cpp
-:0:Runs:1
-:0:Programs:1
-:1:#include <iostream>
-:2:
-:3:int main() {
1:4:  int i = 2;
1:5:  ++i;
1:6:  if (i) {
1:7:    std::cout << "foo" << std::endl;
-:8:  } else {
#####:9:    std::cout << "bar" << std::endl;
-:10:  }
-:11:}

It will generate a gcov file (sourcename.gcov) for each non system header source file in the directory that was given with the record-coverage option.

The gcov format is relatively easy to read, but HTML can be generated using gcovr:

gcovr -g gcovfiles --html --html-details -r . -o example.html

Possible use cases:

  • Get an overview about the coverage of the static analyzer on a given codebase.
  • Collect ideas how to increase the coverage and test them.
  • Evaluate possible cross translation unit coverage patterns.
  • Write rigorous tests about coverage.

Diff Detail

Event Timeline

xazax.hun updated this revision to Diff 75876.Oct 26 2016, 7:18 AM
xazax.hun retitled this revision from to [analyzer] Export coverage information from the analyzer..
xazax.hun updated this object.
xazax.hun set the repository for this revision to rL LLVM.
xazax.hun updated this object.
xazax.hun added subscribers: cfe-commits, dkrupp, o.gyorgy, szepet.
xazax.hun updated this revision to Diff 75923.Oct 26 2016, 11:47 AM
xazax.hun removed rL LLVM as the repository for this revision.
zaks.anna edited edge metadata.Oct 26 2016, 2:01 PM

Please, add multi-file tests and tests where a line is covered more than once.

lib/StaticAnalyzer/Core/ExprEngine.cpp
262

Can this be a debug checker?

274

Would it be better to break if the buffer is invalid?
Should this be hoisted out of the loop?

277

Please, come up with constructive error messages.

281

What does '-' mean in this case? Why is it needed?

test/Analysis/record-coverage.cpp.expected
2

Does '-' mean not covered? If so, why the first 2 statements are not covered?

zaks.anna added inline comments.Oct 26 2016, 2:27 PM
lib/StaticAnalyzer/Core/ExprEngine.cpp
274

I see why this cannot be hoisted.

xazax.hun updated this revision to Diff 76933.Nov 4 2016, 12:57 PM
xazax.hun edited edge metadata.
xazax.hun marked 5 inline comments as done.
  • Improved performance.
  • Fixed an off by one error.
  • Also export unexecuted lines.
  • Added context.
xazax.hun updated this object.Nov 4 2016, 12:57 PM

Please, add multi-file tests and tests where a line is covered more than once.

Ok, I will add it in the next iteration.

lib/StaticAnalyzer/Core/ExprEngine.cpp
262

You mean the dumping part or also collecting the coverage? It can be a debug checker if we add a new callback like "checkBasicBlockBegin". I did not want to add such callback just for a debug check. However, it is possible to move only the dumping part to a separate checker. What would you prefer?

281

The - means lines without executable code. ###### means lines that contains executable code but unexecuted. The lines that has "0" as the line number are attributes to help the tools consume the gcov file.

test/Analysis/record-coverage.cpp.expected
2

There was an off by one error that I fixed.

xazax.hun updated this revision to Diff 77199.Nov 8 2016, 8:18 AM
xazax.hun updated this object.
  • Added a python script to merge gcov files.
  • Fixed an error
  • Multifile test is not added yet, will do so in the next update.

Added a python script to merge gcov files.

When the patches that are being reviewed are growing new functionality, it's much more difficult to review them. Please, submit the python script as a separate patch.

lib/StaticAnalyzer/Core/ExprEngine.cpp
262

I would prefer to add a "checkBasicBlockBegin" callback and move all of this diagnostic code into a debug checker.

277

How was this addressed?

xazax.hun added inline comments.Nov 10 2016, 5:59 AM
lib/StaticAnalyzer/Core/ExprEngine.cpp
262

Do you think the checkers should be able to add state transitions from BeginBasicBlock callback? Would you prefer to have an EndBasicBlock callback for symmetry?

zaks.anna added inline comments.Nov 10 2016, 9:54 AM
lib/StaticAnalyzer/Core/ExprEngine.cpp
262

I cannot think of any right now. The main advantages of having this as a debug checker are:

  • Not having this code in ExprEngine.cpp - it's not related to the core engine functionality.
  • More importantly, discoverability of this functionality.

On the downside, we would not want to add a checker API if it has no useful users.

NoQ edited edge metadata.Nov 10 2016, 11:03 AM

Maybe you could instead make a checker that subscribes for checkEndAnalysis and scans the provided ExplodedGraph's nodes_begin()..nodes_end() for visited statement-based program points (as in PathDiagnosticLocation::getStmt(N))? This should give you per-statement precision, and you'd avoid dealing with the CFG element kinds. That sounds more straightforward and that's essentially how our deadcode checker works (but it suppresses its positives for incomplete analyses - you don't need even that).