1 // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorRange -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.IteratorRange -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 simple_good_end(const std::vector<int> &v) {
9   auto i = v.end();
10   if (i != v.end()) {
11     clang_analyzer_warnIfReached();
12     *i; // no-warning
13   }
14 }
15 
16 void simple_good_end_negated(const std::vector<int> &v) {
17   auto i = v.end();
18   if (!(i == v.end())) {
19     clang_analyzer_warnIfReached();
20     *i; // no-warning
21   }
22 }
23 
24 void simple_bad_end(const std::vector<int> &v) {
25   auto i = v.end();
26   *i; // expected-warning{{Iterator accessed outside of its range}}
27 }
28 
29 void simple_good_begin(const std::vector<int> &v) {
30   auto i = v.begin();
31   if (i != v.begin()) {
32     clang_analyzer_warnIfReached();
33     *--i; // no-warning
34   }
35 }
36 
37 void simple_good_begin_negated(const std::vector<int> &v) {
38   auto i = v.begin();
39   if (!(i == v.begin())) {
40     clang_analyzer_warnIfReached();
41     *--i; // no-warning
42   }
43 }
44 
45 void simple_bad_begin(const std::vector<int> &v) {
46   auto i = v.begin();
47   *--i; // expected-warning{{Iterator accessed outside of its range}}
48 }
49 
50 void copy(const std::vector<int> &v) {
51   auto i1 = v.end();
52   auto i2 = i1;
53   *i2; // expected-warning{{Iterator accessed outside of its range}}
54 }
55 
56 void decrease(const std::vector<int> &v) {
57   auto i = v.end();
58   --i;
59   *i; // no-warning
60 }
61 
62 void copy_and_decrease1(const std::vector<int> &v) {
63   auto i1 = v.end();
64   auto i2 = i1;
65   --i1;
66   *i1; // no-warning
67 }
68 
69 void copy_and_decrease2(const std::vector<int> &v) {
70   auto i1 = v.end();
71   auto i2 = i1;
72   --i1;
73   *i2; // expected-warning{{Iterator accessed outside of its range}}
74 }
75 
76 void copy_and_increase1(const std::vector<int> &v) {
77   auto i1 = v.begin();
78   auto i2 = i1;
79   ++i1;
80   if (i1 == v.end())
81     *i2; // no-warning
82 }
83 
84 void copy_and_increase2(const std::vector<int> &v) {
85   auto i1 = v.begin();
86   auto i2 = i1;
87   ++i1;
88   if (i2 == v.end())
89     *i2; // expected-warning{{Iterator accessed outside of its range}}
90 }
91 
92 void copy_and_increase3(const std::vector<int> &v) {
93   auto i1 = v.begin();
94   auto i2 = i1;
95   ++i1;
96   if (v.end() == i2)
97     *i2; // expected-warning{{Iterator accessed outside of its range}}
98 }
99 
100 void tricky(std::vector<int> &V, int e) {
101   const auto first = V.begin();
102   const auto comp1 = (first != V.end()), comp2 = (first == V.end());
103   if (comp1)
104     *first;
105 }
106 
107 void loop(std::vector<int> &V, int e) {
108   auto start = V.begin();
109   while (true) {
110     auto item = std::find(start, V.end(), e);
111     if (item == V.end())
112       break;
113     *item;          // no-warning
114     start = ++item; // no-warning
115   }
116 }
117 
118 void good_push_back(std::list<int> &L, int n) {
119   auto i0 = --L.cend();
120   L.push_back(n);
121   *++i0; // no-warning
122 }
123 
124 void bad_push_back(std::list<int> &L, int n) {
125   auto i0 = --L.cend();
126   L.push_back(n);
127   ++i0;
128   *++i0; // expected-warning{{Iterator accessed outside of its range}}
129 }
130 
131 void good_pop_back(std::list<int> &L, int n) {
132   auto i0 = --L.cend(); --i0;
133   L.pop_back();
134   *i0; // no-warning
135 }
136 
137 void bad_pop_back(std::list<int> &L, int n) {
138   auto i0 = --L.cend(); --i0;
139   L.pop_back();
140   *++i0; // expected-warning{{Iterator accessed outside of its range}}
141 }
142 
143 void good_push_front(std::list<int> &L, int n) {
144   auto i0 = L.cbegin();
145   L.push_front(n);
146   *--i0; // no-warning
147 }
148 
149 void bad_push_front(std::list<int> &L, int n) {
150   auto i0 = L.cbegin();
151   L.push_front(n);
152   --i0;
153   *--i0; // expected-warning{{Iterator accessed outside of its range}}
154 }
155 
156 void good_pop_front(std::list<int> &L, int n) {
157   auto i0 = ++L.cbegin();
158   L.pop_front();
159   *i0; // no-warning
160 }
161 
162 void bad_pop_front(std::list<int> &L, int n) {
163   auto i0 = ++L.cbegin();
164   L.pop_front();
165   *--i0; // expected-warning{{Iterator accessed outside of its range}}
166 }
167 
168 void bad_move(std::list<int> &L1, std::list<int> &L2) {
169   auto i0 = --L2.cend();
170   L1 = std::move(L2);
171   *++i0; // expected-warning{{Iterator accessed outside of its range}}
172 }
173 
174 void bad_move_push_back(std::list<int> &L1, std::list<int> &L2, int n) {
175   auto i0 = --L2.cend();
176   L2.push_back(n);
177   L1 = std::move(L2);
178   ++i0;
179   *++i0; // expected-warning{{Iterator accessed outside of its range}}
180 }
181