reference, declarationdefinition
definition → references, declarations, derived classes, virtual overrides
reference to multiple definitions → definitions
unreferenced
    1
    2
    3
    4
    5
    6
    7
    8
    9
   10
   11
   12
   13
   14
   15
   16
   17
   18
   19
   20
   21
   22
   23
   24
   25
   26
   27
   28
   29
   30
   31
   32
   33
   34
   35
   36
   37
   38
   39
   40
   41
   42
   43
   44
   45
   46
   47
   48
   49
   50
   51
   52
   53
   54
   55
   56
   57
   58
   59
   60
   61
   62
   63
   64
   65
   66
   67
   68
   69
   70
   71
   72
   73
   74
   75
   76
   77
   78
   79
   80
   81
   82
   83
   84
   85
   86
   87
   88
   89
   90
   91
   92
   93
   94
   95
   96
   97
   98
   99
  100
  101
  102
  103
  104
  105
  106
  107
  108
  109
  110
  111
  112
  113
  114
  115
  116
  117
  118
  119
  120
  121
  122
  123
  124
  125
  126
  127
  128
  129
  130
  131
  132
  133
  134
  135
  136
  137
  138
  139
  140
  141
  142
  143
  144
  145
  146
  147
  148
  149
  150
  151
  152
  153
  154
  155
  156
  157
  158
  159
  160
  161
  162
  163
  164
  165
  166
  167
  168
  169
  170
  171
  172
  173
  174
  175
  176
  177
  178
  179
  180
  181
  182
  183
  184
  185
  186
  187
  188
  189
  190
  191
  192
  193
=====================================
Cross Translation Unit (CTU) Analysis
=====================================

Normally, static analysis works in the boundary of one translation unit (TU).
However, with additional steps and configuration we can enable the analysis to inline the definition of a function from another TU.

.. contents::
   :local:

Manual CTU Analysis
-------------------

Let's consider these source files in our minimal example:

.. code-block:: cpp

  // main.cpp
  int foo();

  int main() {
    return 3 / foo();
  }

.. code-block:: cpp

  // foo.cpp
  int foo() {
    return 0;
  }

And a compilation database:

.. code-block:: bash

  [
    {
      "directory": "/path/to/your/project",
      "command": "clang++ -c foo.cpp -o foo.o",
      "file": "foo.cpp"
    },
    {
      "directory": "/path/to/your/project",
      "command": "clang++ -c main.cpp -o main.o",
      "file": "main.cpp"
    }
  ]

We'd like to analyze `main.cpp` and discover the division by zero bug.
In order to be able to inline the definition of `foo` from `foo.cpp` first we have to generate the `AST` (or `PCH`) file of `foo.cpp`:

.. code-block:: bash

  $ pwd $ /path/to/your/project
  $ clang++ -emit-ast -o foo.cpp.ast foo.cpp
  $ # Check that the .ast file is generated:
  $ ls
  compile_commands.json  foo.cpp.ast  foo.cpp  main.cpp
  $

The next step is to create a CTU index file which holds the `USR` name and location of external definitions in the source files:

.. code-block:: bash

  $ clang-extdef-mapping -p . foo.cpp
  c:@F@foo# /path/to/your/project/foo.cpp
  $ clang-extdef-mapping -p . foo.cpp > externalDefMap.txt

We have to modify `externalDefMap.txt` to contain the name of the `.ast` files instead of the source files:

.. code-block:: bash

  $ sed -i -e "s/.cpp/.cpp.ast/g" externalDefMap.txt

We still have to further modify the `externalDefMap.txt` file to contain relative paths:

.. code-block:: bash

  $ sed -i -e "s|$(pwd)/||g" externalDefMap.txt

Now everything is available for the CTU analysis.
We have to feed Clang with CTU specific extra arguments:

.. code-block:: bash

  $ pwd
  /path/to/your/project
  $ clang++ --analyze -Xclang -analyzer-config -Xclang experimental-enable-naive-ctu-analysis=true -Xclang -analyzer-config -Xclang ctu-dir=. -Xclang -analyzer-output=plist-multi-file main.cpp
  main.cpp:5:12: warning: Division by zero
    return 3 / foo();
           ~~^~~~~~~
  1 warning generated.
  $ # The plist file with the result is generated.
  $ ls
  compile_commands.json  externalDefMap.txt  foo.ast  foo.cpp  foo.cpp.ast  main.cpp  main.plist
  $

