static analyzer: invalidate by-ref arguments passed to constructors in a 'new' expression.

llvm-svn: 129349
This commit is contained in:
Ted Kremenek 2011-04-12 05:12:39 +00:00
parent 57a4a152b2
commit f52718899f
2 changed files with 47 additions and 3 deletions

View File

@ -268,9 +268,9 @@ void ExprEngine::VisitCXXDestructor(const CXXDestructorDecl *DD,
void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
ExplodedNodeSet &Dst) {
unsigned Count = Builder->getCurrentBlockCount();
unsigned blockCount = Builder->getCurrentBlockCount();
DefinedOrUnknownSVal symVal =
svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), Count);
svalBuilder.getConjuredSymbolVal(NULL, CNE, CNE->getType(), blockCount);
const MemRegion *NewReg = cast<loc::MemRegionVal>(symVal).getRegion();
QualType ObjTy = CNE->getType()->getAs<PointerType>()->getPointeeType();
const ElementRegion *EleReg =
@ -297,11 +297,39 @@ void ExprEngine::VisitCXXNewExpr(const CXXNewExpr *CNE, ExplodedNode *Pred,
// Initialize the object region and bind the 'new' expression.
for (ExplodedNodeSet::iterator I = argsEvaluated.begin(),
E = argsEvaluated.end(); I != E; ++I) {
const GRState *state = GetState(*I);
// Accumulate list of regions that are invalidated.
// FIXME: Eventually we should unify the logic for constructor
// processing in one place.
llvm::SmallVector<const MemRegion*, 10> regionsToInvalidate;
for (CXXNewExpr::const_arg_iterator
ai = CNE->constructor_arg_begin(), ae = CNE->constructor_arg_end();
ai != ae; ++ai)
{
SVal val = state->getSVal(*ai);
if (const MemRegion *region = val.getAsRegion())
regionsToInvalidate.push_back(region);
}
if (ObjTy->isRecordType()) {
state = state->invalidateRegion(EleReg, CNE, Count);
regionsToInvalidate.push_back(EleReg);
// Invalidate the regions.
state = state->invalidateRegions(regionsToInvalidate.data(),
regionsToInvalidate.data() +
regionsToInvalidate.size(),
CNE, blockCount, 0,
/* invalidateGlobals = */ true);
} else {
// Invalidate the regions.
state = state->invalidateRegions(regionsToInvalidate.data(),
regionsToInvalidate.data() +
regionsToInvalidate.size(),
CNE, blockCount, 0,
/* invalidateGlobals = */ true);
if (CNE->hasInitializer()) {
SVal V = state->getSVal(*CNE->constructor_arg_begin());
state = state->bindLoc(loc::MemRegionVal(EleReg), V);

View File

@ -378,4 +378,20 @@ char *RDar9269695(char *dst, unsigned int n)
return dst;
}
// Test that we invalidate byref arguments passed to constructors.
class TestInvalidateInCtor {
public:
TestInvalidateInCtor(unsigned &x);
};
unsigned test_invalidate_in_ctor() {
unsigned x;
TestInvalidateInCtor foo(x);
return x; // no-warning
}
unsigned test_invalidate_in_ctor_new() {
unsigned x;
delete (new TestInvalidateInCtor(x));
return x; // no-warning
}