aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/ExprEngine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngine.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngine.cpp81
1 files changed, 28 insertions, 53 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngine.cpp b/lib/StaticAnalyzer/Core/ExprEngine.cpp
index b0edc433c3..09cd02701e 100644
--- a/lib/StaticAnalyzer/Core/ExprEngine.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngine.cpp
@@ -24,7 +24,6 @@
#include "clang/AST/ParentMap.h"
#include "clang/AST/StmtObjC.h"
#include "clang/AST/StmtCXX.h"
-#include "clang/AST/DeclCXX.h"
#include "clang/Basic/Builtins.h"
#include "clang/Basic/SourceManager.h"
#include "clang/Basic/PrettyStackTrace.h"
@@ -357,6 +356,7 @@ void ExprEngine::ProcessStmt(const CFGStmt S,
void ExprEngine::ProcessInitializer(const CFGInitializer Init,
ExplodedNode *Pred) {
ExplodedNodeSet Dst;
+ NodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
// We don't set EntryNode and currentStmt. And we don't clean up state.
const CXXCtorInitializer *BMI = Init.getInitializer();
@@ -369,8 +369,6 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
if (BMI->isAnyMemberInitializer()) {
// Evaluate the initializer.
-
- StmtNodeBuilder Bldr(Pred, Dst, *currentBuilderContext);
ProgramStateRef state = Pred->getState();
const FieldDecl *FD = BMI->getAnyMember();
@@ -384,20 +382,17 @@ void ExprEngine::ProcessInitializer(const CFGInitializer Init,
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, state);
+ Bldr.generateNode(PP, state, Pred);
} else {
assert(BMI->isBaseInitializer());
- // Get the base class declaration.
- const CXXConstructExpr *ctorExpr = cast<CXXConstructExpr>(BMI->getInit());
-
- // Create the base object region.
- SVal baseVal =
- getStoreManager().evalDerivedToBase(thisVal, ctorExpr->getType());
- const MemRegion *baseReg = baseVal.getAsRegion();
- assert(baseReg);
-
- VisitCXXConstructExpr(ctorExpr, baseReg, Pred, Dst);
+ // 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);
}
// Enqueue the new nodes onto the work list.
@@ -439,18 +434,29 @@ void ExprEngine::ProcessAutomaticObjDtor(const CFGAutomaticObjDtor Dtor,
if (const ReferenceType *refType = varType->getAs<ReferenceType>())
varType = refType->getPointeeType();
- const CXXRecordDecl *recordDecl = varType->getAsCXXRecordDecl();
- assert(recordDecl && "get CXXRecordDecl fail");
- const CXXDestructorDecl *dtorDecl = recordDecl->getDestructor();
-
Loc dest = state->getLValue(varDecl, Pred->getLocationContext());
- VisitCXXDestructor(dtorDecl, cast<loc::MemRegionVal>(dest).getRegion(),
+ VisitCXXDestructor(varType, cast<loc::MemRegionVal>(dest).getRegion(),
Dtor.getTriggerStmt(), Pred, Dst);
}
void ExprEngine::ProcessBaseDtor(const CFGBaseDtor D,
- ExplodedNode *Pred, ExplodedNodeSet &Dst) {}
+ ExplodedNode *Pred, ExplodedNodeSet &Dst) {
+ const LocationContext *LCtx = Pred->getLocationContext();
+ ProgramStateRef State = Pred->getState();
+
+ const CXXDestructorDecl *CurDtor = cast<CXXDestructorDecl>(LCtx->getDecl());
+ Loc ThisPtr = getSValBuilder().getCXXThis(CurDtor,
+ LCtx->getCurrentStackFrame());
+ SVal ThisVal = Pred->getState()->getSVal(ThisPtr);
+
+ // Create the base object region.
+ QualType BaseTy = D.getBaseSpecifier()->getType();
+ SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy);
+
+ VisitCXXDestructor(BaseTy, cast<loc::MemRegionVal>(BaseVal).getRegion(),
+ CurDtor->getBody(), Pred, Dst);
+}
void ExprEngine::ProcessMemberDtor(const CFGMemberDtor D,
ExplodedNode *Pred, ExplodedNodeSet &Dst) {}
@@ -459,26 +465,6 @@ void ExprEngine::ProcessTemporaryDtor(const CFGTemporaryDtor D,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {}
-static const VarDecl *findDirectConstruction(const DeclStmt *DS,
- const Expr *Init) {
- for (DeclStmt::const_decl_iterator I = DS->decl_begin(), E = DS->decl_end();
- I != E; ++I) {
- const VarDecl *Var = dyn_cast<VarDecl>(*I);
- if (!Var)
- continue;
- if (Var->getInit() != Init)
- continue;
- // FIXME: We need to decide how copy-elision should work here.
- if (!Var->isDirectInit())
- break;
- if (Var->getType()->isReferenceType())
- break;
- return Var;
- }
-
- return 0;
-}
-
void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
ExplodedNodeSet &DstTop) {
PrettyStackTraceLoc CrashInfo(getContext().getSourceManager(),
@@ -739,20 +725,9 @@ void ExprEngine::Visit(const Stmt *S, ExplodedNode *Pred,
}
case Stmt::CXXTemporaryObjectExprClass:
- case Stmt::CXXConstructExprClass: {
- const CXXConstructExpr *C = cast<CXXConstructExpr>(S);
- const MemRegion *Target = 0;
-
- const LocationContext *LCtx = Pred->getLocationContext();
- const ParentMap &PM = LCtx->getParentMap();
- if (const DeclStmt *DS = dyn_cast_or_null<DeclStmt>(PM.getParent(C)))
- if (const VarDecl *Var = findDirectConstruction(DS, C))
- Target = Pred->getState()->getLValue(Var, LCtx).getAsRegion();
- // If we don't have a destination region, VisitCXXConstructExpr() will
- // create one.
-
+ case Stmt::CXXConstructExprClass: {
Bldr.takeNodes(Pred);
- VisitCXXConstructExpr(C, Target, Pred, Dst);
+ VisitCXXConstructExpr(cast<CXXConstructExpr>(S), Pred, Dst);
Bldr.addNodes(Dst);
break;
}