diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngine.cpp')
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 60 |
1 files changed, 36 insertions, 24 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp index 09cd02701e..cc244a56a3 100644 --- a/lib/StaticAnalyzer/Core/ExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp @@ -358,43 +358,42 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init, ExplodedNodeSet Dst; NodeBuilder Bldr(Pred, Dst, *currentBuilderContext); + ProgramStateRef State = Pred->getState(); + // We don't set EntryNode and currentStmt. And we don't clean up state. const CXXCtorInitializer *BMI = Init.getInitializer(); const StackFrameContext *stackFrame = cast<StackFrameContext>(Pred->getLocationContext()); const CXXConstructorDecl *decl = cast<CXXConstructorDecl>(stackFrame->getDecl()); - SVal thisVal = Pred->getState()->getSVal(svalBuilder.getCXXThis(decl, - stackFrame)); + SVal thisVal = State->getSVal(svalBuilder.getCXXThis(decl, stackFrame)); + // Evaluate the initializer, if necessary if (BMI->isAnyMemberInitializer()) { - // Evaluate the initializer. - ProgramStateRef state = Pred->getState(); - - const FieldDecl *FD = BMI->getAnyMember(); - - // FIXME: This does not work for initializers that call constructors. - SVal FieldLoc = state->getLValue(FD, thisVal); - SVal InitVal = state->getSVal(BMI->getInit(), Pred->getLocationContext()); - state = state->bindLoc(FieldLoc, InitVal); + // Constructors build the object directly in the field, + // but non-objects must be copied in from the initializer. + if (!isa<CXXConstructExpr>(BMI->getInit())) { + SVal FieldLoc; + if (BMI->isIndirectMemberInitializer()) + FieldLoc = State->getLValue(BMI->getIndirectMember(), thisVal); + else + FieldLoc = State->getLValue(BMI->getMember(), thisVal); - // Use a custom node building process. - PostInitializer PP(BMI, stackFrame); - // Builder automatically add the generated node to the deferred set, - // which are processed in the builder's dtor. - Bldr.generateNode(PP, state, Pred); + SVal InitVal = State->getSVal(BMI->getInit(), stackFrame); + State = State->bindLoc(FieldLoc, InitVal); + } } else { assert(BMI->isBaseInitializer()); - // We already did all the work when visiting the CXXConstructExpr. - // Just construct a PostInitializer node so that the diagnostics don't get - // confused. - PostInitializer PP(BMI, stackFrame); - // Builder automatically add the generated node to the deferred set, - // which are processed in the builder's dtor. - Bldr.generateNode(PP, Pred->getState(), Pred); } + // Construct a PostInitializer node whether the state changed or not, + // so that the diagnostics don't get confused. + PostInitializer PP(BMI, stackFrame); + // Builder automatically add the generated node to the deferred set, + // which are processed in the builder's dtor. + Bldr.generateNode(PP, State, Pred); + // Enqueue the new nodes onto the work list. Engine.enqueue(Dst, currentBuilderContext->getBlock(), currentStmtIdx); } @@ -459,7 +458,20 @@ void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D, } void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D, - ExplodedNode *Pred, ExplodedNodeSet &Dst) {} + ExplodedNode *Pred, ExplodedNodeSet &Dst) { + const FieldDecl *Member = D.getFieldDecl(); + ProgramStateRef State = Pred->getState(); + const LocationContext *LCtx = Pred->getLocationContext(); + + const CXXDestructorDecl *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl()); + Loc ThisVal = getSValBuilder().getCXXThis(CurDtor, + LCtx->getCurrentStackFrame()); + SVal FieldVal = State->getLValue(Member, cast<Loc>(State->getSVal(ThisVal))); + + VisitCXXDestructor(Member->getType(), + cast<loc::MemRegionVal>(FieldVal).getRegion(), + CurDtor->getBody(), Pred, Dst); +} void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D, ExplodedNode *Pred, |