From: Jordan Rose Date: Tue, 1 Apr 2014 16:40:06 +0000 (+0000) Subject: [analyzer] Extract a helper for finding the target region for a C++ constructor. X-Git-Url: https://granicus.if.org/sourcecode?a=commitdiff_plain;h=839fe84cab1689ce5f3e4bcd3ba42cd4b5cb298c;p=clang [analyzer] Extract a helper for finding the target region for a C++ constructor. No functionality change. Patch by Alex McCarthy! git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@205328 91177308-0d34-0410-b5e6-96231b3b80d8 --- diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index 5dd16944e7..52fe156e35 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/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 StmtElem = Next.getAs()) { + if (const DeclStmt *DS = dyn_cast(StmtElem->getStmt())) { + if (const VarDecl *Var = dyn_cast(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 InitElem = Next.getAs()) { + const CXXCtorInitializer *Init = InitElem->getInitializer(); + assert(Init->isAnyMemberInitializer()); + + const CXXMethodDecl *CurCtor = cast(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 StmtElem = Next.getAs()) { - if (const DeclStmt *DS = dyn_cast(StmtElem->getStmt())) { - if (const VarDecl *Var = dyn_cast(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 InitElem = Next.getAs()) { - const CXXCtorInitializer *Init = InitElem->getInitializer(); - assert(Init->isAnyMemberInitializer()); - - const CXXMethodDecl *CurCtor = cast(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: