aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core')
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp60
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp19
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCallAndReturn.cpp8
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;
}