summaryrefslogtreecommitdiffstats
path: root/docs/analyzer
diff options
context:
space:
mode:
authordim <dim@FreeBSD.org>2012-12-02 13:20:44 +0000
committerdim <dim@FreeBSD.org>2012-12-02 13:20:44 +0000
commit056abd2059c65a3e908193aeae16fad98017437c (patch)
tree2732d02d7d51218d6eed98ac7fcfc5b8794896b5 /docs/analyzer
parentcc73504950eb7b5dff2dded9bedd67bc36d64641 (diff)
downloadFreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.zip
FreeBSD-src-056abd2059c65a3e908193aeae16fad98017437c.tar.gz
Vendor import of clang release_32 branch r168974 (effectively, 3.2 RC2):
http://llvm.org/svn/llvm-project/cfe/branches/release_32@168974
Diffstat (limited to 'docs/analyzer')
-rw-r--r--docs/analyzer/IPA.txt363
-rw-r--r--docs/analyzer/debug-checks.txt89
2 files changed, 400 insertions, 52 deletions
diff --git a/docs/analyzer/IPA.txt b/docs/analyzer/IPA.txt
index 5691977..016cea9 100644
--- a/docs/analyzer/IPA.txt
+++ b/docs/analyzer/IPA.txt
@@ -1,96 +1,355 @@
Inlining
========
-Inlining Modes
------------------------
--analyzer-ipa=none - All inlining is disabled.
--analyzer-ipa=inlining - Turns on inlining when we can confidently find the function/method body corresponding to the call. (C functions, static functions, devirtualized C++ methods, ObjC class methods, ObjC instance methods when we are confident about the dynamic type of the instance).
--analyzer-ipa=dynamic - Inline instance methods for which the type is determined at runtime and we are not 100% sure that our type info is correct. For virtual calls, inline the most plausible definition.
--analyzer-ipa=dynamic-bifurcate - Same as -analyzer-ipa=dynamic, but the path is split. We inline on one branch and do not inline on the other. This mode does not drop the coverage in cases when the parent class has code that is only exercised when some of its methods are overriden.
+There are several options that control which calls the analyzer will consider for
+inlining. The major one is -analyzer-ipa:
+
+ -analyzer-ipa=none - All inlining is disabled. This is the only mode available
+ in LLVM 3.1 and earlier and in Xcode 4.3 and earlier.
+
+ -analyzer-ipa=basic-inlining - Turns on inlining for C functions, C++ static
+ member functions, and blocks -- essentially, the calls that behave like
+ simple C function calls. This is essentially the mode used in Xcode 4.4.
+
+ -analyzer-ipa=inlining - Turns on inlining when we can confidently find the
+ function/method body corresponding to the call. (C functions, static
+ functions, devirtualized C++ methods, Objective-C class methods, Objective-C
+ instance methods when ExprEngine is confident about the dynamic type of the
+ instance).
+
+ -analyzer-ipa=dynamic - Inline instance methods for which the type is
+ determined at runtime and we are not 100% sure that our type info is
+ correct. For virtual calls, inline the most plausible definition.
+
+ -analyzer-ipa=dynamic-bifurcate - Same as -analyzer-ipa=dynamic, but the path
+ is split. We inline on one branch and do not inline on the other. This mode
+ does not drop the coverage in cases when the parent class has code that is
+ only exercised when some of its methods are overridden.
+
+Currently, -analyzer-ipa=dynamic-bifurcate is the default mode.
+
+While -analyzer-ipa determines in general how aggressively the analyzer will try to
+inline functions, several additional options control which types of functions can
+inlined, in an all-or-nothing way. These options use the analyzer's configuration
+table, so they are all specified as follows:
+
+ -analyzer-config OPTION=VALUE
+
+### c++-inlining ###
+
+This option controls which C++ member functions may be inlined.
+
+ -analyzer-config c++-inlining=[none | methods | constructors | destructors]
+
+Each of these modes implies that all the previous member function kinds will be
+inlined as well; it doesn't make sense to inline destructors without inlining
+constructors, for example.
+
+The default c++-inlining mode is 'methods', meaning only regular member
+functions and overloaded operators will be inlined. Note that no C++ member
+functions will be inlined under -analyzer-ipa=none or
+-analyzer-ipa=basic-inlining.
+
+### c++-template-inlining ###
+
+This option controls whether C++ templated functions may be inlined.
+
+ -analyzer-config c++-template-inlining=[true | false]
+
+Currently, template functions are considered for inlining by default.
+
+The motivation behind this option is that very generic code can be a source
+of false positives, either by considering paths that the caller considers
+impossible (by some unstated precondition), or by inlining some but not all
+of a deep implementation of a function.
+
+### c++-stdlib-inlining ###
+
+This option controls whether functions from the C++ standard library, including
+methods of the container classes in the Standard Template Library, should be
+considered for inlining.
+
+ -analyzer-config c++-template-inlining=[true | false]
+
+Currently, C++ standard library functions are NOT considered for inlining by default.
+
+The standard library functions and the STL in particular are used ubiquitously
+enough that our tolerance for false positives is even lower here. A false
+positive due to poor modeling of the STL leads to a poor user experience, since
+most users would not be comfortable adding assertions to system headers in order
+to silence analyzer warnings.
-Currently, -analyzer-ipa=inlining is the default mode.
Basics of Implementation
-----------------------
-The low-level mechanism of inlining a function is handled in ExprEngine::inlineCall and ExprEngine::processCallExit. If the conditions are right for inlining, a CallEnter node is created and added to the analysis work list. The CallEnter node marks the change to a new LocationContext representing the called function, and its state includes the contents of the new stack frame. When the CallEnter node is actually processed, its single successor will be a edge to the first CFG block in the function.
+The low-level mechanism of inlining a function is handled in
+ExprEngine::inlineCall and ExprEngine::processCallExit.
+
+If the conditions are right for inlining, a CallEnter node is created and added
+to the analysis work list. The CallEnter node marks the change to a new
+LocationContext representing the called function, and its state includes the
+contents of the new stack frame. When the CallEnter node is actually processed,
+its single successor will be a edge to the first CFG block in the function.
+
+Exiting an inlined function is a bit more work, fortunately broken up into
+reasonable steps:
+
+1. The CoreEngine realizes we're at the end of an inlined call and generates a
+ CallExitBegin node.
-Exiting an inlined function is a bit more work, fortunately broken up into reasonable steps:
-1. The CoreEngine realizes we're at the end of an inlined call and generates a CallExitBegin node.
-2. ExprEngine takes over (in processCallExit) and finds the return value of the function, if it has one. This is bound to the expression that triggered the call. (In the case of calls without origin expressions, such as destructors, this step is skipped.)
-3. Dead symbols and bindings are cleaned out from the state, including any local bindings.
-4. A CallExitEnd node is generated, which marks the transition back to the caller's LocationContext.
-5. Custom post-call checks are processed and the final nodes are pushed back onto the work list, so that evaluation of the caller can continue.
+2. ExprEngine takes over (in processCallExit) and finds the return value of the
+ function, if it has one. This is bound to the expression that triggered the
+ call. (In the case of calls without origin expressions, such as destructors,
+ this step is skipped.)
+
+3. Dead symbols and bindings are cleaned out from the state, including any local
+ bindings.
+
+4. A CallExitEnd node is generated, which marks the transition back to the
+ caller's LocationContext.
+
+5. Custom post-call checks are processed and the final nodes are pushed back
+ onto the work list, so that evaluation of the caller can continue.
Retry Without Inlining
------------------------
+----------------------
-In some cases, we would like to retry analyzes without inlining the particular call. Currently, we use this technique to recover the coverage in case we stop analyzing a path due to exceeding the maximum block count inside an inlined function. When this situation is detected, we walk up the path to find the first node before inlining was started and enqueue it on the WorkList with a special ReplayWithoutInlining bit added to it (ExprEngine::replayWithoutInlining).
+In some cases, we would like to retry analysis without inlining a particular
+call.
-Deciding when to inline
+Currently, we use this technique to recover coverage in case we stop
+analyzing a path due to exceeding the maximum block count inside an inlined
+function.
+
+When this situation is detected, we walk up the path to find the first node
+before inlining was started and enqueue it on the WorkList with a special
+ReplayWithoutInlining bit added to it (ExprEngine::replayWithoutInlining). The
+path is then re-analyzed from that point without inlining that particular call.
+
+Deciding When to Inline
-----------------------
-In general, we try to inline as much as possible, since it provides a better summary of what actually happens in the program. However, there are some cases where we choose not to inline:
-- if there is no definition available (of course)
-- if we can't create a CFG or compute variable liveness for the function
-- if we reach a cutoff of maximum stack depth (to avoid infinite recursion)
-- if the function is variadic
-- in C++, we don't inline constructors unless we know the destructor will be inlined as well
-- in C++, we don't inline allocators (custom operator new implementations), since we don't properly handle deallocators (at the time of this writing)
-- "Dynamic" calls are handled specially; see below.
-- Engine:FunctionSummaries map stores additional information about declarations, some of which is collected at runtime based on previous analyzes of the function. We do not inline functions which were not profitable to inline in a different context (for example, if the maximum block count was exceeded, see Retry Without Inlining).
-
-
-Dynamic calls and devirtualization
+
+In general, the analyzer attempts to inline as much as possible, since it
+provides a better summary of what actually happens in the program. There are
+some cases, however, where the analyzer chooses not to inline:
+
+- If there is no definition available for the called function or method. In
+ this case, there is no opportunity to inline.
+
+- If the CFG cannot be constructed for a called function, or the liveness
+ cannot be computed. These are prerequisites for analyzing a function body,
+ with or without inlining.
+
+- If the LocationContext chain for a given ExplodedNode reaches a maximum cutoff
+ depth. This prevents unbounded analysis due to infinite recursion, but also
+ serves as a useful cutoff for performance reasons.
+
+- If the function is variadic. This is not a hard limitation, but an engineering
+ limitation.
+
+ Tracked by: <rdar://problem/12147064> Support inlining of variadic functions
+
+- In C++, constructors are not inlined unless the destructor call will be
+ processed by the ExprEngine. Thus, if the CFG was built without nodes for
+ implicit destructors, or if the destructors for the given object are not
+ represented in the CFG, the constructor will not be inlined. (As an exception,
+ constructors for objects with trivial constructors can still be inlined.)
+ See "C++ Caveats" below.
+
+- In C++, ExprEngine does not inline custom implementations of operator 'new'
+ or operator 'delete', nor does it inline the constructors and destructors
+ associated with these. See "C++ Caveats" below.
+
+- Calls resulting in "dynamic dispatch" are specially handled. See more below.
+
+- The FunctionSummaries map stores additional information about declarations,
+ some of which is collected at runtime based on previous analyses.
+ We do not inline functions which were not profitable to inline in a different
+ context (for example, if the maximum block count was exceeded; see
+ "Retry Without Inlining").
+
+
+Dynamic Calls and Devirtualization
----------------------------------
-"Dynamic" calls are those that are resolved at runtime, such as C++ virtual method calls and Objective-C message sends. Due to the path-sensitive nature of the analyzer, we may be able to figure out the dynamic type of the object whose method is being called and thus "devirtualize" the call, i.e. find the actual method that will be called at runtime. (Obviously this is not always possible.) This is handled by CallEvent's getRuntimeDefinition method.
-Type information is tracked as DynamicTypeInfo, stored within the program state. If no DynamicTypeInfo has been explicitly set for a region, it will be inferred from the region's type or associated symbol. Information from symbolic regions is weaker than from true typed regions; a C++ object declared "A obj" is known to have the class 'A', but a reference "A &ref" may dynamically be a subclass of 'A'. The DynamicTypePropagation checker gathers and propagates the type information.
+"Dynamic" calls are those that are resolved at runtime, such as C++ virtual
+method calls and Objective-C message sends. Due to the path-sensitive nature of
+the analysis, the analyzer may be able to reason about the dynamic type of the
+object whose method is being called and thus "devirtualize" the call.
+
+This path-sensitive devirtualization occurs when the analyzer can determine what
+method would actually be called at runtime. This is possible when the type
+information is constrained enough for a simulated C++/Objective-C object that
+the analyzer can make such a decision.
+
+ == DynamicTypeInfo ==
+
+As the analyzer analyzes a path, it may accrue information to refine the
+knowledge about the type of an object. This can then be used to make better
+decisions about the target method of a call.
+
+Such type information is tracked as DynamicTypeInfo. This is path-sensitive
+data that is stored in ProgramState, which defines a mapping from MemRegions to
+an (optional) DynamicTypeInfo.
+
+If no DynamicTypeInfo has been explicitly set for a MemRegion, it will be lazily
+inferred from the region's type or associated symbol. Information from symbolic
+regions is weaker than from true typed regions.
+
+ EXAMPLE: A C++ object declared "A obj" is known to have the class 'A', but a
+ reference "A &ref" may dynamically be a subclass of 'A'.
+
+The DynamicTypePropagation checker gathers and propagates DynamicTypeInfo,
+updating it as information is observed along a path that can refine that type
+information for a region.
-(Warning: not all of the existing analyzer code has been retrofitted to use DynamicTypeInfo, nor is it universally appropriate. In particular, DynamicTypeInfo always applies to a region with all casts stripped off, but sometimes the information provided by casts can be useful.)
+ WARNING: Not all of the existing analyzer code has been retrofitted to use
+ DynamicTypeInfo, nor is it universally appropriate. In particular,
+ DynamicTypeInfo always applies to a region with all casts stripped
+ off, but sometimes the information provided by casts can be useful.
-When asked to provide a definition, the CallEvents for dynamic calls will use the type info in their state to provide the best definition of the method to be called. In some cases this devirtualization can be perfect or near-perfect, and we can inline the definition as usual. In others we can make a guess, but report that our guess may not be the method actually called at runtime.
-The -analyzer-ipa option has four different modes: none, inlining, dynamic, and dynamic-bifurcate. Under -analyzer-ipa=dynamic, all dynamic calls are inlined, whether we are certain or not that this will actually be the definition used at runtime. Under -analyzer-ipa=inlining, only "near-perfect" devirtualized calls are inlined*, and other dynamic calls are evaluated conservatively (as if no definition were available).
+ == RuntimeDefinition ==
-* Currently, no Objective-C messages are not inlined under -analyzer-ipa=inlining, even if we are reasonably confident of the type of the receiver. We plan to enable this once we have tested our heuristics more thoroughly.
+The basis of devirtualization is CallEvent's getRuntimeDefinition() method,
+which returns a RuntimeDefinition object. When asked to provide a definition,
+the CallEvents for dynamic calls will use the DynamicTypeInfo in their
+ProgramState to attempt to devirtualize the call. In the case of no dynamic
+dispatch, or perfectly constrained devirtualization, the resulting
+RuntimeDefinition contains a Decl corresponding to the definition of the called
+function, and RuntimeDefinition::mayHaveOtherDefinitions will return FALSE.
-The last option, -analyzer-ipa=dynamic-bifurcate, behaves similarly to "dynamic", but performs a conservative invalidation in the general virtual case in /addition/ to inlining. The details of this are discussed below.
+In the case of dynamic dispatch where our information is not perfect, CallEvent
+can make a guess, but RuntimeDefinition::mayHaveOtherDefinitions will return
+TRUE. The RuntimeDefinition object will then also include a MemRegion
+corresponding to the object being called (i.e., the "receiver" in Objective-C
+parlance), which ExprEngine uses to decide whether or not the call should be
+inlined.
+
+ == Inlining Dynamic Calls ==
+
+The -analyzer-ipa option has five different modes: none, basic-inlining,
+inlining, dynamic, and dynamic-bifurcate. Under -analyzer-ipa=dynamic, all
+dynamic calls are inlined, whether we are certain or not that this will actually
+be the definition used at runtime. Under -analyzer-ipa=inlining, only
+"near-perfect" devirtualized calls are inlined*, and other dynamic calls are
+evaluated conservatively (as if no definition were available).
+
+* Currently, no Objective-C messages are not inlined under
+ -analyzer-ipa=inlining, even if we are reasonably confident of the type of the
+ receiver. We plan to enable this once we have tested our heuristics more
+ thoroughly.
+
+The last option, -analyzer-ipa=dynamic-bifurcate, behaves similarly to
+"dynamic", but performs a conservative invalidation in the general virtual case
+in *addition* to inlining. The details of this are discussed below.
+
+As stated above, -analyzer-ipa=basic-inlining does not inline any C++ member
+functions or Objective-C method calls, even if they are non-virtual or can be
+safely devirtualized.
Bifurcation
-----------
-ExprEngine::BifurcateCall implements the -analyzer-ipa=dynamic-bifurcate mode. When a call is made on a region with dynamic type information, we bifurcate the path and add the region's processing mode to the GDM. Currently, there are 2 modes: DynamicDispatchModeInlined and DynamicDispatchModeConservative. Going forward, we consult the state of the region to make decisions on whether the calls should be inlined or not, which ensures that we have at most one split per region. The modes model the cases when the dynamic type information is perfectly correct and when the info is not correct (i.e. where the region is a subclass of the type we store in DynamicTypeInfo).
-Bifurcation mode allows for increased coverage in cases where the parent method contains code which is only executed when the class is subclassed. The disadvantages of this mode are a (considerable?) performance hit and the possibility of false positives on the path where the conservative mode is used.
+ExprEngine::BifurcateCall implements the -analyzer-ipa=dynamic-bifurcate
+mode.
+
+When a call is made on an object with imprecise dynamic type information
+(RuntimeDefinition::mayHaveOtherDefinitions() evaluates to TRUE), ExprEngine
+bifurcates the path and marks the object's region (retrieved from the
+RuntimeDefinition object) with a path-sensitive "mode" in the ProgramState.
+
+Currently, there are 2 modes:
+
+ DynamicDispatchModeInlined - Models the case where the dynamic type information
+ of the receiver (MemoryRegion) is assumed to be perfectly constrained so
+ that a given definition of a method is expected to be the code actually
+ called. When this mode is set, ExprEngine uses the Decl from
+ RuntimeDefinition to inline any dynamically dispatched call sent to this
+ receiver because the function definition is considered to be fully resolved.
+
+ DynamicDispatchModeConservative - Models the case where the dynamic type
+ information is assumed to be incorrect, for example, implies that the method
+ definition is overriden in a subclass. In such cases, ExprEngine does not
+ inline the methods sent to the receiver (MemoryRegion), even if a candidate
+ definition is available. This mode is conservative about simulating the
+ effects of a call.
+Going forward along the symbolic execution path, ExprEngine consults the mode
+of the receiver's MemRegion to make decisions on whether the calls should be
+inlined or not, which ensures that there is at most one split per region.
+
+At a high level, "bifurcation mode" allows for increased semantic coverage in
+cases where the parent method contains code which is only executed when the
+class is subclassed. The disadvantages of this mode are a (considerable?)
+performance hit and the possibility of false positives on the path where the
+conservative mode is used.
Objective-C Message Heuristics
------------------------------
-We rely on a set of heuristics to partition the set of ObjC method calls into ones that require bifurcation and ones that do not (can or cannot be a subclass). Below are the cases when we consider that the dynamic type of the object is precise (cannot be a subclass):
- - If the object was created with +alloc or +new and initialized with an -init method.
- - If the calls are property accesses using dot syntax. This is based on the assumption that children rarely override properties, or do so in an essentially compatible way.
- - If the class interface is declared inside the main source file. In this case it is unlikely that it will be subclassed.
- - If the method is not declared outside of main source file, either by the receiver's class or by any superclasses.
+ExprEngine relies on a set of heuristics to partition the set of Objective-C
+method calls into those that require bifurcation and those that do not. Below
+are the cases when the DynamicTypeInfo of the object is considered precise
+(cannot be a subclass):
+
+ - If the object was created with +alloc or +new and initialized with an -init
+ method.
+
+ - If the calls are property accesses using dot syntax. This is based on the
+ assumption that children rarely override properties, or do so in an
+ essentially compatible way.
+
+ - If the class interface is declared inside the main source file. In this case
+ it is unlikely that it will be subclassed.
-C++ Inlining Caveats
+ - If the method is not declared outside of main source file, either by the
+ receiver's class or by any superclasses.
+
+C++ Caveats
--------------------
-C++11 [class.cdtor]p4 describes how the vtable of an object is modified as it is being constructed or destructed; that is, the type of the object depends on which base constructors have been completed. This is tracked using dynamic type info in the DynamicTypePropagation checker.
-Temporaries are poorly modelled right now because we're not confident in the placement
+C++11 [class.cdtor]p4 describes how the vtable of an object is modified as it is
+being constructed or destructed; that is, the type of the object depends on
+which base constructors have been completed. This is tracked using
+DynamicTypeInfo in the DynamicTypePropagation checker.
+
+There are several limitations in the current implementation:
-'new' is poorly modelled due to some nasty CFG/design issues (elaborated in PR12014). 'delete' is essentially not modelled at all.
+- Temporaries are poorly modeled right now because we're not confident in the
+ placement of their destructors in the CFG. We currently won't inline their
+ constructors unless the destructor is trivial, and don't process their
+ destructors at all, not even to invalidate the region.
-Arrays of objects are modeled very poorly right now. We run only the first constructor and first destructor. Because of this, we don't inline any constructors or destructors for arrays.
+- 'new' is poorly modeled due to some nasty CFG/design issues. This is tracked
+ in PR12014. 'delete' is not modeled at all.
+
+- Arrays of objects are modeled very poorly right now. ExprEngine currently
+ only simulates the first constructor and first destructor. Because of this,
+ ExprEngine does not inline any constructors or destructors for arrays.
CallEvent
=========
-A CallEvent represents a specific call to a function, method, or other body of code. It is path-sensitive, containing both the current state (ProgramStateRef) and stack space (LocationContext), and provides uniform access to the argument values and return type of a call, no matter how the call is written in the source or what sort of code body is being invoked.
+A CallEvent represents a specific call to a function, method, or other body of
+code. It is path-sensitive, containing both the current state (ProgramStateRef)
+and stack space (LocationContext), and provides uniform access to the argument
+values and return type of a call, no matter how the call is written in the
+source or what sort of code body is being invoked.
+
+ NOTE: For those familiar with Cocoa, CallEvent is roughly equivalent to
+ NSInvocation.
-(For those familiar with Cocoa, CallEvent is roughly equivalent to NSInvocation.)
+CallEvent should be used whenever there is logic dealing with function calls
+that does not care how the call occurred.
-CallEvent should be used whenever there is logic dealing with function calls that does not care how the call occurred. Examples include checking that arguments satisfy preconditions (such as __attribute__((nonnull))), and attempting to inline a call.
+Examples include checking that arguments satisfy preconditions (such as
+__attribute__((nonnull))), and attempting to inline a call.
-CallEvents are reference-counted objects managed by a CallEventManager. While there is no inherent issue with persisting them (say, in the state's GDM), they are intended for short-lived use, and can be recreated from CFGElements or StackFrameContexts fairly easily.
+CallEvents are reference-counted objects managed by a CallEventManager. While
+there is no inherent issue with persisting them (say, in a ProgramState's GDM),
+they are intended for short-lived use, and can be recreated from CFGElements or
+non-top-level StackFrameContexts fairly easily.
diff --git a/docs/analyzer/debug-checks.txt b/docs/analyzer/debug-checks.txt
new file mode 100644
index 0000000..6ac451f
--- /dev/null
+++ b/docs/analyzer/debug-checks.txt
@@ -0,0 +1,89 @@
+The analyzer contains a number of checkers which can aid in debugging. Enable them by using the "-analyzer-checker=" flag, followed by the name of the checker.
+
+General Analysis Dumpers
+========================
+These checkers are used to dump the results of various infrastructural analyses to stderr. Some checkers also have "view" variants, which will display a graph using a 'dot' format viewer (such as Graphviz on OS X) instead.
+
+- debug.DumpCallGraph, debug.ViewCallGraph: Show the call graph generated for the current translation unit. This is used to determine the order in which to analyze functions when inlining is enabled.
+- debug.DumpCFG, debug.ViewCFG: Show the CFG generated for each top-level function being analyzed.
+- debug.DumpDominators: Shows the dominance tree for the CFG of each top-level function.
+- debug.DumpLiveVars: Show the results of live variable analysis for each top-level function being analyzed.
+
+
+Path Tracking
+=============
+These checkers print information about the path taken by the analyzer engine.
+
+- debug.DumpCalls: Prints out every function or method call encountered during a path traversal. This is indented to show the call stack, but does NOT do any special handling of branches, meaning different paths could end up interleaved.
+- debug.DumpTraversal: Prints the name of each branch statement encountered during a path traversal ("IfStmt", "WhileStmt", etc). Currently used to check whether the analysis engine is doing BFS or DFS.
+
+
+State Checking
+==============
+These checkers will print out information about the analyzer state in the form of analysis warnings. They are intended for use with the -verify functionality in regression tests.
+
+- debug.TaintTest: Prints out the word "tainted" for every expression that carries taint. At the time of this writing, taint was only introduced by the checks under experimental.security.taint.TaintPropagation; this checker may eventually move to the security.taint package.
+- debug.ExprInspection: Responds to certain function calls, which are modeled after builtins. These function calls should affect the program state other than the evaluation of their arguments; to use them, you will need to declare them within your test file. The available functions are described below.
+
+(FIXME: debug.ExprInspection should probably be renamed, since it no longer only inspects expressions.)
+
+
+ExprInspection checks
+---------------------
+
+- void clang_analyzer_eval(bool);
+
+Prints TRUE if the argument is known to have a non-zero value,
+ FALSE if the argument is known to have a zero or null value, and
+ UNKNOWN if the argument isn't sufficiently constrained on this path.
+You can use this to test other values by using expressions like "x == 5".
+Note that this functionality is currently DISABLED in inlined functions,
+since different calls to the same inlined function could provide different
+information, making it difficult to write proper -verify directives.
+
+In C, the argument can be typed as 'int' or as '_Bool'.
+
+Example usage:
+ clang_analyzer_eval(x); // expected-warning{{UNKNOWN}}
+ if (!x) return;
+ clang_analyzer_eval(x); // expected-warning{{TRUE}}
+
+
+- void clang_analyzer_checkInlined(bool);
+
+If a call occurs within an inlined function, prints TRUE or FALSE according to
+the value of its argument. If a call occurs outside an inlined function,
+nothing is printed.
+
+The intended use of this checker is to assert that a function is inlined at
+least once (by passing 'true' and expecting a warning), or to assert that a
+function is never inlined (by passing 'false' and expecting no warning). The
+argument is technically unnecessary but is intended to clarify intent.
+
+You might wonder why we can't print TRUE if a function is ever inlined and
+FALSE if it is not. The problem is that any inlined function could conceivably
+also be analyzed as a top-level function (in which case both TRUE and FALSE
+would be printed), depending on the value of the -analyzer-inlining option.
+
+In C, the argument can be typed as 'int' or as '_Bool'.
+
+Example usage:
+ int inlined() {
+ clang_analyzer_checkInlined(true); // expected-warning{{TRUE}}
+ return 42;
+ }
+
+ void topLevel() {
+ clang_analyzer_checkInlined(false); // no-warning (not inlined)
+ int value = inlined();
+ // This assertion will not be valid if the previous call was not inlined.
+ clang_analyzer_eval(value == 42); // expected-warning{{TRUE}}
+ }
+
+
+
+Statistics
+==========
+The debug.Stats checker collects various information about the analysis of each function, such as how many blocks were reached and if the analyzer timed out.
+
+There is also an additional -analyzer-stats flag, which enables various statistics within the analyzer engine. Note the Stats checker (which produces at least one bug report per function) may actually change the values reported by -analyzer-stats.
OpenPOWER on IntegriCloud