When the analyzer evaluates a CXXConstructExpr, it looks ahead in the CFG for
the current block to detect what region the object should be constructed into.
If the constructor was directly constructed into a local variable or field
region then there is no need to explicitly bind the constructed value to
the local or field when analyzing the DeclStmt or CXXCtorInitializer that
called the constructor.
Unfortunately, there were situations in which the CXXConstructExpr was
constructed into a temporary region but when evaluating the corresponding
DeclStmt or CXXCtorInitializer the analyzer assumed the object was constructed
into the local or field. This led to spurious warnings about uninitialized
values (PR25777).
To avoid these false positives, this commit factors out the logic for
determining when a CXXConstructExpr will be directly constructed into existing
storage, adds the inverse logic to detect when the corresponding later bind can
be safely skipped, and adds assertions to make sure these two checks are in
sync.
rdar://problem/21947725
llvm-svn: 255859
When a C++ lambda captures a variable-length array, it creates a capture
field to store the size of the array. The initialization expression for this
capture is null, which led the analyzer to crash when initializing the field.
To avoid this, use the size expression from the VLA type to determine the
initialization value.
rdar://problem/23748072
llvm-svn: 254962
Fixes a false positive when temporary destructors are enabled where a temporary
is destroyed after a variable is constructed but before the VarDecl itself is
processed, which occurs when the variable is in the condition of an if or while.
Patch by Alex McCarthy, with an extra test from me.
llvm-svn: 205661
If we're trying to get the zero element region of something that's not a region,
we should be returning UnknownVal, which is what ProgramState::getLValue will
do for us.
Patch by Alex McCarthy!
llvm-svn: 205327
This will let us stage in the modeling of operator new. The -analyzer-config
opton 'c++-inline-allocators' is currently off by default.
Patch by Karthik Bhat!
llvm-svn: 201122
Now that the CFG includes nodes for the destructors in a delete-expression,
process them in the analyzer using the same common destructor interface
currently used for local, member, and base destructors. Also, check for when
the value is known to be null, in which case no destructor is actually run.
This does not yet handle destructors for deleted /arrays/, which may need
more CFG work. It also causes a slight regression in the location of
double delete warnings; the double delete is detected at the destructor
call, which is implicit, and so is reported on the first access within the
destructor instead of at the 'delete' statement. This will be fixed soon.
Patch by Karthik Bhat!
llvm-svn: 191381
This is an improved version of r186498. It enables ExprEngine to reason about
temporary object destructors. However, these destructor calls are never
inlined, since this feature is still broken. Still, this is sufficient to
properly handle noreturn temporary destructors.
Now, the analyzer correctly handles expressions like "a || A()", and executes the
destructor of "A" only on the paths where "a" evaluted to false.
Temporary destructor processing is still off by default and one has to
explicitly request it by setting cfg-temporary-dtors=true.
Reviewers: jordan_rose
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1259
llvm-svn: 189746
Summary:
-fno-exceptions does not implicitly attach a nothrow specifier to every operator
new. Even in this mode, non-nothrow new must not return a null pointer. Failure
to allocate memory can be signalled by other means, or just by killing the
program. This behaviour is consistent with the compiler - even with
-fno-exceptions, the generated code never tests for null (and would segfault if
the opeator actually happened to return null).
Reviewers: jordan_rose
CC: cfe-commits
Differential Revision: http://llvm-reviews.chandlerc.com/D1528
llvm-svn: 189452
Previously, we tried to avoid creating new temporary object regions if
the value to be materialized itself came from a temporary object region.
However, once we became more strict about lvalues vs. rvalues (months
ago), this optimization became dead code, because the input to this
function will always be an rvalue (i.e. a symbolic value or compound
value rather than a region, at least for structs).
This would be a nice optimization to keep, but removing it makes it
simpler to reason about temporary regions.
llvm-svn: 187160
Previously, we asserted that whenever 'new' did not include a constructor
call, the type must be a non-record type. In C++11, however, uniform
initialization syntax (braces) allow 'new' to construct records with
list-initialization: "new Point{1, 2}".
Removing this assertion should be perfectly safe; the code here matches
what VisitDeclStmt does for regions allocated on the stack.
<rdar://problem/14403437>
llvm-svn: 186028
Re-apply r184511, reverted in r184561, with the trivial default constructor
fast path removed -- it turned out not to be necessary here.
Certain expressions can cause a constructor invocation to zero-initialize
its object even if the constructor itself does no initialization. The
analyzer now handles that before evaluating the call to the constructor,
using the same "default binding" mechanism that calloc() uses, rather
than simply ignoring the zero-initialization flag.
<rdar://problem/14212563>
llvm-svn: 184815
In order to make sure virtual base classes are always initialized once,
the AST contains initializers for the base class in /all/ of its
descendents, not just the immediate descendents. However, at runtime,
the most-derived object is responsible for initializing all the virtual
base classes; all the other initializers will be ignored.
The analyzer now checks to see if it's being called from another base
constructor, and if so does not perform virtual base initialization.
<rdar://problem/14236851>
llvm-svn: 184814
Per review from Anna, this really should have been two commits, and besides
it's causing problems on our internal buildbot. Reverting until these have
been worked out.
This reverts r184511 / 98123284826bb4ce422775563ff1a01580ec5766.
llvm-svn: 184561
Certain expressions can cause a constructor invocation to zero-initialize
its object even if the constructor itself does no initialization. The
analyzer now handles that before evaluating the call to the constructor,
using the same "default binding" mechanism that calloc() uses, rather
than simply ignoring the zero-initialization flag.
As a bonus, trivial default constructors are now no longer inlined; they
are instead processed explicitly by ExprEngine. This has a (positive)
effect on the generated path edges: they no longer stop at a default
constructor call unless there's a user-provided implementation.
<rdar://problem/14212563>
llvm-svn: 184511
- Find the correct region to represent the first array element when
constructing a CXXConstructorCall.
- If the array is trivial, model the copy with a primitive load/store.
- Don't warn about the "uninitialized" subscript in the AST -- we don't use
the helper variable that Sema provides.
<rdar://problem/13091608>
llvm-svn: 178602
Evaluating a C++ new expression now includes generating an intermediate
ExplodedNode, and this node could very well represent a previously-
reachable state in the ExplodedGraph. If so, we can short-circuit the
rest of the evaluation.
Caught by the assertion a few lines later.
<rdar://problem/13510065>
llvm-svn: 178401
These types will not have a CXXConstructExpr to do the initialization for
them. Previously we just used a simple call to ProgramState::bindLoc, but
that doesn't trigger proper checker callbacks (like pointer escape).
Found by Anton Yartsev.
llvm-svn: 178160
r175234 allowed the analyzer to model trivial copy/move constructors as
an aggregate bind. This commit extends that to trivial assignment
operators as well. Like the last commit, one of the motivating factors here
is not warning when the right-hand object is partially-initialized, which
can have legitimate uses.
<rdar://problem/13405162>
llvm-svn: 177220
Normally, we need to look through derived-to-base casts when creating
temporary object regions (added in r175854). However, if the temporary
is a pointer (rather than a struct/class instance), we need to /preserve/
the base casts that have been applied.
This also ensures that we really do create a new temporary region when
we need to: MaterializeTemporaryExpr and lvalue CXXDefaultArgExprs.
Fixes PR15342, although the test case doesn't include the crash because
I couldn't isolate it.
llvm-svn: 176069
Use Optional<CFG*> where invalid states were needed previously. In the one case
where that's not possible (beginAutomaticObjDtorsInsert) just use a dummy
CFGAutomaticObjDtor.
Thanks for the help from Jordan Rose & discussion/feedback from Ted Kremenek
and Doug Gregor.
Post commit code review feedback on r175796 by Ted Kremenek.
llvm-svn: 175938
This is a follow-up to r175830, which made sure a temporary object region
created for, say, a struct rvalue matched up with the initial bindings
being stored into it. This does the same for the case in which the AST
actually tells us that we need to create a temporary via a
MaterializeObjectExpr. I've unified the two code paths and moved a static
helper function onto ExprEngine.
This also caused a bit of test churn, causing us to go back to describing
temporary regions without a 'const' qualifier. This seems acceptable; it's
our behavior from a few months ago.
<rdar://problem/13265460> (part 2)
llvm-svn: 175854
This allows MemRegion and MemRegionManager to avoid asking over and over
again whether an class is a virtual base or a non-virtual base.
Minor optimization/cleanup; no functionality change.
llvm-svn: 175716
...after a host of optimizations related to the use of LazyCompoundVals
(our implementation of aggregate binds).
Originally applied in r173951.
Reverted in r174069 because it was causing hangs.
Re-applied in r174212.
Reverted in r174265 because it was /still/ causing hangs.
If this needs to be reverted again it will be punted to far in the future.
llvm-svn: 175234
...again. The problem has not been fixed and our internal buildbot is still
getting hangs.
This reverts r174212, originally applied in r173951, then reverted in r174069.
Will not re-apply until the entire project analyzes successfully on my
local machine.
llvm-svn: 174265
It's causing hangs on our internal analyzer buildbot. Will restore after
investigating.
This reverts r173951 / baa7ca1142990e1ad6d4e9d2c73adb749ff50789.
llvm-svn: 174069
This is faster for the analyzer to process than inlining the constructor
and performing a member-wise copy, and it also solves the problem of
warning when a partially-initialized POD struct is copied.
Before:
CGPoint p;
p.x = 0;
CGPoint p2 = p; <-- assigned value is garbage or undefined
After:
CGPoint p;
p.x = 0;
CGPoint p2 = p; // no-warning
This matches our behavior in C, where we don't see a field-by-field copy.
<rdar://problem/12305288>
llvm-svn: 173951
We don't handle array destructors correctly yet, but we now apply the same
hack (explicitly destroy the first element, implicitly invalidate the rest)
for multidimensional arrays that we already use for linear arrays.
<rdar://problem/12858542>
llvm-svn: 170000
uncovered.
This required manually correcting all of the incorrect main-module
headers I could find, and running the new llvm/utils/sort_includes.py
script over the files.
I also manually added quite a few missing headers that were uncovered by
shuffling the order or moving headers up to be main-module-headers.
llvm-svn: 169237
This is actually required by the C++ standard in
[basic.stc.dynamic.allocation]p3:
If an allocation function declared with a non-throwing
exception-specification fails to allocate storage, it shall return a
null pointer. Any other allocation function that fails to allocate
storage shall indicate failure only by throwing an exception of a type
that would match a handler of type std::bad_alloc.
We don't bother checking for the specific exception type, but just go off
the operator new prototype. This should help with a certain class of lazy
initalization false positives.
<rdar://problem/12115221>
llvm-svn: 166363
This is necessary because further analysis will assume that the SVal's
type matches the AST type. This caused a crash when trying to perform
a derived-to-base cast on a C++ object that had been new'd to be another
object type.
Yet another crash in PR13763.
llvm-svn: 163442
CXXDestructorCall now has a flag for when it is a base destructor call.
Other kinds of destructor calls (locals, fields, temporaries, and 'delete')
all behave as "whole-object" destructors and do not behave differently
from one another (specifically, in these cases we /should/ try to
devirtualize a call to a virtual destructor).
This was causing crashes in both our internal buildbot, the crash still
being tracked in PR13765, and some of the crashes being tracked in PR13763,
due to a assertion failure. (The behavior under -Asserts happened to be
correct anyway.)
Adding this knowledge also allows our DynamicTypePropagation checker to do
a bit less work; the special rules about virtual method calls during a
destructor only require extra handling during base destructors.
llvm-svn: 163348
The problem is that the value of 'this' in a C++ member function call
should always be a region (or NULL). However, if the object is an rvalue,
it has no associated region (only a conjured symbol or LazyCompoundVal).
For now, we handle this in two ways:
1) Actually respect MaterializeTemporaryExpr. Before, it was relying on
CXXConstructExpr to create temporary regions for all struct values.
Now it just does the right thing: if the value is not in a temporary
region, create one.
2) Have CallEvent recognize the case where its 'this' pointer is a
non-region, and just return UnknownVal to keep from confusing clients.
The long-term problem is being tracked internally in <rdar://problem/12137950>,
but this makes many test cases pass.
llvm-svn: 163220
This allows us to better reason about status objects, like Clang's own
llvm::Optional (when its contents are trivially destructible), which are
often intended to be passed around by value.
We still don't inline constructors for temporaries in the general case.
<rdar://problem/11986434>
llvm-svn: 162681
Also rename 'getCurrentBlockCounter()' to 'blockCount()'.
This ripples a bunch of code simplifications; mostly aesthetic,
but makes the code a bit tighter.
llvm-svn: 162349
No need to have the "get", the word "conjure" is a verb too!
Getting a conjured symbol is the same as conjuring one up.
This shortening is largely cosmetic, but just this simple changed
cleaned up a handful of lines, making them less verbose.
llvm-svn: 162348
Like base constructors, delegating constructors require no further
processing in the CFGInitializer node.
Also, add PrettyStackTraceLoc to the initializer and destructor logic
so we can get better stack traces in the future.
llvm-svn: 161283
This ensures that it is valid to reference-count any CallEvents, and we
won't accidentally try to reclaim a CallEvent that lives on the stack.
It also hides an ugly switch statement for handling CallExprs!
There should be no functionality change here.
llvm-svn: 160986
This workaround is fairly lame: we simulate the first element's constructor
and destructor and rely on the region invalidation to "initialize" the rest
of the elements.
llvm-svn: 160809