]> granicus.if.org Git - clang/commitdiff
[Analyzer] Iterator Checker Hotfix: Defer deletion of container data until its last...
authorAdam Balogh <adam.balogh@ericsson.com>
Mon, 30 Jul 2018 08:52:21 +0000 (08:52 +0000)
committerAdam Balogh <adam.balogh@ericsson.com>
Mon, 30 Jul 2018 08:52:21 +0000 (08:52 +0000)
The analyzer may consider a container region as dead while it still has live
iterators. We must defer deletion of the data belonging to such containers
until all its iterators are dead as well to be able to compare the iterator
to the begin and the end of the container which is stored in the container
data.

Differential Revision: https://reviews.llvm.org/D48427

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@338234 91177308-0d34-0410-b5e6-96231b3b80d8

lib/StaticAnalyzer/Checkers/IteratorChecker.cpp

index 56c250cd167839dfb4d9a87d4382fe1d79c8ee69..fc713bc4999f27fffd6348dff0256c4bff140bff 100644 (file)
@@ -291,6 +291,7 @@ const ContainerData *getContainerData(ProgramStateRef State,
                                       const MemRegion *Cont);
 ProgramStateRef setContainerData(ProgramStateRef State, const MemRegion *Cont,
                                  const ContainerData &CData);
+bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont);
 bool isOutOfRange(ProgramStateRef State, const IteratorPosition &Pos);
 bool isZero(ProgramStateRef State, const NonLoc &Val);
 } // namespace
@@ -536,7 +537,11 @@ void IteratorChecker::checkDeadSymbols(SymbolReaper &SR,
   auto ContMap = State->get<ContainerMap>();
   for (const auto Cont : ContMap) {
     if (!SR.isLiveRegion(Cont.first)) {
-      State = State->remove<ContainerMap>(Cont.first);
+      // We must keep the container data while it has live iterators to be able
+      // to compare them to the begin and the end of the container.
+      if (!hasLiveIterators(State, Cont.first)) {
+        State = State->remove<ContainerMap>(Cont.first);
+      }
     }
   }
 
@@ -1188,6 +1193,22 @@ ProgramStateRef relateIteratorPositions(ProgramStateRef State,
   return NewState;
 }
 
+bool hasLiveIterators(ProgramStateRef State, const MemRegion *Cont) {
+  auto RegionMap = State->get<IteratorRegionMap>();
+  for (const auto Reg : RegionMap) {
+    if (Reg.second.getContainer() == Cont)
+      return true;
+  }
+
+  auto SymbolMap = State->get<IteratorSymbolMap>();
+  for (const auto Sym : SymbolMap) {
+    if (Sym.second.getContainer() == Cont)
+      return true;
+  }
+
+  return false;
+}
+
 bool isZero(ProgramStateRef State, const NonLoc &Val) {
   auto &BVF = State->getBasicVals();
   return compare(State, Val,