summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core
Commit message (Collapse)AuthorAgeFilesLines
...
* [analyzer; alternate edges] prune edges whose end/begin locations have the ↵Ted Kremenek2013-05-041-27/+95
| | | | | | | | | | | | | | | | | same statement parents. This change required some minor changes to LocationContextMap to have it map from PathPieces to LocationContexts instead of PathDiagnosticCallPieces to LocationContexts. These changes are in the other diagnostic generation logic as well, but are functionally equivalent. Interestingly, this optimize requires delaying "cleanUpLocation()" until later; possibly after all edges have been optimized. This is because we need PathDiagnosticLocations to refer to the semantic entity (e.g. a statement) as long as possible. Raw source locations tell us nothing about the semantic relationship between two locations in a path. llvm-svn: 181084
* [analyzer;alternate edges] - add in events (loop iterations, etc)Ted Kremenek2013-05-041-7/+15
| | | | | | | These were being dropped due a transcription mistake from the original algorithm. llvm-svn: 181083
* [analyzer] Start hacking up alternate control-flow edge generation. WIP. ↵Ted Kremenek2013-05-031-0/+216
| | | | | | Not guaranteed to do anything useful yet. llvm-svn: 181040
* [analyzer] Check the stack frame when looking for a var's initialization.Jordan Rose2013-05-031-7/+32
| | | | | | | | | | | | | FindLastStoreBRVisitor is responsible for finding where a particular region gets its value; if the region is a VarRegion, it's possible that value was assigned at initialization, i.e. at its DeclStmt. However, if a function is called recursively, the same DeclStmt may be evaluated multiple times in multiple stack frames. FindLastStoreBRVisitor was not taking this into account and just picking the first one it saw. <rdar://problem/13787723> llvm-svn: 180997
* [analyzer] Fix trackNullOrUndef when tracking args that have nil receivers.Jordan Rose2013-05-031-2/+2
| | | | | | | | | | | | | | | There were actually two bugs here: - if we decided to look for an interesting lvalue or call expression, we wouldn't go find its node if we also knew we were at a (different) call. - if we looked through one message send with a nil receiver, we thought we were still looking at an argument to the original call. Put together, this kept us from being able to track the right values, which means sub-par diagnostics and worse false-positive suppression. Noticed by inspection. llvm-svn: 180996
* Make cleanUpLocation() a self-contained function.Ted Kremenek2013-05-031-44/+47
| | | | llvm-svn: 180986
* Re-apply 180974 with the build error fixed. This was the resultTed Kremenek2013-05-031-16/+27
| | | | | | of a weird merge error with git. llvm-svn: 180981
* Revert "Change LocationContextMap to be a temporary instead of shared ↵Rafael Espindola2013-05-031-27/+16
| | | | | | | | variable in BugReporter." This reverts commit 180974. It broke the build. llvm-svn: 180979
* Change LocationContextMap to be a temporary instead of shared variable in ↵Ted Kremenek2013-05-021-16/+27
| | | | | | | | | | | | | BugReporter. BugReporter is used to process ALL bug reports. By using a shared map, we are having mappings from different PathDiagnosticPieces to LocationContexts well beyond the point where we are processing a given report. This state is inherently error prone, and is analogous to using a global variable. Instead, just create a temporary map, one per report, and when we are done with it we throw it away. No extra state. llvm-svn: 180974
* [analyzer] Don't try to evaluate MaterializeTemporaryExpr as a constant.Jordan Rose2013-05-022-3/+15
| | | | | | | | | | | | | | | ...and don't consider '0' to be a null pointer constant if it's the initializer for a float! Apparently null pointer constant evaluation looks through both MaterializeTemporaryExpr and ImplicitCastExpr, so we have to be more careful about types in the callers. For RegionStore this just means giving up a little more; for ExprEngine this means handling the MaterializeTemporaryExpr case explicitly. Follow-up to r180894. llvm-svn: 180944
* [analyzer] Consolidate constant evaluation logic in SValBuilder.Jordan Rose2013-05-014-67/+72
| | | | | | | | | | | | | | | | | | | | | | | | | Previously, this was scattered across Environment (literal expressions), ExprEngine (default arguments), and RegionStore (global constants). The former special-cased several kinds of simple constant expressions, while the latter two deferred to the AST's constant evaluator. Now, these are all unified as SValBuilder::getConstantVal(). To keep Environment fast, the special cases for simple constant expressions have been left in, but the main benefits are that (a) unusual constants like ObjCStringLiterals now work as default arguments and global constant initializers, and (b) we're not duplicating code between ExprEngine and RegionStore. This actually caught a bug in our test suite, which is awesome: we stop tracking allocated memory if it's passed as an argument along with some kind of callback, but not if the callback is 0. We were testing this in a case where the callback parameter had a default value, but that value was 0. After this change, the analyzer now (correctly) flags that as a leak! <rdar://problem/13773117> llvm-svn: 180894
* [analyzer] Don't inline the [cd]tors of C++ iterators.Jordan Rose2013-05-011-27/+21
| | | | | | | | | | | | | | | | | This goes with r178516, which instructed the analyzer not to inline the constructors and destructors of C++ container classes. This goes a step further and does the same thing for iterators, so that the analyzer won't falsely decide we're trying to construct an iterator pointing to a nonexistent element. The heuristic for determining whether something is an iterator is the presence of an 'iterator_category' member. This is controlled under the same -analyzer-config option as container constructor/destructor inlining: 'c++-container-inlining'. <rdar://problem/13770187> llvm-svn: 180890
* Re-apply "[analyzer] Model casts to bool differently from other numbers."Jordan Rose2013-05-012-1/+21
| | | | | | | | | | | | | | This doesn't appear to be the cause of the slowdown. I'll have to try a manual bisect to see if there's really anything there, or if it's just the bot itself taking on additional load. Meanwhile, this change helps with correctness. This changes an assertion and adds a test case, then re-applies r180638, which was reverted in r180714. <rdar://problem/13296133> and PR15863 llvm-svn: 180864
* Revert "[analyzer] Change PathPieces to be a wrapper around an ilist of ↵Ted Kremenek2013-04-295-53/+45
| | | | | | | | (through indirection) PathDiagnosticPieces." Jordan rightly pointed out that we can do the same with std::list. llvm-svn: 180746
* [analyzer] Change PathPieces to be a wrapper around an ilist of (through ↵Ted Kremenek2013-04-295-45/+53
| | | | | | | | | | | | | | | | | | | | | | | indirection) PathDiagnosticPieces. Much of this patch outside of PathDiagnostics.h are just minor syntactic changes due to the return type for operator* and the like changing for the iterator, so the real focus should be on PathPieces itself. This change is motivated so that we can do efficient insertion and removal of individual pieces from within a PathPiece, just like this was a kind of "IR" for static analyzer diagnostics. We currently implement path transformations by iterating over an entire PathPiece and making a copy. This isn't very natural for some algorithms. We use an ilist here instead of std::list because we want operations to rip out/insert nodes in place, just like IR manipulation. This isn't being used yet, but opens the door for more powerful transformation algorithms on diagnostic paths. llvm-svn: 180741
* [analyzer] Remove comparePath's dependency on subscript operator.Ted Kremenek2013-04-291-2/+7
| | | | llvm-svn: 180740
* Revert "[analyzer] Model casts to bool differently from other numbers."Jordan Rose2013-04-291-16/+0
| | | | | | | | | This seems to be causing quite a slowdown on our internal analyzer bot, and I'm not sure why. Needs further investigation. This reverts r180638 / 9e161ea981f22ae017b6af09d660bfc3ddf16a09. llvm-svn: 180714
* [analyzer] Model casts to bool differently from other numbers.Jordan Rose2013-04-261-0/+16
| | | | | | | | | | | | | | | | | | | Casts to bool (and _Bool) are equivalent to checks against zero, not truncations to 1 bit or 8 bits. This improved reasoning does cause a change in the behavior of the alpha BoolAssignment checker. Previously, this checker complained about statements like "bool x = y" if 'y' was known not to be 0 or 1. Now it does not, since that conversion is well-defined. It's hard to say what the "best" behavior here is: this conversion is safe, but might be better written as an explicit comparison against zero. More usefully, besides improving our model of booleans, this fixes spurious warnings when returning the address of a local variable cast to bool. <rdar://problem/13296133> llvm-svn: 180638
* [analyzer] Refactoring + explanatory comment.Anton Yartsev2013-04-241-9/+11
| | | | llvm-svn: 180181
* [analyzer] Refactor BugReport::getLocation and ↵Anna Zaks2013-04-232-99/+71
| | | | | | | | | | | | | | | PathDiagnosticLocation::createEndOfPath for greater code reuse The 2 functions were computing the same location using different logic (each one had edge case bugs that the other one did not). Refactor them to rely on the same logic. The location of the warning reported in text/command line output format will now match that of the plist file. There is one change in the plist output as well. When reporting an error on a BinaryOperator, we use the location of the operator instead of the beginning of the BinaryOperator expression. This matches our output on command line and looks better in most cases. llvm-svn: 180165
* [analyzer] Treat reinterpret_cast like a base cast in certain cases.Jordan Rose2013-04-221-34/+54
| | | | | | | | | | | | | | | | | The analyzer represents all pointer-to-pointer bitcasts the same way, but this can be problematic if an implicit base cast gets layered on top of a manual base cast (performed with reinterpret_cast instead of static_cast). Fix this (and avoid a valid assertion) by looking through cast regions. Using reinterpret_cast this way is only valid if the base class is at the same offset as the derived class; this is checked by -Wreinterpret-base-class. In the interest of performance, the analyzer doesn't repeat this check anywhere; it will just silently do the wrong thing (use the wrong offsets for fields of the base class) if the user code is wrong. PR15394 llvm-svn: 180052
* C++1y: Allow aggregates to have default initializers.Richard Smith2013-04-201-0/+1
| | | | | | | | | | | Add a CXXDefaultInitExpr, analogous to CXXDefaultArgExpr, and use it both in CXXCtorInitializers and in InitListExprs to represent a default initializer. There's an additional complication here: because the default initializer can refer to the initialized object via its 'this' pointer, we need to make sure that 'this' points to the right thing within the evaluation. llvm-svn: 179958
* [analyzer] Ensure BugReporterTracking works on regions with pointer arithmeticAnna Zaks2013-04-205-21/+35
| | | | | | | | | | Introduce a new helper function, which computes the first symbolic region in the base region chain. The corresponding symbol has been used for assuming that a pointer is null. Now, it will also be used for checking if it is null. This ensures that we are tracking a null pointer correctly in the BugReporter. llvm-svn: 179916
* [analyzer] Flip printPretty and printPrettyAsExpr as per suggestion from ↵Anna Zaks2013-04-201-4/+4
| | | | | | Jordan (r179572) llvm-svn: 179915
* [analyzer] Call proper callback for const regions escaped other then on call.Anton Yartsev2013-04-191-1/+2
| | | | llvm-svn: 179846
* [analyzer] Refine 'nil receiver' diagnostics to mention the name of the ↵Ted Kremenek2013-04-181-3/+14
| | | | | | method not called. llvm-svn: 179776
* [analyzer] "Force" LazyCompoundVals on bind when they are simple enough.Jordan Rose2013-04-181-7/+90
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The analyzer uses LazyCompoundVals to represent rvalues of aggregate types, most importantly structs and arrays. This allows us to efficiently copy around an entire struct, rather than doing a memberwise load every time a struct rvalue is encountered. This can also keep memory usage down by allowing several structs to "share" the same snapshotted bindings. However, /lookup/ through LazyCompoundVals can be expensive, especially since they can end up chaining back to the original value. While we try to reuse LazyCompoundVals whenever it's safe, and cache information about this transitivity, the fact is it's sometimes just not a good idea to perpetuate LazyCompoundVals -- the tradeoffs just aren't worth it. This commit changes RegionStore so that binding a LazyCompoundVal to struct will do a memberwise copy if the struct is simple enough. Today's definition of "simple enough" is "up to N scalar members" (see below), but that could easily be changed in the future. This is enough to bring the test case in PR15697 back down to a manageable analysis time (within 20% of its original time, in an unfair test where the new analyzer is not compiled with LTO). The actual value of "N" is controlled by a new -analyzer-config option, 'region-store-small-struct-limit'. It defaults to "2", meaning structs with zero, one, or two scalar members will be considered "simple enough" for this code path. It's worth noting that a more straightforward implementation would do this on load, not on bind, and make use of the structure we already have for this: CompoundVal. A long time ago, this was actually how RegionStore modeled aggregate-to-aggregate copies, but today it's only used for compound literals. Unfortunately, it seems that we've special-cased LazyCompoundVal in certain places (such as liveness checks) but failed to similarly special-case CompoundVal in all of them. Until we're confident that CompoundVal is handled properly everywhere, this solution is safer, since the entire optimization is just an implementation detail of RegionStore. <rdar://problem/13599304> llvm-svn: 179767
* [analyzer] Don't crash if we cache out after making a temporary region.Jordan Rose2013-04-181-1/+5
| | | | | | | | | | | | | | A C++ overloaded operator may be implemented as an instance method, and that instance method may be called on an rvalue object, which has no associated region. The analyzer handles this by creating a temporary region just for the evaluation of this call; however, it is possible that /by creating the region/, the analyzer ends up in a previously-explored state. In this case we don't need to continue along this path. This doesn't actually show any behavioral change now, but it starts being used with the next commit and prevents an assertion failure there. llvm-svn: 179766
* [analyzer] Tweak getDerefExpr more to track DeclRefExprs to references.Anna Zaks2013-04-181-1/+4
| | | | | | | | | | | In the committed example, we now see a note that tells us when the pointer was assumed to be null. This is the only case in which getDerefExpr returned null (failed to get the dereferenced expr) throughout our regression tests. (There were multiple occurrences of this one.) llvm-svn: 179736
* [analyzer] Improve dereferenced expression tracking for MemberExpr with a ↵Anna Zaks2013-04-171-0/+4
| | | | | | dot and non-reference base llvm-svn: 179734
* [analyzer] Gain more precision retrieving the right SVal by specifying the ↵Anna Zaks2013-04-171-1/+7
| | | | | | | | type of the expression. Thanks to Jordan for suggesting the fix. llvm-svn: 179732
* [analyzer] Allow TrackConstraintBRVisitor to work when the value it’s ↵Anna Zaks2013-04-171-2/+9
| | | | | | | | | | tracking is not live in the last node of the path We always register the visitor on a node in which the value we are tracking is live and constrained. However, the visitation can restart at a node, later on the path, in which the value is under constrained because it is no longer live. Previously, we just silently stopped tracking in that case. llvm-svn: 179731
* [analyzer] Don't warn for returning void expressions in void blocks.Jordan Rose2013-04-171-1/+13
| | | | | | | | | | | This was slightly tricky because BlockDecls don't currently store an inferred return type. However, we can rely on the fact that blocks with inferred return types will have return statements that match the inferred type. <rdar://problem/13665798> llvm-svn: 179699
* Implement CapturedStmt ASTTareq A. Siraj2013-04-161-0/+1
| | | | | | | | | | | | | | | CapturedStmt can be used to implement generic function outlining as described in http://lists.cs.uiuc.edu/pipermail/cfe-dev/2013-January/027540.html. CapturedStmt is not exposed to the C api. Serialization and template support are pending. Author: Wei Pan <wei.pan@intel.com> Differential Revision: http://llvm-reviews.chandlerc.com/D370 llvm-svn: 179615
* Basic support for Microsoft property declarations andJohn McCall2013-04-161-0/+1
| | | | | | | | references thereto. Patch by Tong Shen! llvm-svn: 179585
* [analyzer] Do not crash when processing binary "?:" in C++Anna Zaks2013-04-152-9/+32
| | | | | | | | | | | | | | | | | | | | | | When computing the value of ?: expression, we rely on the last expression in the previous basic block to be the resulting value of the expression. This is not the case for binary "?:" operator (GNU extension) in C++. As the last basic block has the expression for the condition subexpression, which is an R-value, whereas the true subexpression is the L-value. Note the operator evaluation just happens to work in C since the true subexpression is an R-value (like the condition subexpression). CFG is the same in C and C++ case, but the AST nodes are different, which the LValue to Rvalue conversion happening after the BinaryConditionalOperator evaluation. Changed the logic to only use the last expression from the predecessor only if it matches either true or false subexpression. Note, the logic needed fortification anyway: L and R were passed but not even used by the function. Also, change the conjureSymbolVal to correctly compute the type, when the expression is an LG-value. llvm-svn: 179574
* [analyzer] Add pretty printing to CXXBaseObjectRegion.Anna Zaks2013-04-151-1/+5
| | | | llvm-svn: 179573
* [analyzer] Address code review for r179395Anna Zaks2013-04-151-15/+24
| | | | | | Mostly refactoring + handle the nested fields by printing the innermost field only. llvm-svn: 179572
* [analyzer] Add more specialized error messages for corner cases as per ↵Anna Zaks2013-04-151-11/+25
| | | | | | Jordan's code review for r179396 llvm-svn: 179571
* [analyzer] Don't assert on a temporary of pointer-to-member type.Jordan Rose2013-04-151-1/+2
| | | | | | | | | | While we don't do anything intelligent with pointers-to-members today, it's perfectly legal to need a temporary of pointer-to-member type to, say, pass by const reference. Tweak an assertion to allow this. PR15742 and PR15747 llvm-svn: 179563
* [analyzer] Be lazy about struct/array global invalidation too.Jordan Rose2013-04-151-10/+7
| | | | | | | | | | Structs and arrays can take advantage of the single top-level global symbol optimization (described in the previous commit) just as well as scalars. No intended behavioral change. llvm-svn: 179555
* [analyzer] Re-enable using global regions as a symbolic base.Jordan Rose2013-04-151-10/+9
| | | | | | | | | | | | | | | | Now that we're invalidating global regions properly, we want to continue taking advantage of a particular optimization: if all global regions are invalidated together, we can represent the bindings of each region with a "derived region value" symbol. Essentially, this lazily links each global region with a single symbol created at invalidation time, rather than binding each region with a new symbolic value. We used to do this, but haven't been for a while; the previous commit re-enabled this code path, and this handles the fallout. <rdar://problem/13464044> llvm-svn: 179554
* [analyzer] Properly invalidate global regions on opaque function calls.Jordan Rose2013-04-151-21/+60
| | | | | | | | | | | | | | | | | | | | This fixes a regression where a call to a function we can't reason about would not actually invalidate global regions that had explicit bindings. void test_that_now_works() { globalInt = 42; clang_analyzer_eval(globalInt == 42); // expected-warning{{TRUE}} invalidateGlobals(); clang_analyzer_eval(globalInt == 42); // expected-warning{{UNKNOWN}} } This has probably been around since the initial "cluster" refactoring of RegionStore, if not longer. <rdar://problem/13464044> llvm-svn: 179553
* [analyzer] Print a diagnostic note even if the region cannot be printed.Anna Zaks2013-04-121-21/+32
| | | | | | | | | There are few cases where we can track the region, but cannot print the note, which makes the testing limited. (Though, I’ve tested this manually by making all regions non-printable.) Even though the applicability is limited now, the enhancement will be more relevant as we start tracking more regions. llvm-svn: 179396
* [analyzer]Print field region even when the base region is not printableAnna Zaks2013-04-122-18/+34
| | | | llvm-svn: 179395
* [analyzer] Show "Returning from ..." note at caller's depth, not callee's.Jordan Rose2013-04-121-0/+2
| | | | | | | | | | | | | | | | | | | | | | | | Before: 1. Calling 'foo' 2. Doing something interesting 3. Returning from 'foo' 4. Some kind of error here After: 1. Calling 'foo' 2. Doing something interesting 3. Returning from 'foo' 4. Some kind of error here The location of the note is already in the caller, not the callee, so this just brings the "depth" attribute in line with that. This only affects plist diagnostic consumers (i.e. Xcode). It's necessary for Xcode to associate the control flow arrows with the right stack frame. <rdar://problem/13634363> llvm-svn: 179351
* [analyzer] Don't emit extra context arrow after returning from an inlined call.Jordan Rose2013-04-121-9/+12
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In this code int getZero() { return 0; } void test() { int problem = 1 / getZero(); // expected-warning {{Division by zero}} } we generate these arrows: +-----------------+ | v int problem = 1 / getZero(); ^ | +---+ where the top one represents the control flow up to the first call, and the bottom one represents the flow to the division.* It turns out, however, that we were generating the top arrow twice, as if attempting to "set up context" after we had already returned from the call. This resulted in poor highlighting in Xcode. * Arguably the best location for the division is the '/', but that's a different problem. <rdar://problem/13326040> llvm-svn: 179350
* [analyzer] Replace isIntegerType() with isIntegerOrEnumerationType().Jordan Rose2013-04-099-21/+26
| | | | | | | | | | | | | | | | | | | | | | | | | Previously, the analyzer used isIntegerType() everywhere, which uses the C definition of "integer". The C++ predicate with the same behavior is isIntegerOrUnscopedEnumerationType(). However, the analyzer is /really/ using this to ask if it's some sort of "integrally representable" type, i.e. it should include C++11 scoped enumerations as well. hasIntegerRepresentation() sounds like the right predicate, but that includes vectors, which the analyzer represents by its elements. This commit audits all uses of isIntegerType() and replaces them with the general isIntegerOrEnumerationType(), except in some specific cases where it makes sense to exclude scoped enumerations, or any enumerations. These cases now use isIntegerOrUnscopedEnumerationType() and getAs<BuiltinType>() plus BuiltinType::isInteger(). isIntegerType() is hereby banned in the analyzer - lib/StaticAnalysis and include/clang/StaticAnalysis. :-) Fixes real assertion failures. PR15703 / <rdar://problem/12350701> llvm-svn: 179081
* [analyzer] When creating a trimmed graph, preserve whether a node is a sink.Jordan Rose2013-04-061-1/+2
| | | | | | | | | | | | | | This is important because sometimes two nodes are identical, except the second one is a sink. This bug has probably been around for a while, but it wouldn't have been an issue in the old report graph algorithm. I'm ashamed to say I actually looked at this the first time around and thought it would never be a problem...and then didn't include an assertion to back that up. PR15684 llvm-svn: 178944
* [analyzer] Remove another redundancy from trackNullOrUndefAnna Zaks2013-04-051-6/+0
| | | | llvm-svn: 178934
OpenPOWER on IntegriCloud