llvm-project/clang/test/Analysis/iterator-modeling.cpp
Balazs Benics 9b2ec87f5b
[analyzer] Avoid creating LazyCompoundVal when possible (#116840)
In #115916 I allowed copying empty structs.
Later in #115917 I changed how objects are copied, and basically when we
would want to copy a struct (an LCV) of a single symbol (likely coming
from an opaque fncall or invalidation), just directly bind that symbol
instead of creating an LCV referring to the symbol. This was an
optimization to skip a layer of indirection.

Now, it turns out I should have apply the same logic in #115916. I
should not have just blindly created an LCV by calling
`createLazyBinding()`, but rather check if I can apply the shortcut
described in #115917 and only create the LCV if the shortcut doesn't
apply.

In this patch I check if there is a single default binding that the copy
would refer to and if so, just return that symbol instead of creating an
LCV.

There shouldn't be any observable changes besides that we should have
fewer LCVs. This change may surface bugs in checkers that were
associating some metadata with entities in a wrong way. Notably,
STLAlgorithmModeling and DebugIteratorModeling checkers would likely
stop working after this change.
I didn't investigate them deeply because they were broken even prior to
this patch. Let me know if I should migrate these checkers to be just as
bugged as they were prior to this patch - thus make the tests pass.
2024-11-29 09:19:33 +01:00

2055 lines
89 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: "conj_$[[#]]{int, LC[[#]], S[[#]], #[[#]]} : Valid ; Container == SymRegion{reg_$[[#]]<std::vector<int> & V>} ; Offset == conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]}",
// 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: "conj_$[[#]]{int, LC[[#]], S[[#]], #[[#]]} : Valid ; Container == SymRegion{reg_$[[#]]<std::vector<int> & V>} ; Offset == conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]}",
// CHECK-NEXT: "i1 : Valid ; Container == SymRegion{reg_$[[#]]<std::vector<int> & V>} ; Offset == conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]}"
// CHECK-NEXT: ]}
*i1;
}