]> granicus.if.org Git - clang/commitdiff
Remove experimental invalid iterators checker from the codebase until we have the...
authorTed Kremenek <kremenek@apple.com>
Wed, 25 Jul 2012 20:02:05 +0000 (20:02 +0000)
committerTed Kremenek <kremenek@apple.com>
Wed, 25 Jul 2012 20:02:05 +0000 (20:02 +0000)
to fix all the issues.  Currently the code is essentially unmaintained and buggy, and
needs major revision (with coupled enhancements to the analyzer core).

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

lib/StaticAnalyzer/Checkers/CMakeLists.txt
lib/StaticAnalyzer/Checkers/Checkers.td
lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp [deleted file]
test/Analysis/iterators.cpp [deleted file]

index 86eb53361a9db98a857de3f4612171f50350d850..16ba5da8b245d1c77170368215de459636bf3706 100644 (file)
@@ -33,7 +33,6 @@ add_clang_library(clangStaticAnalyzerCheckers
   FixedAddressChecker.cpp
   GenericTaintChecker.cpp
   IdempotentOperationChecker.cpp
-  IteratorsChecker.cpp
   LLVMConventionsChecker.cpp
   MacOSKeychainAPIChecker.cpp
   MacOSXAPIChecker.cpp
index 99410def2cae317fb1846b5925f92762503d3088..959c44f60d0f080a44a88e5121d091747faddfa5 100644 (file)
@@ -168,10 +168,6 @@ def ReturnUndefChecker : Checker<"UndefReturn">,
 
 let ParentPackage = CplusplusExperimental in {
 
-def IteratorsChecker : Checker<"Iterators">,
-  HelpText<"Check improper uses of STL vector iterators">,
-  DescFile<"IteratorsChecker.cpp">;
-
 def VirtualCallChecker : Checker<"VirtualCall">,
   HelpText<"Check virtual function calls during construction or destruction">, 
   DescFile<"VirtualCallChecker.cpp">;
diff --git a/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp b/lib/StaticAnalyzer/Checkers/IteratorsChecker.cpp
deleted file mode 100644 (file)
index b0bac33..0000000
+++ /dev/null
@@ -1,603 +0,0 @@
-//=== IteratorsChecker.cpp - Check for Invalidated Iterators ------*- C++ -*----
-//
-//                     The LLVM Compiler Infrastructure
-//
-// This file is distributed under the University of Illinois Open Source
-// License. See LICENSE.TXT for details.
-//
-//===----------------------------------------------------------------------===//
-//
-// This defines IteratorsChecker, a number of small checks for conditions
-// leading to invalid iterators being used.
-// FIXME: Currently only supports 'vector' and 'deque'
-//
-//===----------------------------------------------------------------------===//
-
-#include "clang/AST/DeclTemplate.h"
-#include "clang/Basic/SourceManager.h"
-#include "ClangSACheckers.h"
-#include "clang/StaticAnalyzer/Core/Checker.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/CheckerContext.h"
-#include "clang/StaticAnalyzer/Core/CheckerManager.h"
-#include "clang/StaticAnalyzer/Core/BugReporter/BugType.h"
-#include "clang/StaticAnalyzer/Core/PathSensitive/ProgramStateTrait.h"
-#include "clang/AST/DeclCXX.h"
-#include "clang/AST/ExprCXX.h"
-#include "clang/AST/Type.h"
-#include "clang/AST/PrettyPrinter.h"
-#include "llvm/ADT/SmallPtrSet.h"
-#include "llvm/ADT/StringSwitch.h"
-
-
-using namespace clang;
-using namespace ento;
-
-// This is the state associated with each iterator which includes both the
-// kind of state and the instance used to initialize it.
-// FIXME: add location where invalidated for better error reporting.
-namespace {
-class RefState {
-  enum Kind { BeginValid, EndValid, Invalid, Undefined, Unknown } K;
-  const void *VR;
-
-public:
-  RefState(Kind k, const void *vr) : K(k), VR(vr) {}
-
-  bool isValid() const { return K == BeginValid || K == EndValid; }
-  bool isInvalid() const { return K == Invalid; }
-  bool isUndefined() const { return K == Undefined; }
-  bool isUnknown() const { return K == Unknown; }
-  const MemRegion *getMemRegion() const {
-    if (K == BeginValid || K == EndValid)
-      return(const MemRegion *)VR;
-    return 0;
-  }
-  const MemberExpr *getMemberExpr() const {
-    if (K == Invalid)
-      return(const MemberExpr *)VR;
-    return 0;
-  }
-
-  bool operator==(const RefState &X) const {
-    return K == X.K && VR == X.VR;
-  }
-
-  static RefState getBeginValid(const MemRegion *vr) {
-    assert(vr);
-    return RefState(BeginValid, vr);
-  }
-  static RefState getEndValid(const MemRegion *vr) {
-    assert(vr);
-    return RefState(EndValid, vr);
-  }
-  static RefState getInvalid( const MemberExpr *ME ) {
-    return RefState(Invalid, ME);
-  }
-  static RefState getUndefined( void ) {
-    return RefState(Undefined, 0);
-  }
-  static RefState getUnknown( void ) {
-    return RefState(Unknown, 0);
-  }
-
-  void Profile(llvm::FoldingSetNodeID &ID) const {
-    ID.AddInteger(K);
-    ID.AddPointer(VR);
-  }
-};
-
-enum RefKind { NoKind, VectorKind, VectorIteratorKind };
-
-class IteratorsChecker : 
-    public Checker<check::PreStmt<CXXOperatorCallExpr>,
-                   check::PreStmt<DeclStmt>,
-                   check::PreStmt<CXXMemberCallExpr>,
-                   check::PreStmt<CallExpr> >
-  {
-  // Used when parsing iterators and vectors and deques.
-  BuiltinBug *BT_Invalid, *BT_Undefined, *BT_Incompatible;
-
-public:
-  IteratorsChecker() :
-    BT_Invalid(0), BT_Undefined(0), BT_Incompatible(0)
-  {}
-  static void *getTag() { static int tag; return &tag; }
-    
-  // Checker entry points.
-  void checkPreStmt(const CXXOperatorCallExpr *OCE,
-                    CheckerContext &C) const;
-
-  void checkPreStmt(const DeclStmt *DS,
-                    CheckerContext &C) const;
-
-  void checkPreStmt(const CXXMemberCallExpr *MCE,
-                    CheckerContext &C) const;
-
-  void checkPreStmt(const CallExpr *CE,
-                    CheckerContext &C) const;
-
-private:
-  ProgramStateRef handleAssign(ProgramStateRef state,
-                                   const Expr *lexp,
-                                   const Expr *rexp,
-                                   const LocationContext *LC) const;
-
-  ProgramStateRef handleAssign(ProgramStateRef state,
-                                   const MemRegion *MR,
-                                   const Expr *rexp,
-                                   const LocationContext *LC) const;
-
-  ProgramStateRef invalidateIterators(ProgramStateRef state,
-                                          const MemRegion *MR,
-                                          const MemberExpr *ME) const;
-
-  void checkExpr(CheckerContext &C, const Expr *E) const;
-
-  void checkArgs(CheckerContext &C, const CallExpr *CE) const;
-
-  const MemRegion *getRegion(ProgramStateRef state,
-                             const Expr *E,
-                             const LocationContext *LC) const;
-
-  const DeclRefExpr *getDeclRefExpr(const Expr *E) const;
-};
-
-class IteratorState {
-public:
-  typedef llvm::ImmutableMap<const MemRegion *, RefState> EntryMap;
-};
-} //end anonymous namespace
-
-namespace clang {
-  namespace ento {
-    template <>
-    struct ProgramStateTrait<IteratorState> 
-      : public ProgramStatePartialTrait<IteratorState::EntryMap> {
-      static void *GDMIndex() { return IteratorsChecker::getTag(); }
-    };
-  }
-}
-
-void ento::registerIteratorsChecker(CheckerManager &mgr) {
-  mgr.registerChecker<IteratorsChecker>();
-}
-
-// ===============================================
-// Utility functions used by visitor functions
-// ===============================================
-
-// check a templated type for std::vector or std::deque
-static RefKind getTemplateKind(const NamedDecl *td) {
-  const DeclContext *dc = td->getDeclContext();
-  const NamespaceDecl *nameSpace = dyn_cast<NamespaceDecl>(dc);
-  if (!nameSpace || !isa<TranslationUnitDecl>(nameSpace->getDeclContext())
-      || nameSpace->getName() != "std")
-    return NoKind;
-  
-  StringRef name = td->getName();
-  return llvm::StringSwitch<RefKind>(name)
-    .Cases("vector", "deque", VectorKind)
-    .Default(NoKind);
-}
-
-static RefKind getTemplateKind(const DeclContext *dc) {
-  if (const ClassTemplateSpecializationDecl *td =
-      dyn_cast<ClassTemplateSpecializationDecl>(dc))
-    return getTemplateKind(cast<NamedDecl>(td));
-  return NoKind;
-}
-
-static RefKind getTemplateKind(const TypedefType *tdt) {
-  const TypedefNameDecl *td = tdt->getDecl();
-  RefKind parentKind = getTemplateKind(td->getDeclContext());
-  if (parentKind == VectorKind) {
-    return llvm::StringSwitch<RefKind>(td->getName())
-    .Cases("iterator",
-           "const_iterator",
-           "reverse_iterator", VectorIteratorKind)
-    .Default(NoKind);
-  }
-  return NoKind;
-}
-
-static RefKind getTemplateKind(const TemplateSpecializationType *tsp) {
-  const TemplateName &tname = tsp->getTemplateName();
-  TemplateDecl *td = tname.getAsTemplateDecl();
-  if (!td)
-    return NoKind;
-  return getTemplateKind(td);
-}
-
-static RefKind getTemplateKind(QualType T) {
-  if (const TemplateSpecializationType *tsp = 
-      T->getAs<TemplateSpecializationType>()) {
-    return getTemplateKind(tsp);      
-  }
-  if (const ElaboratedType *ET = dyn_cast<ElaboratedType>(T)) {
-    QualType namedType = ET->getNamedType();
-    if (const TypedefType *tdt = namedType->getAs<TypedefType>()) 
-      return getTemplateKind(tdt);
-    if (const TemplateSpecializationType *tsp = 
-        namedType->getAs<TemplateSpecializationType>()) {
-      return getTemplateKind(tsp);      
-    }
-  }
-  return NoKind;  
-}
-
-// Iterate through our map and invalidate any iterators that were
-// initialized fromt the specified instance MemRegion.
-ProgramStateRef IteratorsChecker::invalidateIterators(ProgramStateRef state,
-                          const MemRegion *MR, const MemberExpr *ME) const {
-  IteratorState::EntryMap Map = state->get<IteratorState>();
-  if (Map.isEmpty())
-    return state;
-
-  // Loop over the entries in the current state.
-  // The key doesn't change, so the map iterators won't change.
-  for (IteratorState::EntryMap::iterator I = Map.begin(), E = Map.end();
-                                                            I != E; ++I) {
-    RefState RS = I.getData();
-    if (RS.getMemRegion() == MR)
-      state = state->set<IteratorState>(I.getKey(), RefState::getInvalid(ME));
-  }
-
-  return state;
-}
-
-// Handle assigning to an iterator where we don't have the LValue MemRegion.
-ProgramStateRef IteratorsChecker::handleAssign(ProgramStateRef state,
-    const Expr *lexp, const Expr *rexp, const LocationContext *LC) const {
-  // Skip the cast if present.
-  if (const MaterializeTemporaryExpr *M 
-                                    = dyn_cast<MaterializeTemporaryExpr>(lexp))
-    lexp = M->GetTemporaryExpr();
-  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(lexp))
-    lexp = ICE->getSubExpr();
-  SVal sv = state->getSVal(lexp, LC);
-  const MemRegion *MR = sv.getAsRegion();
-  if (!MR)
-    return state;
-  RefKind kind = getTemplateKind(lexp->getType());
-
-  // If assigning to a vector, invalidate any iterators currently associated.
-  if (kind == VectorKind)
-    return invalidateIterators(state, MR, 0);
-
-  // Make sure that we are assigning to an iterator.
-  if (getTemplateKind(lexp->getType()) != VectorIteratorKind)
-    return state;
-  return handleAssign(state, MR, rexp, LC);
-}
-
-// handle assigning to an iterator
-ProgramStateRef IteratorsChecker::handleAssign(ProgramStateRef state,
-    const MemRegion *MR, const Expr *rexp, const LocationContext *LC) const {
-  // Assume unknown until we find something definite.
-  state = state->set<IteratorState>(MR, RefState::getUnknown());
-  if (const MaterializeTemporaryExpr *M 
-                                    = dyn_cast<MaterializeTemporaryExpr>(rexp))
-    rexp = M->GetTemporaryExpr();
-  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(rexp))
-    rexp = ICE->getSubExpr();
-  // Need to handle three cases: MemberCall, copy, copy with addition.
-  if (const CallExpr *CE = dyn_cast<CallExpr>(rexp)) {
-    // Handle MemberCall.
-    if (const MemberExpr *ME = dyn_cast<MemberExpr>(CE->getCallee())) {
-      const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ME->getBase());
-      if (!DRE)
-        return state;
-      // Verify that the type is std::vector<T>.
-      if (getTemplateKind(DRE->getType()) != VectorKind)
-          return state;
-      // Now get the MemRegion associated with the instance.
-      const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
-      if (!VD)
-        return state;
-      const MemRegion *IMR = state->getRegion(VD, LC);
-      if (!IMR)
-        return state;
-      // Finally, see if it is one of the calls that will create
-      // a valid iterator and mark it if so, else mark as Unknown.
-      StringRef mName = ME->getMemberDecl()->getName();
-      
-      if (llvm::StringSwitch<bool>(mName)        
-          .Cases("begin", "insert", "erase", true).Default(false)) {
-        return state->set<IteratorState>(MR, RefState::getBeginValid(IMR));
-      }
-      if (mName == "end")
-        return state->set<IteratorState>(MR, RefState::getEndValid(IMR));
-
-      return state->set<IteratorState>(MR, RefState::getUnknown());
-    }
-  }
-  // Handle straight copy from another iterator.
-  if (const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(rexp)) {
-    if (getTemplateKind(DRE->getType()) != VectorIteratorKind)
-      return state;
-    // Now get the MemRegion associated with the instance.
-    const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
-    if (!VD)
-      return state;
-    const MemRegion *IMR = state->getRegion(VD, LC);
-    if (!IMR)
-      return state;
-    // Get the RefState of the iterator being copied.
-    const RefState *RS = state->get<IteratorState>(IMR);
-    if (!RS)
-      return state;
-    // Use it to set the state of the LValue.
-    return state->set<IteratorState>(MR, *RS);
-  }
-  // If we have operator+ or operator- ...
-  if (const CXXOperatorCallExpr *OCE = dyn_cast<CXXOperatorCallExpr>(rexp)) {
-    OverloadedOperatorKind Kind = OCE->getOperator();
-    if (Kind == OO_Plus || Kind == OO_Minus) {
-      // Check left side of tree for a valid value.
-      state = handleAssign( state, MR, OCE->getArg(0), LC);
-      const RefState *RS = state->get<IteratorState>(MR);
-      // If found, return it.
-      if (!RS->isUnknown())
-        return state;
-      // Otherwise return what we find in the right side.
-      return handleAssign(state, MR, OCE->getArg(1), LC);
-    }
-  }
-  // Fall through if nothing matched.
-  return state;
-}
-
-// Iterate through the arguments looking for an Invalid or Undefined iterator.
-void IteratorsChecker::checkArgs(CheckerContext &C, const CallExpr *CE) const {
-  for (CallExpr::const_arg_iterator I = CE->arg_begin(), E = CE->arg_end();
-       I != E; ++I) {
-    checkExpr(C, *I);
-  }
-}
-
-// Get the DeclRefExpr associated with the expression.
-const DeclRefExpr *IteratorsChecker::getDeclRefExpr(const Expr *E) const {
-  // If it is a CXXConstructExpr, need to get the subexpression.
-  if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(E)) {
-    if (CE->getNumArgs()== 1) {
-      CXXConstructorDecl *CD = CE->getConstructor();
-      if (CD->isTrivial())
-        E = CE->getArg(0);
-    }
-  }
-  if (const MaterializeTemporaryExpr *M = dyn_cast<MaterializeTemporaryExpr>(E))
-    E = M->GetTemporaryExpr();
-  if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
-    E = ICE->getSubExpr();
-  // If it isn't one of our types, don't do anything.
-  if (getTemplateKind(E->getType()) != VectorIteratorKind)
-    return NULL;
-  return dyn_cast<DeclRefExpr>(E);
-}
-
-// Get the MemRegion associated with the expresssion.
-const MemRegion *IteratorsChecker::getRegion(ProgramStateRef state,
-    const Expr *E, const LocationContext *LC) const {
-  const DeclRefExpr *DRE = getDeclRefExpr(E);
-  if (!DRE)
-    return NULL;
-  const VarDecl *VD = dyn_cast<VarDecl>(DRE->getDecl());
-  if (!VD)
-    return NULL;
-  // return the MemRegion associated with the iterator
-  return state->getRegion(VD, LC);
-}
-
-// Check the expression and if it is an iterator, generate a diagnostic
-// if the iterator is not valid.
-// FIXME: this method can generate new nodes, and subsequent logic should
-// use those nodes.  We also cannot create multiple nodes at one ProgramPoint
-// with the same tag.
-void IteratorsChecker::checkExpr(CheckerContext &C, const Expr *E) const {
-  ProgramStateRef state = C.getState();
-  const MemRegion *MR = getRegion(state, E, C.getLocationContext());
-  if (!MR)
-    return;
-
-  // Get the state associated with the iterator.
-  const RefState *RS = state->get<IteratorState>(MR);
-  if (!RS)
-    return;
-  if (RS->isInvalid()) {
-    if (ExplodedNode *N = C.addTransition()) {
-      if (!BT_Invalid)
-        // FIXME: We are eluding constness here.
-        const_cast<IteratorsChecker*>(this)->BT_Invalid = new BuiltinBug("");
-
-      std::string msg;
-      const MemberExpr *ME = RS->getMemberExpr();
-      if (ME) {
-        std::string name = ME->getMemberNameInfo().getAsString();
-        msg = "Attempt to use an iterator made invalid by call to '" +
-                                                                  name + "'";
-      }
-      else {
-        msg = "Attempt to use an iterator made invalid by copying another "
-                    "container to its container";
-      }
-
-      BugReport *R = new BugReport(*BT_Invalid, msg, N);
-      R->addRange(getDeclRefExpr(E)->getSourceRange());
-      C.EmitReport(R);
-    }
-  }
-  else if (RS->isUndefined()) {
-    if (ExplodedNode *N = C.addTransition()) {
-      if (!BT_Undefined)
-        // FIXME: We are eluding constness here.
-        const_cast<IteratorsChecker*>(this)->BT_Undefined =
-          new BuiltinBug("Use of iterator that is not defined");
-
-      BugReport *R = new BugReport(*BT_Undefined,
-                                           BT_Undefined->getDescription(), N);
-      R->addRange(getDeclRefExpr(E)->getSourceRange());
-      C.EmitReport(R);
-    }
-  }
-}
-
-// ===============================================
-// Path analysis visitor functions
-// ===============================================
-
-// For a generic Call, just check the args for bad iterators.
-void IteratorsChecker::checkPreStmt(const CallExpr *CE,
-                                    CheckerContext &C) const{
-  
-  // FIXME: These checks are to currently work around a bug
-  // in CheckerManager.
-  if (isa<CXXOperatorCallExpr>(CE))
-    return;
-  if (isa<CXXMemberCallExpr>(CE))
-    return;
-
-  checkArgs(C, CE);
-}
-
-// Handle operator calls. First, if it is operator=, check the argument,
-// and handle assigning and set target state appropriately. Otherwise, for
-// other operators, check the args for bad iterators and handle comparisons.
-void IteratorsChecker::checkPreStmt(const CXXOperatorCallExpr *OCE,
-                                    CheckerContext &C) const
-{
-  const LocationContext *LC = C.getLocationContext();
-  ProgramStateRef state = C.getState();
-  OverloadedOperatorKind Kind = OCE->getOperator();
-  if (Kind == OO_Equal) {
-    checkExpr(C, OCE->getArg(1));
-    state = handleAssign(state, OCE->getArg(0), OCE->getArg(1), LC);
-    C.addTransition(state);
-    return;
-  }
-  else {
-    checkArgs(C, OCE);
-    // If it is a compare and both are iterators, ensure that they are for
-    // the same container.
-    if (Kind == OO_EqualEqual || Kind == OO_ExclaimEqual ||
-        Kind == OO_Less || Kind == OO_LessEqual ||
-        Kind == OO_Greater || Kind == OO_GreaterEqual) {
-      const MemRegion *MR0, *MR1;
-      MR0 = getRegion(state, OCE->getArg(0), LC);
-      if (!MR0)
-        return;
-      MR1 = getRegion(state, OCE->getArg(1), LC);
-      if (!MR1)
-        return;
-      const RefState *RS0, *RS1;
-      RS0 = state->get<IteratorState>(MR0);
-      if (!RS0)
-        return;
-      RS1 = state->get<IteratorState>(MR1);
-      if (!RS1)
-        return;
-      if (RS0->getMemRegion() != RS1->getMemRegion()) {
-      if (ExplodedNode *N = C.addTransition()) {
-          if (!BT_Incompatible)
-            const_cast<IteratorsChecker*>(this)->BT_Incompatible =
-              new BuiltinBug(
-                      "Cannot compare iterators from different containers");
-
-          BugReport *R = new BugReport(*BT_Incompatible,
-                                        BT_Incompatible->getDescription(), N);
-          R->addRange(OCE->getSourceRange());
-          C.EmitReport(R);
-        }
-      }
-    }
-  }
-}
-
-// Need to handle DeclStmts to pick up initializing of iterators and to mark
-// uninitialized ones as Undefined.
-void IteratorsChecker::checkPreStmt(const DeclStmt *DS,
-                                    CheckerContext &C) const {
-  const Decl *D = *DS->decl_begin();
-  const VarDecl *VD = dyn_cast<VarDecl>(D);
-  // Only care about iterators.
-  if (getTemplateKind(VD->getType()) != VectorIteratorKind)
-    return;
-
-  // Get the MemRegion associated with the iterator and mark it as Undefined.
-  ProgramStateRef state = C.getState();
-  Loc VarLoc = state->getLValue(VD, C.getLocationContext());
-  const MemRegion *MR = VarLoc.getAsRegion();
-  if (!MR)
-    return;
-  state = state->set<IteratorState>(MR, RefState::getUndefined());
-
-  // if there is an initializer, handle marking Valid if a proper initializer
-  const Expr *InitEx = VD->getInit();
-  if (InitEx) {
-    // FIXME: This is too syntactic.  Since 'InitEx' will be analyzed first
-    // it should resolve to an SVal that we can check for validity
-    // *semantically* instead of walking through the AST.
-    if (const CXXConstructExpr *CE = dyn_cast<CXXConstructExpr>(InitEx)) {
-      if (CE->getNumArgs() == 1) {
-        const Expr *E = CE->getArg(0);
-        if (const MaterializeTemporaryExpr *M
-                                        = dyn_cast<MaterializeTemporaryExpr>(E))
-          E = M->GetTemporaryExpr();
-        if (const ImplicitCastExpr *ICE = dyn_cast<ImplicitCastExpr>(E))
-          InitEx = ICE->getSubExpr();
-        state = handleAssign(state, MR, InitEx, C.getLocationContext());
-      }
-    }
-  }
-  C.addTransition(state);
-}
-
-
-namespace { struct CalledReserved {}; }
-namespace clang { namespace ento {
-template<> struct ProgramStateTrait<CalledReserved> 
-    :  public ProgramStatePartialTrait<llvm::ImmutableSet<const MemRegion*> > {
-  static void *GDMIndex() { static int index = 0; return &index; }
-};
-}}
-
-// on a member call, first check the args for any bad iterators
-// then, check to see if it is a call to a function that will invalidate
-// the iterators
-void IteratorsChecker::checkPreStmt(const CXXMemberCallExpr *MCE,
-                                    CheckerContext &C) const {
-  // Check the arguments.
-  checkArgs(C, MCE);
-  const MemberExpr *ME = dyn_cast<MemberExpr>(MCE->getCallee());
-  if (!ME)
-    return;
-  // Make sure we have the right kind of container.
-  const DeclRefExpr *DRE = dyn_cast<DeclRefExpr>(ME->getBase());
-  if (!DRE || getTemplateKind(DRE->getType()) != VectorKind)
-    return;
-  SVal tsv = C.getState()->getSVal(DRE, C.getLocationContext());
-  // Get the MemRegion associated with the container instance.
-  const MemRegion *MR = tsv.getAsRegion();
-  if (!MR)
-    return;
-  // If we are calling a function that invalidates iterators, mark them
-  // appropriately by finding matching instances.
-  ProgramStateRef state = C.getState();
-  StringRef mName = ME->getMemberDecl()->getName();
-  if (llvm::StringSwitch<bool>(mName)
-      .Cases("insert", "reserve", "push_back", true)
-      .Cases("erase", "pop_back", "clear", "resize", true)
-      .Default(false)) {
-    // If there was a 'reserve' call, assume iterators are good.
-    if (!state->contains<CalledReserved>(MR))
-      state = invalidateIterators(state, MR, ME);
-  }
-  // Keep track of instances that have called 'reserve'
-  // note: do this after we invalidate any iterators by calling 
-  // 'reserve' itself.
-  if (mName == "reserve")
-    state = state->add<CalledReserved>(MR);
-  
-  if (state != C.getState())
-    C.addTransition(state);
-}
-
diff --git a/test/Analysis/iterators.cpp b/test/Analysis/iterators.cpp
deleted file mode 100644 (file)
index 709b77a..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-// RUN: %clang --analyze -Xclang -analyzer-checker=core,experimental.cplusplus.Iterators -Xclang -verify %s
-// XFAIL: win32
-
-// FIXME: Does not work with inlined C++ methods.
-// XFAIL: *
-// Crashes due to assertion failure.
-// REQUIRES: asserts
-
-#include <vector>
-
-void fum(std::vector<int>::iterator t);
-
-void foo1()
-{
-  // iterators that are defined but not initialized
-  std::vector<int>::iterator it2;
-  fum(it2); // expected-warning{{Use of iterator that is not defined}}
-  *it2;     // expected-warning{{Use of iterator that is not defined}}
-
-  std::vector<int> v, vv;
-  std::vector<int>::iterator it = v.begin();
-  fum(it);  // no-warning
-  *it;  // no-warning
-  // a valid iterator plus an integer is still valid
-  std::vector<int>::iterator et = it + 3;
-  while(it != et) { // no-warning
-    if (*it == 0) // no-warning
-      *it = 1;  // no-warning
-  }
-  // iterators from different instances Cannot be compared
-  et = vv.end();
-  while(it != et) // expected-warning{{Cannot compare iterators from different containers}}
-    ;
-
-  for( std::vector<int>::iterator it = v.begin(); it != v.end(); it++ ) { // no-warning
-    if (*it == 1) // no-warning
-      *it = 0;  // no-warning
-  }
-
-  // copying a valid iterator results in a valid iterator
-  et = it;  // no-warning
-  *et;  // no-warning
-
-  // any combo of valid iterator plus a constant is still valid
-  et = it + 2;  // no-warning
-  *et;  // no-warning
-  et = 2 + it;  // no-warning
-  *et;  // no-warning
-  et = 2 + 4 + it;  // no-warning
-  *et;  // no-warning
-
-  // calling insert invalidates unless assigned to as result, but still
-  // invalidates other iterators on the same instance
-  it = v.insert( it, 1 ); // no-warning
-  *et;  // expected-warning{{Attempt to use an iterator made invalid by call to 'insert'}}
-  ++it; // no-warning
-
-  // calling erase invalidates the iterator
-  v.erase(it);  // no-warning
-  et = it + 2;  // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
-  et = 2 + it + 2;  // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
-  et = 2 + it;  // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
-  ++it; // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
-  it++; // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
-  *it;  // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
-  it = v.insert( it, 1 ); // expected-warning{{Attempt to use an iterator made invalid by call to 'erase'}}
-  // now valid after return from insert
-  *it;  // no-warning
-}
-
-// work with using namespace
-void foo2()
-{
-  using namespace std;
-
-  vector<int> v;
-  vector<int>::iterator it = v.begin();
-  *it;  // no-warning
-  v.insert( it, 1 );  // no-warning
-  *it;  // expected-warning{{Attempt to use an iterator made invalid by call to 'insert'}}
-  it = v.insert( it, 1 ); // expected-warning{{Attempt to use an iterator made invalid by call to 'insert'}}
-  *it;  // no-warning
-}
-
-// using reserve eliminates some warnings
-void foo3()
-{
-  std::vector<long> v;
-  std::vector<long>::iterator b = v.begin();
-  v.reserve( 100 );
-
-  // iterator assigned before the reserve is still invalidated
-  *b; // expected-warning{{Attempt to use an iterator made invalid by call to 'reserve'}}
-  b = v.begin();
-  v.insert( b, 1 ); // no-warning
-
-  // iterator after assignment is still valid (probably)
-  *b; // no-warning
-}
-
-// check on copying one iterator to another
-void foo4()
-{
-  std::vector<float> v, vv;
-  std::vector<float>::iterator it = v.begin();
-  *it;  // no-warning
-  v = vv;
-  *it;  // expected-warning{{Attempt to use an iterator made invalid by copying another container to its container}}
-}
-