1 // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.InvalidatedIterator -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=false %s -verify
2 // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.InvalidatedIterator -analyzer-config aggressive-binary-operation-simplification=true -analyzer-config c++-container-inlining=true -DINLINE=1 %s -verify
3 
4 #include "Inputs/system-header-simulator-cxx.h"
5 
6 void clang_analyzer_warnIfReached();
7 
8 void normal_dereference(std::vector<int> &V) {
9   auto i = V.cbegin();
10   *i; // no-warning
11 }
12 
13 void invalidated_dereference(std::vector<int> &V) {
14   auto i = V.cbegin();
15   V.erase(i);
16   *i; // expected-warning{{Invalidated iterator accessed}}
17 }
18 
19 void normal_prefix_increment(std::vector<int> &V) {
20   auto i = V.cbegin();
21   ++i; // no-warning
22 }
23 
24 void invalidated_prefix_increment(std::vector<int> &V) {
25   auto i = V.cbegin();
26   V.erase(i);
27   ++i; // expected-warning{{Invalidated iterator accessed}}
28 }
29 
30 void normal_prefix_decrement(std::vector<int> &V) {
31   auto i = ++V.cbegin();
32   --i; // no-warning
33 }
34 
35 void invalidated_prefix_decrement(std::vector<int> &V) {
36   auto i = ++V.cbegin();
37   V.erase(i);
38   --i; // expected-warning{{Invalidated iterator accessed}}
39 }
40 
41 void normal_postfix_increment(std::vector<int> &V) {
42   auto i = V.cbegin();
43   i++; // no-warning
44 }
45 
46 void invalidated_postfix_increment(std::vector<int> &V) {
47   auto i = V.cbegin();
48   V.erase(i);
49   i++; // expected-warning{{Invalidated iterator accessed}}
50 }
51 
52 void normal_postfix_decrement(std::vector<int> &V) {
53   auto i = ++V.cbegin();
54   i--; // no-warning
55 }
56 
57 void invalidated_postfix_decrement(std::vector<int> &V) {
58   auto i = ++V.cbegin();
59   V.erase(i);
60   i--; // expected-warning{{Invalidated iterator accessed}}
61 }
62 
63 void normal_increment_by_2(std::vector<int> &V) {
64   auto i = V.cbegin();
65   i += 2; // no-warning
66 }
67 
68 void invalidated_increment_by_2(std::vector<int> &V) {
69   auto i = V.cbegin();
70   V.erase(i);
71   i += 2; // expected-warning{{Invalidated iterator accessed}}
72 }
73 
74 void normal_increment_by_2_copy(std::vector<int> &V) {
75   auto i = V.cbegin();
76   auto j = i + 2; // no-warning
77 }
78 
79 void invalidated_increment_by_2_copy(std::vector<int> &V) {
80   auto i = V.cbegin();
81   V.erase(i);
82   auto j = i + 2; // expected-warning{{Invalidated iterator accessed}}
83 }
84 
85 void normal_decrement_by_2(std::vector<int> &V) {
86   auto i = V.cbegin();
87   i -= 2; // no-warning
88 }
89 
90 void invalidated_decrement_by_2(std::vector<int> &V) {
91   auto i = V.cbegin();
92   V.erase(i);
93   i -= 2; // expected-warning{{Invalidated iterator accessed}}
94 }
95 
96 void normal_decrement_by_2_copy(std::vector<int> &V) {
97   auto i = V.cbegin();
98   auto j = i - 2; // no-warning
99 }
100 
101 void invalidated_decrement_by_2_copy(std::vector<int> &V) {
102   auto i = V.cbegin();
103   V.erase(i);
104   auto j = i - 2; // expected-warning{{Invalidated iterator accessed}}
105 }
106 
107 void normal_subscript(std::vector<int> &V) {
108   auto i = V.cbegin();
109   i[1]; // no-warning
110 }
111 
112 void invalidated_subscript(std::vector<int> &V) {
113   auto i = V.cbegin();
114   V.erase(i);
115   i[1]; // expected-warning{{Invalidated iterator accessed}}
116 }
117 
118 void assignment(std::vector<int> &V) {
119   auto i = V.cbegin();
120   V.erase(i);
121   auto j = V.cbegin(); // no-warning
122 }
123 
124 template<typename T>
125 struct cont_with_ptr_iterator {
126   T *begin() const;
127   T *end() const;
128   T &operator[](size_t);
129   void push_back(const T&);
130   T* erase(T*);
131 };
132 
133 void invalidated_dereference_end_ptr_iterator(cont_with_ptr_iterator<int> &C) {
134   auto i = C.begin();
135   C.erase(i);
136   (void) *i; // expected-warning{{Invalidated iterator accessed}}
137 }
138 
139 void invalidated_prefix_increment_end_ptr_iterator(
140     cont_with_ptr_iterator<int> &C) {
141   auto i = C.begin();
142   C.erase(i);
143   ++i; // expected-warning{{Invalidated iterator accessed}}
144 }
145 
146 void invalidated_prefix_decrement_end_ptr_iterator(
147     cont_with_ptr_iterator<int> &C) {
148   auto i = C.begin() + 1;
149   C.erase(i);
150   --i; // expected-warning{{Invalidated iterator accessed}}
151 }
152 
153 void invalidated_postfix_increment_end_ptr_iterator(
154     cont_with_ptr_iterator<int> &C) {
155   auto i = C.begin();
156   C.erase(i);
157   i++; // expected-warning{{Invalidated iterator accessed}}
158 }
159 
160 void invalidated_postfix_decrement_end_ptr_iterator(
161     cont_with_ptr_iterator<int> &C) {
162   auto i = C.begin() + 1;
163   C.erase(i);
164   i--; // expected-warning{{Invalidated iterator accessed}}
165 }
166 
167 void invalidated_increment_by_2_end_ptr_iterator(
168     cont_with_ptr_iterator<int> &C) {
169   auto i = C.begin();
170   C.erase(i);
171   i += 2; // expected-warning{{Invalidated iterator accessed}}
172 }
173 
174 void invalidated_increment_by_2_copy_end_ptr_iterator(
175     cont_with_ptr_iterator<int> &C) {
176   auto i = C.begin();
177   C.erase(i);
178   auto j = i + 2; // expected-warning{{Invalidated iterator accessed}}
179 }
180 
181 void invalidated_decrement_by_2_end_ptr_iterator(
182     cont_with_ptr_iterator<int> &C) {
183   auto i = C.begin();
184   C.erase(i);
185   i -= 2; // expected-warning{{Invalidated iterator accessed}}
186 }
187 
188 void invalidated_decrement_by_2_copy_end_ptr_iterator(
189     cont_with_ptr_iterator<int> &C) {
190   auto i = C.begin();
191   C.erase(i);
192   auto j = i - 2; // expected-warning{{Invalidated iterator accessed}}
193 }
194 
195 void invalidated_subscript_end_ptr_iterator(cont_with_ptr_iterator<int> &C) {
196   auto i = C.begin();
197   C.erase(i);
198   (void) i[1]; // expected-warning{{Invalidated iterator accessed}}
199 }
200