r178518 - [analyzer] Teach invalidateRegions that regions within LazyCompoundVal need to be invalidated

Anna Zaks ganna at apple.com
Mon Apr 1 18:28:24 PDT 2013


Author: zaks
Date: Mon Apr  1 20:28:24 2013
New Revision: 178518

URL: http://llvm.org/viewvc/llvm-project?rev=178518&view=rev
Log:
[analyzer] Teach invalidateRegions that regions within LazyCompoundVal need to be invalidated

Refactor invalidateRegions to take SVals instead of Regions as input and teach RegionStore
about processing LazyCompoundVal as a top-level “escaping” value.

This addresses several false positives that get triggered by the NewDelete checker, but the
underlying issue is reproducible with other checkers as well (for example, MallocChecker).

Modified:
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
    cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
    cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
    cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
    cfe/trunk/test/Analysis/malloc.cpp

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/CallEvent.h Mon Apr  1 20:28:24 2013
@@ -162,11 +162,11 @@ protected:
   }
 
 
-  typedef SmallVectorImpl<const MemRegion *> RegionList;
+  typedef SmallVectorImpl<SVal> ValueList;
 
   /// \brief Used to specify non-argument regions that will be invalidated as a
   /// result of this call.
-  virtual void getExtraInvalidatedRegions(RegionList &Regions) const {}
+  virtual void getExtraInvalidatedValues(ValueList &Values) const {}
 
 public:
   virtual ~CallEvent() {}
@@ -504,7 +504,7 @@ protected:
   BlockCall(const BlockCall &Other) : SimpleCall(Other) {}
   virtual void cloneTo(void *Dest) const { new (Dest) BlockCall(*this); }
 
-  virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+  virtual void getExtraInvalidatedValues(ValueList &Values) const;
 
 public:
   /// \brief Returns the region associated with this instance of the block.
@@ -548,7 +548,7 @@ public:
 /// it is written.
 class CXXInstanceCall : public AnyFunctionCall {
 protected:
-  virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+  virtual void getExtraInvalidatedValues(ValueList &Values) const;
 
   CXXInstanceCall(const CallExpr *CE, ProgramStateRef St,
                   const LocationContext *LCtx)
@@ -731,7 +731,7 @@ protected:
   CXXConstructorCall(const CXXConstructorCall &Other) : AnyFunctionCall(Other){}
   virtual void cloneTo(void *Dest) const { new (Dest) CXXConstructorCall(*this); }
 
-  virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+  virtual void getExtraInvalidatedValues(ValueList &Values) const;
 
 public:
   virtual const CXXConstructExpr *getOriginExpr() const {
@@ -830,7 +830,7 @@ protected:
   ObjCMethodCall(const ObjCMethodCall &Other) : CallEvent(Other) {}
   virtual void cloneTo(void *Dest) const { new (Dest) ObjCMethodCall(*this); }
 
-  virtual void getExtraInvalidatedRegions(RegionList &Regions) const;
+  virtual void getExtraInvalidatedValues(ValueList &Values) const;
 
   /// Check if the selector may have multiple definitions (may have overrides).
   virtual bool canBeOverridenInSubclass(ObjCInterfaceDecl *IDecl,

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/ProgramState.h Mon Apr  1 20:28:24 2013
@@ -250,6 +250,13 @@ public:
                     ArrayRef<const MemRegion *> ConstRegions =
                       ArrayRef<const MemRegion *>()) const;
 
+  ProgramStateRef
+  invalidateRegions(ArrayRef<SVal> Regions, const Expr *E,
+                    unsigned BlockCount, const LocationContext *LCtx,
+                    bool CausesPointerEscape, InvalidatedSymbols *IS = 0,
+                    const CallEvent *Call = 0,
+                    ArrayRef<SVal> ConstRegions = ArrayRef<SVal>()) const;
+
   /// enterStackFrame - Returns the state for entry to the given stack frame,
   ///  preserving the current state.
   ProgramStateRef enterStackFrame(const CallEvent &Call,
@@ -419,15 +426,16 @@ private:
   friend void ProgramStateRetain(const ProgramState *state);
   friend void ProgramStateRelease(const ProgramState *state);
 
+  /// \sa invalidateValues()
   /// \sa invalidateRegions()
   ProgramStateRef
-  invalidateRegionsImpl(ArrayRef<const MemRegion *> Regions,
+  invalidateRegionsImpl(ArrayRef<SVal> Values,
                         const Expr *E, unsigned BlockCount,
                         const LocationContext *LCtx,
                         bool ResultsInSymbolEscape,
                         InvalidatedSymbols &IS,
                         const CallEvent *Call,
-                        ArrayRef<const MemRegion *> ConstRegions) const;
+                        ArrayRef<SVal> ConstValues) const;
 };
 
 //===----------------------------------------------------------------------===//

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/SVals.h Mon Apr  1 20:28:24 2013
@@ -544,7 +544,8 @@ private:
 };
 
 } // end ento::loc namespace
