forked from OSchip/llvm-project
static analyzer: invalidate by-ref arguments passed to constructors in a 'new' expression.
llvm-svn: 129349
This commit is contained in:
parent
57a4a152b2
commit
f52718899f
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue