diff options
| author | Ted Kremenek <kremenek@apple.com> | 2011-03-12 02:49:15 +0000 | 
|---|---|---|
| committer | Ted Kremenek <kremenek@apple.com> | 2011-03-12 02:49:15 +0000 | 
| commit | f89710b936a825710e16eb6b98a489fcf64a9d9f (patch) | |
| tree | 91c42a784fb39ff10c0bc0f690af707346e67e7b /clang/test/Analysis/iterators.cpp | |
| parent | 52d264cda5a1935752cc4ed6148643a08ac1a6f5 (diff) | |
| download | bcm5719-llvm-f89710b936a825710e16eb6b98a489fcf64a9d9f.tar.gz bcm5719-llvm-f89710b936a825710e16eb6b98a489fcf64a9d9f.zip | |
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).
llvm-svn: 127525
Diffstat (limited to 'clang/test/Analysis/iterators.cpp')
| -rw-r--r-- | clang/test/Analysis/iterators.cpp | 104 | 
1 files changed, 104 insertions, 0 deletions
| diff --git a/clang/test/Analysis/iterators.cpp b/clang/test/Analysis/iterators.cpp new file mode 100644 index 00000000000..21d108bb7eb --- /dev/null +++ b/clang/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}} +} + | 

