Files
llvm-project/clang/test/Analysis/iterators.cpp
Chandler Carruth e3fcb6981f Switch these two tests to use the Clang driver instead of CC1. They want
to do "realistic" includes, and so need the header search logic now in
the driver. This in turn requires switching the CC1 options to the
actual driver options, and passing -Xclang where there is no analogy.

llvm-svn: 143805
2011-11-05 10:15:30 +00:00

106 lines
3.5 KiB
C++

// RUN: %clang --analyze -Xclang -analyzer-checker=core,experimental.cplusplus.Iterators -Xclang -verify %s
// XFAIL: win32
#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}}
}