aboutsummaryrefslogtreecommitdiff
path: root/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'lib/StaticAnalyzer/Core/ExprEngineCXX.cpp')
-rw-r--r--lib/StaticAnalyzer/Core/ExprEngineCXX.cpp64
1 files changed, 41 insertions, 23 deletions
diff --git a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
index b0f2579cd9..ed90dc5891 100644
--- a/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
+++ b/lib/StaticAnalyzer/Core/ExprEngineCXX.cpp
@@ -96,6 +96,26 @@ void ExprEngine::performTrivialCopy(NodeBuilder &Bldr, ExplodedNode *Pred,
}
}
+
+/// Returns a region representing the first element of a (possibly
+/// multi-dimensional) array.
+///
+/// On return, \p Ty will be set to the base type of the array.
+///
+/// If the type is not an array type at all, the original value is returned.
+static SVal makeZeroElementRegion(ProgramStateRef State, SVal LValue,
+ QualType &Ty) {
+ SValBuilder &SVB = State->getStateManager().getSValBuilder();
+ ASTContext &Ctx = SVB.getContext();
+
+ while (const ArrayType *AT = Ctx.getAsArrayType(Ty)) {
+ Ty = AT->getElementType();
+ LValue = State->getLValue(Ty, SVB.makeZeroArrayIndex(), LValue);
+ }
+
+ return LValue;
+}
+
void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
ExplodedNode *Pred,
ExplodedNodeSet &destNodes) {
@@ -103,7 +123,10 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
ProgramStateRef State = Pred->getState();
const MemRegion *Target = 0;
- bool IsArray = false;
+
+ // FIXME: Handle arrays, which run the same constructor for every element.
+ // For now, we just run the first constructor (which should still invalidate
+ // the entire array).
switch (CE->getConstructionKind()) {
case CXXConstructExpr::CK_Complete: {
@@ -118,19 +141,10 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
if (const DeclStmt *DS = dyn_cast<DeclStmt>(StmtElem->getStmt())) {
if (const VarDecl *Var = dyn_cast<VarDecl>(DS->getSingleDecl())) {
if (Var->getInit()->IgnoreImplicit() == CE) {
+ SVal LValue = State->getLValue(Var, LCtx);
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();
- IsArray = true;
- } else {
- Target = State->getLValue(Var, LCtx).getAsRegion();
- }
+ LValue = makeZeroElementRegion(State, LValue, Ty);
+ Target = LValue.getAsRegion();
}
}
}
@@ -146,13 +160,19 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
LCtx->getCurrentStackFrame());
SVal ThisVal = State->getSVal(ThisPtr);
+ const ValueDecl *Field;
+ SVal FieldVal;
if (Init->isIndirectMemberInitializer()) {
- SVal Field = State->getLValue(Init->getIndirectMember(), ThisVal);
- Target = Field.getAsRegion();
+ Field = Init->getIndirectMember();
+ FieldVal = State->getLValue(Init->getIndirectMember(), ThisVal);
} else {
- SVal Field = State->getLValue(Init->getMember(), ThisVal);
- Target = Field.getAsRegion();
+ Field = Init->getMember();
+ FieldVal = State->getLValue(Init->getMember(), ThisVal);
}
+
+ QualType Ty = Field->getType();
+ FieldVal = makeZeroElementRegion(State, FieldVal, Ty);
+ Target = FieldVal.getAsRegion();
}
// FIXME: This will eventually need to handle new-expressions as well.
@@ -202,6 +222,7 @@ void ExprEngine::VisitCXXConstructExpr(const CXXConstructExpr *CE,
ExplodedNodeSet DstEvaluated;
StmtNodeBuilder Bldr(DstPreCall, DstEvaluated, *currBldrCtx);
+ bool IsArray = isa<ElementRegion>(Target);
if (CE->getConstructor()->isTrivial() &&
CE->getConstructor()->isCopyOrMoveConstructor() &&
!IsArray) {
@@ -234,12 +255,9 @@ void ExprEngine::VisitCXXDestructor(QualType ObjectType,
// 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).
- // This is a loop because of multidimensional arrays.
- while (const ArrayType *AT = getContext().getAsArrayType(ObjectType)) {
- ObjectType = AT->getElementType();
- Dest = State->getLValue(ObjectType, getSValBuilder().makeZeroArrayIndex(),
- loc::MemRegionVal(Dest)).getAsRegion();
- }
+ SVal DestVal = loc::MemRegionVal(Dest);
+ DestVal = makeZeroElementRegion(State, DestVal, ObjectType);
+ Dest = DestVal.getAsRegion();
const CXXRecordDecl *RecordDecl = ObjectType->getAsCXXRecordDecl();
assert(RecordDecl && "Only CXXRecordDecls should have destructors");