From cf9ff89663d7fac3759eb2b0bb9030a7bf97e47f Mon Sep 17 00:00:00 2001 From: George Karpenkov Date: Wed, 17 Jan 2018 20:27:26 +0000 Subject: [PATCH] [analyzer] Make isSubRegionOf reflexive All usages of isSubRegionOf separately check for reflexive case, and in any case, set theory tells us that each set is a subset of itself. Differential Revision: https://reviews.llvm.org/D42140 llvm-svn: 322752 --- clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h | 1 + clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp | 2 -- clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp | 2 +- clang/lib/StaticAnalyzer/Core/MemRegion.cpp | 6 +++--- clang/lib/StaticAnalyzer/Core/ProgramState.cpp | 3 +-- clang/lib/StaticAnalyzer/Core/RegionStore.cpp | 4 ++-- 6 files changed, 8 insertions(+), 10 deletions(-) diff --git a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h index 8ab6656..ac214c2 100644 --- a/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h +++ b/clang/include/clang/StaticAnalyzer/Core/PathSensitive/MemRegion.h @@ -103,6 +103,7 @@ public: const MemRegion *getBaseRegion() const; /// Check if the region is a subregion of the given region. + /// Each region is a subregion of itself. virtual bool isSubRegionOf(const MemRegion *R) const; const MemRegion *StripCasts(bool StripBaseCasts = true) const; diff --git a/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp b/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp index 497978f..c6493fe 100644 --- a/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp +++ b/clang/lib/StaticAnalyzer/Checkers/MisusedMovedObjectChecker.cpp @@ -101,8 +101,6 @@ static ProgramStateRef removeFromState(ProgramStateRef State, const MemRegion *Region) { if (!Region) return State; - // Note: The isSubRegionOf function is not reflexive. - State = State->remove(Region); for (auto &E : State->get()) { if (E.first->isSubRegionOf(Region)) State = State->remove(E.first); diff --git a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp index 3eaa20d..6b9aaa6 100644 --- a/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp +++ b/clang/lib/StaticAnalyzer/Core/BugReporterVisitors.cpp @@ -1838,7 +1838,7 @@ UndefOrNullArgVisitor::VisitNode(const ExplodedNode *N, const MemRegion *ArgReg = Call->getArgSVal(Idx).getAsRegion(); // Are we tracking the argument or its subregion? - if ( !ArgReg || (ArgReg != R && !R->isSubRegionOf(ArgReg->StripCasts()))) + if ( !ArgReg || !R->isSubRegionOf(ArgReg->StripCasts())) continue; // Check the function parameter type. diff --git a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp index cb8ba6d..aa54544 100644 --- a/clang/lib/StaticAnalyzer/Core/MemRegion.cpp +++ b/clang/lib/StaticAnalyzer/Core/MemRegion.cpp @@ -103,15 +103,15 @@ MemRegionManager::~MemRegionManager() { //===----------------------------------------------------------------------===// bool SubRegion::isSubRegionOf(const MemRegion* R) const { - const MemRegion* r = getSuperRegion(); - while (r != nullptr) { + const MemRegion* r = this; + do { if (r == R) return true; if (const SubRegion* sr = dyn_cast(r)) r = sr->getSuperRegion(); else break; - } + } while (r != nullptr); return false; } diff --git a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp index 5b6b733..871bbf0 100644 --- a/clang/lib/StaticAnalyzer/Core/ProgramState.cpp +++ b/clang/lib/StaticAnalyzer/Core/ProgramState.cpp @@ -781,8 +781,7 @@ bool ProgramState::isTainted(SymbolRef Sym, TaintTagType Kind) const { // complete. For example, this would not currently identify // overlapping fields in a union as tainted. To identify this we can // check for overlapping/nested byte offsets. - if (Kind == I.second && - (R == I.first || R->isSubRegionOf(I.first))) + if (Kind == I.second && R->isSubRegionOf(I.first)) return true; } } diff --git a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp index e2e69bb..604adde 100644 --- a/clang/lib/StaticAnalyzer/Core/RegionStore.cpp +++ b/clang/lib/StaticAnalyzer/Core/RegionStore.cpp @@ -871,7 +871,7 @@ collectSubRegionBindings(SmallVectorImpl &Bindings, } else if (NextKey.hasSymbolicOffset()) { const MemRegion *Base = NextKey.getConcreteOffsetRegion(); - if (Top->isSubRegionOf(Base)) { + if (Top->isSubRegionOf(Base) && Top != Base) { // Case 3: The next key is symbolic and we just changed something within // its concrete region. We don't know if the binding is still valid, so // we'll be conservative and include it. @@ -881,7 +881,7 @@ collectSubRegionBindings(SmallVectorImpl &Bindings, } else if (const SubRegion *BaseSR = dyn_cast(Base)) { // Case 4: The next key is symbolic, but we changed a known // super-region. In this case the binding is certainly included. - if (Top == Base || BaseSR->isSubRegionOf(Top)) + if (BaseSR->isSubRegionOf(Top)) if (isCompatibleWithFields(NextKey, FieldsInSymbolicSubregions)) Bindings.push_back(*I); } -- 2.7.4