Add initial version of "IteratorsChecker", a checker to find misues uses of C++ iterators.

This checker was created by Jim Goodnow II, and I migrated it to the
new Checker interface (recent changes by Argiris).

git-svn-id: https://llvm.org/svn/llvm-project/cfe/trunk@127525 91177308-0d34-0410-b5e6-96231b3b80d8
diff --git a/test/Analysis/iterators.cpp b/test/Analysis/iterators.cpp
new file mode 100644
index 0000000..21d108b
--- /dev/null
+++ b/test/Analysis/iterators.cpp
@@ -0,0 +1,104 @@
+// RUN: %clang_cc1 -analyze -analyzer-checker=core,core.experimental.Iterators -verify %s
+
+#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}}
+}
+