[analyzer] Use evalBind for C++ new of scalar types.

These types will not have a CXXConstructExpr to do the initialization for
them. Previously we just used a simple call to ProgramState::bindLoc, but
that doesn't trigger proper checker callbacks (like pointer escape).

Found by Anton Yartsev.

llvm-svn: 178160
This commit is contained in:
Jordan Rose 2013-03-27 18:10:35 +00:00
parent b365d40415
commit 3503cb3572
2 changed files with 26 additions and 8 deletions

View File

@ -331,20 +331,23 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
State = State->BindExpr(CNE, LCtx, symVal); State = State->BindExpr(CNE, LCtx, symVal);
} }
Bldr.generateNode(CNE, Pred, State);
// If the type is not a record, we won't have a CXXConstructExpr as an // If the type is not a record, we won't have a CXXConstructExpr as an
// initializer. Copy the value over. // initializer. Copy the value over.
if (const Expr *Init = CNE->getInitializer()) { if (const Expr *Init = CNE->getInitializer()) {
if (!isa<CXXConstructExpr>(Init)) { if (!isa<CXXConstructExpr>(Init)) {
QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType(); assert(Bldr.getResults().size() == 1);
(void)ObjTy; ExplodedNode *TmpN = *Bldr.getResults().begin();
assert(!ObjTy->isRecordType()); Bldr.takeNodes(TmpN);
assert(!CNE->getType()->getPointeeCXXRecordDecl());
SVal Location = State->getSVal(CNE, LCtx); SVal Location = State->getSVal(CNE, LCtx);
if (Optional<Loc> LV = Location.getAs<Loc>()) bool FirstInit = (Location == symVal);
State = State->bindLoc(*LV, State->getSVal(Init, LCtx)); evalBind(Dst, CNE, TmpN, Location, State->getSVal(Init, LCtx), FirstInit);
} }
} }
Bldr.generateNode(CNE, Pred, State);
} }
void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE, void ExprEngine::VisitCXXDeleteExpr(const CXXDeleteExpr *CDE,

View File

@ -76,7 +76,22 @@ struct PtrWrapper {
PtrWrapper *testNewInvalidation() { PtrWrapper *testNewInvalidation() {
// Ensure that we don't consider this a leak. // Ensure that we don't consider this a leak.
return new PtrWrapper(static_cast<int *>(malloc(4))); return new PtrWrapper(static_cast<int *>(malloc(4))); // no-warning
}
void testNewInvalidationPlacement(PtrWrapper *w) {
// Ensure that we don't consider this a leak.
new (w) PtrWrapper(static_cast<int *>(malloc(4))); // no-warning
}
int **testNewInvalidationScalar() {
// Ensure that we don't consider this a leak.
return new (int *)(static_cast<int *>(malloc(4))); // no-warning
}
void testNewInvalidationScalarPlacement(int **p) {
// Ensure that we don't consider this a leak.
new (p) (int *)(static_cast<int *>(malloc(4))); // no-warning
} }
//-------------------------------------------------------------------- //--------------------------------------------------------------------