diff options
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 42 |
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); } } |