-} // end GR namespace
+
+} // end ento namespace
 
 } // end clang namespace
 

Modified: cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h (original)
+++ cfe/trunk/include/clang/StaticAnalyzer/Core/PathSensitive/Store.h Mon Apr  1 20:28:24 2013
@@ -178,30 +178,40 @@ public:
   ///  invalidate additional regions that may have changed based on accessing
   ///  the given regions. Optionally, invalidates non-static globals as well.
   /// \param[in] store The initial store
-  /// \param[in] Regions The regions to invalidate.
+  /// \param[in] Values The values to invalidate.
+  /// \param[in] ConstValues The values to invalidate; these are known to be
+  ///   const, so only regions accesible from them should be invalidated.
   /// \param[in] E The current statement being evaluated. Used to conjure
   ///   symbols to mark the values of invalidated regions.
   /// \param[in] Count The current block count. Used to conjure
   ///   symbols to mark the values of invalidated regions.
-  /// \param[in,out] IS A set to fill with any symbols that are no longer
-  ///   accessible. Pass \c NULL if this information will not be used.
   /// \param[in] Call The call expression which will be used to determine which
   ///   globals should get invalidated.
+  /// \param[in,out] IS A set to fill with any symbols that are no longer
+  ///   accessible. Pass \c NULL if this information will not be used.
   /// \param[in,out] ConstIS A set to fill with any symbols corresponding to
-  ///   the ConstRegions.
+  ///   the ConstValues.
+  /// \param[in,out] InvalidatedTopLevel A vector to fill with regions
+  ////  explicitely being invalidated. Pass \c NULL if this
+  ///   information will not be used.
+  /// \param[in,out] InvalidatedTopLevelConst A vector to fill with const 
+  ////  regions explicitely being invalidated. Pass \c NULL if this
+  ///   information will not be used.
   /// \param[in,out] Invalidated A vector to fill with any regions being
   ///   invalidated. This should include any regions explicitly invalidated
   ///   even if they do not currently have bindings. Pass \c NULL if this
   ///   information will not be used.
   virtual StoreRef invalidateRegions(Store store,
-                                     ArrayRef<const MemRegion *> Regions,
-                                     const Expr *E, unsigned Count,
-                                     const LocationContext *LCtx,
-                                     InvalidatedSymbols &IS,
-                                     const CallEvent *Call,
-                                     ArrayRef<const MemRegion *> ConstRegions,
-                                     InvalidatedSymbols &ConstIS,
-                                     InvalidatedRegions *Invalidated) = 0;
+                                  ArrayRef<SVal> Values,
+                                  ArrayRef<SVal> ConstValues,
+                                  const Expr *E, unsigned Count,
+                                  const LocationContext *LCtx,
+                                  const CallEvent *Call,
+                                  InvalidatedSymbols &IS,
+                                  InvalidatedSymbols &ConstIS,
+                                  InvalidatedRegions *InvalidatedTopLevel,
+                                  InvalidatedRegions *InvalidatedTopLevelConst,
+                                  InvalidatedRegions *Invalidated) = 0;
 
   /// enterStackFrame - Let the StoreManager to do something when execution
   /// engine is about to execute into a callee.

