xref: /llvm-project/clang/test/Analysis/iterator-range.cpp (revision a393e68b27fcc8b78256407c99c6179acea056fe)
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 bad_move(std::list<int> &L1, std::list<int> &L2) {
119   auto i0 = --L2.cend();
120   L1 = std::move(L2);
121   *++i0; // expected-warning{{Iterator accessed outside of its range}}
122 }
123