Commit Graph

1774 Commits

Author SHA1 Message Date
George Karpenkov 151407c35b [analyzer] Add Javascript to analyzer HTML output to allow keyboard navigation.
Differential Revision: https://reviews.llvm.org/D41414

llvm-svn: 321320
2017-12-21 22:57:51 +00:00
Artem Dergachev 9d3ca9a5ae [analyzer] Fix zero-initialization of stack VLAs under ObjC ARC.
Using ARC, strong, weak, and autoreleasing stack variables are implicitly
initialized with nil. This includes variable-length arrays of Objective-C object
pointers. However, in the analyzer we don't zero-initialize them. We used to,
but it accidentally regressed after r289618.

Under ARC, the array variable's initializer within DeclStmt is an
ImplicitValueInitExpr. Environment doesn't maintain any bindings for this
expression kind - instead it always knows that it's a known constant
(0 in our case), so it just returns the known value by calling
SValBuilder::makeZeroVal() (see EnvironmentManager::getSVal().
Commit r289618 had introduced reasonable behavior of SValBuilder::makeZeroVal()
for the arrays, which produces a zero-length compoundVal{}. When such value
is bound to arrays, in RegionStoreManager::bindArray() "remaining" items in the
array are default-initialized with zero, as in
RegionStoreManager::setImplicitDefaultValue(). The similar mechanism works when
an array is initialized by an initializer list that is too short, eg.
  int a[3] = { 1, 2 };
would result in a[2] initialized with 0. However, in case of variable-length
arrays it didn't know if any more items need to be added,
because, well, the length is variable.

Add the default binding anyway, regardless of how many actually need
to be added. We don't really care how many, because the default binding covers
the whole array anyway.

Differential Revision: https://reviews.llvm.org/D41478
rdar://problem/35477763

llvm-svn: 321290
2017-12-21 18:43:02 +00:00
Artem Dergachev fbd9678d2f [analyzer] De-duplicate path diagnostics for each exploded graph node.
The bugreporter::trackNullOrUndefValue() mechanism contains a system of bug
reporter visitors that recursively call each other in order to track where a
null or undefined value came from, where each visitor represents a particular
tracking mechanism (track how the value was stored, track how the value was
returned from a function, track how the value was constrained to null, etc.).

Each visitor is only added once per value it needs to track. Almost. One
exception from this rule would be FindLastStoreBRVisitor that has two operation
modes: it contains a flag that indicates whether null stored values should be
suppressed. Two instances of FindLastStoreBRVisitor with different values of
this flag are considered to be different visitors, so they can be added twice
and produce the same diagnostic twice. This was indeed the case in the affected
test.

With the current logic of this whole machinery, such duplication seems
unavoidable. We should be able to safely add visitors with different flag
values without constructing duplicate diagnostic pieces. Hence the effort
in this commit to de-duplicate diagnostics regardless of what visitors
have produced them.

Differential Revision: https://reviews.llvm.org/D41258

llvm-svn: 321135
2017-12-20 01:17:53 +00:00
Artem Dergachev fee10106d9 [analyzer] trackNullOrUndefValue: always track through parentheses and casts.
When trying to figure out where a null or undefined value came from,
parentheses and cast expressions are either completely irrelevant, or,
in the case of lvalue-to-rvale cast, straightforwardly lead us in the right
direction when we remove them.

There is a regression that causes a certain diagnostic to appear twice in the
path-notes.cpp test (changed to FIXME). It would be addressed in the next
commit.

Differential revision: https://reviews.llvm.org/D41254

llvm-svn: 321133
2017-12-20 01:03:22 +00:00
Artem Dergachev fcad574c4e [analyzer] trackNullOrUndefValue: track last store to non-variables.
When reporting certain kinds of analyzer warnings, we use the
bugreporter::trackNullOrUndefValue mechanism, which is part of public checker
API, to understand where a zero, null-pointer, or garbage value came from,
which would highlight important events with respect to that value in the
diagnostic path notes, and help us suppress various false positives that result
from values appearing from particular sources.

Previously, we've lost track of the value when it was written into a memory
region that is not a plain variable. Now try to resume tracking in this
situation by finding where the last write to this region has occured.

Differential revision: https://reviews.llvm.org/D41253

llvm-svn: 321130
2017-12-20 00:47:17 +00:00
Artem Dergachev e8ba3ec453 [analyzer] Fix a crash during C++17 aggregate construction of base objects.
Since C++17, classes that have base classes can potentially be initialized as
aggregates. Trying to construct such objects through brace initialization was
causing the analyzer to crash when the base class has a non-trivial constructor,
while figuring target region for the base class constructor, because the parent
stack frame didn't contain the constructor of the subclass, because there is
no constructor for subclass, merely aggregate initialization.

This patch avoids the crash, but doesn't provide the actually correct region
for the constructor, which still remains to be fixed. Instead, construction
goes into a fake temporary region which would be immediately discarded. Similar
extremely conservative approach is used for other cases in which the logic for
finding the target region is not yet implemented, including aggregate
initialization with fields instead of base-regions (which is not C++17-specific
but also never worked, just didn't crash).

Differential revision: https://reviews.llvm.org/D40841

rdar://problem/35441058

llvm-svn: 321128
2017-12-20 00:40:38 +00:00
Richard Smith c70f1d63f8 [c++20] P0515R3: Parsing support and basic AST construction for operator <=>.
Adding the new enumerator forced a bunch more changes into this patch than I
would have liked. The -Wtautological-compare warning was extended to properly
check the new comparison operator, clang-format needed updating because it uses
precedence levels as weights for determining where to break lines (and several
operators increased their precedence levels with this change), thread-safety
analysis needed changes to build its own IL properly for the new operator.

All "real" semantic checking for this operator has been deferred to a future
patch. For now, we use the relational comparison rules and arbitrarily give
the builtin form of the operator a return type of 'void'.

llvm-svn: 320707
2017-12-14 15:16:18 +00:00
Artem Dergachev 3ef5deb3a7 [analyzer] In getSVal() API, disable auto-detection of void type as char type.
This is a follow-up from r314910. When a checker developer attempts to
dereference a location in memory through ProgramState::getSVal(Loc) or
ProgramState::getSVal(const MemRegion *), without specifying the second
optional QualType parameter for the type of the value he tries to find at this
location, the type is auto-detected from location type. If the location
represents a value beyond a void pointer, we thought that auto-detecting the
type as 'char' is a good idea. However, in most practical cases, the correct
behavior would be to specify the type explicitly, as it is available from other
sources, and the few cases where we actually need to take a 'char' are
workarounds rather than an intended behavior. Therefore, try to fail with an
easy-to-understand assertion when asked to read from a void pointer location.

Differential Revision: https://reviews.llvm.org/D38801

llvm-svn: 320451
2017-12-12 02:27:55 +00:00
George Karpenkov 8d345cb8a5 [analyzer] do not crash on cases where an array subscript is an rvalue
Array subscript is almost always an lvalue, except for a few cases where
it is not, such as a subscript into an Objective-C property, or a
return from the function.
This commit prevents crashing in such cases.

Fixes rdar://34829842

Differential Revision: https://reviews.llvm.org/D40584

llvm-svn: 319834
2017-12-05 21:19:59 +00:00
Artem Dergachev 748d8a28ef [analyzer] Mark heap-based symbolic regions in debug dumps.
They are now printed as HeapSymRegion{$x} in order to discriminate between that
and regular SymRegion{$x}, which are two different regions, having different
parent reginos (memory spaces) - HeapSpaceRegion and UnknownSpaceRegion
respectively.

Differential Revision: https://reviews.llvm.org/D40793

llvm-svn: 319793
2017-12-05 17:14:39 +00:00
George Karpenkov ad142fd8d3 [analyzer] [NFC] remove duplicated function
Two copies of getSymLERange in RangeConstraintManager are virtually
identical, which is clearly bad.
This patch uses lambdas to call one from another (assuming that we would
like to avoid getting ranges from the state when necessary).

Differential Revision: https://reviews.llvm.org/D39709

llvm-svn: 319697
2017-12-04 21:00:05 +00:00
Devin Coughlin a565a7b9b8 [analyzer] Don't treat lambda-captures float constexprs as undefined
RegionStore has special logic to evaluate captured constexpr variables.
However, if the constexpr initializer cannot be evaluated as an integer, the
value is treated as undefined. This leads to false positives when, for example,
a constexpr float is captured by a lambda.

To fix this, treat a constexpr capture that cannot be evaluated as unknown
rather than undefined.

rdar://problem/35784662

llvm-svn: 319638
2017-12-04 04:46:47 +00:00
Roman Lebedev 88b56caa0e [analyzer] Fix false negative on post-increment of uninitialized variable.
Summary:
Currently clang static analyzer does warn on:
```
int x;
x+=1;
x-=1;
x=x+1;
x=x-1;
```
But does warn on:
```
int x;
x++;
x--;
--x;
++x;
```

This differential should fix that.
Fixes https://bugs.llvm.org/show_bug.cgi?id=35419

Reviewers: dcoughlin, NoQ

Reviewed By: dcoughlin

Subscribers: NoQ, xazax.hun, szepet, cfe-commits, a.sidorin

Tags: #clang

Differential Revision: https://reviews.llvm.org/D40463

llvm-svn: 319411
2017-11-30 09:18:35 +00:00
Devin Coughlin 9a2c14a73a [analyzer] Fix unreachable creating PathDiagnosticLocation with widen-loops=true
In the original design of the analyzer, it was assumed that a BlockEntrance
doesn't create a new binding on the Store, but this assumption isn't true when
'widen-loops' is set to true. Fix this by finding an appropriate location
BlockEntrace program points.

Patch by Henry Wong!

Differential Revision: https://reviews.llvm.org/D37187

llvm-svn: 319333
2017-11-29 18:25:37 +00:00
Artem Dergachev 052436f768 [analyzer] pr34766: Fix a crash on explicit std::initializer_list constructor.
We didn't support the following syntax:

  (std::initializer_list<int>){12}

which suddenly produces CompoundLiteralExpr that contains
CXXStdInitializerListExpr.

Lift the assertion and instead pass the value through CompoundLiteralExpr
transparently, as it doesn't add much.

Differential Revision: https://reviews.llvm.org/D39803

llvm-svn: 319058
2017-11-27 17:37:09 +00:00
Artem Dergachev db9a5954d4 [analyzer] pr34404: Fix a crash on modeling pointers to indirect members.
We were crashing whenever a C++ pointer-to-member was taken, that was pointing
to a member of an anonymous structure field within a class, eg.

  struct A {
    struct {
     int x;
    };
  };
  // ...
  &A::x;

Differential Revision: https://reviews.llvm.org/D39800

llvm-svn: 319055
2017-11-27 17:31:16 +00:00
Eric Christopher f18016c640 Add NDEBUG checks around LLVM_DUMP_METHOD functions for Wunused-function warnings.
llvm-svn: 318371
2017-11-16 03:18:09 +00:00
George Karpenkov 8ee82ed81b [analyzer] [NFC] Minor ExprEngineC refactoring
Move a repeated block of code into a function.

Differential Revision: https://reviews.llvm.org/D39584

llvm-svn: 317849
2017-11-09 23:33:37 +00:00
George Karpenkov d860e7a6b8 [analyzer] do not crash when trying to convert an APSInt to an unexpected type
This is the issue breaking the postgresql bot, purely by chance exposed
through taint checker, somehow appearing after
https://reviews.llvm.org/D38358 got committed.

The backstory is that the taint checker requests SVal for the value of
the pointer, and analyzer has a "fast path" in the getter to return a
constant when we know that the value is constant.
Unfortunately, the getter requires a cast to get signedness correctly,
and for the pointer `void *` the cast crashes.

This is more of a band-aid patch, as I am not sure what could be done
here "correctly", but it should be applied in any case to avoid the
crash.

Differential Revision: https://reviews.llvm.org/D39862

llvm-svn: 317839
2017-11-09 21:49:38 +00:00
George Karpenkov bbb66ad7b2 [analyzer] assume bitwise arithmetic axioms
Patches the solver to assume that bitwise OR of an unsigned value with a
constant always produces a value larger-or-equal than the constant, and
bitwise AND with a constant always produces a value less-or-equal than
the constant.

This patch is especially useful in the context of using bitwise
arithmetic for error code encoding: the analyzer would be able to state
that the error code produced using a bitwise OR is non-zero.

Differential Revision: https://reviews.llvm.org/D39707

llvm-svn: 317820
2017-11-09 19:06:22 +00:00
Artem Dergachev 5904fba8c9 [analyzer] Fix a crash on logical operators with vectors.
Do not crash when trying to compute x && y or x || y where x and y are
of a vector type.

For now we do not seem to properly model operations with vectors. In particular,
operations && and || on a pair of vectors are not short-circuit, unlike regular
logical operators, so even our CFG is incorrect.

Avoid the crash, add respective FIXME tests for later.

Differential Revision: https://reviews.llvm.org/D39682

rdar://problem/34317663

llvm-svn: 317700
2017-11-08 17:27:58 +00:00
George Karpenkov 85a34aa21e [analyzer] [NFC] very minor ExprEngineC refactoring
Differential Revision: https://reviews.llvm.org/D39577

llvm-svn: 317294
2017-11-03 00:41:29 +00:00
George Karpenkov 0c3a7c2015 [analyzer] Use the same filename for the header and the implementation of BugReporterVisitor
Differential Revision: https://reviews.llvm.org/D37935

llvm-svn: 316963
2017-10-30 22:31:57 +00:00
Gabor Horvath 4581f7497b [analyzer] Left shifting a negative value is undefined
The analyzer did not return an UndefVal in case a negative value was left
shifted. I also altered the UndefResultChecker to emit a clear warning in this
case.

Differential Revision: https://reviews.llvm.org/D39423

llvm-svn: 316924
2017-10-30 17:06:42 +00:00
Gabor Horvath 404fcd3069 [analyzer] Use the signature of the primary template for issue hash calculation
Now when a template is instantiated more times and there is a bug found in the
instantiations the issue hash will be different for each instantiation even if
every other property of the bug (path, message, location) is the same.

This patch aims to resolve this issue. Note that explicit specializations still
generate different hashes but that is intended.

Differential Revision: https://reviews.llvm.org/D38728

llvm-svn: 316900
2017-10-30 12:16:07 +00:00
Gabor Horvath bb81bfb69c [analyzer] Handle ObjC messages conservatively in CallDescription
Differential Revision: https://reviews.llvm.org/D37470

llvm-svn: 316885
2017-10-30 08:47:13 +00:00
Peter Szecsi 1496d188a0 [analyzer] LoopUnrolling: check the bitwidth of the used numbers (pr34943)
The loop unrolling feature aims to track the maximum possible steps a loop can
make. In order to implement this, it investigates the initial value of the 
counter variable and the bound number. (It has to be known.)
These numbers are used as llvm::APInts, however, it was not checked if their
bitwidths are the same which lead to some crashes.
This revision solves this problem by extending the "shorter" one (to the length
of the "longer" one).
For the detailed bug report, see: https://bugs.llvm.org/show_bug.cgi?id=34943

Differential Revision: https://reviews.llvm.org/D38922

llvm-svn: 316830
2017-10-28 12:19:08 +00:00
George Karpenkov 3d64d6ee54 [Analyzer] Do not use static storage to for implementations created in BodyFarm.cpp
Differential Revision: https://reviews.llvm.org/D39208

llvm-svn: 316400
2017-10-23 23:59:52 +00:00
Alexander Shaposhnikov 9a21d28b5d [analyzer] Fix handling of labels in getLValueElement
In getLValueElement Base may represent the address of a label 
(as in the newly-added test case), in this case it's not a loc::MemRegionVal 
and Base.castAs<loc::MemRegionVal>() triggers an assert, this diff makes 
getLValueElement return UnknownVal instead.

Differential revision: https://reviews.llvm.org/D39174

llvm-svn: 316399
2017-10-23 23:46:06 +00:00
Gabor Horvath d3a8570231 [analyzer] Dump signed integers in SymIntExpr and IntSymExpr correctly
Patch by: Adam Balogh!

Differential Revision: https://reviews.llvm.org/D39048

llvm-svn: 316157
2017-10-19 11:58:21 +00:00
Artem Dergachev cd25c38dc0 [analyzer] pr28449: Fix support for various array initializers.
In some cases the analyzer didn't expect an array-type variable to be
initialized with anything other than a string literal. The patch essentially
removes the assertion, and ensures relatively sane behavior.

There is a bigger problem with these initializers. Currently our memory model
(RegionStore) is being ordered to initialize the array with a region that
is assumed to be storing the initializer rvalue, and it guesses to copy
the contents of that region to the array variable. However, it would make
more sense for RegionStore to receive the correct initializer in the first
place. This problem isn't addressed with this patch.

rdar://problem/27248428
Differential Revision: https://reviews.llvm.org/D23963

llvm-svn: 315750
2017-10-13 20:54:56 +00:00
NAKAMURA Takumi 5dadfd4bde SVal::getAsSymbol(bool IncludeBaseRegions): Follow clang/StaticAnalyzer/Core/PathSensitive/SVals.h, s/IncludeBaseRegion/IncludeBaseRegions/g [-Wdocumentation]
llvm-svn: 315572
2017-10-12 09:42:12 +00:00
Daniel Marjamaki d3d83681bc [Analyzer] Clarify error messages for undefined result
Differential Revision: https://reviews.llvm.org/D30295

llvm-svn: 315462
2017-10-11 14:49:35 +00:00
Gabor Horvath 21524676a2 [analyzer] Implement pointer arithmetic on constants
Patch by: Rafael Stahl!

Differential Revision: https://reviews.llvm.org/D37478

llvm-svn: 315296
2017-10-10 11:01:49 +00:00
Artem Dergachev 59428d182f [analyzer] Fix leak false positives on stuff put in C++/ObjC initializer lists.
The analyzer now realizes that C++ std::initializer_list objects and
Objective-C boxed structure/array/dictionary expressions can potentially
maintain a reference to the objects that were put into them. This avoids
false memory leak posivites and a few other issues.

This is a conservative behavior; for now, we do not model what actually happens
to the objects after being passed into such initializer lists.

rdar://problem/32918288
Differential Revision: https://reviews.llvm.org/D35216

llvm-svn: 314975
2017-10-05 08:43:32 +00:00
Artem Dergachev 9445b89c49 [analyzer] Fix autodetection of binding types.
In ProgramState::getSVal(Location, Type) API which dereferences a pointer value,
when the optional Type parameter is not supplied and the Location is not typed,
type should have been guessed on a best-effort basis by inspecting the Location
more deeply. However, this never worked; the auto-detected type was instead
a pointer type to the correct type.

Fixed the issue and added various test cases to demonstrate which parts of the
analyzer were affected (uninitialized pointer argument checker, C++ trivial copy
modeling, Google test API modeling checker).

Additionally, autodetected void types are automatically replaced with char,
in order to simplify checker APIs. Which means that if the location is a void
pointer, getSVal() would read the first byte through this pointer
and return its symbolic value.

Fixes pr34305.

Differential Revision: https://reviews.llvm.org/D38358

llvm-svn: 314910
2017-10-04 15:59:40 +00:00
Artem Dergachev 8c80061535 [analyzer] Match more patterns in bugreporter::getDerefExpr() API.
This function can now track null pointer through simple pointer arithmetic,
such as '*&*(p + 2)' => 'p' and so on, displaying intermediate diagnostic pieces
for the user to understand where the null pointer is coming from.

Differential Revision: https://reviews.llvm.org/D37025

llvm-svn: 314290
2017-09-27 09:50:45 +00:00
Artem Dergachev 2064e82277 [analyzer] Fix and refactor bugreporter::getDerefExpr() API.
This API is used by checkers (and other entities) in order to track where does
a value originate from, by jumping from an expression value of which is equal
to that value to the expression from which this value has "appeared". For
example, it may be an lvalue from which the rvalue was loaded, or a function
call from which the dereferenced pointer was returned.

The function now avoids incorrectly unwrapping implicit lvalue-to-rvalue casts,
which caused crashes and incorrect intermediate diagnostic pieces. It also no
longer relies on how the expression is written when guessing what it means.

Fixes pr34373 and pr34731.

rdar://problem/33594502

Differential Revision: https://reviews.llvm.org/D37023

llvm-svn: 314287
2017-09-27 09:33:37 +00:00
Alexander Shaposhnikov f4963ff162 [analyzer] Fix crash on modeling of pointer arithmetic
This patch fixes analyzer's crash on the newly added test case 
(see also https://bugs.llvm.org/show_bug.cgi?id=34374).
Pointers subtraction appears to be modeled incorrectly 
in the following example:
  char* p;
  auto n = p - reinterpret_cast<char*>((unsigned long)1);
In this case the analyzer (built without this patch) 
tries to create a symbolic value for the difference 
treating reinterpret_cast<char*>((unsigned long)1) 
as an integer, that is not correct.

Differential revision: https://reviews.llvm.org/D38214

Test plan: make check-all

llvm-svn: 314141
2017-09-25 19:32:33 +00:00
George Karpenkov 504e236003 [Analyzer] Log when auto-synthesized body is used.
Differential Revision: https://reviews.llvm.org/D37910

llvm-svn: 313944
2017-09-22 00:37:12 +00:00
George Karpenkov 50657f6bd6 [CSA] [NFC] Move AnalysisContext.h to AnalysisDeclContext.h
The implementation is in AnalysisDeclContext.cpp and the class is called
AnalysisDeclContext.

Making those match up has numerous benefits, including:

 - Easier jump from header to/from implementation.
 - Easily identify filename from class.

Differential Revision: https://reviews.llvm.org/D37500

llvm-svn: 312671
2017-09-06 21:45:03 +00:00
George Karpenkov 7b9cf1c4c3 [NFC] [CSA] Move AnyFunctionCall::getRuntimeDefinition implementation to cpp.
Differential Revision: https://reviews.llvm.org/D37499

llvm-svn: 312670
2017-09-06 21:45:01 +00:00
Simon Pilgrim 108f36d5b9 Removed dead code (PR34467). NFCI.
The for loop already checks that Idx < NumOfArgs.

llvm-svn: 312525
2017-09-05 10:37:13 +00:00
Rui Ueyama 5ad6bdf2fd Remove trailing space.
llvm-svn: 311936
2017-08-28 21:38:14 +00:00
Alexander Shaposhnikov 18d77984fb [analyzer] Fix crash in modeling arithmetic
This diff fixes modeling of arithmetic 
expressions where pointers are treated as integers 
(i.e. via C-style / reinterpret casts).
For now we return UnknownVal unless the operation is a comparison.

Test plan: make check-all

Differential revision: https://reviews.llvm.org/D37120

llvm-svn: 311935
2017-08-28 21:15:21 +00:00
Peter Szecsi 0db84863d0 [StaticAnalyzer] LoopUnrolling: Keep track the maximum number of steps for each loop
This way the unrolling can be restricted for loops which will take at most a
given number of steps. It is defined as 128 in this patch and it seems to have
a good number for that purpose.

Differential Revision: https://reviews.llvm.org/D37181

llvm-svn: 311883
2017-08-28 10:50:28 +00:00
Peter Szecsi d0604acd8e [StaticAnalyzer] LoopUnrolling: Excluding loops which splits the state
Added check if the execution of the last step of the given unrolled loop has
generated more branches. If yes, than treat it as a normal (non-unrolled) loop
in the remaining part of the analysis.

Differential Revision: https://reviews.llvm.org/D36962

llvm-svn: 311881
2017-08-28 10:34:50 +00:00
Peter Szecsi d91554bc91 [StaticAnalyzer] LoopUnrolling fixes
1. The LoopUnrolling feature needs the LoopExit included in the CFG so added this
dependency via the config options
2. The LoopExit element can be encountered even if we haven't encountered the 
block of the corresponding LoopStmt. So the asserts were not right.
3. If we are caching out the Node then we get a nullptr from generateNode which
case was not handled.


Differential Revision: https://reviews.llvm.org/D37103

llvm-svn: 311880
2017-08-28 10:21:24 +00:00
Peter Szecsi 3c3e1b0b54 [StaticAnalyzer] LoopUnrolling: Track a LoopStack in order to completely unroll specific loops
The LoopExit CFG information provides the opportunity to not mark the loops but
having a stack which tracks if a loop is unrolled or not. So in case of
simulating a loop we just add it and the information if it meets the
requirements to be unrolled to the top of the stack.

Differential Revision: https://reviews.llvm.org/D35684

llvm-svn: 311346
2017-08-21 16:32:57 +00:00
Peter Szecsi 4aa5e10fcc [StaticAnalyzer] Handle LoopExit CFGElement in the analyzer
This patch adds handling of the LoopExit CFGElements to the StaticAnalyzer.
This is reached by introducing a new ProgramPoint.
Tests will be added in a following commit.

Differential Revision: https://reviews.llvm.org/D35670

llvm-svn: 311344
2017-08-21 16:10:19 +00:00