[clang] 23022b9 - [Analyzer][NFC] Separate white-box tests for iterator modelling from iterator checker tests
Adam Balogh via cfe-commits
cfe-commits at lists.llvm.org
Thu Nov 14 07:31:25 PST 2019
Author: Adam Balogh
Date: 2019-11-14T16:32:19+01:00
New Revision: 23022b93293676890b2c707616aaa8327f0e3708
URL: https://github.com/llvm/llvm-project/commit/23022b93293676890b2c707616aaa8327f0e3708
DIFF: https://github.com/llvm/llvm-project/commit/23022b93293676890b2c707616aaa8327f0e3708.diff
LOG: [Analyzer][NFC] Separate white-box tests for iterator modelling from iterator checker tests
The recently committed debug.IteratorDebugging checker enables
standalone white-box testing of the modelling of containers and
iterators. For the three checkers based on iterator modelling only
simple tests are needed.
Differential Revision: https://reviews.llvm.org/D70123
Added:
clang/test/Analysis/iterator-modelling.cpp
Modified:
clang/test/Analysis/Inputs/system-header-simulator-cxx.h
clang/test/Analysis/diagnostics/explicit-suppression.cpp
clang/test/Analysis/invalidated-iterator.cpp
clang/test/Analysis/iterator-range.cpp
clang/test/Analysis/mismatched-iterator.cpp
Removed:
################################################################################
diff --git a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h
index 26248a4d1f51..77b87627f6e3 100644
--- a/clang/test/Analysis/Inputs/system-header-simulator-cxx.h
+++ b/clang/test/Analysis/Inputs/system-header-simulator-cxx.h
@@ -74,8 +74,12 @@ template <typename T, typename Ptr, typename Ref> struct __vector_iterator {
diff erence_type operator-(const __vector_iterator<U, Ptr2, Ref2> &rhs);
Ref operator*() const { return *ptr; }
- Ptr operator->() const { return *ptr; }
+ Ptr operator->() const { return ptr; }
+ Ref operator[](
diff erence_type n) {
+ return *(ptr+n);
+ }
+
bool operator==(const iterator &rhs) const { return ptr == rhs.ptr; }
bool operator==(const const_iterator &rhs) const { return ptr == rhs.ptr; }
@@ -125,8 +129,12 @@ template <typename T, typename Ptr, typename Ref> struct __deque_iterator {
}
Ref operator*() const { return *ptr; }
- Ptr operator->() const { return *ptr; }
+ Ptr operator->() const { return ptr; }
+ Ref operator[](
diff erence_type n) {
+ return *(ptr+n);
+ }
+
bool operator==(const iterator &rhs) const { return ptr == rhs.ptr; }
bool operator==(const const_iterator &rhs) const { return ptr == rhs.ptr; }
@@ -165,7 +173,7 @@ template <typename T, typename Ptr, typename Ref> struct __list_iterator {
}
Ref operator*() const { return item->data; }
- Ptr operator->() const { return item->data; }
+ Ptr operator->() const { return &item->data; }
bool operator==(const iterator &rhs) const { return item == rhs->item; }
bool operator==(const const_iterator &rhs) const { return item == rhs->item; }
@@ -201,7 +209,7 @@ template <typename T, typename Ptr, typename Ref> struct __fwdl_iterator {
return tmp;
}
Ref operator*() const { return item->data; }
- Ptr operator->() const { return item->data; }
+ Ptr operator->() const { return &item->data; }
bool operator==(const iterator &rhs) const { return item == rhs->item; }
bool operator==(const const_iterator &rhs) const { return item == rhs->item; }
@@ -255,15 +263,16 @@ namespace std {
template<typename T>
class vector {
+ T *_start;
+ T *_finish;
+ T *_end_of_storage;
+
+ public:
typedef T value_type;
typedef size_t size_type;
typedef __vector_iterator<T, T *, T &> iterator;
typedef __vector_iterator<T, const T *, const T &> const_iterator;
- T *_start;
- T *_finish;
- T *_end_of_storage;
- public:
vector() : _start(0), _finish(0), _end_of_storage(0) {}
template <typename InputIterator>
vector(InputIterator first, InputIterator last);
@@ -333,6 +342,7 @@ namespace std {
T data;
__item *prev, *next;
} *_start, *_finish;
+
public:
typedef T value_type;
typedef size_t size_type;
@@ -399,15 +409,16 @@ namespace std {
template<typename T>
class deque {
+ T *_start;
+ T *_finish;
+ T *_end_of_storage;
+
+ public:
typedef T value_type;
typedef size_t size_type;
typedef __deque_iterator<T, T *, T &> iterator;
typedef __deque_iterator<T, const T *, const T &> const_iterator;
- T *_start;
- T *_finish;
- T *_end_of_storage;
- public:
deque() : _start(0), _finish(0), _end_of_storage(0) {}
template <typename InputIterator>
deque(InputIterator first, InputIterator last);
@@ -483,6 +494,7 @@ namespace std {
T data;
__item *next;
} *_start;
+
public:
typedef T value_type;
typedef size_t size_type;
diff --git a/clang/test/Analysis/diagnostics/explicit-suppression.cpp b/clang/test/Analysis/diagnostics/explicit-suppression.cpp
index c10aaa528e0d..f7db7a280545 100644
--- a/clang/test/Analysis/diagnostics/explicit-suppression.cpp
+++ b/clang/test/Analysis/diagnostics/explicit-suppression.cpp
@@ -19,6 +19,6 @@ class C {
void testCopyNull(C *I, C *E) {
std::copy(I, E, (C *)0);
#ifndef SUPPRESSED
- // expected-warning at ../Inputs/system-header-simulator-cxx.h:686 {{Called C++ object pointer is null}}
+ // expected-warning at ../Inputs/system-header-simulator-cxx.h:698 {{Called C++ object pointer is null}}
#endif
}
diff --git a/clang/test/Analysis/invalidated-iterator.cpp b/clang/test/Analysis/invalidated-iterator.cpp
index de37c9c055b9..4505aedd4e36 100644
--- a/clang/test/Analysis/invalidated-iterator.cpp
+++ b/clang/test/Analysis/invalidated-iterator.cpp
@@ -5,760 +5,119 @@
void clang_analyzer_warnIfReached();
-void bad_copy_assign_operator1_list(std::list<int> &L1,
- const std::list<int> &L2) {
- auto i0 = L1.cbegin();
- L1 = L2;
- *i0; // expected-warning{{Invalidated iterator accessed}}
- clang_analyzer_warnIfReached();
+void normal_dereference(std::vector<int> &V) {
+ auto i = V.cbegin();
+ *i; // no-warning
}
-void bad_copy_assign_operator1_vector(std::vector<int> &V1,
- const std::vector<int> &V2) {
- auto i0 = V1.cbegin();
- V1 = V2;
- *i0; // expected-warning{{Invalidated iterator accessed}}
+void invalidated_dereference(std::vector<int> &V) {
+ auto i = V.cbegin();
+ V.erase(i);
+ *i; // expected-warning{{Invalidated iterator accessed}}
}
-void bad_copy_assign_operator1_deque(std::deque<int> &D1,
- const std::deque<int> &D2) {
- auto i0 = D1.cbegin();
- D1 = D2;
- *i0; // expected-warning{{Invalidated iterator accessed}}
+void normal_prefix_increment(std::vector<int> &V) {
+ auto i = V.cbegin();
+ ++i; // no-warning
}
-void bad_copy_assign_operator1_forward_list(std::forward_list<int> &FL1,
- const std::forward_list<int> &FL2) {
- auto i0 = FL1.cbegin();
- FL1 = FL2;
- *i0; // expected-warning{{Invalidated iterator accessed}}
+void invalidated_prefix_increment(std::vector<int> &V) {
+ auto i = V.cbegin();
+ V.erase(i);
+ ++i; // expected-warning{{Invalidated iterator accessed}}
}
-void bad_assign1_list(std::list<int> &L, int n) {
- auto i0 = L.cbegin();
- L.assign(10, n);
- *i0; // expected-warning{{Invalidated iterator accessed}}
+void normal_prefix_decrement(std::vector<int> &V) {
+ auto i = ++V.cbegin();
+ --i; // no-warning
}
-void bad_assign1_vector(std::vector<int> &V, int n) {
- auto i0 = V.cbegin();
- V.assign(10, n);
- *i0; // expected-warning{{Invalidated iterator accessed}}
+void invalidated_prefix_decrement(std::vector<int> &V) {
+ auto i = ++V.cbegin();
+ V.erase(i);
+ --i; // expected-warning{{Invalidated iterator accessed}}
}
-void bad_assign1_deque(std::deque<int> &D, int n) {
- auto i0 = D.cbegin();
- D.assign(10, n);
- *i0; // expected-warning{{Invalidated iterator accessed}}
+void normal_postfix_increment(std::vector<int> &V) {
+ auto i = V.cbegin();
+ i++; // no-warning
}
-void bad_assign1_forward_list(std::forward_list<int> &FL, int n) {
- auto i0 = FL.cbegin();
- FL.assign(10, n);
- *i0; // expected-warning{{Invalidated iterator accessed}}
+void invalidated_postfix_increment(std::vector<int> &V) {
+ auto i = V.cbegin();
+ V.erase(i);
+ i++; // expected-warning{{Invalidated iterator accessed}}
}
-void good_clear1_list(std::list<int> &L) {
- auto i0 = L.cend();
- L.clear();
- --i0; // no-warning
+void normal_postfix_decrement(std::vector<int> &V) {
+ auto i = ++V.cbegin();
+ i--; // no-warning
}
-void bad_clear1_list(std::list<int> &L) {
- auto i0 = L.cbegin(), i1 = L.cend();
- L.clear();
- *i0; // expected-warning{{Invalidated iterator accessed}}
+void invalidated_postfix_decrement(std::vector<int> &V) {
+ auto i = ++V.cbegin();
+ V.erase(i);
+ i--; // expected-warning{{Invalidated iterator accessed}}
}
-void bad_clear1_vector(std::vector<int> &V) {
- auto i0 = V.cbegin(), i1 = V.cend();
- V.clear();
- *i0; // expected-warning{{Invalidated iterator accessed}}
+void normal_increment_by_2(std::vector<int> &V) {
+ auto i = V.cbegin();
+ i += 2; // no-warning
}
-void bad_clear1_vector_decr(std::vector<int> &V) {
- auto i0 = V.cbegin(), i1 = V.cend();
- V.clear();
- --i1; // expected-warning{{Invalidated iterator accessed}}
+void invalidated_increment_by_2(std::vector<int> &V) {
+ auto i = V.cbegin();
+ V.erase(i);
+ i += 2; // expected-warning{{Invalidated iterator accessed}}
}
-void bad_clear1_deque(std::deque<int> &D) {
- auto i0 = D.cbegin(), i1 = D.cend();
- D.clear();
- *i0; // expected-warning{{Invalidated iterator accessed}}
+void normal_increment_by_2_copy(std::vector<int> &V) {
+ auto i = V.cbegin();
+ auto j = i + 2; // no-warning
}
-void bad_clear1_deque_decr(std::deque<int> &D) {
- auto i0 = D.cbegin(), i1 = D.cend();
- D.clear();
- --i1; // expected-warning{{Invalidated iterator accessed}}
+void invalidated_increment_by_2_copy(std::vector<int> &V) {
+ auto i = V.cbegin();
+ V.erase(i);
+ auto j = i + 2; // expected-warning{{Invalidated iterator accessed}}
}
-void good_push_back1_list(std::list<int> &L, int n) {
- auto i0 = L.cbegin(), i1 = L.cend();
- L.push_back(n);
- *i0; // no-warning
- --i1; // no-warning
+void normal_decrement_by_2(std::vector<int> &V) {
+ auto i = V.cbegin();
+ i -= 2; // no-warning
}
-void good_push_back1_vector(std::vector<int> &V, int n) {
- auto i0 = V.cbegin(), i1 = V.cend();
- V.push_back(n);
- *i0; // no-warning
+void invalidated_decrement_by_2(std::vector<int> &V) {
+ auto i = V.cbegin();
+ V.erase(i);
+ i -= 2; // expected-warning{{Invalidated iterator accessed}}
}
-void bad_push_back1_vector(std::vector<int> &V, int n) {
- auto i0 = V.cbegin(), i1 = V.cend();
- V.push_back(n);
- --i1; // expected-warning{{Invalidated iterator accessed}}
+void normal_decrement_by_2_copy(std::vector<int> &V) {
+ auto i = V.cbegin();
+ auto j = i - 2; // no-warning
}
-void bad_push_back1_deque(std::deque<int> &D, int n) {
- auto i0 = D.cbegin(), i1 = D.cend();
- D.push_back(n);
- *i0; // expected-warning{{Invalidated iterator accessed}}
+void invalidated_decrement_by_2_copy(std::vector<int> &V) {
+ auto i = V.cbegin();
+ V.erase(i);
+ auto j = i - 2; // expected-warning{{Invalidated iterator accessed}}
}
-void bad_push_back1_deque_decr(std::deque<int> &D, int n) {
- auto i0 = D.cbegin(), i1 = D.cend();
- D.push_back(n);
- --i1; // expected-warning{{Invalidated iterator accessed}}
+void normal_subscript(std::vector<int> &V) {
+ auto i = V.cbegin();
+ i[1]; // no-warning
}
-void good_emplace_back1_list(std::list<int> &L, int n) {
- auto i0 = L.cbegin(), i1 = L.cend();
- L.emplace_back(n);
- *i0; // no-warning
- --i1; // no-warning
+void invalidated_subscript(std::vector<int> &V) {
+ auto i = V.cbegin();
+ V.erase(i);
+ i[1]; // expected-warning{{Invalidated iterator accessed}}
}
-void good_emplace_back1_vector(std::vector<int> &V, int n) {
- auto i0 = V.cbegin(), i1 = V.cend();
- V.emplace_back(n);
- *i0; // no-warning
+void assignment(std::vector<int> &V) {
+ auto i = V.cbegin();
+ V.erase(i);
+ auto j = V.cbegin(); // no-warning
}
-void bad_emplace_back1_vector(std::vector<int> &V, int n) {
- auto i0 = V.cbegin(), i1 = V.cend();
- V.emplace_back(n);
- --i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_emplace_back1_deque(std::deque<int> &D, int n) {
- auto i0 = D.cbegin(), i1 = D.cend();
- D.emplace_back(n);
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_emplace_back1_deque_decr(std::deque<int> &D, int n) {
- auto i0 = D.cbegin(), i1 = D.cend();
- D.emplace_back(n);
- --i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_pop_back1_list(std::list<int> &L, int n) {
- auto i0 = L.cbegin(), i1 = L.cend(), i2 = i1--;
- L.pop_back();
- *i0; // no-warning
- *i2; // no-warning
-}
-
-void bad_pop_back1_list(std::list<int> &L, int n) {
- auto i0 = L.cbegin(), i1 = L.cend(), i2 = i1--;
- L.pop_back();
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_pop_back1_vector(std::vector<int> &V, int n) {
- auto i0 = V.cbegin(), i1 = V.cend(), i2 = i1--;
- V.pop_back();
- *i0; // no-warning
-}
-
-void bad_pop_back1_vector(std::vector<int> &V, int n) {
- auto i0 = V.cbegin(), i1 = V.cend(), i2 = i1--;
- V.pop_back();
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_pop_back1_vector_decr(std::vector<int> &V, int n) {
- auto i0 = V.cbegin(), i1 = V.cend(), i2 = i1--;
- V.pop_back();
- --i2; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_pop_back1_deque(std::deque<int> &D, int n) {
- auto i0 = D.cbegin(), i1 = D.cend(), i2 = i1--;
- D.pop_back();
- *i0; // no-warning
-}
-
-void bad_pop_back1_deque(std::deque<int> &D, int n) {
- auto i0 = D.cbegin(), i1 = D.cend(), i2 = i1--;
- D.pop_back();
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_pop_back1_deque_decr(std::deque<int> &D, int n) {
- auto i0 = D.cbegin(), i1 = D.cend(), i2 = i1--;
- D.pop_back();
- --i2; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_push_front1_list(std::list<int> &L, int n) {
- auto i0 = L.cbegin(), i1 = L.cend();
- L.push_front(n);
- *i0; // no-warning
- --i1; // no-warning
-}
-
-void bad_push_front1_deque(std::deque<int> &D, int n) {
- auto i0 = D.cbegin(), i1 = D.cend();
- D.push_front(n);
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_push_front1_deque_decr(std::deque<int> &D, int n) {
- auto i0 = D.cbegin(), i1 = D.cend();
- D.push_front(n);
- --i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_push_front1_forward_list(std::forward_list<int> &FL, int n) {
- auto i0 = FL.cbegin(), i1 = FL.cend();
- FL.push_front(n);
- *i0; // no-warning
-}
-
-void good_emplace_front1_list(std::list<int> &L, int n) {
- auto i0 = L.cbegin(), i1 = L.cend();
- L.emplace_front(n);
- *i0; // no-warning
- --i1; // no-warning
-}
-
-void bad_emplace_front1_deque(std::deque<int> &D, int n) {
- auto i0 = D.cbegin(), i1 = D.cend();
- D.emplace_front(n);
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_emplace_front1_deque_decr(std::deque<int> &D, int n) {
- auto i0 = D.cbegin(), i1 = D.cend();
- D.emplace_front(n);
- --i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_emplace_front1_forward_list(std::forward_list<int> &FL, int n) {
- auto i0 = FL.cbegin(), i1 = FL.cend();
- FL.emplace_front(n);
- *i0; // no-warning
-}
-
-void good_pop_front1_list(std::list<int> &L, int n) {
- auto i1 = L.cbegin(), i0 = i1++;
- L.pop_front();
- *i1; // no-warning
-}
-
-void bad_pop_front1_list(std::list<int> &L, int n) {
- auto i1 = L.cbegin(), i0 = i1++;
- L.pop_front();
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_pop_front1_deque(std::deque<int> &D, int n) {
- auto i1 = D.cbegin(), i0 = i1++;
- D.pop_front();
- *i1; // no-warning
-}
-
-void bad_pop_front1_deque(std::deque<int> &D, int n) {
- auto i1 = D.cbegin(), i0 = i1++;
- D.pop_front();
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_pop_front1_forward_list(std::forward_list<int> &FL, int n) {
- auto i1 = FL.cbegin(), i0 = i1++;
- FL.pop_front();
- *i1; // no-warning
-}
-
-void bad_pop_front1_forward_list(std::forward_list<int> &FL, int n) {
- auto i1 = FL.cbegin(), i0 = i1++;
- FL.pop_front();
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_insert1_list1(std::list<int> &L, int n) {
- auto i1 = L.cbegin(), i0 = i1++;
- L.insert(i1, n);
- *i0; // no-warning
- *i1; // no-warning
-}
-
-void good_insert1_list2(std::list<int> &L, int n) {
- auto i1 = L.cbegin(), i0 = i1++;
- i1 = L.insert(i1, n);
- *i1; // no-warning
-}
-
-void good_insert1_vector1(std::vector<int> &V, int n) {
- auto i1 = V.cbegin(), i0 = i1++;
- V.insert(i1, n);
- *i0; // no-warning
-}
-
-void good_insert1_vector2(std::vector<int> &V, int n) {
- auto i1 = V.cbegin(), i0 = i1++;
- i1 = V.insert(i1, n);
- *i1; // no-warning
-}
-
-void bad_insert1_vector(std::vector<int> &V, int n) {
- auto i1 = V.cbegin(), i0 = i1++;
- V.insert(i1, n);
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_insert1_deque(std::deque<int> &D, int n) {
- auto i1 = D.cbegin(), i0 = i1++;
- i0 = D.insert(i1, n);
- *i0; // no-warning
-}
-
-void bad_insert1_deque1(std::deque<int> &D, int n) {
- auto i1 = D.cbegin(), i0 = i1++;
- D.insert(i1, n);
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_insert1_deque2(std::deque<int> &D, int n) {
- auto i1 = D.cbegin(), i0 = i1++;
- D.insert(i1, n);
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_insert2_list1(std::list<int> &L, int n) {
- auto i1 = L.cbegin(), i0 = i1++;
- L.insert(i1, std::move(n));
- *i0; // no-warning
- *i1; // no-warning
-}
-
-void good_insert2_list2(std::list<int> &L, int n) {
- auto i1 = L.cbegin(), i0 = i1++;
- i1 = L.insert(i1, std::move(n));
- *i1; // no-warning
-}
-
-void good_insert2_vector1(std::vector<int> &V, int n) {
- auto i1 = V.cbegin(), i0 = i1++;
- V.insert(i1, std::move(n));
- *i0; // no-warning
-}
-
-void good_insert2_vector2(std::vector<int> &V, int n) {
- auto i1 = V.cbegin(), i0 = i1++;
- i1 = V.insert(i1, std::move(n));
- *i1; // no-warning
-}
-
-void bad_insert2_vector(std::vector<int> &V, int n) {
- auto i1 = V.cbegin(), i0 = i1++;
- V.insert(i1, std::move(n));
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_insert2_deque(std::deque<int> &D, int n) {
- auto i1 = D.cbegin(), i0 = i1++;
- i1 = D.insert(i1, std::move(n));
- *i1; // no-warning
-}
-
-void bad_insert2_deque1(std::deque<int> &D, int n) {
- auto i1 = D.cbegin(), i0 = i1++;
- D.insert(i1, std::move(n));
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_insert2_deque2(std::deque<int> &D, int n) {
- auto i1 = D.cbegin(), i0 = i1++;
- D.insert(i1, std::move(n));
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_insert3_list1(std::list<int> &L, int n) {
- auto i1 = L.cbegin(), i0 = i1++;
- L.insert(i1, 10, n);
- *i0; // no-warning
- *i1; // no-warning
-}
-
-void good_insert3_list2(std::list<int> &L, int n) {
- auto i1 = L.cbegin(), i0 = i1++;
- i1 = L.insert(i1, 10, n);
- *i1; // no-warning
-}
-
-void good_insert3_vector1(std::vector<int> &V, int n) {
- auto i1 = V.cbegin(), i0 = i1++;
- V.insert(i1, 10, n);
- *i0; // no-warning
-}
-
-void good_insert3_vector2(std::vector<int> &V, int n) {
- auto i1 = V.cbegin(), i0 = i1++;
- i1 = V.insert(i1, 10, n);
- *i1; // no-warning
-}
-
-void bad_insert3_vector(std::vector<int> &V, int n) {
- auto i1 = V.cbegin(), i0 = i1++;
- V.insert(i1, 10, n);
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_insert3_deque(std::deque<int> &D, int n) {
- auto i1 = D.cbegin(), i0 = i1++;
- i1 = D.insert(i1, 10, std::move(n));
- *i1; // no-warning
-}
-
-void bad_insert3_deque1(std::deque<int> &D, int n) {
- auto i1 = D.cbegin(), i0 = i1++;
- D.insert(i1, 10, std::move(n));
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_insert3_deque2(std::deque<int> &D, int n) {
- auto i1 = D.cbegin(), i0 = i1++;
- D.insert(i1, 10, std::move(n));
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_insert4_list1(std::list<int> &L1, std::list<int> &L2, int n) {
- auto i1 = L1.cbegin(), i0 = i1++;
- L1.insert(i1, L2.cbegin(), L2.cend());
- *i0; // no-warning
- *i1; // no-warning
-}
-
-void good_insert4_list2(std::list<int> &L1, std::list<int> &L2, int n) {
- auto i1 = L1.cbegin(), i0 = i1++;
- i1 = L1.insert(i1, L2.cbegin(), L2.cend());
- *i1; // no-warning
-}
-
-void good_insert4_vector1(std::vector<int> &V1, std::vector<int> &V2, int n) {
- auto i1 = V1.cbegin(), i0 = i1++;
- V1.insert(i1, V2.cbegin(), V2.cend());
- *i0; // no-warning
-}
-
-void good_insert4_vector2(std::vector<int> &V1, std::vector<int> &V2, int n) {
- auto i1 = V1.cbegin(), i0 = i1++;
- i1 = V1.insert(i1, V2.cbegin(), V2.cend());
- *i1; // no-warning
-}
-
-void bad_insert4_vector(std::vector<int> &V1, std::vector<int> &V2, int n) {
- auto i1 = V1.cbegin(), i0 = i1++;
- V1.insert(i1, V2.cbegin(), V2.cend());
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_insert4_deque(std::deque<int> &D1, std::deque<int> &D2, int n) {
- auto i1 = D1.cbegin(), i0 = i1++;
- i1 = D1.insert(i1, D2.cbegin(), D2.cend());
- *i1; // no-warning
-}
-
-void bad_insert4_deque1(std::deque<int> &D1, std::deque<int> &D2, int n) {
- auto i1 = D1.cbegin(), i0 = i1++;
- D1.insert(i1, D2.cbegin(), D2.cend());
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_insert4_deque2(std::deque<int> &D1, std::deque<int> &D2, int n) {
- auto i1 = D1.cbegin(), i0 = i1++;
- D1.insert(i1, D2.cbegin(), D2.cend());
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_insert5_list1(std::list<int> &L) {
- auto i1 = L.cbegin(), i0 = i1++;
- L.insert(i1, {1, 2, 3, 4});
- *i0; // no-warning
- *i1; // no-warning
-}
-
-void good_insert5_list2(std::list<int> &L) {
- auto i1 = L.cbegin(), i0 = i1++;
- i1 = L.insert(i1, {1, 2, 3, 4});
- *i1; // no-warning
-}
-
-void good_insert5_vector1(std::vector<int> &V) {
- auto i1 = V.cbegin(), i0 = i1++;
- V.insert(i1, {1, 2, 3, 4});
- *i0; // no-warning
-}
-
-void good_insert5_vector2(std::vector<int> &V) {
- auto i1 = V.cbegin(), i0 = i1++;
- i1 = V.insert(i1, {1, 2, 3, 4});
- *i1; // no-warning
-}
-
-void bad_insert5_vector(std::vector<int> &V) {
- auto i1 = V.cbegin(), i0 = i1++;
- V.insert(i1, {1, 2, 3, 4});
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_insert5_deque(std::deque<int> &D) {
- auto i1 = D.cbegin(), i0 = i1++;
- i1 = D.insert(i1, {1, 2, 3, 4});
- *i1; // no-warning
-}
-
-void bad_insert5_deque1(std::deque<int> &D) {
- auto i1 = D.cbegin(), i0 = i1++;
- D.insert(i1, {1, 2, 3, 4});
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_insert5_deque2(std::deque<int> &D) {
- auto i1 = D.cbegin(), i0 = i1++;
- D.insert(i1, {1, 2, 3, 4});
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_emplace1_list(std::list<int> &L, int n) {
- auto i1 = L.cbegin(), i0 = i1++;
- L.emplace(i1, n);
- *i0; // no-warning
- *i1; // no-warning
-}
-
-void good_emplace1_vector(std::vector<int> &V, int n) {
- auto i1 = V.cbegin(), i0 = i1++;
- V.emplace(i1, n);
- *i0; // no-warning
-}
-
-void bad_emplace1_vector(std::vector<int> &V, int n) {
- auto i1 = V.cbegin(), i0 = i1++;
- V.emplace(i1, n);
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_emplace1_deque1(std::deque<int> &D, int n) {
- auto i1 = D.cbegin(), i0 = i1++;
- D.emplace(i1, n);
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_emplace1_deque2(std::deque<int> &D, int n) {
- auto i1 = D.cbegin(), i0 = i1++;
- D.emplace(i1, n);
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_erase1_list1(std::list<int> &L) {
- auto i2 = L.cbegin(), i0 = i2++, i1 = i2++;
- L.erase(i1);
- *i0; // no-warning
- *i2; // no-warning
-}
-
-void good_erase1_list2(std::list<int> &L) {
- auto i0 = L.cbegin();
- i0 = L.erase(i0);
- *i0; // no-warning
-}
-
-void bad_erase1_list(std::list<int> &L) {
- auto i0 = L.cbegin();
- L.erase(i0);
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_erase1_vector1(std::vector<int> &V) {
- auto i2 = V.cbegin(), i0 = i2++, i1 = i2++;
- V.erase(i1);
- *i0; // no-warning
-}
-
-void good_erase1_vector2(std::vector<int> &V) {
- auto i0 = V.cbegin();
- i0 = V.erase(i0);
- *i0; // no-warning
-}
-
-void bad_erase1_vector1(std::vector<int> &V) {
- auto i1 = V.cbegin(), i0 = i1++;
- V.erase(i0);
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_erase1_vector2(std::vector<int> &V) {
- auto i1 = V.cbegin(), i0 = i1++;
- V.erase(i0);
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_erase1_deque(std::deque<int> &D) {
- auto i0 = D.cbegin();
- i0 = D.erase(i0);
- *i0; // no-warning
-}
-
-void bad_erase1_deque1(std::deque<int> &D) {
- auto i2 = D.cbegin(), i0 = i2++, i1 = i2++;
- D.erase(i1);
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_erase1_deque2(std::deque<int> &D) {
- auto i2 = D.cbegin(), i0 = i2++, i1 = i2++;
- D.erase(i1);
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_erase1_deque3(std::deque<int> &D) {
- auto i2 = D.cbegin(), i0 = i2++, i1 = i2++;
- D.erase(i1);
- *i2; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_erase2_list1(std::list<int> &L) {
- auto i3 = L.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;
- L.erase(i1, i3);
- *i0; // no-warning
- *i3; // no-warning
-}
-
-void good_erase2_list2(std::list<int> &L) {
- auto i2 = L.cbegin(), i0 = i2++, i1 = i2++;
- i0 = L.erase(i0, i2);
- *i0; // no-warning
-}
-
-void bad_erase2_list1(std::list<int> &L) {
- auto i2 = L.cbegin(), i0 = i2++, i1 = i2++;
- L.erase(i0, i2);
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_erase2_list2(std::list<int> &L) {
- auto i2 = L.cbegin(), i0 = i2++, i1 = i2++;
- L.erase(i0, i2);
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_erase2_vector1(std::vector<int> &V) {
- auto i3 = V.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;;
- V.erase(i1, i3);
- *i0; // no-warning
-}
-
-void good_erase2_vector2(std::vector<int> &V) {
- auto i2 = V.cbegin(), i0 = i2++, i1 = i2++;
- i0 = V.erase(i0, i2);
- *i0; // no-warning
-}
-
-void bad_erase2_vector1(std::vector<int> &V) {
- auto i2 = V.cbegin(), i0 = i2++, i1 = i2++;
- V.erase(i0, i2);
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_erase2_vector2(std::vector<int> &V) {
- auto i2 = V.cbegin(), i0 = i2++, i1 = i2++;
- V.erase(i0, i2);
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_erase2_vector3(std::vector<int> &V) {
- auto i2 = V.cbegin(), i0 = i2++, i1 = i2++;
- V.erase(i0, i2);
- *i2; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_erase2_deque(std::deque<int> &D) {
- auto i2 = D.cbegin(), i0 = i2++, i1 = i2++;
- i0 = D.erase(i0, i2);
- *i0; // no-warning
-}
-
-void bad_erase2_deque1(std::deque<int> &D) {
- auto i3 = D.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;
- D.erase(i1, i3);
- *i0; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_erase2_deque2(std::deque<int> &D) {
- auto i3 = D.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;
- D.erase(i1, i3);
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_erase2_deque3(std::deque<int> &D) {
- auto i3 = D.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;
- D.erase(i1, i3);
- *i2; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_erase2_deque4(std::deque<int> &D) {
- auto i3 = D.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;
- D.erase(i1, i3);
- *i3; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_erase_after1_forward_list1(std::forward_list<int> &FL) {
- auto i2 = FL.cbegin(), i0 = i2++, i1 = i2++;
- FL.erase_after(i0);
- *i0; // no-warning
- *i2; // no-warning
-}
-
-void good_erase_after1_forward_lis2(std::forward_list<int> &FL) {
- auto i1 = FL.cbegin(), i0 = i1++;
- i1 = FL.erase_after(i0);
- *i1; // no-warning
-}
-
-void bad_erase_after1_forward_list(std::forward_list<int> &FL) {
- auto i1 = FL.cbegin(), i0 = i1++;
- FL.erase_after(i0);
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void good_erase_after2_forward_list1(std::forward_list<int> &FL) {
- auto i3 = FL.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;
- FL.erase_after(i0, i3);
- *i0; // no-warning
- *i3; // no-warning
-}
-
-void good_erase_after2_forward_list2(std::forward_list<int> &FL) {
- auto i3 = FL.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;
- i2 = FL.erase_after(i0, i3);
- *i2; // no-warning
-}
-
-void bad_erase_after2_forward_list1(std::forward_list<int> &FL) {
- auto i3 = FL.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;
- FL.erase_after(i0, i3);
- *i1; // expected-warning{{Invalidated iterator accessed}}
-}
-
-void bad_erase_after2_forward_list2(std::forward_list<int> &FL) {
- auto i3 = FL.cbegin(), i0 = i3++, i1 = i3++, i2 = i3++;
- FL.erase_after(i0, i3);
- *i2; // expected-warning{{Invalidated iterator accessed}}
-}
diff --git a/clang/test/Analysis/iterator-modelling.cpp b/clang/test/Analysis/iterator-modelling.cpp
new file mode 100644
index 000000000000..92427528e7c0
--- /dev/null
+++ b/clang/test/Analysis/iterator-modelling.cpp
@@ -0,0 +1,1972 @@
+// 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
+// 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
+
+#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&);
+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{{$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{{$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{{$v.begin() + 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(j)); //expected-warning{{$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{{$v.end() - 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(j)); //expected-warning{{$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{{$v.begin() + 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(j)); //expected-warning{{$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{{$v.end() - 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(j)); //expected-warning{{$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{{$v.begin() + 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{{$v.end() - 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(i2)); //expected-warning{{$v.end()}}
+}
+
+void plus(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(i2)); //expected-warning{{$v.begin() + 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(i2)); //expected-warning{{$v.end() - 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{{$v.begin() + 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); //expected-warning{{$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{{$v.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); //expected-warning{{$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{{$v.end() - 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); //expected-warning{{$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{{$v.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); //expected-warning{{$v.end() - 1}}
+}
+
+////////////////////////////////////////////////////////////////////////////////
+///
+/// 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_container_begin(L1)); // expected-warning{{$L2.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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_container_begin(V1)); // expected-warning{{$V2.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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_container_begin(D1)); // expected-warning{{$D2.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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_container_begin(FL1)); // expected-warning{{$FL2.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end() + 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.end() - 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(V)); // expected-warning{{$V.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(V)); // expected-warning{{$V.end() + 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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}}
+
+ clang_analyzer_express(clang_analyzer_container_begin(D)); // expected-warning{{$D.begin()}}
+ clang_analyzer_express(clang_analyzer_container_end(D)); // expected-warning{{$D.end()}} FIXME: Should be $D.end() + 1 (to correctly track the container's size)
+}
+
+/// 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_container_begin(L)); // expected-warning{{$L.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end() + 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(V)); // expected-warning{{$V.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(V)); // expected-warning{{$V.end() + 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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}}
+
+ clang_analyzer_express(clang_analyzer_container_begin(D)); // expected-warning{{$D.begin()}}
+ clang_analyzer_express(clang_analyzer_container_end(D)); // expected-warning{{$D.end()}} FIXME: Should be $D.end() + 1 (to correctly track the container's size)
+}
+
+/// 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_container_begin(L)); // expected-warning{{$L.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end() - 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(V)); // expected-warning{{$V.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(V)); // expected-warning{{$V.end() - 1}}
+}
+
+/// 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_container_begin(D)); // expected-warning{{$D.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$D.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(D)); // expected-warning{{$D.end() - 1}}
+}
+
+/// 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_container_begin(L)); // expected-warning{{$L.begin() - 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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}}
+
+ clang_analyzer_express(clang_analyzer_container_begin(D)); // expected-warning{{$D.begin()}} FIXME: Should be $D.begin() - 1 (to correctly track the container's size)
+
+ clang_analyzer_express(clang_analyzer_container_end(D)); // expected-warning{{$D.end()}}
+}
+
+/// 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_container_begin(FL)); // expected-warning{{$FL.begin() - 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(FL)); // expected-warning{{$FL.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin() - 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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}}
+
+ clang_analyzer_express(clang_analyzer_container_begin(D)); // expected-warning{{$D.begin()}} FIXME: Should be $D.begin - 1 (to correctly track the container's size)
+
+ clang_analyzer_express(clang_analyzer_container_end(D)); // expected-warning{{$D.end()}}
+}
+
+/// 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_container_begin(FL)); // expected-warning{{$FL.begin() - 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(FL)); // expected-warning{{$FL.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin() + 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.begin() + 1}}
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(D)); // expected-warning{{$D.begin() + 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$D.begin() + 1}}
+
+ clang_analyzer_express(clang_analyzer_container_end(D)); // expected-warning{{$D.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(FL)); // expected-warning{{$FL.begin() + 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$FL.begin() + 1}}
+
+ clang_analyzer_express(clang_analyzer_container_end(FL)); // expected-warning{{$FL.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}} FIXME: Should be $L.begin() - 1
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+ // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $L.begin() - 1
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}} FIXME: Should be $L.begin() - 1
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} FIXME: Should be $L.begin() - 1
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.begin() + 1}}
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.begin()
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$i1}}
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i - 1
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.end() - 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.end() - 1}} FIXME: should be $L.end() - 2
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(V)); // expected-warning{{$V.begin()}} FIXME: Should be $V.begin() - 1
+ // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $V.begin() - 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); // FIXME: expect warning $V.end()
+}
+
+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_container_begin(V)); // expected-warning{{$V.begin()}} FIXME: Should be $V.begin() - 1
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} FIXME: Should be $V.begin() - 1
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); // FIXME: expect -warning $V.begin()
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); // FIXME: expect warning $V.end()
+}
+
+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_container_begin(V)); // expected-warning{{$V.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expecte warning $i1 - 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); FIXME expect warning $V.end()
+}
+
+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_container_begin(V)); // expected-warning{{$V.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); FIXME: expect warning $V.end() + 1
+ // 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_container_begin(V)); // expected-warning{{$V.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); FIXME: expect warning $V.end()
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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_container_begin(D)); // expected-warning{{$D.begin()}} FIXME: Should be $D.begin() - 1
+ // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $D.begin() - 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning $D.end()
+}
+
+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_container_begin(D)); // expected-warning{{$D.begin()}} FIXME: Should be $D.begin - 1
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.begin() - 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning $D.end()
+}
+
+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_container_begin(D)); // expected-warning{{$D.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 - 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning $D.end()
+}
+
+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_container_begin(D)); // expected-warning{{$D.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning $D.end() + 1
+ // 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_container_begin(D)); // expected-warning{{$D.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning $D.end()
+ // 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_container_begin(FL)); // expected-warning{{$FL.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}}
+ // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $FL.begin() + 1
+
+ clang_analyzer_express(clang_analyzer_container_end(FL)); // expected-warning{{$FL.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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_container_begin(FL)); // expected-warning{{$FL.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$FL.begin() + 1}}
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $FL.begin() + 2
+
+ clang_analyzer_express(clang_analyzer_container_end(FL)); // expected-warning{{$FL.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(FL)); // expected-warning{{$FL.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}}
+
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$i1}}
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1
+
+ clang_analyzer_express(clang_analyzer_container_end(FL)); // expected-warning{{$FL.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}} FIXME: Should be $L.begin() - 1
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+ // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $L.begin() - 1
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}} FIXME: Should be $L.begin() - 1
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}} FIXME: Should be $L.begin() - 1
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.begin() + 1}}
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.begin()
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$i1}}
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i - 1
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.end() - 1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.end() - 1}} FIXME: should be $L.end() - 2
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(V)); // expected-warning{{$V.begin()}} FIXME: Should be $V.begin() - 1
+ // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $V.begin() - 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); // FIXME: expect warning $V.end()
+}
+
+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_container_begin(V)); // expected-warning{{$V.begin()}} FIXME: Should be $V.begin() - 1
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} FIXME: Should be $V.begin() - 1
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); // FIXME: expect -warning $V.begin()
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); // FIXME: expect warning $V.end()
+}
+
+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_container_begin(V)); // expected-warning{{$V.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expecte warning $i1 - 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); FIXME expect warning $V.end()
+}
+
+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_container_begin(V)); // expected-warning{{$V.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); FIXME: expect warning $V.end() + 1
+ // 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_container_begin(V)); // expected-warning{{$V.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); FIXME: expect warning $V.end()
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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_container_begin(D)); // expected-warning{{$D.begin()}} FIXME: Should be $D.begin() - 1
+ // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $D.begin() - 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning $D.end()
+}
+
+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_container_begin(D)); // expected-warning{{$D.begin()}} FIXME: Should be $D.begin - 1
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.begin() - 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning $D.end()
+}
+
+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_container_begin(D)); // expected-warning{{$D.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 - 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning $D.end()
+}
+
+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_container_begin(D)); // expected-warning{{$D.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning $D.end() + 1
+ // 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_container_begin(D)); // expected-warning{{$D.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning $D.end()
+ // 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_container_begin(FL)); // expected-warning{{$FL.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}}
+ // clang_analyzer_express(clang_analyzer_iterator_position(i2)); FIXME: expect warning $FL.begin() + 1
+
+ clang_analyzer_express(clang_analyzer_container_end(FL)); // expected-warning{{$FL.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$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_container_begin(FL)); // expected-warning{{$FL.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$FL.begin() + 1}}
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $FL.begin() + 2
+
+ clang_analyzer_express(clang_analyzer_container_end(FL)); // expected-warning{{$FL.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(FL)); // expected-warning{{$FL.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}}
+
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$i1}}
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1
+
+ clang_analyzer_express(clang_analyzer_container_end(FL)); // expected-warning{{$FL.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}} FIXME: Should be$L.begin() + 1
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$L.begin() + 1}}
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $L.begin() + 1
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}} FIXME: Should be $L.begin() + 1
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$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_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(L)); // expected-warning{{$L.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$L.begin()}}
+
+ clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_begin(V)); // expected-warning{{$V.begin()}} FIXME: Should be $V.begin() + 1
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.begin() + 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); FIXME: expect warning $V.end()
+}
+
+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_container_begin(V)); // expected-warning{{$V.begin()}} FIXME: Should be $V.begin() + 1
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}} FIXME: Should be $V.begin() + 1
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $V.begin() + 2
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); FIXME: expect warning $V.end()
+}
+
+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_container_begin(V)); // expected-warning{{$V.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); FIXME: expect warning $V.end()
+}
+
+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_container_begin(V)); // expected-warning{{$V.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$V.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_container_end(V)); FIXME: expect warning $V.end()
+ // 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_container_begin(D)); // expected-warning{{$D.begin()}} FIXME: Should be $D.begin() + 1
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.begin() + 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning{{$D.end()
+}
+
+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_container_begin(D)); // expected-warning{{$D.begin()}} FIXME: Should be $D.begin() + 1
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $D.begin() + 2
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning $D.end()
+}
+
+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_container_begin(D)); // expected-warning{{$D.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_iterator_position(i3)); FIXME: expect warning $i1 + 1
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning $D.end()
+}
+
+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_container_begin(D)); // expected-warning{{$D.begin()}}
+
+ // clang_analyzer_express(clang_analyzer_container_end(D)); FIXME: expect warning $D.end()
+ // 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_container_begin(FL)); // expected-warning{{$FL.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i2)); // expected-warning{{$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_container_end(FL)); // expected-warning{{$FL.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$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_container_begin(FL)); // expected-warning{{$FL.begin()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i0)); // expected-warning{{$FL.begin()}}
+
+ clang_analyzer_express(clang_analyzer_iterator_position(i1)); // expected-warning{{$i1}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i3)); // expected-warning{{$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_container_end(FL)); // expected-warning{{$FL.end()}}
+ clang_analyzer_express(clang_analyzer_iterator_position(i4)); // expected-warning{{$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();
+ ptr
diff _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 at -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 at -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 at -1{{FALSE}} expected-warning at -1{{TRUE}}
+ if (V.end() != first) {
+ clang_analyzer_eval(clang_analyzer_container_end(V) ==
+ clang_analyzer_iterator_position(first)); // expected-warning at -1{{FALSE}} expected-warning at -1 0-1{{TRUE}} FIXME: should only expect FALSE in every case
+ }
+}
diff --git a/clang/test/Analysis/iterator-range.cpp b/clang/test/Analysis/iterator-range.cpp
index 93f69e47f563..71af17a1f3d0 100644
--- a/clang/test/Analysis/iterator-range.cpp
+++ b/clang/test/Analysis/iterator-range.cpp
@@ -5,240 +5,376 @@
void clang_analyzer_warnIfReached();
-void simple_good_end(const std::vector<int> &v) {
- auto i = v.end();
- if (i != v.end()) {
- clang_analyzer_warnIfReached();
- *i; // no-warning
- }
+// Dereference - operator*()
+
+void deref_begin(const std::vector<int> &V) {
+ auto i = V.begin();
+ *i; // no-warning
+}
+
+void deref_begind_begin(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ *i; // no-warning
+}
+
+template <typename Iter> Iter return_any_iterator(const Iter &It);
+
+void deref_unknown(const std::vector<int> &V) {
+ auto i = return_any_iterator(V.begin());
+ *i; // no-warning
}
-void simple_good_end_negated(const std::vector<int> &v) {
- auto i = v.end();
- if (!(i == v.end())) {
- clang_analyzer_warnIfReached();
- *i; // no-warning
- }
+void deref_ahead_of_end(const std::vector<int> &V) {
+ auto i = --V.end();
+ *i; // no-warning
}
-void simple_bad_end(const std::vector<int> &v) {
- auto i = v.end();
+void deref_end(const std::vector<int> &V) {
+ auto i = V.end();
*i; // expected-warning{{Past-the-end iterator dereferenced}}
- clang_analyzer_warnIfReached();
}
-void copy(const std::vector<int> &v) {
- auto i1 = v.end();
- auto i2 = i1;
- *i2; // expected-warning{{Past-the-end iterator dereferenced}}
+// Prefix increment - operator++()
+
+void incr_begin(const std::vector<int> &V) {
+ auto i = V.begin();
+ ++i; // no-warning
+}
+
+void incr_behind_begin(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ ++i; // no-warning
+}
+
+void incr_unknown(const std::vector<int> &V) {
+ auto i = return_any_iterator(V.begin());
+ ++i; // no-warning
+}
+
+void incr_ahead_of_end(const std::vector<int> &V) {
+ auto i = --V.end();
+ ++i; // no-warning
+}
+
+void incr_end(const std::vector<int> &V) {
+ auto i = V.end();
+ ++i; // expected-warning{{Iterator incremented behind the past-the-end iterator}}
+}
+
+// Postfix increment - operator++(int)
+
+void begin_incr(const std::vector<int> &V) {
+ auto i = V.begin();
+ i++; // no-warning
+}
+
+void behind_begin_incr(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ i++; // no-warning
+}
+
+void unknown_incr(const std::vector<int> &V) {
+ auto i = return_any_iterator(V.begin());
+ i++; // no-warning
+}
+
+void ahead_of_end_incr(const std::vector<int> &V) {
+ auto i = --V.end();
+ i++; // no-warning
+}
+
+void end_incr(const std::vector<int> &V) {
+ auto i = V.end();
+ i++; // expected-warning{{Iterator incremented behind the past-the-end iterator}}
+}
+
+// Prefix decrement - operator--()
+
+void decr_begin(const std::vector<int> &V) {
+ auto i = V.begin();
+ --i; // expected-warning{{Iterator decremented ahead of its valid range}}
+}
+
+void decr_behind_begin(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ --i; // no-warning
+}
+
+void decr_unknown(const std::vector<int> &V) {
+ auto i = return_any_iterator(V.begin());
+ --i; // no-warning
+}
+
+void decr_ahead_of_end(const std::vector<int> &V) {
+ auto i = --V.end();
+ --i; // no-warning
+}
+
+void decr_end(const std::vector<int> &V) {
+ auto i = V.end();
+ --i; // no-warning
+}
+
+// Postfix decrement - operator--(int)
+
+void begin_decr(const std::vector<int> &V) {
+ auto i = V.begin();
+ i--; // expected-warning{{Iterator decremented ahead of its valid range}}
+}
+
+void behind_begin_decr(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ i--; // no-warning
}
-void decrease(const std::vector<int> &v) {
- auto i = v.end();
+void unknown_decr(const std::vector<int> &V) {
+ auto i = return_any_iterator(V.begin());
+ i--; // no-warning
+}
+
+void ahead_of_end_decr(const std::vector<int> &V) {
+ auto i = --V.end();
+ i--; // no-warning
+}
+
+void end_decr(const std::vector<int> &V) {
+ auto i = V.end();
+ i--; // no-warning
+}
+
+// Addition assignment - operator+=(int)
+
+void incr_by_2_begin(const std::vector<int> &V) {
+ auto i = V.begin();
+ i += 2; // no-warning
+}
+
+void incr_by_2_behind_begin(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ i += 2; // no-warning
+}
+
+void incr_by_2_unknown(const std::vector<int> &V) {
+ auto i = return_any_iterator(V.begin());
+ i += 2; // no-warning
+}
+
+void incr_by_2_ahead_by_2_of_end(const std::vector<int> &V) {
+ auto i = --V.end();
--i;
- *i; // no-warning
+ i += 2; // no-warning
}
-void copy_and_decrease1(const std::vector<int> &v) {
- auto i1 = v.end();
- auto i2 = i1;
- --i1;
- *i1; // no-warning
+void incr_by_2_ahead_of_end(const std::vector<int> &V) {
+ auto i = --V.end();
+ i += 2; // expected-warning{{Iterator incremented behind the past-the-end iterator}}
}
-void copy_and_decrease2(const std::vector<int> &v) {
- auto i1 = v.end();
- auto i2 = i1;
- --i1;
- *i2; // expected-warning{{Past-the-end iterator dereferenced}}
+void incr_by_2_end(const std::vector<int> &V) {
+ auto i = V.end();
+ i += 2; // expected-warning{{Iterator incremented behind the past-the-end iterator}}
}
-void copy_and_increase1(const std::vector<int> &v) {
- auto i1 = v.begin();
- auto i2 = i1;
- ++i1;
- if (i1 == v.end())
- *i2; // no-warning
+// Addition - operator+(int)
+
+void incr_by_2_copy_begin(const std::vector<int> &V) {
+ auto i = V.begin();
+ auto j = i + 2; // no-warning
}
-void copy_and_increase2(const std::vector<int> &v) {
- auto i1 = v.begin();
- auto i2 = i1;
- ++i1;
- if (i2 == v.end())
- *i2; // expected-warning{{Past-the-end iterator dereferenced}}
+void incr_by_2_copy_behind_begin(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ auto j = i + 2; // no-warning
}
-void copy_and_increase3(const std::vector<int> &v) {
- auto i1 = v.begin();
- auto i2 = i1;
- ++i1;
- if (v.end() == i2)
- *i2; // expected-warning{{Past-the-end iterator dereferenced}}
+void incr_by_2_copy_unknown(const std::vector<int> &V) {
+ auto i = return_any_iterator(V.begin());
+ auto j = i + 2; // no-warning
}
-template <class InputIterator, class 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 incr_by_2_copy_ahead_by_2_of_end(const std::vector<int> &V) {
+ auto i = --V.end();
+ --i;
+ auto j = i + 2; // no-warning
}
-void good_non_std_find(std::vector<int> &V, int e) {
- auto first = nonStdFind(V.begin(), V.end(), e);
- if (V.end() != first)
- *first; // no-warning
+void incr_by_2_copy_ahead_of_end(const std::vector<int> &V) {
+ auto i = --V.end();
+ auto j = i + 2; // expected-warning{{Iterator incremented behind the past-the-end iterator}}
}
-void bad_non_std_find(std::vector<int> &V, int e) {
- auto first = nonStdFind(V.begin(), V.end(), e);
- *first; // expected-warning{{Past-the-end iterator dereferenced}}
+void incr_by_2_copy_end(const std::vector<int> &V) {
+ auto i = V.end();
+ auto j = i + 2; // expected-warning{{Iterator incremented behind the past-the-end iterator}}
}
-void tricky(std::vector<int> &V, int e) {
- const auto first = V.begin();
- const auto comp1 = (first != V.end()), comp2 = (first == V.end());
- if (comp1)
- *first; // no-warning
+// Subtraction assignment - operator-=(int)
+
+void decr_by_2_begin(const std::vector<int> &V) {
+ auto i = V.begin();
+ i -= 2; // expected-warning{{Iterator decremented ahead of its valid range}}
}
-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;
- *item; // no-warning
- start = ++item; // no-warning
- }
+void decr_by_2_behind_begin(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ i -= 2; // expected-warning{{Iterator decremented ahead of its valid range}}
}
-void good_push_back(std::list<int> &L, int n) {
- auto i0 = --L.cend();
- L.push_back(n);
- *++i0; // no-warning
+void decr_by_2_behind_begin_by_2(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ ++i;
+ i -= 2; // no-warning
}
-void bad_push_back(std::list<int> &L, int n) {
- auto i0 = --L.cend();
- L.push_back(n);
- ++i0;
- *++i0; // expected-warning{{Past-the-end iterator dereferenced}}
+void decr_by_2_unknown(const std::vector<int> &V) {
+ auto i = return_any_iterator(V.begin());
+ i -= 2; // no-warning
}
-void good_pop_back(std::list<int> &L, int n) {
- auto i0 = --L.cend(); --i0;
- L.pop_back();
- *i0; // no-warning
+void decr_by_2_ahead_of_end(const std::vector<int> &V) {
+ auto i = --V.end();
+ i -= 2; // no-warning
}
-void bad_pop_back(std::list<int> &L, int n) {
- auto i0 = --L.cend(); --i0;
- L.pop_back();
- *++i0; // expected-warning{{Past-the-end iterator dereferenced}}
+void decr_by_2_end(const std::vector<int> &V) {
+ auto i = V.end();
+ i -= 2; // no-warning
}
-void good_push_front(std::list<int> &L, int n) {
- auto i0 = L.cbegin();
- L.push_front(n);
- *--i0; // no-warning
+// Subtraction - operator-(int)
+
+void decr_by_2_copy_begin(const std::vector<int> &V) {
+ auto i = V.begin();
+ auto j = i - 2; // expected-warning{{Iterator decremented ahead of its valid range}}
}
-void bad_push_front(std::list<int> &L, int n) {
- auto i0 = L.cbegin();
- L.push_front(n);
- --i0;
- --i0; // expected-warning{{Iterator decremented ahead of its valid range}}
+void decr_by_2_copy_behind_begin(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ auto j = i - 2; // expected-warning{{Iterator decremented ahead of its valid range}}
}
-void good_pop_front(std::list<int> &L, int n) {
- auto i0 = ++L.cbegin();
- L.pop_front();
- *i0; // no-warning
+void decr_by_2_copy_behind_begin_by_2(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ ++i;
+ auto j = i - 2; // no-warning
}
-void bad_pop_front(std::list<int> &L, int n) {
- auto i0 = ++L.cbegin();
- L.pop_front();
- --i0; // expected-warning{{Iterator decremented ahead of its valid range}}
+void decr_by_2_copy_unknown(const std::vector<int> &V) {
+ auto i = return_any_iterator(V.begin());
+ auto j = i - 2; // no-warning
}
-void bad_move(std::list<int> &L1, std::list<int> &L2) {
- auto i0 = --L2.cend();
- L1 = std::move(L2);
- *++i0; // expected-warning{{Past-the-end iterator dereferenced}}
+void decr_by_2_copy_ahead_of_end(const std::vector<int> &V) {
+ auto i = --V.end();
+ auto j = i - 2; // no-warning
}
-void bad_move_push_back(std::list<int> &L1, std::list<int> &L2, int n) {
- auto i0 = --L2.cend();
- L2.push_back(n);
- L1 = std::move(L2);
- ++i0;
- *++i0; // expected-warning{{Past-the-end iterator dereferenced}}
+void decr_by_2_copy_end(const std::vector<int> &V) {
+ auto i = V.end();
+ auto j = i - 2; // no-warning
}
-void good_incr_begin(const std::list<int> &L) {
- auto i0 = L.begin();
- ++i0; // no-warning
+//
+// Subscript - operator[](int)
+//
+
+// By zero
+
+void subscript_zero_begin(const std::vector<int> &V) {
+ auto i = V.begin();
+ auto j = i[0]; // no-warning
}
-void bad_decr_begin(const std::list<int> &L) {
- auto i0 = L.begin();
- --i0; // expected-warning{{Iterator decremented ahead of its valid range}}
+void subscript_zero_behind_begin(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ auto j = i[0]; // no-warning
}
-void good_decr_end(const std::list<int> &L) {
- auto i0 = L.end();
- --i0; // no-warning
+void subscript_zero_unknown(const std::vector<int> &V) {
+ auto i = return_any_iterator(V.begin());
+ auto j = i[0]; // no-warning
}
-void bad_incr_end(const std::list<int> &L) {
- auto i0 = L.end();
- ++i0; // expected-warning{{Iterator incremented behind the past-the-end iterator}}
+void subscript_zero_ahead_of_end(const std::vector<int> &V) {
+ auto i = --V.end();
+ auto j = i[0]; // no-warning
}
-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;
-};
+void subscript_zero_end(const std::vector<int> &V) {
+ auto i = V.end();
+ auto j = i[0]; // expected-warning{{Past-the-end iterator dereferenced}}
+}
-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);
-};
+// By negative number
-struct simple_container {
- typedef simple_derived_iterator iterator;
+void subscript_negative_begin(const std::vector<int> &V) {
+ auto i = V.begin();
+ auto j = i[-1]; // no-warning FIXME: expect warning Iterator decremented ahead of its valid range
+}
+
+void subscript_negative_behind_begin(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ auto j = i[-1]; // no-warning
+}
+
+void subscript_negative_unknown(const std::vector<int> &V) {
+ auto i = return_any_iterator(V.begin());
+ auto j = i[-1]; // no-warning
+}
+
+void subscript_negative_ahead_of_end(const std::vector<int> &V) {
+ auto i = --V.end();
+ auto j = i[-1]; // no-warning
+}
+
+void subscript_negative_end(const std::vector<int> &V) {
+ auto i = V.end();
+ auto j = i[-1]; // // expected-warning{{Past-the-end iterator dereferenced}} FIXME: expect no warning
+}
+
+// By positive number
+
+void subscript_positive_begin(const std::vector<int> &V) {
+ auto i = V.begin();
+ auto j = i[1]; // no-warning
+}
+
+void subscript_positive_behind_begin(const std::vector<int> &V) {
+ auto i = ++V.begin();
+ auto j = i[1]; // no-warning
+}
- iterator begin();
- iterator end();
+void subscript_positive_unknown(const std::vector<int> &V) {
+ auto i = return_any_iterator(V.begin());
+ auto j = i[1]; // no-warning
+}
+
+void subscript_positive_ahead_of_end(const std::vector<int> &V) {
+ auto i = --V.end();
+ auto j = i[1]; // no-warning FIXME: expected warning Past-the-end iterator dereferenced
+}
+
+void subscript_positive_end(const std::vector<int> &V) {
+ auto i = V.end();
+ auto j = i[1]; // expected-warning{{Past-the-end iterator dereferenced}} FIXME: expect warning Iterator incremented behind the past-the-end iterator
+}
+
+//
+// Structure member dereference operators
+//
+
+struct S {
+ int n;
};
-void good_derived(simple_container c) {
- auto i0 = c.end();
- if (i0 != c.end()) {
- clang_analyzer_warnIfReached();
- *i0; // no-warning
- }
+// Member dereference - operator->()
+
+void arrow_deref_begin(const std::vector<S> &V) {
+ auto i = V.begin();
+ int n = i->n; // no-warning
}
-void iter_
diff (std::vector<int> &V) {
- auto i0 = V.begin(), i1 = V.end();
- ptr
diff _t len = i1 - i0; // no-crash
+void arrow_deref_end(const std::vector<S> &V) {
+ auto i = V.end();
+ int n = i->n; // expected-warning{{Past-the-end iterator dereferenced}}
}
diff --git a/clang/test/Analysis/mismatched-iterator.cpp b/clang/test/Analysis/mismatched-iterator.cpp
index 26a71c399c70..c58d14d72fda 100644
--- a/clang/test/Analysis/mismatched-iterator.cpp
+++ b/clang/test/Analysis/mismatched-iterator.cpp
@@ -3,203 +3,118 @@
#include "Inputs/system-header-simulator-cxx.h"
-void good_insert1(std::vector<int> &v, int n) {
- v.insert(v.cbegin(), n); // no-warning
+void good_insert1(std::vector<int> &V, int n) {
+ V.insert(V.cbegin(), n); // no-warning
}
-
-void good_insert2(std::vector<int> &v, int len, int n) {
- v.insert(v.cbegin(), len, n); // no-warning
-}
-
-void good_insert3(std::vector<int> &v1, std::vector<int> &v2) {
- v1.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // no-warning
-}
-
-void good_insert4(std::vector<int> &v, int len, int n) {
- v.insert(v.cbegin(), {n-1, n, n+1}); // no-warning
-}
-
-void good_insert_find(std::vector<int> &v, int n, int m) {
- auto i = std::find(v.cbegin(), v.cend(), n);
- v.insert(i, m); // no-warning
-}
-
-void good_erase1(std::vector<int> &v) {
- v.erase(v.cbegin()); // no-warning
-}
-
-void good_erase2(std::vector<int> &v) {
- v.erase(v.cbegin(), v.cend()); // no-warning
-}
-
-void good_emplace(std::vector<int> &v, int n) {
- v.emplace(v.cbegin(), n); // no-warning
-}
-
-void good_ctor(std::vector<int> &v) {
- std::vector<int> new_v(v.cbegin(), v.cend()); // no-warning
-}
-
-void good_find(std::vector<int> &v, int n) {
- std::find(v.cbegin(), v.cend(), n); // no-warning
-}
-
-void good_find_first_of(std::vector<int> &v1, std::vector<int> &v2) {
- std::find_first_of(v1.cbegin(), v1.cend(), v2.cbegin(), v2.cend()); // no-warning
-}
-
-void good_copy(std::vector<int> &v1, std::vector<int> &v2, int n) {
- std::copy(v1.cbegin(), v1.cend(), v2.begin()); // no-warning
-}
-
-void good_move_find1(std::vector<int> &v1, std::vector<int> &v2, int n) {
- auto i0 = v2.cbegin();
- v1 = std::move(v2);
- std::find(i0, v1.cend(), n); // no-warning
-}
-
-void bad_insert1(std::vector<int> &v1, std::vector<int> &v2, int n) {
- v2.insert(v1.cbegin(), n); // expected-warning{{Container accessed using foreign iterator argument}}
-}
-
-void bad_insert2(std::vector<int> &v1, std::vector<int> &v2, int len, int n) {
- v2.insert(v1.cbegin(), len, n); // expected-warning{{Container accessed using foreign iterator argument}}
-}
-
-void bad_insert3(std::vector<int> &v1, std::vector<int> &v2) {
- v2.insert(v1.cbegin(), v2.cbegin(), v2.cend()); // expected-warning{{Container accessed using foreign iterator argument}}
- v1.insert(v1.cbegin(), v1.cbegin(), v2.cend()); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
- v1.insert(v1.cbegin(), v2.cbegin(), v1.cend()); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
+void good_insert2(std::vector<int> &V, int len, int n) {
+ V.insert(V.cbegin(), len, n); // no-warning
}
-void bad_insert4(std::vector<int> &v1, std::vector<int> &v2, int len, int n) {
- v2.insert(v1.cbegin(), {n-1, n, n+1}); // expected-warning{{Container accessed using foreign iterator argument}}
+void good_insert3(std::vector<int> &V1, std::vector<int> &V2) {
+ V1.insert(V1.cbegin(), V2.cbegin(), V2.cend()); // no-warning
}
-void bad_erase1(std::vector<int> &v1, std::vector<int> &v2) {
- v2.erase(v1.cbegin()); // expected-warning{{Container accessed using foreign iterator argument}}
+void good_insert4(std::vector<int> &V, int len, int n) {
+ V.insert(V.cbegin(), {n-1, n, n+1}); // no-warning
}
-void bad_erase2(std::vector<int> &v1, std::vector<int> &v2) {
- v2.erase(v2.cbegin(), v1.cend()); // expected-warning{{Container accessed using foreign iterator argument}}
- v2.erase(v1.cbegin(), v2.cend()); // expected-warning{{Container accessed using foreign iterator argument}}
- v2.erase(v1.cbegin(), v1.cend()); // expected-warning{{Container accessed using foreign iterator argument}}
+void good_insert_find(std::vector<int> &V, int n, int m) {
+ auto i = std::find(V.cbegin(), V.cend(), n);
+ V.insert(i, m); // no-warning
}
-void bad_emplace(std::vector<int> &v1, std::vector<int> &v2, int n) {
- v2.emplace(v1.cbegin(), n); // expected-warning{{Container accessed using foreign iterator argument}}
+void good_erase1(std::vector<int> &V) {
+ V.erase(V.cbegin()); // no-warning
}
-void good_move_find2(std::vector<int> &v1, std::vector<int> &v2, int n) {
- auto i0 = --v2.cend();
- v1 = std::move(v2);
- std::find(i0, v1.cend(), n); // no-warning
+void good_erase2(std::vector<int> &V) {
+ V.erase(V.cbegin(), V.cend()); // no-warning
}
-void good_move_find3(std::vector<int> &v1, std::vector<int> &v2, int n) {
- auto i0 = v2.cend();
- v1 = std::move(v2);
- v2.push_back(n); // expected-warning{{Method called on moved-from object of type 'std::vector'}}
- std::find(v2.cbegin(), i0, n); // no-warning
+void good_emplace(std::vector<int> &V, int n) {
+ V.emplace(V.cbegin(), n); // no-warning
}
-void good_comparison(std::vector<int> &v) {
- if (v.cbegin() == v.cend()) {} // no-warning
+void good_ctor(std::vector<int> &V) {
+ std::vector<int> new_v(V.cbegin(), V.cend()); // no-warning
}
-void bad_ctor(std::vector<int> &v1, std::vector<int> &v2) {
- std::vector<int> new_v(v1.cbegin(), v2.cend()); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
+void good_find(std::vector<int> &V, int n) {
+ std::find(V.cbegin(), V.cend(), n); // no-warning
}
-void bad_find(std::vector<int> &v1, std::vector<int> &v2, int n) {
- std::find(v1.cbegin(), v2.cend(), n); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
+void good_find_first_of(std::vector<int> &V1, std::vector<int> &V2) {
+ std::find_first_of(V1.cbegin(), V1.cend(), V2.cbegin(), V2.cend()); // no-warning
}
-void bad_find_first_of(std::vector<int> &v1, std::vector<int> &v2) {
- std::find_first_of(v1.cbegin(), v2.cend(), v2.cbegin(), v2.cend()); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
- std::find_first_of(v1.cbegin(), v1.cend(), v2.cbegin(), v1.cend()); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
+void good_copy(std::vector<int> &V1, std::vector<int> &V2, int n) {
+ std::copy(V1.cbegin(), V1.cend(), V2.begin()); // no-warning
}
-void bad_move_find1(std::vector<int> &v1, std::vector<int> &v2, int n) {
- auto i0 = v2.cbegin();
- v1 = std::move(v2);
- std::find(i0, v2.cend(), n); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
- // expected-warning at -1{{Method called on moved-from object of type 'std::vector'}}
+void bad_insert1(std::vector<int> &V1, std::vector<int> &V2, int n) {
+ V2.insert(V1.cbegin(), n); // expected-warning{{Container accessed using foreign iterator argument}}
}
-void bad_insert_find(std::vector<int> &v1, std::vector<int> &v2, int n, int m) {
- auto i = std::find(v1.cbegin(), v1.cend(), n);
- v2.insert(i, m); // expected-warning{{Container accessed using foreign iterator argument}}
+void bad_insert2(std::vector<int> &V1, std::vector<int> &V2, int len, int n) {
+ V2.insert(V1.cbegin(), len, n); // expected-warning{{Container accessed using foreign iterator argument}}
}
-void good_overwrite(std::vector<int> &v1, std::vector<int> &v2, int n) {
- auto i = v1.cbegin();
- i = v2.cbegin();
- v2.insert(i, n); // no-warning
+void bad_insert3(std::vector<int> &V1, std::vector<int> &V2) {
+ V2.insert(V1.cbegin(), V2.cbegin(), V2.cend()); // expected-warning{{Container accessed using foreign iterator argument}}
+ V1.insert(V1.cbegin(), V1.cbegin(), V2.cend()); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
+ V1.insert(V1.cbegin(), V2.cbegin(), V1.cend()); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
}
-void bad_overwrite(std::vector<int> &v1, std::vector<int> &v2, int n) {
- auto i = v1.cbegin();
- i = v2.cbegin();
- v1.insert(i, n); // expected-warning{{Container accessed using foreign iterator argument}}
+void bad_insert4(std::vector<int> &V1, std::vector<int> &V2, int len, int n) {
+ V2.insert(V1.cbegin(), {n-1, n, n+1}); // expected-warning{{Container accessed using foreign iterator argument}}
}
-template<typename Container, typename Iterator>
-bool is_cend(Container cont, Iterator it) {
- return it == cont.cend();
+void bad_erase1(std::vector<int> &V1, std::vector<int> &V2) {
+ V2.erase(V1.cbegin()); // expected-warning{{Container accessed using foreign iterator argument}}
}
-void good_empty(std::vector<int> &v) {
- is_cend(v, v.cbegin()); // no-warning
+void bad_erase2(std::vector<int> &V1, std::vector<int> &V2) {
+ V2.erase(V2.cbegin(), V1.cend()); // expected-warning{{Container accessed using foreign iterator argument}}
+ V2.erase(V1.cbegin(), V2.cend()); // expected-warning{{Container accessed using foreign iterator argument}}
+ V2.erase(V1.cbegin(), V1.cend()); // expected-warning{{Container accessed using foreign iterator argument}}
}
-void bad_empty(std::vector<int> &v1, std::vector<int> &v2) {
- is_cend(v1, v2.cbegin()); // expected-warning at -8{{Iterators of
diff erent containers used where the same container is expected}}
+void bad_emplace(std::vector<int> &V1, std::vector<int> &V2, int n) {
+ V2.emplace(V1.cbegin(), n); // expected-warning{{Container accessed using foreign iterator argument}}
}
-void good_move(std::vector<int> &v1, std::vector<int> &v2) {
- const auto i0 = ++v2.cbegin();
- v1 = std::move(v2);
- v1.erase(i0); // no-warning
+void good_comparison(std::vector<int> &V) {
+ if (V.cbegin() == V.cend()) {} // no-warning
}
-void bad_move(std::vector<int> &v1, std::vector<int> &v2) {
- const auto i0 = ++v2.cbegin();
- v1 = std::move(v2);
- v2.erase(i0); // expected-warning{{Container accessed using foreign iterator argument}}
- // expected-warning at -1{{Method called on moved-from object of type 'std::vector'}}
+void bad_comparison(std::vector<int> &V1, std::vector<int> &V2) {
+ if (V1.cbegin() != V2.cend()) {} // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
}
-void bad_move_find2(std::vector<int> &v1, std::vector<int> &v2, int n) {
- auto i0 = --v2.cend();
- v1 = std::move(v2);
- std::find(i0, v2.cend(), n); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
- // expected-warning at -1{{Method called on moved-from object of type 'std::vector'}}
+void bad_ctor(std::vector<int> &V1, std::vector<int> &V2) {
+ std::vector<int> new_v(V1.cbegin(), V2.cend()); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
}
-void bad_move_find3(std::vector<int> &v1, std::vector<int> &v2, int n) {
- auto i0 = v2.cend();
- v1 = std::move(v2);
- std::find(v1.cbegin(), i0, n); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
+void bad_find(std::vector<int> &V1, std::vector<int> &V2, int n) {
+ std::find(V1.cbegin(), V2.cend(), n); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
}
-void bad_comparison(std::vector<int> &v1, std::vector<int> &v2) {
- if (v1.cbegin() != v2.cend()) { // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
- *v1.cbegin();
- }
+void bad_find_first_of(std::vector<int> &V1, std::vector<int> &V2) {
+ std::find_first_of(V1.cbegin(), V2.cend(), V2.cbegin(), V2.cend()); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
+ std::find_first_of(V1.cbegin(), V1.cend(), V2.cbegin(), V1.cend()); // expected-warning{{Iterators of
diff erent containers used where the same container is expected}}
}
std::vector<int> &return_vector_ref();
void ignore_conjured1() {
- std::vector<int> &v1 = return_vector_ref(), &v2 = return_vector_ref();
+ std::vector<int> &V1 = return_vector_ref(), &V2 = return_vector_ref();
- v2.erase(v1.cbegin()); // no-warning
+ V2.erase(V1.cbegin()); // no-warning
}
void ignore_conjured2() {
- std::vector<int> &v1 = return_vector_ref(), &v2 = return_vector_ref();
+ std::vector<int> &V1 = return_vector_ref(), &V2 = return_vector_ref();
- if (v1.cbegin() == v2.cbegin()) {} //no-warning
+ if (V1.cbegin() == V2.cbegin()) {} //no-warning
}
More information about the cfe-commits
mailing list