Modified: cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/CallEvent.cpp Mon Apr  1 20:28:24 2013
@@ -140,9 +140,10 @@ ProgramStateRef CallEvent::invalidateReg
                                              ProgramStateRef Orig) const {
   ProgramStateRef Result = (Orig ? Orig : getState());
 
-  SmallVector<const MemRegion *, 8> ConstRegions;
-  SmallVector<const MemRegion *, 8> RegionsToInvalidate;
-  getExtraInvalidatedRegions(RegionsToInvalidate);
+  SmallVector<SVal, 8> ConstValues;
+  SmallVector<SVal, 8> ValuesToInvalidate;
+
+  getExtraInvalidatedValues(ValuesToInvalidate);
 
   // Indexes of arguments whose values will be preserved by the call.
   llvm::SmallSet<unsigned, 4> PreserveArgs;
@@ -150,25 +151,21 @@ ProgramStateRef CallEvent::invalidateReg
     findPtrToConstParams(PreserveArgs, *this);
 
   for (unsigned Idx = 0, Count = getNumArgs(); Idx != Count; ++Idx) {
-    const MemRegion *R = getArgSVal(Idx).getAsRegion();
-    if (!R)
-      continue;
-
     // Mark this region for invalidation.  We batch invalidate regions
     // below for efficiency.
     if (PreserveArgs.count(Idx))
-      ConstRegions.push_back(R);
+      ConstValues.push_back(getArgSVal(Idx));
     else
-      RegionsToInvalidate.push_back(R);
+      ValuesToInvalidate.push_back(getArgSVal(Idx));
   }
 
   // Invalidate designated regions using the batch invalidation API.
   // NOTE: Even if RegionsToInvalidate is empty, we may still invalidate
   //  global variables.
-  return Result->invalidateRegions(RegionsToInvalidate, getOriginExpr(),
+  return Result->invalidateRegions(ValuesToInvalidate, getOriginExpr(),
                                    BlockCount, getLocationContext(),
                                    /*CausedByPointerEscape*/ true,
-                                   /*Symbols=*/0, this, ConstRegions);
+                                   /*Symbols=*/0, this, ConstValues);
 }
 
 ProgramPoint CallEvent::getProgramPoint(bool IsPreVisit,
@@ -374,9 +371,8 @@ const FunctionDecl *CXXInstanceCall::get
   return getSVal(CE->getCallee()).getAsFunctionDecl();
 }
 
