1 // 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
2 
3 // 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
4 
5 // RUN: %clang_analyze_cc1 -std=c++11 -analyzer-checker=core,cplusplus,alpha.cplusplus.IteratorModeling,debug.ExprInspection -analyzer-config aggressive-binary-operation-simplification=true %s 2>&1 | FileCheck %s
6 
7 #include "Inputs/system-header-simulator-cxx.h"
8 
9 template <typename Container>
10 long clang_analyzer_container_begin(const Container&);
11 template <typename Container>
12 long clang_analyzer_container_end(const Container&);
13 
14 void clang_analyzer_denote(long, const char*);
15 void clang_analyzer_express(long);
16 void clang_analyzer_eval(bool);
17 void clang_analyzer_warnIfReached();
18 
19 void begin(const std::vector<int> &V) {
20   V.begin();
21 
22   clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
23   clang_analyzer_express(clang_analyzer_container_begin(V)); //expected-warning{{$V.begin()}}
24 }
25 
26 void end(const std::vector<int> &V) {
27   V.end();
28 
29   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
30   clang_analyzer_express(clang_analyzer_container_end(V)); //expected-warning{{$V.end()}}
31 }
32 
33 ////////////////////////////////////////////////////////////////////////////////
34 ///
35 /// C O N T A I N E R   A S S I G N M E N T S
36 ///
37 ////////////////////////////////////////////////////////////////////////////////
38 
39 // Move
40 
41 void move_assignment(std::vector<int> &V1, std::vector<int> &V2) {
42   V1.cbegin();
43   V1.cend();
44   V2.cbegin();
45   V2.cend();
46   long B1 = clang_analyzer_container_begin(V1);
47   long E1 = clang_analyzer_container_end(V1);
48   long B2 = clang_analyzer_container_begin(V2);
49   long E2 = clang_analyzer_container_end(V2);
50   V1 = std::move(V2);
51   clang_analyzer_eval(clang_analyzer_container_begin(V1) == B2); //expected-warning{{TRUE}}
52   clang_analyzer_eval(clang_analyzer_container_end(V2) == E2); //expected-warning{{TRUE}}
53 }
54 
55 ////////////////////////////////////////////////////////////////////////////////
56 ///
57 /// C O N T A I N E R   M O D I F I E R S
58 ///
59 ////////////////////////////////////////////////////////////////////////////////
60 
61 /// push_back()
62 ///
63 /// Design decision: extends containers to the ->RIGHT-> (i.e. the
64 /// past-the-end position of the container is incremented).
65 
66 void push_back(std::vector<int> &V, int n) {
67   V.cbegin();
68   V.cend();
69 
70   clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
71   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
72 
73   V.push_back(n);
74 
75   clang_analyzer_express(clang_analyzer_container_begin(V)); // expected-warning{{$V.begin()}}
76   clang_analyzer_express(clang_analyzer_container_end(V)); // expected-warning{{$V.end() + 1}}
77 }
78 
79 /// emplace_back()
80 ///
81 /// Design decision: extends containers to the ->RIGHT-> (i.e. the
82 /// past-the-end position of the container is incremented).
83 
84 void emplace_back(std::vector<int> &V, int n) {
85   V.cbegin();
86   V.cend();
87 
88   clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
89   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
90 
91   V.emplace_back(n);
92 
93   clang_analyzer_express(clang_analyzer_container_begin(V)); // expected-warning{{$V.begin()}}
94   clang_analyzer_express(clang_analyzer_container_end(V)); // expected-warning{{$V.end() + 1}}
95 }
96 
97 /// pop_back()
98 ///
99 /// Design decision: shrinks containers to the <-LEFT<- (i.e. the
100 /// past-the-end position of the container is decremented).
101 
102 void pop_back(std::vector<int> &V, int n) {
103   V.cbegin();
104   V.cend();
105 
106   clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
107   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
108 
109   V.pop_back();
110 
111   clang_analyzer_express(clang_analyzer_container_begin(V)); // expected-warning{{$V.begin()}}
112   clang_analyzer_express(clang_analyzer_container_end(V)); // expected-warning{{$V.end() - 1}}
113 }
114 
115 /// push_front()
116 ///
117 /// Design decision: extends containers to the <-LEFT<- (i.e. the first
118 /// position of the container is decremented).
119 
120 void push_front(std::deque<int> &D, int n) {
121   D.cbegin();
122   D.cend();
123 
124   clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
125   clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
126 
127   D.push_front(n);
128 
129   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)
130   clang_analyzer_express(clang_analyzer_container_end(D)); // expected-warning{{$D.end()}}
131 }
132 
133 /// emplace_front()
134 ///
135 /// Design decision: extends containers to the <-LEFT<- (i.e. the first
136 /// position of the container is decremented).
137 
138 void deque_emplace_front(std::deque<int> &D, int n) {
139   D.cbegin();
140   D.cend();
141 
142   clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
143   clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
144 
145   D.emplace_front(n);
146 
147   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)
148   clang_analyzer_express(clang_analyzer_container_end(D)); // expected-warning{{$D.end()}}
149 }
150 
151 /// pop_front()
152 ///
153 /// Design decision: shrinks containers to the ->RIGHT-> (i.e. the first
154 /// position of the container is incremented).
155 
156 void deque_pop_front(std::deque<int> &D, int n) {
157   D.cbegin();
158   D.cend();
159 
160   clang_analyzer_denote(clang_analyzer_container_begin(D), "$D.begin()");
161   clang_analyzer_denote(clang_analyzer_container_end(D), "$D.end()");
162 
163   D.pop_front();
164 
165   clang_analyzer_express(clang_analyzer_container_begin(D)); // expected-warning{{$D.begin() + 1}}
166   clang_analyzer_express(clang_analyzer_container_end(D)); // expected-warning{{$D.end()}}
167 }
168 
169 void clang_analyzer_printState();
170 
171 void print_state(std::vector<int> &V) {
172   V.cbegin();
173   clang_analyzer_printState();
174 
175 // CHECK:      "checker_messages": [
176 // CHECK-NEXT:   { "checker": "alpha.cplusplus.ContainerModeling", "messages": [
177 // CHECK-NEXT:     "Container Data :",
178 // CHECK-NEXT:     "SymRegion{reg_$[[#]]<std::vector<int> & V>} : [ conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]} .. <Unknown> ]"
179 // CHECK-NEXT:   ]}
180 
181   V.cend();
182   clang_analyzer_printState();
183 
184 // CHECK:      "checker_messages": [
185 // CHECK-NEXT:   { "checker": "alpha.cplusplus.ContainerModeling", "messages": [
186 // CHECK-NEXT:     "Container Data :",
187 // CHECK-NEXT:     "SymRegion{reg_$[[#]]<std::vector<int> & V>} : [ conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]} .. conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]} ]"
188 // CHECK-NEXT:   ]}
189 }
190