From 9d5d308c9be367ec41cc6a89f215d45f675b4617 Mon Sep 17 00:00:00 2001 From: Ted Kremenek Date: Tue, 12 Apr 2011 05:12:39 +0000 Subject: [PATCH] static analyzer: invalidate by-ref arguments passed to constructors in a 'new' expression. git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129349 91177308-0d34-0410-b5e6-96231b3b80d8 --- lib/StaticAnalyzer/Core/CXXExprEngine.cpp | 34 +++++++++++++++++++++-- test/Analysis/misc-ps-region-store.cpp | 16 +++++++++++ 2 files changed, 47 insertions(+), 3 deletions(-) diff --git a/lib/StaticAnalyzer/Core/CXXExprEngine.cpp b/lib/StaticAnalyzer/Core/CXXExprEngine.cpp index 6365bce05f..e04ba758d8 100644 --- a/lib/StaticAnalyzer/Core/CXXExprEngine.cpp +++ b/lib/StaticAnalyzer/Core/CXXExprEngine.cpp @@ -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(symVal).getRegion(); QualType ObjTy = CNE->getType()->getAs()->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 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); diff --git a/test/Analysis/misc-ps-region-store.cpp b/test/Analysis/misc-ps-region-store.cpp index 1846bdb397..b122bffaae 100644 --- a/test/Analysis/misc-ps-region-store.cpp +++ b/test/Analysis/misc-ps-region-store.cpp @@ -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 +} -- 2.40.0