xref: /netbsd-src/external/apache2/llvm/dist/clang/docs/analyzer/developer-docs/DebugChecks.rst (revision e038c9c4676b0f19b1b7dd08a940c6ed64a6d5ae)
17330f729Sjoerg============
27330f729SjoergDebug Checks
37330f729Sjoerg============
47330f729Sjoerg
57330f729Sjoerg.. contents::
67330f729Sjoerg   :local:
77330f729Sjoerg
87330f729SjoergThe analyzer contains a number of checkers which can aid in debugging. Enable
97330f729Sjoergthem by using the "-analyzer-checker=" flag, followed by the name of the
107330f729Sjoergchecker.
117330f729Sjoerg
127330f729Sjoerg
137330f729SjoergGeneral Analysis Dumpers
147330f729Sjoerg========================
157330f729Sjoerg
167330f729SjoergThese checkers are used to dump the results of various infrastructural analyses
177330f729Sjoergto stderr. Some checkers also have "view" variants, which will display a graph
187330f729Sjoergusing a 'dot' format viewer (such as Graphviz on macOS) instead.
197330f729Sjoerg
207330f729Sjoerg- debug.DumpCallGraph, debug.ViewCallGraph: Show the call graph generated for
217330f729Sjoerg  the current translation unit. This is used to determine the order in which to
227330f729Sjoerg  analyze functions when inlining is enabled.
237330f729Sjoerg
247330f729Sjoerg- debug.DumpCFG, debug.ViewCFG: Show the CFG generated for each top-level
257330f729Sjoerg  function being analyzed.
267330f729Sjoerg
277330f729Sjoerg- debug.DumpDominators: Shows the dominance tree for the CFG of each top-level
287330f729Sjoerg  function.
297330f729Sjoerg
307330f729Sjoerg- debug.DumpLiveVars: Show the results of live variable analysis for each
317330f729Sjoerg  top-level function being analyzed.
327330f729Sjoerg
33*e038c9c4Sjoerg- debug.DumpLiveExprs: Show the results of live expression analysis for each
347330f729Sjoerg  top-level function being analyzed.
357330f729Sjoerg
367330f729Sjoerg- debug.ViewExplodedGraph: Show the Exploded Graphs generated for the
377330f729Sjoerg  analysis of different functions in the input translation unit. When there
387330f729Sjoerg  are several functions analyzed, display one graph per function. Beware
397330f729Sjoerg  that these graphs may grow very large, even for small functions.
407330f729Sjoerg
417330f729SjoergPath Tracking
427330f729Sjoerg=============
437330f729Sjoerg
447330f729SjoergThese checkers print information about the path taken by the analyzer engine.
457330f729Sjoerg
467330f729Sjoerg- debug.DumpCalls: Prints out every function or method call encountered during a
477330f729Sjoerg  path traversal. This is indented to show the call stack, but does NOT do any
487330f729Sjoerg  special handling of branches, meaning different paths could end up
497330f729Sjoerg  interleaved.
507330f729Sjoerg
517330f729Sjoerg- debug.DumpTraversal: Prints the name of each branch statement encountered
527330f729Sjoerg  during a path traversal ("IfStmt", "WhileStmt", etc). Currently used to check
537330f729Sjoerg  whether the analysis engine is doing BFS or DFS.
547330f729Sjoerg
557330f729Sjoerg
567330f729SjoergState Checking
577330f729Sjoerg==============
587330f729Sjoerg
597330f729SjoergThese checkers will print out information about the analyzer state in the form
607330f729Sjoergof analysis warnings. They are intended for use with the -verify functionality
617330f729Sjoergin regression tests.
627330f729Sjoerg
637330f729Sjoerg- debug.TaintTest: Prints out the word "tainted" for every expression that
647330f729Sjoerg  carries taint. At the time of this writing, taint was only introduced by the
657330f729Sjoerg  checks under experimental.security.taint.TaintPropagation; this checker may
667330f729Sjoerg  eventually move to the security.taint package.
677330f729Sjoerg
687330f729Sjoerg- debug.ExprInspection: Responds to certain function calls, which are modeled
697330f729Sjoerg  after builtins. These function calls should affect the program state other
707330f729Sjoerg  than the evaluation of their arguments; to use them, you will need to declare
717330f729Sjoerg  them within your test file. The available functions are described below.
727330f729Sjoerg
737330f729Sjoerg(FIXME: debug.ExprInspection should probably be renamed, since it no longer only
747330f729Sjoerginspects expressions.)
757330f729Sjoerg
767330f729Sjoerg
777330f729SjoergExprInspection checks
787330f729Sjoerg---------------------
797330f729Sjoerg
807330f729Sjoerg- ``void clang_analyzer_eval(bool);``
817330f729Sjoerg
827330f729Sjoerg  Prints TRUE if the argument is known to have a non-zero value, FALSE if the
837330f729Sjoerg  argument is known to have a zero or null value, and UNKNOWN if the argument
847330f729Sjoerg  isn't sufficiently constrained on this path.  You can use this to test other
857330f729Sjoerg  values by using expressions like "x == 5".  Note that this functionality is
867330f729Sjoerg  currently DISABLED in inlined functions, since different calls to the same
877330f729Sjoerg  inlined function could provide different information, making it difficult to
887330f729Sjoerg  write proper -verify directives.
897330f729Sjoerg
907330f729Sjoerg  In C, the argument can be typed as 'int' or as '_Bool'.
917330f729Sjoerg
927330f729Sjoerg  Example usage::
937330f729Sjoerg
947330f729Sjoerg    clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
957330f729Sjoerg    if (!x) return;
967330f729Sjoerg    clang_analyzer_eval(x); // expected-warning{{TRUE}}
977330f729Sjoerg
987330f729Sjoerg
997330f729Sjoerg- ``void clang_analyzer_checkInlined(bool);``
1007330f729Sjoerg
1017330f729Sjoerg  If a call occurs within an inlined function, prints TRUE or FALSE according to
1027330f729Sjoerg  the value of its argument. If a call occurs outside an inlined function,
1037330f729Sjoerg  nothing is printed.
1047330f729Sjoerg
1057330f729Sjoerg  The intended use of this checker is to assert that a function is inlined at
1067330f729Sjoerg  least once (by passing 'true' and expecting a warning), or to assert that a
1077330f729Sjoerg  function is never inlined (by passing 'false' and expecting no warning). The
1087330f729Sjoerg  argument is technically unnecessary but is intended to clarify intent.
1097330f729Sjoerg
1107330f729Sjoerg  You might wonder why we can't print TRUE if a function is ever inlined and
1117330f729Sjoerg  FALSE if it is not. The problem is that any inlined function could conceivably
1127330f729Sjoerg  also be analyzed as a top-level function (in which case both TRUE and FALSE
1137330f729Sjoerg  would be printed), depending on the value of the -analyzer-inlining option.
1147330f729Sjoerg
1157330f729Sjoerg  In C, the argument can be typed as 'int' or as '_Bool'.
1167330f729Sjoerg
1177330f729Sjoerg  Example usage::
1187330f729Sjoerg
1197330f729Sjoerg    int inlined() {
1207330f729Sjoerg      clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
1217330f729Sjoerg      return 42;
1227330f729Sjoerg    }
1237330f729Sjoerg
1247330f729Sjoerg    void topLevel() {
1257330f729Sjoerg      clang_analyzer_checkInlined(false); // no-warning (not inlined)
1267330f729Sjoerg      int value = inlined();
1277330f729Sjoerg      // This assertion will not be valid if the previous call was not inlined.
1287330f729Sjoerg      clang_analyzer_eval(value == 42); // expected-warning{{TRUE}}
1297330f729Sjoerg    }
1307330f729Sjoerg
1317330f729Sjoerg- ``void clang_analyzer_warnIfReached();``
1327330f729Sjoerg
1337330f729Sjoerg  Generate a warning if this line of code gets reached by the analyzer.
1347330f729Sjoerg
1357330f729Sjoerg  Example usage::
1367330f729Sjoerg
1377330f729Sjoerg    if (true) {
1387330f729Sjoerg      clang_analyzer_warnIfReached();  // expected-warning{{REACHABLE}}
1397330f729Sjoerg    }
1407330f729Sjoerg    else {
1417330f729Sjoerg      clang_analyzer_warnIfReached();  // no-warning
1427330f729Sjoerg    }
1437330f729Sjoerg
1447330f729Sjoerg- ``void clang_analyzer_numTimesReached();``
1457330f729Sjoerg
1467330f729Sjoerg  Same as above, but include the number of times this call expression
1477330f729Sjoerg  gets reached by the analyzer during the current analysis.
1487330f729Sjoerg
1497330f729Sjoerg  Example usage::
1507330f729Sjoerg
1517330f729Sjoerg    for (int x = 0; x < 3; ++x) {
1527330f729Sjoerg      clang_analyzer_numTimesReached(); // expected-warning{{3}}
1537330f729Sjoerg    }
1547330f729Sjoerg
1557330f729Sjoerg- ``void clang_analyzer_warnOnDeadSymbol(int);``
1567330f729Sjoerg
1577330f729Sjoerg  Subscribe for a delayed warning when the symbol that represents the value of
1587330f729Sjoerg  the argument is garbage-collected by the analyzer.
1597330f729Sjoerg
1607330f729Sjoerg  When calling 'clang_analyzer_warnOnDeadSymbol(x)', if value of 'x' is a
1617330f729Sjoerg  symbol, then this symbol is marked by the ExprInspection checker. Then,
1627330f729Sjoerg  during each garbage collection run, the checker sees if the marked symbol is
1637330f729Sjoerg  being collected and issues the 'SYMBOL DEAD' warning if it does.
1647330f729Sjoerg  This way you know where exactly, up to the line of code, the symbol dies.
1657330f729Sjoerg
1667330f729Sjoerg  It is unlikely that you call this function after the symbol is already dead,
1677330f729Sjoerg  because the very reference to it as the function argument prevents it from
1687330f729Sjoerg  dying. However, if the argument is not a symbol but a concrete value,
1697330f729Sjoerg  no warning would be issued.
1707330f729Sjoerg
1717330f729Sjoerg  Example usage::
1727330f729Sjoerg
1737330f729Sjoerg    do {
1747330f729Sjoerg      int x = generate_some_integer();
1757330f729Sjoerg      clang_analyzer_warnOnDeadSymbol(x);
1767330f729Sjoerg    } while(0);  // expected-warning{{SYMBOL DEAD}}
1777330f729Sjoerg
1787330f729Sjoerg
1797330f729Sjoerg- ``void clang_analyzer_explain(a single argument of any type);``
1807330f729Sjoerg
1817330f729Sjoerg  This function explains the value of its argument in a human-readable manner
1827330f729Sjoerg  in the warning message. You can make as many overrides of its prototype
1837330f729Sjoerg  in the test code as necessary to explain various integral, pointer,
1847330f729Sjoerg  or even record-type values. To simplify usage in C code (where overloading
1857330f729Sjoerg  the function declaration is not allowed), you may append an arbitrary suffix
1867330f729Sjoerg  to the function name, without affecting functionality.
1877330f729Sjoerg
1887330f729Sjoerg  Example usage::
1897330f729Sjoerg
1907330f729Sjoerg    void clang_analyzer_explain(int);
1917330f729Sjoerg    void clang_analyzer_explain(void *);
1927330f729Sjoerg
1937330f729Sjoerg    // Useful in C code
1947330f729Sjoerg    void clang_analyzer_explain_int(int);
1957330f729Sjoerg
1967330f729Sjoerg    void foo(int param, void *ptr) {
1977330f729Sjoerg      clang_analyzer_explain(param); // expected-warning{{argument 'param'}}
1987330f729Sjoerg      clang_analyzer_explain_int(param); // expected-warning{{argument 'param'}}
1997330f729Sjoerg      if (!ptr)
2007330f729Sjoerg        clang_analyzer_explain(ptr); // expected-warning{{memory address '0'}}
2017330f729Sjoerg    }
2027330f729Sjoerg
2037330f729Sjoerg- ``void clang_analyzer_dump( /* a single argument of any type */);``
2047330f729Sjoerg
2057330f729Sjoerg  Similar to clang_analyzer_explain, but produces a raw dump of the value,
2067330f729Sjoerg  same as SVal::dump().
2077330f729Sjoerg
2087330f729Sjoerg  Example usage::
2097330f729Sjoerg
2107330f729Sjoerg    void clang_analyzer_dump(int);
2117330f729Sjoerg    void foo(int x) {
2127330f729Sjoerg      clang_analyzer_dump(x); // expected-warning{{reg_$0<x>}}
2137330f729Sjoerg    }
2147330f729Sjoerg
2157330f729Sjoerg- ``size_t clang_analyzer_getExtent(void *);``
2167330f729Sjoerg
2177330f729Sjoerg  This function returns the value that represents the extent of a memory region
2187330f729Sjoerg  pointed to by the argument. This value is often difficult to obtain otherwise,
2197330f729Sjoerg  because no valid code that produces this value. However, it may be useful
2207330f729Sjoerg  for testing purposes, to see how well does the analyzer model region extents.
2217330f729Sjoerg
2227330f729Sjoerg  Example usage::
2237330f729Sjoerg
2247330f729Sjoerg    void foo() {
2257330f729Sjoerg      int x, *y;
2267330f729Sjoerg      size_t xs = clang_analyzer_getExtent(&x);
2277330f729Sjoerg      clang_analyzer_explain(xs); // expected-warning{{'4'}}
2287330f729Sjoerg      size_t ys = clang_analyzer_getExtent(&y);
2297330f729Sjoerg      clang_analyzer_explain(ys); // expected-warning{{'8'}}
2307330f729Sjoerg    }
2317330f729Sjoerg
2327330f729Sjoerg- ``void clang_analyzer_printState();``
2337330f729Sjoerg
2347330f729Sjoerg  Dumps the current ProgramState to the stderr. Quickly lookup the program state
2357330f729Sjoerg  at any execution point without ViewExplodedGraph or re-compiling the program.
2367330f729Sjoerg  This is not very useful for writing tests (apart from testing how ProgramState
2377330f729Sjoerg  gets printed), but useful for debugging tests. Also, this method doesn't
2387330f729Sjoerg  produce a warning, so it gets printed on the console before all other
2397330f729Sjoerg  ExprInspection warnings.
2407330f729Sjoerg
2417330f729Sjoerg  Example usage::
2427330f729Sjoerg
2437330f729Sjoerg    void foo() {
2447330f729Sjoerg      int x = 1;
2457330f729Sjoerg      clang_analyzer_printState(); // Read the stderr!
2467330f729Sjoerg    }
2477330f729Sjoerg
2487330f729Sjoerg- ``void clang_analyzer_hashDump(int);``
2497330f729Sjoerg
2507330f729Sjoerg  The analyzer can generate a hash to identify reports. To debug what information
2517330f729Sjoerg  is used to calculate this hash it is possible to dump the hashed string as a
2527330f729Sjoerg  warning of an arbitrary expression using the function above.
2537330f729Sjoerg
2547330f729Sjoerg  Example usage::
2557330f729Sjoerg
2567330f729Sjoerg    void foo() {
2577330f729Sjoerg      int x = 1;
2587330f729Sjoerg      clang_analyzer_hashDump(x); // expected-warning{{hashed string for x}}
2597330f729Sjoerg    }
2607330f729Sjoerg
2617330f729Sjoerg- ``void clang_analyzer_denote(int, const char *);``
2627330f729Sjoerg
2637330f729Sjoerg  Denotes symbols with strings. A subsequent call to clang_analyzer_express()
2647330f729Sjoerg  will expresses another symbol in terms of these string. Useful for testing
2657330f729Sjoerg  relationships between different symbols.
2667330f729Sjoerg
2677330f729Sjoerg  Example usage::
2687330f729Sjoerg
2697330f729Sjoerg    void foo(int x) {
2707330f729Sjoerg      clang_analyzer_denote(x, "$x");
2717330f729Sjoerg      clang_analyzer_express(x + 1); // expected-warning{{$x + 1}}
2727330f729Sjoerg    }
2737330f729Sjoerg
2747330f729Sjoerg- ``void clang_analyzer_express(int);``
2757330f729Sjoerg
2767330f729Sjoerg  See clang_analyzer_denote().
2777330f729Sjoerg
278*e038c9c4Sjoerg- ``void clang_analyzer_isTainted(a single argument of any type);``
279*e038c9c4Sjoerg
280*e038c9c4Sjoerg  Queries the analyzer whether the expression used as argument is tainted or not.
281*e038c9c4Sjoerg  This is useful in tests, where we don't want to issue warning for all tainted
282*e038c9c4Sjoerg  expressions but only check for certain expressions.
283*e038c9c4Sjoerg  This would help to reduce the *noise* that the `TaintTest` debug checker would
284*e038c9c4Sjoerg  introduce and let you focus on the `expected-warning`'s that you really care
285*e038c9c4Sjoerg  about.
286*e038c9c4Sjoerg
287*e038c9c4Sjoerg  Example usage::
288*e038c9c4Sjoerg
289*e038c9c4Sjoerg    int read_integer() {
290*e038c9c4Sjoerg      int n;
291*e038c9c4Sjoerg      clang_analyzer_isTainted(n);     // expected-warning{{NO}}
292*e038c9c4Sjoerg      scanf("%d", &n);
293*e038c9c4Sjoerg      clang_analyzer_isTainted(n);     // expected-warning{{YES}}
294*e038c9c4Sjoerg      clang_analyzer_isTainted(n + 2); // expected-warning{{YES}}
295*e038c9c4Sjoerg      clang_analyzer_isTainted(n > 0); // expected-warning{{YES}}
296*e038c9c4Sjoerg      int next_tainted_value = n; // no-warning
297*e038c9c4Sjoerg      return n;
298*e038c9c4Sjoerg    }
299*e038c9c4Sjoerg
300*e038c9c4Sjoerg- ``clang_analyzer_dumpExtent(a single argument of any type)``
301*e038c9c4Sjoerg- ``clang_analyzer_dumpElementCount(a single argument of any type)``
302*e038c9c4Sjoerg
303*e038c9c4Sjoerg  Dumps out the extent and the element count of the argument.
304*e038c9c4Sjoerg
305*e038c9c4Sjoerg  Example usage::
306*e038c9c4Sjoerg
307*e038c9c4Sjoerg    void array() {
308*e038c9c4Sjoerg      int a[] = {1, 3};
309*e038c9c4Sjoerg      clang_analyzer_dumpExtent(a);       // expected-warning {{8 S64b}}
310*e038c9c4Sjoerg      clang_analyzer_dumpElementCount(a); // expected-warning {{2 S64b}}
311*e038c9c4Sjoerg    }
312*e038c9c4Sjoerg
3137330f729SjoergStatistics
3147330f729Sjoerg==========
3157330f729Sjoerg
3167330f729SjoergThe debug.Stats checker collects various information about the analysis of each
3177330f729Sjoergfunction, such as how many blocks were reached and if the analyzer timed out.
3187330f729Sjoerg
3197330f729SjoergThere is also an additional -analyzer-stats flag, which enables various
3207330f729Sjoergstatistics within the analyzer engine. Note the Stats checker (which produces at
3217330f729Sjoergleast one bug report per function) may actually change the values reported by
3227330f729Sjoerg-analyzer-stats.
3237330f729Sjoerg
3247330f729SjoergOutput testing checkers
3257330f729Sjoerg=======================
3267330f729Sjoerg
3277330f729Sjoerg- debug.ReportStmts reports a warning at **every** statement, making it a very
3287330f729Sjoerg  useful tool for testing thoroughly bug report construction and output
3297330f729Sjoerg  emission.
330