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.cpp42
1 files changed, 30 insertions, 12 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 107debdd4c4..8e157b1df3f 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -102,6 +102,7 @@ SVal ExprEngine::makeZeroElementRegion(ProgramStateRef State, SVal LValue,
const MemRegion *
ExprEngine::getRegionForConstructedObject(const CXXConstructExpr *CE,
ExplodedNode *Pred,
+ const ConstructionContext *CC,
EvalCallOptions &CallOpts) {
const LocationContext *LCtx = Pred->getLocationContext();
ProgramStateRef State = Pred->getState();
@@ -109,7 +110,7 @@ ExprEngine::getRegionForConstructedObject(const CXXConstructExpr *CE,
// See if we're constructing an existing region by looking at the
// current construction context.
- if (auto CC = getCurrentCFGElement().getAs<CFGConstructor>()) {
+ if (CC) {
if (const Stmt *TriggerStmt = CC->getTriggerStmt()) {
if (const CXXNewExpr *CNE = dyn_cast<CXXNewExpr>(TriggerStmt)) {
if (AMgr.getAnalyzerOptions().mayInlineCXXAllocator()) {
@@ -225,10 +226,20 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
// the entire array).
EvalCallOptions CallOpts;
+ auto C = getCurrentCFGElement().getAs<CFGConstructor>();
+ const ConstructionContext *CC = C ? C->getConstructionContext() : nullptr;
+
+ const CXXBindTemporaryExpr *BTE = nullptr;
switch (CE->getConstructionKind()) {
case CXXConstructExpr::CK_Complete: {
- Target = getRegionForConstructedObject(CE, Pred, CallOpts);
+ Target = getRegionForConstructedObject(CE, Pred, CC, CallOpts);
+ if (CC && AMgr.getAnalyzerOptions().includeTemporaryDtorsInCFG() &&
+ !CallOpts.IsCtorOrDtorWithImproperlyModeledTargetRegion &&
+ CallOpts.IsTemporaryCtorOrDtor) {
+ // May as well be a ReturnStmt.
+ BTE = dyn_cast<CXXBindTemporaryExpr>(CC->getTriggerStmt());
+ }
break;
}
case CXXConstructExpr::CK_VirtualBase:
@@ -296,17 +307,18 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
ExplodedNodeSet DstPreVisit;
getCheckerManager().runCheckersForPreStmt(DstPreVisit, Pred, CE, *this);
+ // FIXME: Is it possible and/or useful to do this before PreStmt?
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();
+ for (ExplodedNodeSet::iterator I = DstPreVisit.begin(),
+ E = DstPreVisit.end();
+ I != E; ++I) {
+ ProgramStateRef State = (*I)->getState();
+ if (CE->requiresZeroInitialization()) {
+ // Type of the zero doesn't matter.
+ SVal ZeroVal = svalBuilder.makeZeroVal(getContext().CharTy);
+
// 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
@@ -320,9 +332,15 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
// since it's then possible to be initializing one part of a multi-
// dimensional array.
State = State->bindDefault(loc::MemRegionVal(Target), ZeroVal, LCtx);
- Bldr.generateNode(CE, *I, State, /*tag=*/nullptr,
- ProgramPoint::PreStmtKind);
}
+
+ if (BTE) {
+ State = addInitializedTemporary(State, BTE, LCtx,
+ cast<CXXTempObjectRegion>(Target));
+ }
+
+ Bldr.generateNode(CE, *I, State, /*tag=*/nullptr,
+ ProgramPoint::PreStmtKind);
}
}
OpenPOWER on IntegriCloud