Commit b198f16e authored by Adam Balogh's avatar Adam Balogh
Browse files

[Analyzer] Model STL Algoirthms to improve the iterator checkers

STL Algorithms are usually implemented in a tricky for performance
reasons which is too complicated for the analyzer. Furthermore inlining
them is costly. Instead of inlining we should model their behavior
according to the specifications.

This patch is the first step towards STL Algorithm modeling. It models
all the `find()`-like functions in a simple way: the result is either
found or not. In the future it can be extended to only return success if
container modeling is also extended in a way the it keeps track of
trivial insertions and deletions.

Differential Revision: https://reviews.llvm.org/D70818
parent 307e0d54
Loading
Loading
Loading
Loading
+13 −0
Original line number Diff line number Diff line
@@ -622,6 +622,19 @@ def IteratorModeling : Checker<"IteratorModeling">,
  Documentation<NotDocumented>,
  Hidden;

def STLAlgorithmModeling : Checker<"STLAlgorithmModeling">,
  HelpText<"Models the algorithm library of the C++ STL.">,
  CheckerOptions<[
    CmdLineOption<Boolean,
                  "AggressiveStdFindModeling",
                  "Enables exploration of the failure branch in std::find-like "
                  "functions.",
                  "false",
                  Released>
  ]>,
  Dependencies<[ContainerModeling]>,
  Documentation<NotDocumented>;

def InvalidatedIteratorChecker : Checker<"InvalidatedIterator">,
  HelpText<"Check for use of invalidated iterators">,
  Dependencies<[IteratorModeling]>,
+1 −0
Original line number Diff line number Diff line
@@ -99,6 +99,7 @@ add_clang_library(clangStaticAnalyzerCheckers
  SmartPtrModeling.cpp
  StackAddrEscapeChecker.cpp
  StdLibraryFunctionsChecker.cpp
  STLAlgorithmModeling.cpp
  StreamChecker.cpp
  Taint.cpp
  TaintTesterChecker.cpp
+14 −0
Original line number Diff line number Diff line
@@ -177,6 +177,20 @@ ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val,
  return nullptr;
}

ProgramStateRef createIteratorPosition(ProgramStateRef State, const SVal &Val,
                                       const MemRegion *Cont, const Stmt* S,
                                       const LocationContext *LCtx,
                                       unsigned blockCount) {
  auto &StateMgr = State->getStateManager();
  auto &SymMgr = StateMgr.getSymbolManager();
  auto &ACtx = StateMgr.getContext();

  auto Sym = SymMgr.conjureSymbol(S, LCtx, ACtx.LongTy, blockCount);
  State = assumeNoOverflow(State, Sym, 4);
  return setIteratorPosition(State, Val,
                             IteratorPosition::getPosition(Cont, Sym));
}

ProgramStateRef advancePosition(ProgramStateRef State, const SVal &Iter,
                                OverloadedOperatorKind Op,
                                const SVal &Distance) {
+4 −0
Original line number Diff line number Diff line
@@ -159,6 +159,10 @@ const IteratorPosition *getIteratorPosition(ProgramStateRef State,
                                            const SVal &Val);
ProgramStateRef setIteratorPosition(ProgramStateRef State, const SVal &Val,
                                    const IteratorPosition &Pos);
ProgramStateRef createIteratorPosition(ProgramStateRef State, const SVal &Val,
                                       const MemRegion *Cont, const Stmt* S,
                                       const LocationContext *LCtx,
                                       unsigned blockCount);
ProgramStateRef advancePosition(ProgramStateRef State,
                                const SVal &Iter,
                                OverloadedOperatorKind Op,
+3 −6
Original line number Diff line number Diff line
@@ -487,12 +487,9 @@ void IteratorModeling::assignToContainer(CheckerContext &C, const Expr *CE,
  Cont = Cont->getMostDerivedObjectRegion();

  auto State = C.getState();
  auto &SymMgr = C.getSymbolManager();
  auto Sym = SymMgr.conjureSymbol(CE, C.getLocationContext(),
                                  C.getASTContext().LongTy, C.blockCount());
  State = assumeNoOverflow(State, Sym, 4);
  State = setIteratorPosition(State, RetVal,
                              IteratorPosition::getPosition(Cont, Sym));
  const auto *LCtx = C.getLocationContext();
  State = createIteratorPosition(State, RetVal, Cont, CE, LCtx, C.blockCount());

  C.addTransition(State);
}

Loading