]> granicus.if.org Git - clang/commitdiff
static analyzer: invalidate by-ref arguments passed to constructors in a 'new' expres...
authorTed Kremenek <kremenek@apple.com>
Tue, 12 Apr 2011 05:12:39 +0000 (05:12 +0000)
committerTed Kremenek <kremenek@apple.com>
Tue, 12 Apr 2011 05:12:39 +0000 (05:12 +0000)
git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@129349 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Core/CXXExprEngine.cpp
test/Analysis/misc-ps-region-store.cpp

index 6365bce05fe35d20d968551189465c79a1ba72f3..e04ba758d8806cad5e3fa945341660e884ae3ae4 100644 (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);
index 1846bdb397648721415cd632b5d82929e5da4474..b122bffaaec0e797e185d620544d06e13c7f2f05 100644 (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
+}