diff options
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngine.cpp | 60 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCXX.cpp | 19 | ||||
-rw-r--r-- | lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp | 8 |
3 files changed, 60 insertions, 27 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, diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp index b21928866c..88fba2919e 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp @@ -63,6 +63,25 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE, if (Var->getInit() == CE) Target = State->getLValue(Var, LCtx).getAsRegion(); + // Is this a constructor for a member? + if (const CFGInitializer *InitElem = dyn_cast<CFGInitializer>(&Next)) { + 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); + + if (Init->isIndirectMemberInitializer()) { + SVal Field = State->getLValue(Init->getIndirectMember(), ThisVal); + Target = cast<loc::MemRegionVal>(Field).getRegion(); + } else { + SVal Field = State->getLValue(Init->getMember(), ThisVal); + Target = cast<loc::MemRegionVal>(Field).getRegion(); + } + } + // FIXME: This will eventually need to handle new-expressions as well. } diff --git a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp index 29481c6512..bc6aeaa036 100644 --- a/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp +++ b/lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp @@ -305,13 +305,15 @@ bool ExprEngine::inlineCall(const CallEvent &Call, if (!ADC->getCFGBuildOptions().AddImplicitDtors || !ADC->getCFGBuildOptions().AddInitializers) return false; - // FIXME: This is a hack. We don't handle member or temporary constructors + + // FIXME: This is a hack. We don't handle temporary destructors // right now, so we shouldn't inline their constructors. if (const CXXConstructorCall *Ctor = dyn_cast<CXXConstructorCall>(&Call)) { const CXXConstructExpr *CtorExpr = Ctor->getOriginExpr(); if (CtorExpr->getConstructionKind() == CXXConstructExpr::CK_Complete) - if (!isa<VarRegion>(Ctor->getCXXThisVal().getAsRegion())) - return false; + if (const MemRegion *Target = Ctor->getCXXThisVal().getAsRegion()) + if (!isa<DeclRegion>(Target)) + return false; } break; } |