xref: /llvm-project/clang/test/Analysis/container-modeling.cpp (revision 1a27d63a8891076ad9176f1a70f372003bc55c2f)
1a3f4d17aSAdam Balogh // 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 -analyzer-output=text -verify
29a08a3faSAdam Balogh 
3a3f4d17aSAdam Balogh // 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 -analyzer-output=text -verify
49a08a3faSAdam Balogh 
59a08a3faSAdam Balogh // 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
69a08a3faSAdam Balogh 
79a08a3faSAdam Balogh #include "Inputs/system-header-simulator-cxx.h"
89a08a3faSAdam Balogh 
99a08a3faSAdam Balogh template <typename Container>
109a08a3faSAdam Balogh long clang_analyzer_container_begin(const Container&);
119a08a3faSAdam Balogh template <typename Container>
129a08a3faSAdam Balogh long clang_analyzer_container_end(const Container&);
139a08a3faSAdam Balogh 
149a08a3faSAdam Balogh void clang_analyzer_denote(long, const char*);
159a08a3faSAdam Balogh void clang_analyzer_express(long);
169a08a3faSAdam Balogh void clang_analyzer_eval(bool);
179a08a3faSAdam Balogh void clang_analyzer_warnIfReached();
189a08a3faSAdam Balogh 
begin(const std::vector<int> & V)199a08a3faSAdam Balogh void begin(const std::vector<int> &V) {
209a08a3faSAdam Balogh   V.begin();
219a08a3faSAdam Balogh 
229a08a3faSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
239a08a3faSAdam Balogh   clang_analyzer_express(clang_analyzer_container_begin(V)); // expected-warning{{$V.begin()}}
24a3f4d17aSAdam Balogh                                                              // expected-note@-1{{$V.begin()}}
259a08a3faSAdam Balogh }
269a08a3faSAdam Balogh 
end(const std::vector<int> & V)279a08a3faSAdam Balogh void end(const std::vector<int> &V) {
289a08a3faSAdam Balogh   V.end();
299a08a3faSAdam Balogh 
309a08a3faSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
319a08a3faSAdam Balogh   clang_analyzer_express(clang_analyzer_container_end(V)); // expected-warning{{$V.end()}}
32a3f4d17aSAdam Balogh                                                            // expected-note@-1{{$V.end()}}
339a08a3faSAdam Balogh }
349a08a3faSAdam Balogh 
359a08a3faSAdam Balogh ////////////////////////////////////////////////////////////////////////////////
369a08a3faSAdam Balogh ///
379a08a3faSAdam Balogh /// C O N T A I N E R   A S S I G N M E N T S
389a08a3faSAdam Balogh ///
399a08a3faSAdam Balogh ////////////////////////////////////////////////////////////////////////////////
409a08a3faSAdam Balogh 
419a08a3faSAdam Balogh // Move
429a08a3faSAdam Balogh 
move_assignment(std::vector<int> & V1,std::vector<int> & V2)439a08a3faSAdam Balogh void move_assignment(std::vector<int> &V1, std::vector<int> &V2) {
449a08a3faSAdam Balogh   V1.cbegin();
459a08a3faSAdam Balogh   V1.cend();
469a08a3faSAdam Balogh   V2.cbegin();
479a08a3faSAdam Balogh   V2.cend();
489a08a3faSAdam Balogh   long B1 = clang_analyzer_container_begin(V1);
499a08a3faSAdam Balogh   long E1 = clang_analyzer_container_end(V1);
509a08a3faSAdam Balogh   long B2 = clang_analyzer_container_begin(V2);
519a08a3faSAdam Balogh   long E2 = clang_analyzer_container_end(V2);
529a08a3faSAdam Balogh   V1 = std::move(V2);
539a08a3faSAdam Balogh   clang_analyzer_eval(clang_analyzer_container_begin(V1) == B2); // expected-warning{{TRUE}}
54a3f4d17aSAdam Balogh                                                                  // expected-note@-1{{TRUE}}
559a08a3faSAdam Balogh   clang_analyzer_eval(clang_analyzer_container_end(V2) == E2); // expected-warning{{TRUE}}
56a3f4d17aSAdam Balogh                                                                // expected-note@-1{{TRUE}}
579a08a3faSAdam Balogh }
589a08a3faSAdam Balogh 
599a08a3faSAdam Balogh ////////////////////////////////////////////////////////////////////////////////
609a08a3faSAdam Balogh ///
619a08a3faSAdam Balogh /// C O N T A I N E R   M O D I F I E R S
629a08a3faSAdam Balogh ///
639a08a3faSAdam Balogh ////////////////////////////////////////////////////////////////////////////////
649a08a3faSAdam Balogh 
659a08a3faSAdam Balogh /// push_back()
669a08a3faSAdam Balogh ///
67a3f4d17aSAdam Balogh /// Design decision: extends containers to the ->BACK-> (i.e. the
689a08a3faSAdam Balogh /// past-the-end position of the container is incremented).
699a08a3faSAdam Balogh 
70a3f4d17aSAdam Balogh void clang_analyzer_dump(void*);
71a3f4d17aSAdam Balogh 
push_back(std::vector<int> & V,int n)729a08a3faSAdam Balogh void push_back(std::vector<int> &V, int n) {
739a08a3faSAdam Balogh   V.cbegin();
749a08a3faSAdam Balogh   V.cend();
759a08a3faSAdam Balogh 
769a08a3faSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
779a08a3faSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
789a08a3faSAdam Balogh 
79*1a27d63aSAdam Balogh   V.push_back(n); // expected-note 2{{Container 'V' extended to the back by 1 position}}
809a08a3faSAdam Balogh 
819a08a3faSAdam Balogh   clang_analyzer_express(clang_analyzer_container_begin(V)); // expected-warning{{$V.begin()}}
82a3f4d17aSAdam Balogh                                                              // expected-note@-1{{$V.begin()}}
839a08a3faSAdam Balogh   clang_analyzer_express(clang_analyzer_container_end(V)); // expected-warning{{$V.end() + 1}}
84a3f4d17aSAdam Balogh                                                            // expected-note@-1{{$V.end() + 1}}
859a08a3faSAdam Balogh }
869a08a3faSAdam Balogh 
879a08a3faSAdam Balogh /// emplace_back()
889a08a3faSAdam Balogh ///
89a3f4d17aSAdam Balogh /// Design decision: extends containers to the ->BACK-> (i.e. the
909a08a3faSAdam Balogh /// past-the-end position of the container is incremented).
919a08a3faSAdam Balogh 
emplace_back(std::vector<int> & V,int n)929a08a3faSAdam Balogh void emplace_back(std::vector<int> &V, int n) {
939a08a3faSAdam Balogh   V.cbegin();
949a08a3faSAdam Balogh   V.cend();
959a08a3faSAdam Balogh 
969a08a3faSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
979a08a3faSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
989a08a3faSAdam Balogh 
99a3f4d17aSAdam Balogh   V.emplace_back(n); // expected-note 2{{Container 'V' extended to the back by 1 position}}
100a3f4d17aSAdam Balogh 
1019a08a3faSAdam Balogh   clang_analyzer_express(clang_analyzer_container_begin(V)); // expected-warning{{$V.begin()}}
102a3f4d17aSAdam Balogh                                                              // expected-note@-1{{$V.begin()}}
1039a08a3faSAdam Balogh   clang_analyzer_express(clang_analyzer_container_end(V)); // expected-warning{{$V.end() + 1}}
104a3f4d17aSAdam Balogh                                                            // expected-note@-1{{$V.end() + 1}}
1059a08a3faSAdam Balogh }
1069a08a3faSAdam Balogh 
1079a08a3faSAdam Balogh /// pop_back()
1089a08a3faSAdam Balogh ///
109a3f4d17aSAdam Balogh /// Design decision: shrinks containers to the <-FRONT<- (i.e. the
1109a08a3faSAdam Balogh /// past-the-end position of the container is decremented).
1119a08a3faSAdam Balogh 
pop_back(std::vector<int> & V,int n)1129a08a3faSAdam Balogh void pop_back(std::vector<int> &V, int n) {
1139a08a3faSAdam Balogh   V.cbegin();
1149a08a3faSAdam Balogh   V.cend();
1159a08a3faSAdam Balogh 
1169a08a3faSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_begin(V), "$V.begin()");
1179a08a3faSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
1189a08a3faSAdam Balogh 
119a3f4d17aSAdam Balogh   V.pop_back(); // expected-note 2{{Container 'V' shrank from the back by 1 position}}
120a3f4d17aSAdam Balogh 
1219a08a3faSAdam Balogh 
1229a08a3faSAdam Balogh   clang_analyzer_express(clang_analyzer_container_begin(V)); // expected-warning{{$V.begin()}}
123a3f4d17aSAdam Balogh                                                              // expected-note@-1{{$V.begin()}}
1249a08a3faSAdam Balogh   clang_analyzer_express(clang_analyzer_container_end(V)); // expected-warning{{$V.end() - 1}}
125a3f4d17aSAdam Balogh                                                            // expected-note@-1{{$V.end() - 1}}
1269a08a3faSAdam Balogh }
1279a08a3faSAdam Balogh 
1289a08a3faSAdam Balogh /// push_front()
1299a08a3faSAdam Balogh ///
130a3f4d17aSAdam Balogh /// Design decision: extends containers to the <-FRONT<- (i.e. the first
1319a08a3faSAdam Balogh /// position of the container is decremented).
1329a08a3faSAdam Balogh 
push_front(std::list<int> & L,int n)133a3f4d17aSAdam Balogh void push_front(std::list<int> &L, int n) {
134a3f4d17aSAdam Balogh   L.cbegin();
135a3f4d17aSAdam Balogh   L.cend();
1369a08a3faSAdam Balogh 
137a3f4d17aSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
138a3f4d17aSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
1399a08a3faSAdam Balogh 
140a3f4d17aSAdam Balogh   L.push_front(n); // expected-note 2{{Container 'L' extended to the front by 1 position}}
1419a08a3faSAdam Balogh 
142a3f4d17aSAdam Balogh   clang_analyzer_express(clang_analyzer_container_begin(L)); // expected-warning{{$L.begin() - 1}}
143a3f4d17aSAdam Balogh                                                              // expected-note@-1{{$L.begin() - 1}}
144a3f4d17aSAdam Balogh   clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
145a3f4d17aSAdam Balogh                                                            // expected-note@-1{{$L.end()}}
1469a08a3faSAdam Balogh }
1479a08a3faSAdam Balogh 
1489a08a3faSAdam Balogh /// emplace_front()
1499a08a3faSAdam Balogh ///
150a3f4d17aSAdam Balogh /// Design decision: extends containers to the <-FRONT<- (i.e. the first
1519a08a3faSAdam Balogh /// position of the container is decremented).
1529a08a3faSAdam Balogh 
emplace_front(std::list<int> & L,int n)153a3f4d17aSAdam Balogh void emplace_front(std::list<int> &L, int n) {
154a3f4d17aSAdam Balogh   L.cbegin();
155a3f4d17aSAdam Balogh   L.cend();
1569a08a3faSAdam Balogh 
157a3f4d17aSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
158a3f4d17aSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
1599a08a3faSAdam Balogh 
160a3f4d17aSAdam Balogh   L.emplace_front(n); // expected-note 2{{Container 'L' extended to the front by 1 position}}
1619a08a3faSAdam Balogh 
162a3f4d17aSAdam Balogh   clang_analyzer_express(clang_analyzer_container_begin(L)); // expected-warning{{$L.begin() - 1}}
163a3f4d17aSAdam Balogh                                                              // expected-note@-1{{$L.begin() - 1}}
164a3f4d17aSAdam Balogh   clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
165a3f4d17aSAdam Balogh                                                            // expected-note@-1{{$L.end()}}
1669a08a3faSAdam Balogh }
1679a08a3faSAdam Balogh 
1689a08a3faSAdam Balogh /// pop_front()
1699a08a3faSAdam Balogh ///
170a3f4d17aSAdam Balogh /// Design decision: shrinks containers to the ->BACK-> (i.e. the first
1719a08a3faSAdam Balogh /// position of the container is incremented).
1729a08a3faSAdam Balogh 
pop_front(std::list<int> & L,int n)173a3f4d17aSAdam Balogh void pop_front(std::list<int> &L, int n) {
174a3f4d17aSAdam Balogh   L.cbegin();
175a3f4d17aSAdam Balogh   L.cend();
1769a08a3faSAdam Balogh 
177a3f4d17aSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_begin(L), "$L.begin()");
178a3f4d17aSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_end(L), "$L.end()");
1799a08a3faSAdam Balogh 
180a3f4d17aSAdam Balogh   L.pop_front(); // expected-note 2{{Container 'L' shrank from the front by 1 position}}
1819a08a3faSAdam Balogh 
182a3f4d17aSAdam Balogh   clang_analyzer_express(clang_analyzer_container_begin(L)); // expected-warning{{$L.begin() + 1}}
183a3f4d17aSAdam Balogh                                                              // expected-note@-1{{$L.begin() + 1}}
184a3f4d17aSAdam Balogh   clang_analyzer_express(clang_analyzer_container_end(L)); // expected-warning{{$L.end()}}
185a3f4d17aSAdam Balogh                                                            // expected-note@-1{{$L.end()}}
1869a08a3faSAdam Balogh }
1879a08a3faSAdam Balogh 
188a3f4d17aSAdam Balogh ////////////////////////////////////////////////////////////////////////////////
189a3f4d17aSAdam Balogh ///
190a3f4d17aSAdam Balogh /// O T H E R   T E S T S
191a3f4d17aSAdam Balogh ///
192a3f4d17aSAdam Balogh ////////////////////////////////////////////////////////////////////////////////
193a3f4d17aSAdam Balogh 
194a3f4d17aSAdam Balogh /// Track local variable
195a3f4d17aSAdam Balogh 
push_back()196a3f4d17aSAdam Balogh void push_back() {
197a3f4d17aSAdam Balogh   std::vector<int> V;
198a3f4d17aSAdam Balogh   V.end();
199a3f4d17aSAdam Balogh 
200a3f4d17aSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_end(V), "$V.end()");
201a3f4d17aSAdam Balogh 
202a3f4d17aSAdam Balogh   V.push_back(1); // expected-note{{Container 'V' extended to the back by 1 position}}
203a3f4d17aSAdam Balogh 
204a3f4d17aSAdam Balogh   clang_analyzer_express(clang_analyzer_container_end(V)); // expected-warning{{$V.end() + 1}}
205a3f4d17aSAdam Balogh                                                            // expected-note@-1{{$V.end() + 1}}
206a3f4d17aSAdam Balogh }
207a3f4d17aSAdam Balogh 
208a3f4d17aSAdam Balogh /// Track the right container only
209a3f4d17aSAdam Balogh 
push_back1(std::vector<int> & V1,std::vector<int> & V2,int n)210a3f4d17aSAdam Balogh void push_back1(std::vector<int> &V1, std::vector<int> &V2, int n) {
211a3f4d17aSAdam Balogh   V1.cbegin();
212a3f4d17aSAdam Balogh   V1.cend();
213a3f4d17aSAdam Balogh   V2.cbegin();
214a3f4d17aSAdam Balogh   V2.cend();
215a3f4d17aSAdam Balogh 
216a3f4d17aSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_begin(V1), "$V1.begin()");
217a3f4d17aSAdam Balogh 
218*1a27d63aSAdam Balogh   V2.push_back(n); // no-note
219a3f4d17aSAdam Balogh 
220a3f4d17aSAdam Balogh   clang_analyzer_express(clang_analyzer_container_begin(V1)); // expected-warning{{$V1.begin()}}
221a3f4d17aSAdam Balogh                                                               // expected-note@-1{{$V1.begin()}}
222a3f4d17aSAdam Balogh }
223a3f4d17aSAdam Balogh 
push_back2(std::vector<int> & V1,std::vector<int> & V2,int n)224a3f4d17aSAdam Balogh void push_back2(std::vector<int> &V1, std::vector<int> &V2, int n) {
225a3f4d17aSAdam Balogh   V1.cbegin();
226a3f4d17aSAdam Balogh   V1.cend();
227a3f4d17aSAdam Balogh   V2.cbegin();
228a3f4d17aSAdam Balogh   V2.cend();
229a3f4d17aSAdam Balogh 
230a3f4d17aSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_begin(V1), "$V1.begin()");
231a3f4d17aSAdam Balogh   clang_analyzer_denote(clang_analyzer_container_begin(V2), "$V2.begin()");
232a3f4d17aSAdam Balogh 
233*1a27d63aSAdam Balogh   V1.push_back(n); // expected-note{{Container 'V1' extended to the back by 1 position}}
234*1a27d63aSAdam Balogh                    // Only once!
235a3f4d17aSAdam Balogh 
236a3f4d17aSAdam Balogh   clang_analyzer_express(clang_analyzer_container_begin(V1)); // expected-warning{{$V1.begin()}}
237a3f4d17aSAdam Balogh                                                               // expected-note@-1{{$V1.begin()}}
238a3f4d17aSAdam Balogh 
239a3f4d17aSAdam Balogh   clang_analyzer_express(clang_analyzer_container_begin(V2)); // expected-warning{{$V2.begin()}}
240a3f4d17aSAdam Balogh                                                               // expected-note@-1{{$V2.begin()}}
241a3f4d17aSAdam Balogh }
242a3f4d17aSAdam Balogh 
243a3f4d17aSAdam Balogh /// Print Container Data as Part of the Program State
244a3f4d17aSAdam Balogh 
2459a08a3faSAdam Balogh void clang_analyzer_printState();
2469a08a3faSAdam Balogh 
print_state(std::vector<int> & V)2479a08a3faSAdam Balogh void print_state(std::vector<int> &V) {
2489a08a3faSAdam Balogh   V.cbegin();
2499a08a3faSAdam Balogh   clang_analyzer_printState();
2509a08a3faSAdam Balogh 
2519a08a3faSAdam Balogh // CHECK:      "checker_messages": [
2529a08a3faSAdam Balogh // CHECK-NEXT:   { "checker": "alpha.cplusplus.ContainerModeling", "messages": [
2539a08a3faSAdam Balogh // CHECK-NEXT:     "Container Data :",
2549a08a3faSAdam Balogh // CHECK-NEXT:     "SymRegion{reg_$[[#]]<std::vector<int> & V>} : [ conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]} .. <Unknown> ]"
2559a08a3faSAdam Balogh // CHECK-NEXT:   ]}
2569a08a3faSAdam Balogh 
2579a08a3faSAdam Balogh   V.cend();
2589a08a3faSAdam Balogh   clang_analyzer_printState();
2599a08a3faSAdam Balogh 
2609a08a3faSAdam Balogh // CHECK:      "checker_messages": [
2619a08a3faSAdam Balogh // CHECK-NEXT:   { "checker": "alpha.cplusplus.ContainerModeling", "messages": [
2629a08a3faSAdam Balogh // CHECK-NEXT:     "Container Data :",
2639a08a3faSAdam Balogh // CHECK-NEXT:     "SymRegion{reg_$[[#]]<std::vector<int> & V>} : [ conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]} .. conj_$[[#]]{long, LC[[#]], S[[#]], #[[#]]} ]"
2649a08a3faSAdam Balogh // CHECK-NEXT:   ]}
2659a08a3faSAdam Balogh }
266