summaryrefslogtreecommitdiffstats
path: root/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
diff options
context:
space:
mode:
authorJordan Rose <jordan_rose@apple.com>2012-07-26 20:04:25 +0000
committerJordan Rose <jordan_rose@apple.com>2012-07-26 20:04:25 +0000
commit20edae8749c7967718d2f2bfca76b1a6d39eca8f (patch)
treee12266cca834b1c4ea7c42f0bc42a01643898ac2 /clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
parent54529a347e13c789ebb544fdae75a2651085b95f (diff)
downloadbcm5719-llvm-20edae8749c7967718d2f2bfca76b1a6d39eca8f.tar.gz
bcm5719-llvm-20edae8749c7967718d2f2bfca76b1a6d39eca8f.zip
[analyzer] Don't crash on array constructors and destructors.
This workaround is fairly lame: we simulate the first element's constructor and destructor and rely on the region invalidation to "initialize" the rest of the elements. llvm-svn: 160809
Diffstat (limited to 'clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp')
-rw-r--r--clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp43
1 files changed, 34 insertions, 9 deletions
diff --git a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index 88fba2919e8..bb7f8c7596b 100644
--- a/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/clang/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -57,12 +57,27 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
CFGElement Next = (*B)[currentStmtIdx+1];
// Is this a constructor for a local variable?
- if (const CFGStmt *StmtElem = dyn_cast<CFGStmt>(&Next))
- if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt()))
- if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl()))
- if (Var->getInit() == CE)
- Target = State->getLValue(Var, LCtx).getAsRegion();
-
+ if (const CFGStmt *StmtElem = dyn_cast<CFGStmt>(&Next)) {
+ if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt())) {
+ if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) {
+ if (Var->getInit()->IgnoreImplicit() == CE) {
+ QualType Ty = Var->getType();
+ if (const ArrayType *AT = getContext().getAsArrayType(Ty)) {
+ // FIXME: Handle arrays, which run the same constructor for
+ // every element. This workaround will just run the first
+ // constructor (which should still invalidate the entire array).
+ SVal Base = State->getLValue(Var, LCtx);
+ Target = State->getLValue(AT->getElementType(),
+ getSValBuilder().makeZeroArrayIndex(),
+ Base).getAsRegion();
+ } else {
+ 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();
@@ -75,10 +90,10 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
if (Init->isIndirectMemberInitializer()) {
SVal Field = State->getLValue(Init->getIndirectMember(), ThisVal);
- Target = cast<loc::MemRegionVal>(Field).getRegion();
+ Target = Field.getAsRegion();
} else {
SVal Field = State->getLValue(Init->getMember(), ThisVal);
- Target = cast<loc::MemRegionVal>(Field).getRegion();
+ Target = Field.getAsRegion();
}
}
@@ -104,7 +119,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
// Cast to the base type.
QualType BaseTy = CE->getType();
SVal BaseVal = getStoreManager().evalDerivedToBase(ThisVal, BaseTy);
- Target = cast<loc::MemRegionVal>(BaseVal).getRegion();
+ Target = BaseVal.getAsRegion();
}
break;
}
@@ -135,6 +150,16 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType,
const Stmt *S,
ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
+ // FIXME: We need to run the same destructor on every element of the array.
+ // This workaround will just run the first destructor (which will still
+ // invalidate the entire array).
+ if (const ArrayType *AT = getContext().getAsArrayType(ObjectType)) {
+ ObjectType = AT->getElementType();
+ Dest = Pred->getState()->getLValue(ObjectType,
+ getSValBuilder().makeZeroArrayIndex(),
+ loc::MemRegionVal(Dest)).getAsRegion();
+ }
+
const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl();
assert(RecordDecl && "Only CXXRecordDecls should have destructors");
const CXXDestructorDecl *DtorDecl = RecordDecl->getDestructor();
OpenPOWER on IntegriCloud