summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp59
1 files changed, 49 insertions, 10 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index ed90dc58918..96ea9f53395 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -176,6 +176,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
}
// FIXME: This will eventually need to handle new-expressions as well.
+ // Don't forget to update the pre-constructor initialization code below.
}
// If we couldn't find an existing region to construct into, assume we're
@@ -215,22 +216,60 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
ExplodedNodeSet DstPreVisit;
getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this);
+
+ bool IsArray = isa<ElementRegion>(Target);
+ ExplodedNodeSet PreInitialized;
+ {
+ StmtNodeBuilder Bldr(DstPreVisit, PreInitialized, *currBldrCtx);
+ if (CE->requiresZeroInitialization()) {
+ // Type of the zero doesn't matter.
+ SVal ZeroVal = svalBuilder.makeZeroVal(getContext().CharTy);
+
+ for (ExplodedNodeSet::iterator I = DstPreVisit.begin(),
+ E = DstPreVisit.end();
+ I != E; ++I) {
+ ProgramStateRef State = (*I)->getState();
+ // FIXME: Once we properly handle constructors in new-expressions, we'll
+ // need to invalidate the region before setting a default value, to make
+ // sure there aren't any lingering bindings around. This probably needs
+ // to happen regardless of whether or not the object is zero-initialized
+ // to handle random fields of a placement-initialized object picking up
+ // old bindings. We might only want to do it when we need to, though.
+ // FIXME: This isn't actually correct for arrays -- we need to zero-
+ // initialize the entire array, not just the first element -- but our
+ // handling of arrays everywhere else is weak as well, so this shouldn't
+ // actually make things worse.
+ State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal);
+ Bldr.generateNode(CE, *I, State, /*tag=*/0, ProgramPoint::PreStmtKind);
+ }
+ }
+ }
+
ExplodedNodeSet DstPreCall;
- getCheckerManager().runCheckersForPreCall(DstPreCall, DstPreVisit,
+ getCheckerManager().runCheckersForPreCall(DstPreCall, PreInitialized,
*Call, *this);
ExplodedNodeSet DstEvaluated;
StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx);
- bool IsArray = isa<ElementRegion>(Target);
- if (CE->getConstructor()->isTrivial() &&
- CE->getConstructor()->isCopyOrMoveConstructor() &&
- !IsArray) {
- // FIXME: Handle other kinds of trivial constructors as well.
- for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
- I != E; ++I)
- performTrivialCopy(Bldr, *I, *Call);
-
+ if (CE->getConstructor()->isTrivial() && !IsArray) {
+ if (CE->getConstructor()->isCopyOrMoveConstructor()) {
+ for (ExplodedNodeSet::iterator I = DstPreCall.begin(),
+ E = DstPreCall.end();
+ I != E; ++I)
+ performTrivialCopy(Bldr, *I, *Call);
+ } else {
+ assert(CE->getConstructor()->isDefaultConstructor());
+
+ // We still have to bind the return value.
+ for (ExplodedNodeSet::iterator I = DstPreCall.begin(),
+ E = DstPreCall.end();
+ I != E; ++I) {
+ ProgramStateRef State = (*I)->getState();
+ State = bindReturnValue(*Call, LCtx, State);
+ Bldr.generateNode(CE, *I, State);
+ }
+ }
} else {
for (ExplodedNodeSet::iterator I = DstPreCall.begin(), E = DstPreCall.end();
I != E; ++I)
OpenPOWER on IntegriCloud