forked from OSchip/llvm-project
106 lines
3.5 KiB
C++
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}}
|
|
}
|
|
|