diff options
author | Jordan Rose <jordan_rose@apple.com> | 2014-04-01 16:40:06 +0000 |
---|---|---|
committer | Jordan Rose <jordan_rose@apple.com> | 2014-04-01 16:40:06 +0000 |
commit | 17f416085916e969a19bda802ad3d2968064a8cd (patch) | |
tree | 9474450ad6e45ceb796f44b427dfc8dc2f988aa5 /clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | |
parent | a78de33494dc8d0201021b6e7d5cd854cd5f00af (diff) | |
download | bcm5719-llvm-17f416085916e969a19bda802ad3d2968064a8cd.tar.gz bcm5719-llvm-17f416085916e969a19bda802ad3d2968064a8cd.zip |
[analyzer] Extract a helper for finding the target region for a C++ constructor.
No functionality change.
Patch by Alex McCarthy!
llvm-svn: 205328
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp')
-rw-r--r-- | clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 121 |
1 files changed, 65 insertions, 56 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 5dd16944e78..52fe156e352 100644 --- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -102,6 +102,70 @@ static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue, return LValue; } + +static const MemRegion *getRegionForConstructedObject( + const CXXConstructExpr *CE, ExplodedNode *Pred, ExprEngine &Eng, + unsigned int CurrStmtIdx) { + const LocationContext *LCtx = Pred->getLocationContext(); + ProgramStateRef State = Pred->getState(); + const NodeBuilderContext &CurrBldrCtx = Eng.getBuilderContext(); + + // See if we're constructing an existing region by looking at the next + // element in the CFG. + const CFGBlock *B = CurrBldrCtx.getBlock(); + if (CurrStmtIdx + 1 < B->size()) { + CFGElement Next = (*B)[CurrStmtIdx+1]; + + // Is this a constructor for a local variable? + if (Optional<CFGStmt> StmtElem = Next.getAs<CFGStmt>()) { + if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt())) { + if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) { + if (Var->getInit()->IgnoreImplicit() == CE) { + SVal LValue = State->getLValue(Var, LCtx); + QualType Ty = Var->getType(); + LValue = makeZeroElementRegion(State, LValue, Ty); + return LValue.getAsRegion(); + } + } + } + } + + // Is this a constructor for a member? + if (Optional<CFGInitializer> InitElem = Next.getAs<CFGInitializer>()) { + const CXXCtorInitializer *Init = InitElem->getInitializer(); + assert(Init->isAnyMemberInitializer()); + + const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); + Loc ThisPtr = Eng.getSValBuilder().getCXXThis(CurCtor, + LCtx->getCurrentStackFrame()); + SVal ThisVal = State->getSVal(ThisPtr); + + const ValueDecl *Field; + SVal FieldVal; + if (Init->isIndirectMemberInitializer()) { + Field = Init->getIndirectMember(); + FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal); + } else { + Field = Init->getMember(); + FieldVal = State->getLValue(Init->getMember(), ThisVal); + } + + QualType Ty = Field->getType(); + FieldVal = makeZeroElementRegion(State, FieldVal, Ty); + return FieldVal.getAsRegion(); + } + + // FIXME: This will eventually need to handle new-expressions as well. + // Don't forget to update the pre-constructor initialization code in + // ExprEngine::VisitCXXConstructExpr. + } + + // If we couldn't find an existing region to construct into, assume we're + // constructing a temporary. + MemRegionManager &MRMgr = Eng.getSValBuilder().getRegionManager(); + return MRMgr.getCXXTempObjectRegion(CE, LCtx); +} + void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, ExplodedNode *Pred, ExplodedNodeSet &destNodes) { @@ -116,62 +180,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, switch (CE->getConstructionKind()) { case CXXConstructExpr::CK_Complete: { - // See if we're constructing an existing region by looking at the next - // element in the CFG. - const CFGBlock *B = currBldrCtx->getBlock(); - if (currStmtIdx + 1 < B->size()) { - CFGElement Next = (*B)[currStmtIdx+1]; - - // Is this a constructor for a local variable? - if (Optional<CFGStmt> StmtElem = Next.getAs<CFGStmt>()) { - if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt())) { - if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) { - if (Var->getInit()->IgnoreImplicit() == CE) { - SVal LValue = State->getLValue(Var, LCtx); - QualType Ty = Var->getType(); - LValue = makeZeroElementRegion(State, LValue, Ty); - Target = LValue.getAsRegion(); - } - } - } - } - - // Is this a constructor for a member? - if (Optional<CFGInitializer> InitElem = Next.getAs<CFGInitializer>()) { - const CXXCtorInitializer *Init = InitElem->getInitializer(); - assert(Init->isAnyMemberInitializer()); - - const CXXMethodDecl *CurCtor = cast<CXXMethodDecl>(LCtx->getDecl()); - Loc ThisPtr = getSValBuilder().getCXXThis(CurCtor, - LCtx->getCurrentStackFrame()); - SVal ThisVal = State->getSVal(ThisPtr); - - const ValueDecl *Field; - SVal FieldVal; - if (Init->isIndirectMemberInitializer()) { - Field = Init->getIndirectMember(); - FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal); - } else { - Field = Init->getMember(); - FieldVal = State->getLValue(Init->getMember(), ThisVal); - } - - QualType Ty = Field->getType(); - FieldVal = makeZeroElementRegion(State, FieldVal, Ty); - Target = FieldVal.getAsRegion(); - } - - // 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 - // constructing a temporary. - if (!Target) { - MemRegionManager &MRMgr = getSValBuilder().getRegionManager(); - Target = MRMgr.getCXXTempObjectRegion(CE, LCtx); - } - + Target = getRegionForConstructedObject(CE, Pred, *this, currStmtIdx); break; } case CXXConstructExpr::CK_VirtualBase: |