xref: /aosp_15_r20/external/clang/docs/analyzer/DebugChecks.rst (revision 67e74705e28f6214e480b399dd47ea732279e315)
1*67e74705SXin Li============
2*67e74705SXin LiDebug Checks
3*67e74705SXin Li============
4*67e74705SXin Li
5*67e74705SXin Li.. contents::
6*67e74705SXin Li   :local:
7*67e74705SXin Li
8*67e74705SXin LiThe analyzer contains a number of checkers which can aid in debugging. Enable
9*67e74705SXin Lithem by using the "-analyzer-checker=" flag, followed by the name of the
10*67e74705SXin Lichecker.
11*67e74705SXin Li
12*67e74705SXin Li
13*67e74705SXin LiGeneral Analysis Dumpers
14*67e74705SXin Li========================
15*67e74705SXin Li
16*67e74705SXin LiThese checkers are used to dump the results of various infrastructural analyses
17*67e74705SXin Lito stderr. Some checkers also have "view" variants, which will display a graph
18*67e74705SXin Liusing a 'dot' format viewer (such as Graphviz on OS X) instead.
19*67e74705SXin Li
20*67e74705SXin Li- debug.DumpCallGraph, debug.ViewCallGraph: Show the call graph generated for
21*67e74705SXin Li  the current translation unit. This is used to determine the order in which to
22*67e74705SXin Li  analyze functions when inlining is enabled.
23*67e74705SXin Li
24*67e74705SXin Li- debug.DumpCFG, debug.ViewCFG: Show the CFG generated for each top-level
25*67e74705SXin Li  function being analyzed.
26*67e74705SXin Li
27*67e74705SXin Li- debug.DumpDominators: Shows the dominance tree for the CFG of each top-level
28*67e74705SXin Li  function.
29*67e74705SXin Li
30*67e74705SXin Li- debug.DumpLiveVars: Show the results of live variable analysis for each
31*67e74705SXin Li  top-level function being analyzed.
32*67e74705SXin Li
33*67e74705SXin Li- debug.ViewExplodedGraph: Show the Exploded Graphs generated for the
34*67e74705SXin Li  analysis of different functions in the input translation unit. When there
35*67e74705SXin Li  are several functions analyzed, display one graph per function. Beware
36*67e74705SXin Li  that these graphs may grow very large, even for small functions.
37*67e74705SXin Li
38*67e74705SXin LiPath Tracking
39*67e74705SXin Li=============
40*67e74705SXin Li
41*67e74705SXin LiThese checkers print information about the path taken by the analyzer engine.
42*67e74705SXin Li
43*67e74705SXin Li- debug.DumpCalls: Prints out every function or method call encountered during a
44*67e74705SXin Li  path traversal. This is indented to show the call stack, but does NOT do any
45*67e74705SXin Li  special handling of branches, meaning different paths could end up
46*67e74705SXin Li  interleaved.
47*67e74705SXin Li
48*67e74705SXin Li- debug.DumpTraversal: Prints the name of each branch statement encountered
49*67e74705SXin Li  during a path traversal ("IfStmt", "WhileStmt", etc). Currently used to check
50*67e74705SXin Li  whether the analysis engine is doing BFS or DFS.
51*67e74705SXin Li
52*67e74705SXin Li
53*67e74705SXin LiState Checking
54*67e74705SXin Li==============
55*67e74705SXin Li
56*67e74705SXin LiThese checkers will print out information about the analyzer state in the form
57*67e74705SXin Liof analysis warnings. They are intended for use with the -verify functionality
58*67e74705SXin Liin regression tests.
59*67e74705SXin Li
60*67e74705SXin Li- debug.TaintTest: Prints out the word "tainted" for every expression that
61*67e74705SXin Li  carries taint. At the time of this writing, taint was only introduced by the
62*67e74705SXin Li  checks under experimental.security.taint.TaintPropagation; this checker may
63*67e74705SXin Li  eventually move to the security.taint package.
64*67e74705SXin Li
65*67e74705SXin Li- debug.ExprInspection: Responds to certain function calls, which are modeled
66*67e74705SXin Li  after builtins. These function calls should affect the program state other
67*67e74705SXin Li  than the evaluation of their arguments; to use them, you will need to declare
68*67e74705SXin Li  them within your test file. The available functions are described below.
69*67e74705SXin Li
70*67e74705SXin Li(FIXME: debug.ExprInspection should probably be renamed, since it no longer only
71*67e74705SXin Liinspects expressions.)
72*67e74705SXin Li
73*67e74705SXin Li
74*67e74705SXin LiExprInspection checks
75*67e74705SXin Li---------------------
76*67e74705SXin Li
77*67e74705SXin Li- void clang_analyzer_eval(bool);
78*67e74705SXin Li
79*67e74705SXin Li  Prints TRUE if the argument is known to have a non-zero value, FALSE if the
80*67e74705SXin Li  argument is known to have a zero or null value, and UNKNOWN if the argument
81*67e74705SXin Li  isn't sufficiently constrained on this path.  You can use this to test other
82*67e74705SXin Li  values by using expressions like "x == 5".  Note that this functionality is
83*67e74705SXin Li  currently DISABLED in inlined functions, since different calls to the same
84*67e74705SXin Li  inlined function could provide different information, making it difficult to
85*67e74705SXin Li  write proper -verify directives.
86*67e74705SXin Li
87*67e74705SXin Li  In C, the argument can be typed as 'int' or as '_Bool'.
88*67e74705SXin Li
89*67e74705SXin Li  Example usage::
90*67e74705SXin Li
91*67e74705SXin Li    clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
92*67e74705SXin Li    if (!x) return;
93*67e74705SXin Li    clang_analyzer_eval(x); // expected-warning{{TRUE}}
94*67e74705SXin Li
95*67e74705SXin Li
96*67e74705SXin Li- void clang_analyzer_checkInlined(bool);
97*67e74705SXin Li
98*67e74705SXin Li  If a call occurs within an inlined function, prints TRUE or FALSE according to
99*67e74705SXin Li  the value of its argument. If a call occurs outside an inlined function,
100*67e74705SXin Li  nothing is printed.
101*67e74705SXin Li
102*67e74705SXin Li  The intended use of this checker is to assert that a function is inlined at
103*67e74705SXin Li  least once (by passing 'true' and expecting a warning), or to assert that a
104*67e74705SXin Li  function is never inlined (by passing 'false' and expecting no warning). The
105*67e74705SXin Li  argument is technically unnecessary but is intended to clarify intent.
106*67e74705SXin Li
107*67e74705SXin Li  You might wonder why we can't print TRUE if a function is ever inlined and
108*67e74705SXin Li  FALSE if it is not. The problem is that any inlined function could conceivably
109*67e74705SXin Li  also be analyzed as a top-level function (in which case both TRUE and FALSE
110*67e74705SXin Li  would be printed), depending on the value of the -analyzer-inlining option.
111*67e74705SXin Li
112*67e74705SXin Li  In C, the argument can be typed as 'int' or as '_Bool'.
113*67e74705SXin Li
114*67e74705SXin Li  Example usage::
115*67e74705SXin Li
116*67e74705SXin Li    int inlined() {
117*67e74705SXin Li      clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
118*67e74705SXin Li      return 42;
119*67e74705SXin Li    }
120*67e74705SXin Li
121*67e74705SXin Li    void topLevel() {
122*67e74705SXin Li      clang_analyzer_checkInlined(false); // no-warning (not inlined)
123*67e74705SXin Li      int value = inlined();
124*67e74705SXin Li      // This assertion will not be valid if the previous call was not inlined.
125*67e74705SXin Li      clang_analyzer_eval(value == 42); // expected-warning{{TRUE}}
126*67e74705SXin Li    }
127*67e74705SXin Li
128*67e74705SXin Li- void clang_analyzer_warnIfReached();
129*67e74705SXin Li
130*67e74705SXin Li  Generate a warning if this line of code gets reached by the analyzer.
131*67e74705SXin Li
132*67e74705SXin Li  Example usage::
133*67e74705SXin Li
134*67e74705SXin Li    if (true) {
135*67e74705SXin Li      clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
136*67e74705SXin Li    }
137*67e74705SXin Li    else {
138*67e74705SXin Li      clang_analyzer_warnIfReached();  // no-warning
139*67e74705SXin Li    }
140*67e74705SXin Li
141*67e74705SXin Li- void clang_analyzer_warnOnDeadSymbol(int);
142*67e74705SXin Li
143*67e74705SXin Li  Subscribe for a delayed warning when the symbol that represents the value of
144*67e74705SXin Li  the argument is garbage-collected by the analyzer.
145*67e74705SXin Li
146*67e74705SXin Li  When calling 'clang_analyzer_warnOnDeadSymbol(x)', if value of 'x' is a
147*67e74705SXin Li  symbol, then this symbol is marked by the ExprInspection checker. Then,
148*67e74705SXin Li  during each garbage collection run, the checker sees if the marked symbol is
149*67e74705SXin Li  being collected and issues the 'SYMBOL DEAD' warning if it does.
150*67e74705SXin Li  This way you know where exactly, up to the line of code, the symbol dies.
151*67e74705SXin Li
152*67e74705SXin Li  It is unlikely that you call this function after the symbol is already dead,
153*67e74705SXin Li  because the very reference to it as the function argument prevents it from
154*67e74705SXin Li  dying. However, if the argument is not a symbol but a concrete value,
155*67e74705SXin Li  no warning would be issued.
156*67e74705SXin Li
157*67e74705SXin Li  Example usage::
158*67e74705SXin Li
159*67e74705SXin Li    do {
160*67e74705SXin Li      int x = generate_some_integer();
161*67e74705SXin Li      clang_analyzer_warnOnDeadSymbol(x);
162*67e74705SXin Li    } while(0);  // expected-warning{{SYMBOL DEAD}}
163*67e74705SXin Li
164*67e74705SXin Li
165*67e74705SXin Li- void clang_analyzer_explain(a single argument of any type);
166*67e74705SXin Li
167*67e74705SXin Li  This function explains the value of its argument in a human-readable manner
168*67e74705SXin Li  in the warning message. You can make as many overrides of its prototype
169*67e74705SXin Li  in the test code as necessary to explain various integral, pointer,
170*67e74705SXin Li  or even record-type values.
171*67e74705SXin Li
172*67e74705SXin Li  Example usage::
173*67e74705SXin Li
174*67e74705SXin Li    void clang_analyzer_explain(int);
175*67e74705SXin Li    void clang_analyzer_explain(void *);
176*67e74705SXin Li
177*67e74705SXin Li    void foo(int param, void *ptr) {
178*67e74705SXin Li      clang_analyzer_explain(param); // expected-warning{{argument 'param'}}
179*67e74705SXin Li      if (!ptr)
180*67e74705SXin Li        clang_analyzer_explain(ptr); // expected-warning{{memory address '0'}}
181*67e74705SXin Li    }
182*67e74705SXin Li
183*67e74705SXin Li- size_t clang_analyzer_getExtent(void *);
184*67e74705SXin Li
185*67e74705SXin Li  This function returns the value that represents the extent of a memory region
186*67e74705SXin Li  pointed to by the argument. This value is often difficult to obtain otherwise,
187*67e74705SXin Li  because no valid code that produces this value. However, it may be useful
188*67e74705SXin Li  for testing purposes, to see how well does the analyzer model region extents.
189*67e74705SXin Li
190*67e74705SXin Li  Example usage::
191*67e74705SXin Li
192*67e74705SXin Li    void foo() {
193*67e74705SXin Li      int x, *y;
194*67e74705SXin Li      size_t xs = clang_analyzer_getExtent(&x);
195*67e74705SXin Li      clang_analyzer_explain(xs); // expected-warning{{'4'}}
196*67e74705SXin Li      size_t ys = clang_analyzer_getExtent(&y);
197*67e74705SXin Li      clang_analyzer_explain(ys); // expected-warning{{'8'}}
198*67e74705SXin Li    }
199*67e74705SXin Li
200*67e74705SXin LiStatistics
201*67e74705SXin Li==========
202*67e74705SXin Li
203*67e74705SXin LiThe debug.Stats checker collects various information about the analysis of each
204*67e74705SXin Lifunction, such as how many blocks were reached and if the analyzer timed out.
205*67e74705SXin Li
206*67e74705SXin LiThere is also an additional -analyzer-stats flag, which enables various
207*67e74705SXin Listatistics within the analyzer engine. Note the Stats checker (which produces at
208*67e74705SXin Lileast one bug report per function) may actually change the values reported by
209*67e74705SXin Li-analyzer-stats.
210