This manual procedure is error-prone and not scalable, therefore to analyze real projects it is recommended to use `CodeChecker` or `scan-build-py`.

Automated CTU Analysis with CodeChecker
---------------------------------------
The `CodeChecker <https://github.com/Ericsson/codechecker>`_ project fully supports automated CTU analysis with Clang.
Once we have set up the `PATH` environment variable and we activated the python `venv` then it is all it takes:

.. code-block:: bash

  $ CodeChecker analyze --ctu compile_commands.json -o reports
  [INFO 2019-07-16 17:21] - Pre-analysis started.
  [INFO 2019-07-16 17:21] - Collecting data for ctu analysis.
  [INFO 2019-07-16 17:21] - [1/2] foo.cpp
  [INFO 2019-07-16 17:21] - [2/2] main.cpp
  [INFO 2019-07-16 17:21] - Pre-analysis finished.
  [INFO 2019-07-16 17:21] - Starting static analysis ...
  [INFO 2019-07-16 17:21] - [1/2] clangsa analyzed foo.cpp successfully.
  [INFO 2019-07-16 17:21] - [2/2] clangsa analyzed main.cpp successfully.
  [INFO 2019-07-16 17:21] - ----==== Summary ====----
  [INFO 2019-07-16 17:21] - Successfully analyzed
  [INFO 2019-07-16 17:21] -   clangsa: 2
  [INFO 2019-07-16 17:21] - Total analyzed compilation commands: 2
  [INFO 2019-07-16 17:21] - ----=================----
  [INFO 2019-07-16 17:21] - Analysis finished.
  [INFO 2019-07-16 17:21] - To view results in the terminal use the "CodeChecker parse" command.
  [INFO 2019-07-16 17:21] - To store results use the "CodeChecker store" command.
  [INFO 2019-07-16 17:21] - See --help and the user guide for further options about parsing and storing the reports.
  [INFO 2019-07-16 17:21] - ----=================----
  [INFO 2019-07-16 17:21] - Analysis length: 0.659618854523 sec.
  $ ls
  compile_commands.json  foo.cpp  foo.cpp.ast  main.cpp  reports
  $ tree reports
  reports
  ├── compile_cmd.json
  ├── compiler_info.json
  ├── foo.cpp_53f6fbf7ab7ec9931301524b551959e2.plist
  ├── main.cpp_23db3d8df52ff0812e6e5a03071c8337.plist
  ├── metadata.json
  └── unique_compile_commands.json

  0 directories, 6 files
  $

The `plist` files contain the results of the analysis, which may be viewed with the regular analysis tools.
E.g. one may use `CodeChecker parse` to view the results in command line:

.. code-block:: bash

  $ CodeChecker parse reports
  [HIGH] /home/egbomrt/ctu_mini_raw_project/main.cpp:5:12: Division by zero [core.DivideZero]
    return 3 / foo();
             ^

  Found 1 defect(s) in main.cpp


  ----==== Summary ====----
  -----------------------
  Filename | Report count
  -----------------------
  main.cpp |            1
  -----------------------
  -----------------------
  Severity | Report count
  -----------------------
  HIGH     |            1
  -----------------------
  ----=================----
  Total number of reports: 1
  ----=================----

Or we can use `CodeChecker parse -e html` to export the results into HTML format:

.. code-block:: bash

  $ CodeChecker parse -e html -o html_out reports
  $ firefox html_out/index.html

Automated CTU Analysis with scan-build-py (don't do it)
-------------------------------------------------------
We actively develop CTU with CodeChecker as a "runner" script, `scan-build-py` is not actively developed for CTU.
`scan-build-py` has various errors and issues, expect it to work with the very basic projects only.

Example usage of scan-build-py:

.. code-block:: bash

  $ /your/path/to/llvm-project/clang/tools/scan-build-py/bin/analyze-build --ctu
  analyze-build: Run 'scan-view /tmp/scan-build-2019-07-17-17-53-33-810365-7fqgWk' to examine bug reports.
  $ /your/path/to/llvm-project/clang/tools/scan-view/bin/scan-view /tmp/scan-build-2019-07-17-17-53-33-810365-7fqgWk
  Starting scan-view at: http://127.0.0.1:8181
    Use Ctrl-C to exit.
  [6336:6431:0717/175357.633914:ERROR:browser_process_sub_thread.cc(209)] Waited 5 ms for network service
  Opening in existing browser session.
  ^C
  $