2053 lines
88 KiB
C++
2053 lines
88 KiB
C++
|
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=false %s -verify -analyzer-config display-checker-name=false
|
||
|
|
||
|
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify -analyzer-config display-checker-name=false
|
||
|
|
||
|
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 -DSTD_ADVANCE_INLINE_LEVEL=0 %s -verify -analyzer-config display-checker-name=false
|
||
|
|
||
|
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 -DSTD_ADVANCE_INLINE_LEVEL=1 %s -verify -analyzer-config display-checker-name=false
|
||
|
|
||
|
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,debug.DebugIteratorModeling,debug.ExprInspection -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 -DSTD_ADVANCE_INLINE_LEVEL=2 %s -verify -analyzer-config display-checker-name=false
|
||
|
|
||
|
// RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorModeling,debug.ExprInspection -analyzer-config aggressive-binary-operation-simplification=true %s 2>&1 | FileCheck %s
|
||
|
|
||
|
#include "Inputs/system-header-simulator-cxx.h"
|
||
|
|
||
|
template <typename Container>
|
||
|
long clang_analyzer_container_begin(const Container&);
|
||
|
template <typename Container>
|
||
|
long clang_analyzer_container_end(const Container&);
|
||
|
template <typename Iterator>
|
||
|
long clang_analyzer_iterator_position(const Iterator&);
|
||
|
long clang_analyzer_iterator_position(int*);
|
||
|
template <typename Iterator>
|
||
|
void* clang_analyzer_iterator_container(const Iterator&);
|
||
|
template <typename Iterator>
|
||
|
bool clang_analyzer_iterator_validity(const Iterator&);
|
||
|
|
||
|
void clang_analyzer_denote(long, const char*);
|
||
|
void clang_analyzer_express(long);
|
||
|
void clang_analyzer_eval(bool);
|
||
|
void clang_analyzer_warnIfReached();
|
||
|
|
||
|
void begin(const std::vector<int> &v) {
|
||
|
auto i = v.begin();
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i) == &v); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.begin(){{$}}}}
|
||
|
|
||
|
if (i != v.begin()) {
|
||
|
clang_analyzer_warnIfReached();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void end(const std::vector<int> &v) {
|
||
|
auto i = v.end();
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i) == &v); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.end(){{$}}}}
|
||
|
|
||
|
if (i != v.end()) {
|
||
|
clang_analyzer_warnIfReached();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void prefix_increment(const std::vector<int> &v) {
|
||
|
auto i = v.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
|
||
|
|
||
|
auto j = ++i;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.begin() + 1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(j)); // expected-warning-re {{$v.begin() + 1{{$}}}}
|
||
|
}
|
||
|
|
||
|
void prefix_decrement(const std::vector<int> &v) {
|
||
|
auto i = v.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
|
||
|
auto j = --i;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.end() - 1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(j)); // expected-warning-re {{$v.end() - 1{{$}}}}
|
||
|
}
|
||
|
|
||
|
void postfix_increment(const std::vector<int> &v) {
|
||
|
auto i = v.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
|
||
|
|
||
|
auto j = i++;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.begin() + 1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(j)); // expected-warning-re {{$v.begin(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void postfix_decrement(const std::vector<int> &v) {
|
||
|
auto i = v.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
|
||
|
auto j = i--;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.end() - 1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(j)); // expected-warning-re {{$v.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void plus_equal(const std::vector<int> &v) {
|
||
|
auto i = v.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
|
||
|
|
||
|
i += 2;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.begin() + 2{{$}}}}
|
||
|
}
|
||
|
|
||
|
void plus_equal_negative(const std::vector<int> &v) {
|
||
|
auto i = v.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
|
||
|
i += -2;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.end() - 2{{$}}}}
|
||
|
}
|
||
|
|
||
|
void minus_equal(const std::vector<int> &v) {
|
||
|
auto i = v.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
|
||
|
i -= 2;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.end() - 2{{$}}}}
|
||
|
}
|
||
|
|
||
|
void minus_equal_negative(const std::vector<int> &v) {
|
||
|
auto i = v.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
|
||
|
|
||
|
i -= -2;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.begin() + 2{{$}}}}
|
||
|
}
|
||
|
|
||
|
void copy(const std::vector<int> &v) {
|
||
|
auto i1 = v.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
|
||
|
auto i2 = i1;
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$v.end(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$v.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void plus_lhs(const std::vector<int> &v) {
|
||
|
auto i1 = v.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
|
||
|
|
||
|
auto i2 = i1 + 2;
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re{{$v.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re{{$v.begin() + 2{{$}}}}
|
||
|
}
|
||
|
|
||
|
void plus_rhs(const std::vector<int> &v) {
|
||
|
auto i1 = v.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
|
||
|
|
||
|
auto i2 = 2 + i1;
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re{{$v.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re{{$v.begin() + 2{{$}}}}
|
||
|
}
|
||
|
|
||
|
void plus_lhs_negative(const std::vector<int> &v) {
|
||
|
auto i1 = v.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
|
||
|
auto i2 = i1 + (-2);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$v.end(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$v.end() - 2{{$}}}}
|
||
|
}
|
||
|
|
||
|
void plus_rhs_negative(const std::vector<int> &v) {
|
||
|
auto i1 = v.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
|
||
|
auto i2 = (-2) + i1;
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$v.end(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$v.end() - 2{{$}}}}
|
||
|
}
|
||
|
|
||
|
void minus(const std::vector<int> &v) {
|
||
|
auto i1 = v.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
|
||
|
auto i2 = i1 - 2;
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$v.end(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$v.end() - 2{{$}}}}
|
||
|
}
|
||
|
|
||
|
void minus_negative(const std::vector<int> &v) {
|
||
|
auto i1 = v.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
|
||
|
|
||
|
auto i2 = i1 - (-2);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &v); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$v.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$v.begin() + 2{{$}}}}
|
||
|
}
|
||
|
|
||
|
void copy_and_increment1(const std::vector<int> &v) {
|
||
|
auto i1 = v.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
|
||
|
|
||
|
auto i2 = i1;
|
||
|
++i1;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$v.begin() + 1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$v.begin(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void copy_and_increment2(const std::vector<int> &v) {
|
||
|
auto i1 = v.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
|
||
|
|
||
|
auto i2 = i1;
|
||
|
++i2;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$v.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$v.begin() + 1{{$}}}}
|
||
|
}
|
||
|
|
||
|
void copy_and_decrement1(const std::vector<int> &v) {
|
||
|
auto i1 = v.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
|
||
|
auto i2 = i1;
|
||
|
--i1;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$v.end() - 1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$v.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void copy_and_decrement2(const std::vector<int> &v) {
|
||
|
auto i1 = v.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
|
||
|
auto i2 = i1;
|
||
|
--i2;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$v.end(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$v.end() - 1{{$}}}}
|
||
|
}
|
||
|
|
||
|
/// std::advance(), std::prev(), std::next()
|
||
|
|
||
|
void std_advance_minus(const std::vector<int> &v) {
|
||
|
auto i = v.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
|
||
|
std::advance(i, -1);
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.end() - 1{{$}}}}
|
||
|
}
|
||
|
|
||
|
void std_advance_plus(const std::vector<int> &v) {
|
||
|
auto i = v.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
|
||
|
|
||
|
std::advance(i, 1);
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning-re {{$v.begin() + 1{{$}}}}
|
||
|
}
|
||
|
|
||
|
void std_prev(const std::vector<int> &v) {
|
||
|
auto i = v.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
|
||
|
auto j = std::prev(i);
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(j)); // expected-warning-re {{$v.end() - 1{{$}}}}
|
||
|
}
|
||
|
|
||
|
void std_prev2(const std::vector<int> &v) {
|
||
|
auto i = v.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(v), "$v.end()");
|
||
|
|
||
|
auto j = std::prev(i, 2);
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(j)); // expected-warning-re {{$v.end() - 2{{$}}}}
|
||
|
}
|
||
|
|
||
|
void std_next(const std::vector<int> &v) {
|
||
|
auto i = v.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
|
||
|
|
||
|
auto j = std::next(i);
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(j)); // expected-warning-re {{$v.begin() + 1{{$}}}}
|
||
|
}
|
||
|
|
||
|
void std_next2(const std::vector<int> &v) {
|
||
|
auto i = v.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(v), "$v.begin()");
|
||
|
|
||
|
auto j = std::next(i, 2);
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(j)); // expected-warning-re {{$v.begin() + 2{{$}}}}
|
||
|
}
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
///
|
||
|
/// C O N T A I N E R A S S I G N M E N T S
|
||
|
///
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
// Copy
|
||
|
|
||
|
void list_copy_assignment(std::list<int> &L1, const std::list<int> &L2) {
|
||
|
auto i0 = L1.cbegin();
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
L1 = L2;
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
void vector_copy_assignment(std::vector<int> &V1, const std::vector<int> &V2) {
|
||
|
auto i0 = V1.cbegin();
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
V1 = V2;
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
void deque_copy_assignment(std::deque<int> &D1, const std::deque<int> &D2) {
|
||
|
auto i0 = D1.cbegin();
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
D1 = D2;
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
void forward_list_copy_assignment(std::forward_list<int> &FL1,
|
||
|
const std::forward_list<int> &FL2) {
|
||
|
auto i0 = FL1.cbegin();
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
FL1 = FL2;
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
// Move
|
||
|
|
||
|
void list_move_assignment(std::list<int> &L1, std::list<int> &L2) {
|
||
|
auto i0 = L1.cbegin(), i1 = L2.cbegin(), i2 = --L2.cend(), i3 = L2.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L2), "$L2.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L2), "$L2.end()");
|
||
|
|
||
|
L1 = std::move(L2);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i3)); //expected-warning{{TRUE}} FIXME: Should be FALSE.
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i1) == &L1); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &L1); // expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L2.begin(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void vector_move_assignment(std::vector<int> &V1, std::vector<int> &V2) {
|
||
|
auto i0 = V1.cbegin(), i1 = V2.cbegin(), i2 = --V2.cend(), i3 = V2.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V2), "$V2.begin()");
|
||
|
|
||
|
V1 = std::move(V2);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i3)); //expected-warning{{TRUE}} FIXME: Should be FALSE.
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i1) == &V1); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &V1); // expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$V2.begin(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void deque_move_assignment(std::deque<int> &D1, std::deque<int> &D2) {
|
||
|
auto i0 = D1.cbegin(), i1 = D2.cbegin(), i2 = --D2.cend(), i3 = D2.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D2), "$D2.begin()");
|
||
|
|
||
|
D1 = std::move(D2);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i3)); //expected-warning{{TRUE}} FIXME: Should be FALSE.
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i1) == &D1); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &D1); // expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$D2.begin(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void forward_list_move_assignment(std::forward_list<int> &FL1,
|
||
|
std::forward_list<int> &FL2) {
|
||
|
auto i0 = FL1.cbegin(), i1 = FL2.cbegin(), i2 = FL2.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(FL2), "$FL2.begin()");
|
||
|
|
||
|
FL1 = std::move(FL2);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}} FIXME: Should be FALSE.
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i1) == &FL1); // expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$FL2.begin(){{$}}}}
|
||
|
}
|
||
|
|
||
|
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
///
|
||
|
/// C O N T A I N E R M O D I F I E R S
|
||
|
///
|
||
|
////////////////////////////////////////////////////////////////////////////////
|
||
|
|
||
|
/// assign()
|
||
|
///
|
||
|
/// - Invalidates all iterators, including the past-the-end iterator for all
|
||
|
/// container types.
|
||
|
|
||
|
void list_assign(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = L.cend();
|
||
|
L.assign(10, n);
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
void vector_assign(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = V.cend();
|
||
|
V.assign(10, n);
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
void deque_assign(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = D.cend();
|
||
|
D.assign(10, n);
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
void forward_list_assign(std::forward_list<int> &FL, int n) {
|
||
|
auto i0 = FL.cbegin(), i1 = FL.cend();
|
||
|
FL.assign(10, n);
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
/// clear()
|
||
|
///
|
||
|
/// - Invalidates all iterators, including the past-the-end iterator for all
|
||
|
/// container types.
|
||
|
|
||
|
void list_clear(std::list<int> &L) {
|
||
|
auto i0 = L.cbegin(), i1 = L.cend();
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
L.clear();
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
void vector_clear(std::vector<int> &V) {
|
||
|
auto i0 = V.cbegin(), i1 = V.cend();
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
V.clear();
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
void deque_clear(std::deque<int> &D) {
|
||
|
auto i0 = D.cbegin(), i1 = D.cend();
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
D.clear();
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
void forward_list_clear(std::forward_list<int> &FL) {
|
||
|
auto i0 = FL.cbegin(), i1 = FL.cend();
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
FL.clear();
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
/// push_back()
|
||
|
///
|
||
|
/// - Design decision: extends containers to the ->RIGHT-> (i.e. the
|
||
|
/// past-the-end position of the container is incremented).
|
||
|
///
|
||
|
/// - Iterator invalidation rules depend the container type.
|
||
|
|
||
|
/// std::list-like containers: No iterators are invalidated.
|
||
|
|
||
|
void list_push_back(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
L.push_back(n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end() - 1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} FIXME: Should be $L.end() + 1
|
||
|
}
|
||
|
|
||
|
/// std::vector-like containers: The past-the-end iterator is invalidated.
|
||
|
|
||
|
void vector_push_back(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
V.push_back(n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$V.end() - 1{{$}}}}
|
||
|
}
|
||
|
|
||
|
/// std::deque-like containers: All iterators, including the past-the-end
|
||
|
/// iterator, are invalidated.
|
||
|
|
||
|
void deque_push_back(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
D.push_back(n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
/// emplace_back()
|
||
|
///
|
||
|
/// - Design decision: extends containers to the ->RIGHT-> (i.e. the
|
||
|
/// past-the-end position of the container is incremented).
|
||
|
///
|
||
|
/// - Iterator invalidation rules depend the container type.
|
||
|
|
||
|
/// std::list-like containers: No iterators are invalidated.
|
||
|
|
||
|
void list_emplace_back(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
L.emplace_back(n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end() - 1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} FIXME: Should be $L.end() + 1
|
||
|
}
|
||
|
|
||
|
/// std::vector-like containers: The past-the-end iterator is invalidated.
|
||
|
|
||
|
void vector_emplace_back(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
V.emplace_back(n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$V.end() - 1{{$}}}}
|
||
|
}
|
||
|
|
||
|
/// std::deque-like containers: All iterators, including the past-the-end
|
||
|
/// iterator, are invalidated.
|
||
|
|
||
|
void deque_emplace_back(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
D.emplace_back(n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
/// pop_back()
|
||
|
///
|
||
|
/// - Design decision: shrinks containers to the <-LEFT<- (i.e. the
|
||
|
/// past-the-end position of the container is decremented).
|
||
|
///
|
||
|
/// - Iterator invalidation rules depend the container type.
|
||
|
|
||
|
/// std::list-like containers: Iterators to the last element are invalidated.
|
||
|
|
||
|
void list_pop_back(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
L.pop_back();
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}} FIXME: Should be $L.end() - 1
|
||
|
}
|
||
|
|
||
|
/// std::vector-like containers: Iterators to the last element, as well as the
|
||
|
/// past-the-end iterator, are invalidated.
|
||
|
|
||
|
void vector_pop_back(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
V.pop_back();
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}}
|
||
|
}
|
||
|
|
||
|
/// std::deque-like containers: Iterators to the last element are invalidated.
|
||
|
/// The past-the-end iterator is also invalidated.
|
||
|
/// Other iterators are not affected.
|
||
|
|
||
|
void deque_pop_back(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
D.pop_back();
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$D.begin(){{$}}}}
|
||
|
}
|
||
|
|
||
|
/// push_front()
|
||
|
///
|
||
|
/// - Design decision: extends containers to the <-LEFT<- (i.e. the first
|
||
|
/// position of the container is decremented).
|
||
|
///
|
||
|
/// - Iterator invalidation rules depend the container type.
|
||
|
|
||
|
/// std::list-like containers: No iterators are invalidated.
|
||
|
|
||
|
void list_push_front(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
L.push_front(n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
/// std::deque-like containers: All iterators, including the past-the-end
|
||
|
/// iterator, are invalidated.
|
||
|
|
||
|
void deque_push_front(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
D.push_front(n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
/// std::forward_list-like containers: No iterators are invalidated.
|
||
|
|
||
|
void forward_list_push_front(std::forward_list<int> &FL, int n) {
|
||
|
auto i0 = FL.cbegin(), i1 = FL.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()");
|
||
|
|
||
|
FL.push_front(n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$FL.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
/// emplace_front()
|
||
|
///
|
||
|
/// - Design decision: extends containers to the <-LEFT<- (i.e. the first
|
||
|
/// position of the container is decremented).
|
||
|
///
|
||
|
/// - Iterator invalidation rules depend the container type.
|
||
|
|
||
|
/// std::list-like containers: No iterators are invalidated.
|
||
|
|
||
|
void list_emplace_front(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
L.emplace_front(n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
/// std::deque-like containers: All iterators, including the past-the-end
|
||
|
/// iterator, are invalidated.
|
||
|
|
||
|
void deque_emplace_front(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
D.emplace_front(n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
}
|
||
|
|
||
|
/// std::forward_list-like containers: No iterators are invalidated.
|
||
|
|
||
|
void forward_list_emplace_front(std::forward_list<int> &FL, int n) {
|
||
|
auto i0 = FL.cbegin(), i1 = FL.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()");
|
||
|
|
||
|
FL.emplace_front(n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$FL.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
/// pop_front()
|
||
|
///
|
||
|
/// - Design decision: shrinks containers to the ->RIGHT-> (i.e. the first
|
||
|
/// position of the container is incremented).
|
||
|
///
|
||
|
/// - Iterator invalidation rules depend the container type.
|
||
|
|
||
|
/// std::list-like containers: Iterators to the first element are invalidated.
|
||
|
|
||
|
void list_pop_front(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = ++L.cbegin(), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
L.pop_front();
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.begin() + 1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
/// std::deque-like containers: Iterators to the first element are invalidated.
|
||
|
/// Other iterators are not affected.
|
||
|
|
||
|
void deque_pop_front(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = ++D.cbegin(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
D.pop_front();
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$D.begin() + 1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$D.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
/// std::forward_list-like containers: Iterators to the first element are
|
||
|
/// invalidated.
|
||
|
|
||
|
void forward_list_pop_front(std::list<int> &FL, int n) {
|
||
|
auto i0 = FL.cbegin(), i1 = ++FL.cbegin(), i2 = FL.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()");
|
||
|
|
||
|
FL.pop_front();
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$FL.begin() + 1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$FL.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
/// insert()
|
||
|
///
|
||
|
/// - Design decision: shifts positions to the <-LEFT<- (i.e. all iterator
|
||
|
/// ahead of the insertion point are decremented; if the
|
||
|
/// relation between the insertion point and the first
|
||
|
/// position of the container is known, the first position
|
||
|
/// of the container is also decremented).
|
||
|
///
|
||
|
/// - Iterator invalidation rules depend the container type.
|
||
|
|
||
|
/// std::list-like containers: No iterators are invalidated.
|
||
|
|
||
|
void list_insert_begin(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
auto i2 = L.insert(i0, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $L.begin() - 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void list_insert_behind_begin(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = ++L.cbegin(), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
auto i3 = L.insert(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} FIXME: Should be $L.begin() - 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.begin() + 1{{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.begin()
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
template <typename Iter> Iter return_any_iterator(const Iter &It);
|
||
|
|
||
|
void list_insert_unknown(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = return_any_iterator(L.cbegin()), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
clang_analyzer_denote(clang_analyzer_iterator_position(i1), "$i1");
|
||
|
|
||
|
auto i3 = L.insert(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$i1{{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i - 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void list_insert_ahead_of_end(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
auto i3 = L.insert(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end() - 1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.end() - 2
|
||
|
}
|
||
|
|
||
|
void list_insert_end(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
auto i3 = L.insert(i2, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end() - 1{{$}}}} FIXME: should be $L.end() - 2
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.end() - 1
|
||
|
}
|
||
|
|
||
|
/// std::vector-like containers: Only the iterators before the insertion point
|
||
|
/// remain valid. The past-the-end iterator is also
|
||
|
/// invalidated.
|
||
|
|
||
|
void vector_insert_begin(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
auto i2 = V.insert(i0, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $V.begin() - 1
|
||
|
}
|
||
|
|
||
|
void vector_insert_behind_begin(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = ++V.cbegin(), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
auto i3 = V.insert(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} FIXME: Should be $V.begin() - 1
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); // FIXME: expect -warning $V.begin()
|
||
|
}
|
||
|
|
||
|
void vector_insert_unknown(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = return_any_iterator(V.cbegin()), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
clang_analyzer_denote(clang_analyzer_iterator_position(i1), "$i1");
|
||
|
|
||
|
auto i3 = V.insert(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expecte warning $i1 - 1
|
||
|
}
|
||
|
|
||
|
void vector_insert_ahead_of_end(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
auto i3 = V.insert(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.end() - 2
|
||
|
}
|
||
|
|
||
|
void vector_insert_end(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
auto i3 = V.insert(i2, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$V.end() - 1{{$}}}} FIXME: Should be $V.end() - 2
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.end() - 1
|
||
|
}
|
||
|
|
||
|
/// std::deque-like containers: All iterators, including the past-the-end
|
||
|
/// iterator, are invalidated.
|
||
|
|
||
|
void deque_insert_begin(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
auto i2 = D.insert(i0, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $D.begin() - 1
|
||
|
}
|
||
|
|
||
|
void deque_insert_behind_begin(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = ++D.cbegin(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
auto i3 = D.insert(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.begin() - 1
|
||
|
}
|
||
|
|
||
|
void deque_insert_unknown(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = return_any_iterator(D.cbegin()), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
clang_analyzer_denote(clang_analyzer_iterator_position(i1), "$i1");
|
||
|
|
||
|
auto i3 = D.insert(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 - 1
|
||
|
}
|
||
|
|
||
|
void deque_insert_ahead_of_end(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
auto i3 = D.insert(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.end() - 2
|
||
|
}
|
||
|
|
||
|
void deque_insert_end(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
auto i3 = D.insert(i2, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.end() - 1
|
||
|
}
|
||
|
|
||
|
/// insert_after() [std::forward_list-like containers]
|
||
|
///
|
||
|
/// - Design decision: shifts positions to the ->RIGHT-> (i.e. all iterator
|
||
|
/// ahead of the insertion point are incremented; if the
|
||
|
/// relation between the insertion point and the past-the-end
|
||
|
/// position of the container is known, the first position of
|
||
|
/// the container is also incremented).
|
||
|
///
|
||
|
/// - No iterators are invalidated.
|
||
|
|
||
|
void forward_list_insert_after_begin(std::forward_list<int> &FL, int n) {
|
||
|
auto i0 = FL.cbegin(), i1 = FL.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()");
|
||
|
|
||
|
auto i2 = FL.insert_after(i0, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $FL.begin() + 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$FL.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void forward_list_insert_after_behind_begin(std::forward_list<int> &FL, int n) {
|
||
|
auto i0 = FL.cbegin(), i1 = ++FL.cbegin(), i2 = FL.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()");
|
||
|
|
||
|
auto i3 = FL.insert_after(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$FL.begin() + 1{{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $FL.begin() + 2
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$FL.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void forward_list_insert_after_unknown(std::forward_list<int> &FL, int n) {
|
||
|
auto i0 = FL.cbegin(), i1 = return_any_iterator(FL.cbegin()), i2 = FL.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()");
|
||
|
clang_analyzer_denote(clang_analyzer_iterator_position(i1), "$i1");
|
||
|
|
||
|
auto i3 = FL.insert_after(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$i1{{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$FL.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
/// emplace()
|
||
|
///
|
||
|
/// - Design decision: shifts positions to the <-LEFT<- (i.e. all iterator
|
||
|
/// ahead of the emplacement point are decremented; if the
|
||
|
/// relation between the emplacement point and the first
|
||
|
/// position of the container is known, the first position
|
||
|
/// of the container is also decremented).
|
||
|
///
|
||
|
/// - Iterator invalidation rules depend the container type.
|
||
|
|
||
|
/// std::list-like containers: No iterators are invalidated.
|
||
|
|
||
|
void list_emplace_begin(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
auto i2 = L.emplace(i0, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $L.begin() - 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void list_emplace_behind_begin(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = ++L.cbegin(), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
auto i3 = L.emplace(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} FIXME: Should be $L.begin() - 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.begin() + 1{{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.begin()
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
template <typename Iter> Iter return_any_iterator(const Iter &It);
|
||
|
|
||
|
void list_emplace_unknown(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = return_any_iterator(L.cbegin()), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
clang_analyzer_denote(clang_analyzer_iterator_position(i1), "$i1");
|
||
|
|
||
|
auto i3 = L.emplace(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$i1{{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i - 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void list_emplace_ahead_of_end(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
auto i3 = L.emplace(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end() - 1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.end() - 2
|
||
|
}
|
||
|
|
||
|
void list_emplace_end(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
auto i3 = L.emplace(i2, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.end() - 1{{$}}}} FIXME: should be $L.end() - 2
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.end() - 1
|
||
|
}
|
||
|
|
||
|
/// std::vector-like containers: Only the iterators before the emplacement point
|
||
|
/// remain valid. The past-the-end iterator is also
|
||
|
/// invalidated.
|
||
|
|
||
|
void vector_emplace_begin(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
auto i2 = V.emplace(i0, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $V.begin() - 1
|
||
|
}
|
||
|
|
||
|
void vector_emplace_behind_begin(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = ++V.cbegin(), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
auto i3 = V.emplace(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} FIXME: Should be $V.begin() - 1
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); // FIXME: expect -warning $V.begin()
|
||
|
}
|
||
|
|
||
|
void vector_emplace_unknown(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = return_any_iterator(V.cbegin()), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
clang_analyzer_denote(clang_analyzer_iterator_position(i1), "$i1");
|
||
|
|
||
|
auto i3 = V.emplace(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expecte warning $i1 - 1
|
||
|
}
|
||
|
|
||
|
void vector_emplace_ahead_of_end(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
auto i3 = V.emplace(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.end() - 2
|
||
|
}
|
||
|
|
||
|
void vector_emplace_end(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
auto i3 = V.emplace(i2, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$V.end() - 1{{$}}}} FIXME: Should be $V.end() - 2
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.end() - 1
|
||
|
}
|
||
|
|
||
|
/// std::deque-like containers: All iterators, including the past-the-end
|
||
|
/// iterator, are invalidated.
|
||
|
|
||
|
void deque_emplace_begin(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
auto i2 = D.emplace(i0, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $D.begin() - 1
|
||
|
}
|
||
|
|
||
|
void deque_emplace_behind_begin(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = ++D.cbegin(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
auto i3 = D.emplace(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.begin() - 1
|
||
|
}
|
||
|
|
||
|
void deque_emplace_unknown(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = return_any_iterator(D.cbegin()), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
clang_analyzer_denote(clang_analyzer_iterator_position(i1), "$i1");
|
||
|
|
||
|
auto i3 = D.emplace(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 - 1
|
||
|
}
|
||
|
|
||
|
void deque_emplace_ahead_of_end(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
auto i3 = D.emplace(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.end() - 2
|
||
|
}
|
||
|
|
||
|
void deque_emplace_end(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
auto i3 = D.emplace(i2, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.end() - 1
|
||
|
}
|
||
|
|
||
|
/// emplace_after() [std::forward_list-like containers]
|
||
|
///
|
||
|
/// - Design decision: shifts positions to the ->RIGHT-> (i.e. all iterator
|
||
|
/// ahead of the emplacement point are incremented; if the
|
||
|
/// relation between the emplacement point and the
|
||
|
/// past-the-end position of the container is known, the
|
||
|
/// first position of the container is also incremented).
|
||
|
///
|
||
|
/// - No iterators are invalidated.
|
||
|
|
||
|
void forward_list_emplace_after_begin(std::forward_list<int> &FL, int n) {
|
||
|
auto i0 = FL.cbegin(), i1 = FL.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()");
|
||
|
|
||
|
auto i2 = FL.emplace_after(i0, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $FL.begin() + 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$FL.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void forward_list_emplace_after_behind_begin(std::forward_list<int> &FL,
|
||
|
int n) {
|
||
|
auto i0 = FL.cbegin(), i1 = ++FL.cbegin(), i2 = FL.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()");
|
||
|
|
||
|
auto i3 = FL.emplace_after(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$FL.begin() + 1{{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $FL.begin() + 2
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$FL.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void forward_list_emplace_after_unknown(std::forward_list<int> &FL, int n) {
|
||
|
auto i0 = FL.cbegin(), i1 = return_any_iterator(FL.cbegin()), i2 = FL.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()");
|
||
|
clang_analyzer_denote(clang_analyzer_iterator_position(i1), "$i1");
|
||
|
|
||
|
auto i3 = FL.emplace_after(i1, n);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$i1{{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$FL.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
/// erase()
|
||
|
///
|
||
|
/// - Design decision: shifts positions to the ->RIGHT-> (i.e. all iterator
|
||
|
/// ahead of the ereased element are incremented; if the
|
||
|
/// relation between the position of the erased element
|
||
|
/// and the first position of the container is known, the
|
||
|
/// first position of the container is also incremented).
|
||
|
///
|
||
|
/// - Iterator invalidation rules depend the container type.
|
||
|
|
||
|
/// std::list-like containers: Iterators to the erased element are invalidated.
|
||
|
/// Other iterators are not affected.
|
||
|
|
||
|
void list_erase_begin(std::list<int> &L) {
|
||
|
auto i0 = L.cbegin(), i1 = ++L.cbegin(), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
auto i3 = L.erase(i0);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$L.begin() + 1{{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.begin() + 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void list_erase_behind_begin(std::list<int> &L, int n) {
|
||
|
auto i0 = L.cbegin(), i1 = ++L.cbegin(), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
auto i3 = L.erase(i1);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}} FIXME: Should be $L.begin() + 1
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.begin() + 2
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void list_erase_unknown(std::list<int> &L) {
|
||
|
auto i0 = L.cbegin(), i1 = return_any_iterator(L.cbegin()), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
clang_analyzer_denote(clang_analyzer_iterator_position(i1), "$i1");
|
||
|
|
||
|
auto i3 = L.erase(i1);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void list_erase_ahead_of_end(std::list<int> &L) {
|
||
|
auto i0 = L.cbegin(), i1 = --L.cend(), i2 = L.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
|
||
|
|
||
|
auto i3 = L.erase(i1);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$L.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$L.end(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.end()
|
||
|
}
|
||
|
|
||
|
/// std::vector-like containers: Invalidates iterators at or after the point of
|
||
|
/// the erase, including the past-the-end iterator.
|
||
|
|
||
|
void vector_erase_begin(std::vector<int> &V) {
|
||
|
auto i0 = V.cbegin(), i1 = ++V.cbegin(), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
auto i3 = V.erase(i0);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.begin() + 1
|
||
|
}
|
||
|
|
||
|
void vector_erase_behind_begin(std::vector<int> &V, int n) {
|
||
|
auto i0 = V.cbegin(), i1 = ++V.cbegin(), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
auto i3 = V.erase(i1);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}} FIXME: Should be $V.begin() + 1
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.begin() + 2
|
||
|
}
|
||
|
|
||
|
void vector_erase_unknown(std::vector<int> &V) {
|
||
|
auto i0 = V.cbegin(), i1 = return_any_iterator(V.cbegin()), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
clang_analyzer_denote(clang_analyzer_iterator_position(i1), "$i1");
|
||
|
|
||
|
auto i3 = V.erase(i1);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1
|
||
|
}
|
||
|
|
||
|
void vector_erase_ahead_of_end(std::vector<int> &V) {
|
||
|
auto i0 = V.cbegin(), i1 = --V.cend(), i2 = V.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
|
||
|
|
||
|
auto i3 = V.erase(i1);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$V.begin(){{$}}}}
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.end()
|
||
|
}
|
||
|
|
||
|
/// std::deque-like containers: All iterators are invalidated, unless the erased
|
||
|
/// element is at the end or the beginning of the
|
||
|
/// container, in which case only the iterators to
|
||
|
/// the erased element are invalidated. The
|
||
|
/// past-the-end iterator is also invalidated unless
|
||
|
/// the erased element is at the beginning of the
|
||
|
/// container and the last element is not erased.
|
||
|
|
||
|
void deque_erase_begin(std::deque<int> &D) {
|
||
|
auto i0 = D.cbegin(), i1 = ++D.cbegin(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
auto i3 = D.erase(i0);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.begin() + 1
|
||
|
}
|
||
|
|
||
|
void deque_erase_behind_begin(std::deque<int> &D, int n) {
|
||
|
auto i0 = D.cbegin(), i1 = ++D.cbegin(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
auto i3 = D.erase(i1);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.begin() + 2
|
||
|
}
|
||
|
|
||
|
void deque_erase_unknown(std::deque<int> &D) {
|
||
|
auto i0 = D.cbegin(), i1 = return_any_iterator(D.cbegin()), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
clang_analyzer_denote(clang_analyzer_iterator_position(i1), "$i1");
|
||
|
|
||
|
auto i3 = D.erase(i1);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1
|
||
|
}
|
||
|
|
||
|
void deque_erase_ahead_of_end(std::deque<int> &D) {
|
||
|
auto i0 = D.cbegin(), i1 = --D.cend(), i2 = D.cend();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
|
||
|
|
||
|
auto i3 = D.erase(i1);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.end()
|
||
|
}
|
||
|
|
||
|
/// erase_after() [std::forward_list-like containers]
|
||
|
///
|
||
|
/// - Design decision: shifts positions to the <-LEFT<- (i.e. all iterator
|
||
|
/// begind of the ereased element are decremented; if the
|
||
|
/// relation between the position of the erased element
|
||
|
/// and the past-the-end position of the container is known,
|
||
|
/// the past-the-end position of the container is also
|
||
|
/// decremented).
|
||
|
///
|
||
|
/// - Iterators to the erased element are invalidated. Other iterators are not
|
||
|
/// affected.
|
||
|
|
||
|
|
||
|
void forward_list_erase_after_begin(std::forward_list<int> &FL) {
|
||
|
auto i0 = FL.cbegin(), i1 = ++FL.cbegin(), i2 = i1, i3 = FL.cend();
|
||
|
++i2;
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()");
|
||
|
|
||
|
auto i4 = FL.erase_after(i0);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i3)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning-re {{$FL.begin() + 2{{$}}}} FIXME: Should be $FL.begin() + 1
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i4)); FIXME: expect warning $FL.begin() + 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning-re {{$FL.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
void forward_list_erase_after_unknown(std::forward_list<int> &FL) {
|
||
|
auto i0 = FL.cbegin(), i1 = return_any_iterator(FL.cbegin()), i2 = i1,
|
||
|
i3 = i1, i4 = FL.cend();
|
||
|
++i2;
|
||
|
++i3;
|
||
|
++i3;
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(FL), "$FL.begin()");
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(FL), "$FL.end()");
|
||
|
clang_analyzer_denote(clang_analyzer_iterator_position(i1), "$i1");
|
||
|
|
||
|
auto i5 = FL.erase_after(i1);
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i0)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i1)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i2)); //expected-warning{{FALSE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i3)); //expected-warning{{TRUE}}
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_validity(i4)); //expected-warning{{TRUE}}
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning-re {{$FL.begin(){{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning-re {{$i1{{$}}}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning-re {{$i1 + 2{{$}}}} FIXME: Should be $i1 + 1
|
||
|
// clang_analyzer_express(clang_analyzer_iterator_position(i5)); FIXME: expect warning $i1 + 1
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i4)); // expected-warning-re {{$FL.end(){{$}}}}
|
||
|
}
|
||
|
|
||
|
struct simple_iterator_base {
|
||
|
simple_iterator_base();
|
||
|
simple_iterator_base(const simple_iterator_base& rhs);
|
||
|
simple_iterator_base &operator=(const simple_iterator_base& rhs);
|
||
|
virtual ~simple_iterator_base();
|
||
|
bool friend operator==(const simple_iterator_base &lhs,
|
||
|
const simple_iterator_base &rhs);
|
||
|
bool friend operator!=(const simple_iterator_base &lhs,
|
||
|
const simple_iterator_base &rhs);
|
||
|
private:
|
||
|
int *ptr;
|
||
|
};
|
||
|
|
||
|
struct simple_derived_iterator: public simple_iterator_base {
|
||
|
int& operator*();
|
||
|
int* operator->();
|
||
|
simple_iterator_base &operator++();
|
||
|
simple_iterator_base operator++(int);
|
||
|
simple_iterator_base &operator--();
|
||
|
simple_iterator_base operator--(int);
|
||
|
};
|
||
|
|
||
|
struct simple_container {
|
||
|
typedef simple_derived_iterator iterator;
|
||
|
|
||
|
iterator begin();
|
||
|
iterator end();
|
||
|
};
|
||
|
|
||
|
void good_derived(simple_container c) {
|
||
|
auto i0 = c.end();
|
||
|
|
||
|
if (i0 != c.end()) {
|
||
|
clang_analyzer_warnIfReached();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void iter_diff(std::vector<int> &V) {
|
||
|
auto i0 = V.begin(), i1 = V.end();
|
||
|
ptrdiff_t len = i1 - i0; // no-crash
|
||
|
}
|
||
|
|
||
|
void deferred_assumption(std::vector<int> &V, int e) {
|
||
|
const auto first = V.begin();
|
||
|
const auto comp1 = (first != V.end()), comp2 = (first == V.end());
|
||
|
if (comp1) {
|
||
|
clang_analyzer_eval(clang_analyzer_container_end(V) ==
|
||
|
clang_analyzer_iterator_position(first)); // expected-warning@-1{{FALSE}}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void loop(std::vector<int> &V, int e) {
|
||
|
auto start = V.begin();
|
||
|
while (true) {
|
||
|
auto item = std::find(start, V.end(), e);
|
||
|
if (item == V.end())
|
||
|
break;
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_container_end(V) ==
|
||
|
clang_analyzer_iterator_position(item)); // expected-warning@-1{{FALSE}}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template <typename InputIterator, typename T>
|
||
|
InputIterator nonStdFind(InputIterator first, InputIterator last,
|
||
|
const T &val) {
|
||
|
for (auto i = first; i != last; ++i) {
|
||
|
if (*i == val) {
|
||
|
return i;
|
||
|
}
|
||
|
}
|
||
|
return last;
|
||
|
}
|
||
|
|
||
|
void non_std_find(std::vector<int> &V, int e) {
|
||
|
auto first = nonStdFind(V.begin(), V.end(), e);
|
||
|
clang_analyzer_eval(clang_analyzer_container_end(V) ==
|
||
|
clang_analyzer_iterator_position(first)); // expected-warning@-1{{FALSE}} expected-warning@-1{{TRUE}}
|
||
|
if (V.end() != first) {
|
||
|
clang_analyzer_eval(clang_analyzer_container_end(V) ==
|
||
|
clang_analyzer_iterator_position(first)); // expected-warning@-1{{FALSE}}
|
||
|
}
|
||
|
}
|
||
|
|
||
|
template<typename T>
|
||
|
struct cont_with_ptr_iterator {
|
||
|
typedef T* iterator;
|
||
|
T* begin() const;
|
||
|
T* end() const;
|
||
|
};
|
||
|
|
||
|
void begin_ptr_iterator(const cont_with_ptr_iterator<int> &c) {
|
||
|
auto i = c.begin();
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i) == &c); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(c), "$c.begin()");
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning{{$c.begin()}}
|
||
|
|
||
|
if (i != c.begin()) {
|
||
|
clang_analyzer_warnIfReached();
|
||
|
}
|
||
|
}
|
||
|
|
||
|
void prefix_increment_ptr_iterator(const cont_with_ptr_iterator<int> &c) {
|
||
|
auto i = c.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(c), "$c.begin()");
|
||
|
|
||
|
auto j = ++i;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning{{$c.begin() + 1}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(j)); // expected-warning{{$c.begin() + 1}}
|
||
|
}
|
||
|
|
||
|
void prefix_decrement_ptr_iterator(const cont_with_ptr_iterator<int> &c) {
|
||
|
auto i = c.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(c), "$c.end()");
|
||
|
|
||
|
auto j = --i;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning{{$c.end() - 1}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(j)); // expected-warning{{$c.end() - 1}}
|
||
|
}
|
||
|
|
||
|
void postfix_increment_ptr_iterator(const cont_with_ptr_iterator<int> &c) {
|
||
|
auto i = c.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(c), "$c.begin()");
|
||
|
|
||
|
auto j = i++;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning{{$c.begin() + 1}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(j)); // expected-warning{{$c.begin()}}
|
||
|
}
|
||
|
|
||
|
void postfix_decrement_ptr_iterator(const cont_with_ptr_iterator<int> &c) {
|
||
|
auto i = c.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(c), "$c.end()");
|
||
|
|
||
|
auto j = i--;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning{{$c.end() - 1}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(j)); // expected-warning{{$c.end()}}
|
||
|
}
|
||
|
|
||
|
void plus_equal_ptr_iterator(const cont_with_ptr_iterator<int> &c) {
|
||
|
auto i = c.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(c), "$c.begin()");
|
||
|
|
||
|
i += 2;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning{{$c.begin() + 2}}
|
||
|
}
|
||
|
|
||
|
void minus_equal_ptr_iterator(const cont_with_ptr_iterator<int> &c) {
|
||
|
auto i = c.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(c), "$c.end()");
|
||
|
|
||
|
i -= 2;
|
||
|
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i)); // expected-warning{{$c.end() - 2}}
|
||
|
}
|
||
|
|
||
|
void minus_equal_ptr_iterator_variable(const cont_with_ptr_iterator<int> &c,
|
||
|
int n) {
|
||
|
auto i = c.end();
|
||
|
|
||
|
i -= n; // no-crash
|
||
|
}
|
||
|
|
||
|
void plus_lhs_ptr_iterator(const cont_with_ptr_iterator<int> &c) {
|
||
|
auto i1 = c.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(c), "$c.begin()");
|
||
|
|
||
|
auto i2 = i1 + 2;
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &c); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$c.begin()}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$c.begin() + 2}}
|
||
|
}
|
||
|
|
||
|
void plus_rhs_ptr_iterator(const cont_with_ptr_iterator<int> &c) {
|
||
|
auto i1 = c.begin();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_begin(c), "$c.begin()");
|
||
|
|
||
|
auto i2 = 2 + i1;
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &c); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$c.begin()}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$c.begin() + 2}}
|
||
|
}
|
||
|
|
||
|
void minus_ptr_iterator(const cont_with_ptr_iterator<int> &c) {
|
||
|
auto i1 = c.end();
|
||
|
|
||
|
clang_analyzer_denote(clang_analyzer_container_end(c), "$c.end()");
|
||
|
|
||
|
auto i2 = i1 - 2;
|
||
|
|
||
|
clang_analyzer_eval(clang_analyzer_iterator_container(i2) == &c); // expected-warning{{TRUE}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$c.end()}}
|
||
|
clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$c.end() - 2}}
|
||
|
}
|
||
|
|
||
|
void ptr_iter_diff(cont_with_ptr_iterator<int> &c) {
|
||
|
auto i0 = c.begin(), i1 = c.end();
|
||
|
ptrdiff_t len = i1 - i0; // no-crash
|
||
|
}
|
||
|
|
||
|
void ptr_iter_cmp_nullptr(cont_with_ptr_iterator<int> &c) {
|
||
|
auto i0 = c.begin();
|
||
|
if (i0 != nullptr) // no-crash
|
||
|
++i0;
|
||
|
}
|
||
|
|
||
|
void clang_analyzer_printState();
|
||
|
|
||
|
void print_state(std::vector<int> &V) {
|
||
|
const auto i0 = V.cbegin();
|
||
|
clang_analyzer_printState();
|
||
|
|
||
|
// CHECK: "checker_messages": [
|
||
|
// CHECK: { "checker": "alpha.cplusplus.IteratorModeling", "messages": [
|
||
|
// CHECK-NEXT: "Iterator Positions :",
|
||
|
// CHECK-NEXT: "i0 : Valid ; Container == SymRegion{reg_$[[#]]<std::vector<int> & V>} ; Offset == conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]}"
|
||
|
// CHECK-NEXT: ]}
|
||
|
|
||
|
*i0;
|
||
|
const auto i1 = V.cend();
|
||
|
clang_analyzer_printState();
|
||
|
|
||
|
// CHECK: "checker_messages": [
|
||
|
// CHECK: { "checker": "alpha.cplusplus.IteratorModeling", "messages": [
|
||
|
// CHECK-NEXT: "Iterator Positions :",
|
||
|
// CHECK-NEXT: "i1 : Valid ; Container == SymRegion{reg_$[[#]]<std::vector<int> & V>} ; Offset == conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]}"
|
||
|
// CHECK-NEXT: ]}
|
||
|
|
||
|
*i1;
|
||
|
}
|