368 lines · plain
1============2Debug Checks3============4 5.. contents::6 :local:7 8The analyzer contains a number of checkers which can aid in debugging. Enable9them by using the "-analyzer-checker=" flag, followed by the name of the10checker.11 12These checkers are especially useful when analyzing a specific function, using13the `-analyze-function` flag. The flag accepts the function name for C code,14like `-analyze-function=myfunction`.15For C++ code, due to overloading, the function name must include the16parameter list, like `-analyze-function="myfunction(int, _Bool)"`.17 18Note that `bool` must be spelled as `_Bool` in the parameter list.19Refer to the output of `-analyzer-display-progress` to find the fully qualified20function name.21 22There are cases when this name can still collide. For example with template23function instances with non-deducible (aka. explicit) template parameters.24In such cases, prefer passing a USR instead of a function name can resolve this25ambiguity, like this: `-analyze-function="c:@S@Window@F@overloaded#I#"`.26 27Use the `clang-extdef-mapping` tool to find the USR for different functions.28 29General Analysis Dumpers30========================31 32These checkers are used to dump the results of various infrastructural analyses33to stderr. Some checkers also have "view" variants, which will display a graph34using a 'dot' format viewer (such as Graphviz on macOS) instead.35 36- debug.DumpCallGraph, debug.ViewCallGraph: Show the call graph generated for37 the current translation unit. This is used to determine the order in which to38 analyze functions when inlining is enabled.39 40- debug.DumpCFG, debug.ViewCFG: Show the CFG generated for each top-level41 function being analyzed.42 43- debug.DumpDominators: Shows the dominance tree for the CFG of each top-level44 function.45 46- debug.DumpLiveVars: Show the results of live variable analysis for each47 top-level function being analyzed.48 49- debug.DumpLiveExprs: Show the results of live expression analysis for each50 top-level function being analyzed.51 52- debug.ViewExplodedGraph: Show the Exploded Graphs generated for the53 analysis of different functions in the input translation unit. When there54 are several functions analyzed, display one graph per function. Beware55 that these graphs may grow very large, even for small functions.56 57Path Tracking58=============59 60These checkers print information about the path taken by the analyzer engine.61 62- debug.DumpCalls: Prints out every function or method call encountered during a63 path traversal. This is indented to show the call stack, but does NOT do any64 special handling of branches, meaning different paths could end up65 interleaved.66 67- debug.DumpTraversal: Prints the name of each branch statement encountered68 during a path traversal ("IfStmt", "WhileStmt", etc). Currently used to check69 whether the analysis engine is doing BFS or DFS.70 71 72State Checking73==============74 75These checkers will print out information about the analyzer state in the form76of analysis warnings. They are intended for use with the -verify functionality77in regression tests.78 79- debug.TaintTest: Prints out the word "tainted" for every expression that80 carries taint. At the time of this writing, taint was only introduced by the81 checks under experimental.security.taint.TaintPropagation; this checker may82 eventually move to the security.taint package.83 84- debug.ExprInspection: Responds to certain function calls, which are modeled85 after builtins. These function calls should affect the program state other86 than the evaluation of their arguments; to use them, you will need to declare87 them within your test file. The available functions are described below.88 89(FIXME: debug.ExprInspection should probably be renamed, since it no longer only90inspects expressions.)91 92 93ExprInspection checks94---------------------95 96- ``void clang_analyzer_eval(bool);``97 98 Prints TRUE if the argument is known to have a non-zero value, FALSE if the99 argument is known to have a zero or null value, and UNKNOWN if the argument100 isn't sufficiently constrained on this path. You can use this to test other101 values by using expressions like "x == 5". Note that this functionality is102 currently DISABLED in inlined functions, since different calls to the same103 inlined function could provide different information, making it difficult to104 write proper -verify directives.105 106 In C, the argument can be typed as 'int' or as '_Bool'.107 108 Example usage::109 110 clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}111 if (!x) return;112 clang_analyzer_eval(x); // expected-warning{{TRUE}}113 114 115- ``void clang_analyzer_checkInlined(bool);``116 117 If a call occurs within an inlined function, prints TRUE or FALSE according to118 the value of its argument. If a call occurs outside an inlined function,119 nothing is printed.120 121 The intended use of this checker is to assert that a function is inlined at122 least once (by passing 'true' and expecting a warning), or to assert that a123 function is never inlined (by passing 'false' and expecting no warning). The124 argument is technically unnecessary but is intended to clarify intent.125 126 You might wonder why we can't print TRUE if a function is ever inlined and127 FALSE if it is not. The problem is that any inlined function could conceivably128 also be analyzed as a top-level function (in which case both TRUE and FALSE129 would be printed), depending on the value of the -analyzer-inlining option.130 131 In C, the argument can be typed as 'int' or as '_Bool'.132 133 Example usage::134 135 int inlined() {136 clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}137 return 42;138 }139 140 void topLevel() {141 clang_analyzer_checkInlined(false); // no-warning (not inlined)142 int value = inlined();143 // This assertion will not be valid if the previous call was not inlined.144 clang_analyzer_eval(value == 42); // expected-warning{{TRUE}}145 }146 147- ``void clang_analyzer_warnIfReached();``148 149 Generate a warning if this line of code gets reached by the analyzer.150 151 Example usage::152 153 if (true) {154 clang_analyzer_warnIfReached(); // expected-warning{{REACHABLE}}155 }156 else {157 clang_analyzer_warnIfReached(); // no-warning158 }159 160- ``void clang_analyzer_numTimesReached();``161 162 Same as above, but include the number of times this call expression163 gets reached by the analyzer during the current analysis.164 165 Example usage::166 167 for (int x = 0; x < 3; ++x) {168 clang_analyzer_numTimesReached(); // expected-warning{{3}}169 }170 171- ``void clang_analyzer_warnOnDeadSymbol(int);``172 173 Subscribe for a delayed warning when the symbol that represents the value of174 the argument is garbage-collected by the analyzer.175 176 When calling 'clang_analyzer_warnOnDeadSymbol(x)', if value of 'x' is a177 symbol, then this symbol is marked by the ExprInspection checker. Then,178 during each garbage collection run, the checker sees if the marked symbol is179 being collected and issues the 'SYMBOL DEAD' warning if it does.180 This way you know where exactly, up to the line of code, the symbol dies.181 182 It is unlikely that you call this function after the symbol is already dead,183 because the very reference to it as the function argument prevents it from184 dying. However, if the argument is not a symbol but a concrete value,185 no warning would be issued.186 187 Example usage::188 189 do {190 int x = generate_some_integer();191 clang_analyzer_warnOnDeadSymbol(x);192 } while(0); // expected-warning{{SYMBOL DEAD}}193 194 195- ``void clang_analyzer_explain(a single argument of any type);``196 197 This function explains the value of its argument in a human-readable manner198 in the warning message. You can make as many overrides of its prototype199 in the test code as necessary to explain various integral, pointer,200 or even record-type values. To simplify usage in C code (where overloading201 the function declaration is not allowed), you may append an arbitrary suffix202 to the function name, without affecting functionality.203 204 Example usage::205 206 void clang_analyzer_explain(int);207 void clang_analyzer_explain(void *);208 209 // Useful in C code210 void clang_analyzer_explain_int(int);211 212 void foo(int param, void *ptr) {213 clang_analyzer_explain(param); // expected-warning{{argument 'param'}}214 clang_analyzer_explain_int(param); // expected-warning{{argument 'param'}}215 if (!ptr)216 clang_analyzer_explain(ptr); // expected-warning{{memory address '0'}}217 }218 219- ``void clang_analyzer_dump( /* a single argument of any type */);``220 221 Similar to clang_analyzer_explain, but produces a raw dump of the value,222 same as SVal::dump().223 224 Example usage::225 226 void clang_analyzer_dump(int);227 void foo(int x) {228 clang_analyzer_dump(x); // expected-warning{{reg_$0<x>}}229 }230 231- ``size_t clang_analyzer_getExtent(void *);``232 233 This function returns the value that represents the extent of a memory region234 pointed to by the argument. This value is often difficult to obtain otherwise,235 because no valid code that produces this value. However, it may be useful236 for testing purposes, to see how well does the analyzer model region extents.237 238 Example usage::239 240 void foo() {241 int x, *y;242 size_t xs = clang_analyzer_getExtent(&x);243 clang_analyzer_explain(xs); // expected-warning{{'4'}}244 size_t ys = clang_analyzer_getExtent(&y);245 clang_analyzer_explain(ys); // expected-warning{{'8'}}246 }247 248- ``void clang_analyzer_printState();``249 250 Dumps the current ProgramState to the stderr. Quickly lookup the program state251 at any execution point without ViewExplodedGraph or re-compiling the program.252 This is not very useful for writing tests (apart from testing how ProgramState253 gets printed), but useful for debugging tests. Also, this method doesn't254 produce a warning, so it gets printed on the console before all other255 ExprInspection warnings.256 257 Example usage::258 259 void foo() {260 int x = 1;261 clang_analyzer_printState(); // Read the stderr!262 }263 264- ``void clang_analyzer_hashDump(int);``265 266 The analyzer can generate a hash to identify reports. To debug what information267 is used to calculate this hash it is possible to dump the hashed string as a268 warning of an arbitrary expression using the function above.269 270 Example usage::271 272 void foo() {273 int x = 1;274 clang_analyzer_hashDump(x); // expected-warning{{hashed string for x}}275 }276 277- ``void clang_analyzer_denote(int, const char *);``278 279 Denotes symbols with strings. A subsequent call to clang_analyzer_express()280 will expresses another symbol in terms of these string. Useful for testing281 relationships between different symbols.282 283 Example usage::284 285 void foo(int x) {286 clang_analyzer_denote(x, "$x");287 clang_analyzer_express(x + 1); // expected-warning{{$x + 1}}288 }289 290- ``void clang_analyzer_express(int);``291 292 See clang_analyzer_denote().293 294- ``void clang_analyzer_isTainted(a single argument of any type);``295 296 Queries the analyzer whether the expression used as argument is tainted or not.297 This is useful in tests, where we don't want to issue warning for all tainted298 expressions but only check for certain expressions.299 This would help to reduce the *noise* that the `TaintTest` debug checker would300 introduce and let you focus on the `expected-warning`'s that you really care301 about.302 303 Example usage::304 305 int read_integer() {306 int n;307 clang_analyzer_isTainted(n); // expected-warning{{NO}}308 scanf("%d", &n);309 clang_analyzer_isTainted(n); // expected-warning{{YES}}310 clang_analyzer_isTainted(n + 2); // expected-warning{{YES}}311 clang_analyzer_isTainted(n > 0); // expected-warning{{YES}}312 int next_tainted_value = n; // no-warning313 return n;314 }315 316- ``clang_analyzer_dumpExtent(a single argument of any type)``317- ``clang_analyzer_dumpElementCount(a single argument of any type)``318 319 Dumps out the extent and the element count of the argument.320 321 Example usage::322 323 void array() {324 int a[] = {1, 3};325 clang_analyzer_dumpExtent(a); // expected-warning {{8 S64b}}326 clang_analyzer_dumpElementCount(a); // expected-warning {{2 S64b}}327 }328 329- ``clang_analyzer_value(a single argument of integer or pointer type)``330 331 Prints an associated value for the given argument.332 Supported argument types are integers, enums and pointers.333 The value can be represented either as a range set or as a concrete integer.334 For the rest of the types function prints ``n/a`` (aka not available).335 336 **Note:** This function will print nothing when clang uses Z3 as the337 constraint manager (which is an unsupported and badly broken analysis mode338 that's distinct from the supported and stable "Z3 refutation" aka "Z3339 crosscheck" mode).340 341 Example usage::342 343 void print(char c, unsigned u) {344 clang_analyzer_value(c); // expected-warning {{8s:{ [-128, 127] }}}345 if(u != 42)346 clang_analyzer_value(u); // expected-warning {{32u:{ [0, 41], [43, 4294967295] }}}347 else348 clang_analyzer_value(u); // expected-warning {{32u:42}}349 }350 351Statistics352==========353 354The debug.Stats checker collects various information about the analysis of each355function, such as how many blocks were reached and if the analyzer timed out.356 357There is also an additional -analyzer-stats flag, which enables various358statistics within the analyzer engine. Note the Stats checker (which produces at359least one bug report per function) may actually change the values reported by360-analyzer-stats.361 362Output testing checkers363=======================364 365- debug.ReportStmts reports a warning at **every** statement, making it a very366 useful tool for testing thoroughly bug report construction and output367 emission.368