-void CXXInstanceCall::getExtraInvalidatedRegions(RegionList &Regions) const {
-  if (const MemRegion *R = getCXXThisVal().getAsRegion())
-    Regions.push_back(R);
+void CXXInstanceCall::getExtraInvalidatedValues(ValueList &Values) const {
+  Values.push_back(getCXXThisVal());
 }
 
 SVal CXXInstanceCall::getCXXThisVal() const {
@@ -529,10 +525,10 @@ CallEvent::param_iterator BlockCall::par
   return D->param_end();
 }
 
-void BlockCall::getExtraInvalidatedRegions(RegionList &Regions) const {
+void BlockCall::getExtraInvalidatedValues(ValueList &Values) const {
   // FIXME: This also needs to invalidate captured globals.
   if (const MemRegion *R = getBlockRegion())
-    Regions.push_back(R);
+    Values.push_back(loc::MemRegionVal(R));
 }
 
 void BlockCall::getInitialStackFrameContents(const StackFrameContext *CalleeCtx,
@@ -550,9 +546,9 @@ SVal CXXConstructorCall::getCXXThisVal()
   return UnknownVal();
 }
 
-void CXXConstructorCall::getExtraInvalidatedRegions(RegionList &Regions) const {
+void CXXConstructorCall::getExtraInvalidatedValues(ValueList &Values) const {
   if (Data)
-    Regions.push_back(static_cast<const MemRegion *>(Data));
+    Values.push_back(loc::MemRegionVal(static_cast<const MemRegion *>(Data)));
 }
 
 void CXXConstructorCall::getInitialStackFrameContents(
@@ -604,9 +600,8 @@ CallEvent::param_iterator ObjCMethodCall
 }
 
 void
-ObjCMethodCall::getExtraInvalidatedRegions(RegionList &Regions) const {
-  if (const MemRegion *R = getReceiverSVal().getAsRegion())
-    Regions.push_back(R);
+ObjCMethodCall::getExtraInvalidatedValues(ValueList &Values) const {
+  Values.push_back(getReceiverSVal());
 }
 
 SVal ObjCMethodCall::getSelfSVal() const {

Modified: cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/ProgramState.cpp Mon Apr  1 20:28:24 2013
@@ -141,6 +141,7 @@ ProgramStateRef ProgramState::bindDefaul
 }
 
 typedef ArrayRef<const MemRegion *> RegionList;
+typedef ArrayRef<SVal> ValueList;
 
 ProgramStateRef 
 ProgramState::invalidateRegions(RegionList Regions,
@@ -150,54 +151,92 @@ ProgramState::invalidateRegions(RegionLi
                                 InvalidatedSymbols *IS,
                                 const CallEvent *Call,
                                 RegionList ConstRegions) const {
+  SmallVector<SVal, 8> Values;
+  for (RegionList::const_iterator I = Regions.begin(),
+                                  E = Regions.end(); I != E; ++I)
+    Values.push_back(loc::MemRegionVal(*I));
+
+  SmallVector<SVal, 8> ConstValues;
+  for (RegionList::const_iterator I = ConstRegions.begin(),
+                                  E = ConstRegions.end(); I != E; ++I)
+    ConstValues.push_back(loc::MemRegionVal(*I));
+
   if (!IS) {
     InvalidatedSymbols invalidated;
-    return invalidateRegionsImpl(Regions, E, Count, LCtx,
+    return invalidateRegionsImpl(Values, E, Count, LCtx,
                                  CausedByPointerEscape,
-                                 invalidated, Call, ConstRegions);
+                                 invalidated, Call, ConstValues);
   }
-  return invalidateRegionsImpl(Regions, E, Count, LCtx, CausedByPointerEscape,
-                               *IS, Call, ConstRegions);
+  return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape,
+                               *IS, Call, ConstValues);
 }
 
-ProgramStateRef 
-ProgramState::invalidateRegionsImpl(RegionList Regions,
+ProgramStateRef
+ProgramState::invalidateRegions(ValueList Values,
+                                const Expr *E, unsigned Count,
+                                const LocationContext *LCtx,
+                                bool CausedByPointerEscape,
+                                InvalidatedSymbols *IS,
+                                const CallEvent *Call,
+                                ValueList ConstValues) const {
+  if (!IS) {
+    InvalidatedSymbols invalidated;
+    return invalidateRegionsImpl(Values, E, Count, LCtx,
+                                 CausedByPointerEscape,
+                                 invalidated, Call, ConstValues);
+  }
+  return invalidateRegionsImpl(Values, E, Count, LCtx, CausedByPointerEscape,
+                               *IS, Call, ConstValues);
+}
+
+ProgramStateRef
+ProgramState::invalidateRegionsImpl(ValueList Values,
                                     const Expr *E, unsigned Count,
                                     const LocationContext *LCtx,
                                     bool CausedByPointerEscape,
                                     InvalidatedSymbols &IS,
                                     const CallEvent *Call,
-                                    RegionList ConstRegions) const {
+                                    ValueList ConstValues) const {
   ProgramStateManager &Mgr = getStateManager();
   SubEngine* Eng = Mgr.getOwningEngine();
   InvalidatedSymbols ConstIS;
 
   if (Eng) {
+    StoreManager::InvalidatedRegions TopLevelInvalidated;
+    StoreManager::InvalidatedRegions TopLevelConstInvalidated;
     StoreManager::InvalidatedRegions Invalidated;
     const StoreRef &newStore
-      = Mgr.StoreMgr->invalidateRegions(getStore(), Regions, E, Count, LCtx, IS,
-                                        Call, ConstRegions, ConstIS,
-                                        &Invalidated);
+    = Mgr.StoreMgr->invalidateRegions(getStore(), Values, ConstValues,
+                                      E, Count, LCtx, Call,
+                                      IS, ConstIS,
+                                      &TopLevelInvalidated,
+                                      &TopLevelConstInvalidated,
+                                      &Invalidated);
 
     ProgramStateRef newState = makeWithStore(newStore);
 
     if (CausedByPointerEscape) {
-      newState = Eng->notifyCheckersOfPointerEscape(newState,
-                                               &IS, Regions, Invalidated, Call);
-      if (!ConstRegions.empty()) {
+      newState = Eng->notifyCheckersOfPointerEscape(newState, &IS,
+                                                    TopLevelInvalidated,
+                                                    Invalidated, Call);
+      if (!ConstValues.empty()) {
         StoreManager::InvalidatedRegions Empty;
         newState = Eng->notifyCheckersOfPointerEscape(newState, &ConstIS,
-                                                      ConstRegions, Empty, Call,
+                                                      TopLevelConstInvalidated,
+                                                      Empty, Call,
                                                       true);
       }
     }
 
-    return Eng->processRegionChanges(newState, &IS, Regions, Invalidated, Call);
+    return Eng->processRegionChanges(newState, &IS,
+                                     TopLevelInvalidated, Invalidated,
+                                     Call);
   }
 
   const StoreRef &newStore =
-    Mgr.StoreMgr->invalidateRegions(getStore(), Regions, E, Count, LCtx, IS,
-                                    Call, ConstRegions, ConstIS, NULL);
+  Mgr.StoreMgr->invalidateRegions(getStore(), Values, ConstValues,
+                                  E, Count, LCtx, Call,
+                                  IS, ConstIS, NULL, NULL, NULL);
   return makeWithStore(newStore);
 }
 

Modified: cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp (original)
+++ cfe/trunk/lib/StaticAnalyzer/Core/RegionStore.cpp Mon Apr  1 20:28:24 2013
@@ -318,6 +318,7 @@ public:
 //===----------------------------------------------------------------------===//
 
 namespace {
+class invalidateRegionsWorker;
 
 class RegionStoreManager : public StoreManager {
 public:
@@ -331,6 +332,13 @@ private:
                          SValListTy> LazyBindingsMapTy;
   LazyBindingsMapTy LazyBindingsMap;
 
+  /// \brief A helper used to populate the work list with the given set of
+  /// regions.
+  void populateWorkList(invalidateRegionsWorker &W,
+                        ArrayRef<SVal> Values,
+                        bool IsArrayOfConstRegions,
+                        InvalidatedRegions *TopLevelRegions);
+
 public:
   RegionStoreManager(ProgramStateManager& mgr, const RegionStoreFeatures &f)
     : StoreManager(mgr), Features(f),
@@ -365,14 +373,17 @@ public:
                                            RegionBindingsRef B,
                                            InvalidatedRegions *Invalidated);
 
-  StoreRef invalidateRegions(Store store, ArrayRef<const MemRegion *> Regions,
+  StoreRef invalidateRegions(Store store,
+                             ArrayRef<SVal> Values,
+                             ArrayRef<SVal> ConstValues,
                              const Expr *E, unsigned Count,
                              const LocationContext *LCtx,
-                             InvalidatedSymbols &IS,
                              const CallEvent *Call,
-                             ArrayRef<const MemRegion *> ConstRegions,
+                             InvalidatedSymbols &IS,
                              InvalidatedSymbols &ConstIS,
-                             InvalidatedRegions *Invalidated);
+                             InvalidatedRegions *Invalidated,
+                             InvalidatedRegions *InvalidatedTopLevel,
+                             InvalidatedRegions *InvalidatedTopLevelConst);
 
   bool scanReachableSymbols(Store S, const MemRegion *R,
                             ScanReachableSymbols &Callbacks);
@@ -1062,15 +1073,48 @@ RegionStoreManager::invalidateGlobalRegi
   return B;
 }
 
+void RegionStoreManager::populateWorkList(invalidateRegionsWorker &W,
+                                          ArrayRef<SVal> Values,
+                                          bool IsArrayOfConstRegions,
+                                          InvalidatedRegions *TopLevelRegions) {
+  for (ArrayRef<SVal>::iterator I = Values.begin(),
+                                E = Values.end(); I != E; ++I) {
+    SVal V = *I;
+    if (Optional<nonloc::LazyCompoundVal> LCS =
+        V.getAs<nonloc::LazyCompoundVal>()) {
+
+      const SValListTy &Vals = getInterestingValues(*LCS);
+
+      for (SValListTy::const_iterator I = Vals.begin(),
+                                      E = Vals.end(); I != E; ++I) {
+        // Note: the last argumet is false here because these are
+        // non-top-level regions.
+        if (const MemRegion *R = (*I).getAsRegion())
+          W.AddToWorkList(R, /*IsConst=*/ false);
+      }
+      continue;
+    }
+
+    if (const MemRegion *R = V.getAsRegion()) {
+      if (TopLevelRegions)
+        TopLevelRegions->push_back(R);
+      W.AddToWorkList(R, /*IsConst=*/ IsArrayOfConstRegions);
+      continue;
+    }
+  }
+}
+
 StoreRef
 RegionStoreManager::invalidateRegions(Store store,
-                                      ArrayRef<const MemRegion *> Regions,
+                                      ArrayRef<SVal> Values,
+                                      ArrayRef<SVal> ConstValues,
                                       const Expr *Ex, unsigned Count,
                                       const LocationContext *LCtx,
-                                      InvalidatedSymbols &IS,
                                       const CallEvent *Call,
-                                      ArrayRef<const MemRegion *> ConstRegions,
+                                      InvalidatedSymbols &IS,
                                       InvalidatedSymbols &ConstIS,
+                                      InvalidatedRegions *TopLevelRegions,
+                                      InvalidatedRegions *TopLevelConstRegions,
                                       InvalidatedRegions *Invalidated) {
   RegionBindingsRef B = RegionStoreManager::getRegionBindings(store);
   invalidateRegionsWorker W(*this, StateMgr, B, Ex, Count, LCtx, IS, ConstIS,
@@ -1080,15 +1124,10 @@ RegionStoreManager::invalidateRegions(St
   W.GenerateClusters();
 
   // Add the regions to the worklist.
-  for (ArrayRef<const MemRegion *>::iterator
-       I = Regions.begin(), E = Regions.end(); I != E; ++I)
-    W.AddToWorkList(*I, /*IsConst=*/false);
-
-  for (ArrayRef<const MemRegion *>::iterator I = ConstRegions.begin(),
-                                             E = ConstRegions.end();
-       I != E; ++I) {
-    W.AddToWorkList(*I, /*IsConst=*/true);
-  }
+  populateWorkList(W, Values, /*IsArrayOfConstRegions*/ false,
+                   TopLevelRegions);
+  populateWorkList(W, ConstValues, /*IsArrayOfConstRegions*/ true,
+                   TopLevelConstRegions);
 
   W.RunWorkList();
 

Modified: cfe/trunk/test/Analysis/malloc.cpp
URL: http://llvm.org/viewvc/llvm-project/cfe/trunk/test/Analysis/malloc.cpp?rev=178518&r1=178517&r2=178518&view=diff
==============================================================================
--- cfe/trunk/test/Analysis/malloc.cpp (original)
+++ cfe/trunk/test/Analysis/malloc.cpp Mon Apr  1 20:28:24 2013
@@ -5,7 +5,7 @@ void *malloc(size_t);
 void free(void *);
 void *realloc(void *ptr, size_t size);
 void *calloc(size_t nmemb, size_t size);
-
+char *strdup(const char *s);
 
 void checkThatMallocCheckerIsRunning() {
   malloc(4);
@@ -67,3 +67,36 @@ struct X get() {
   result.a = malloc(4);
   return result; // no-warning
 }
+
+// Ensure that regions accessible through a LazyCompoundVal trigger region escape.
+// Malloc checker used to report leaks for the following two test cases.
+struct Property {
+  char* getterName;
+  Property(char* n)
+  : getterName(n) {}
+
+};
+void append(Property x);
+
+void appendWrapper(char *getterName) {
+  append(Property(getterName));
+}
+void foo(const char* name) {
+  char* getterName = strdup(name);
+  appendWrapper(getterName); // no-warning
+}
+
+struct NestedProperty {
+  Property prop;
+  NestedProperty(Property p)
+  : prop(p) {}
+};
+void appendNested(NestedProperty x);
+
+void appendWrapperNested(char *getterName) {
+  appendNested(NestedProperty(Property(getterName)));
+}
+void fooNested(const char* name) {
+  char* getterName = strdup(name);
+  appendWrapperNested(getterName); // no-warning
+}
\ No newline at end of file





More information about the cfe-commits mailing list