1 | // RUN: %clang_analyze_cc1 -w -verify %s\ |
2 | // RUN: -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks\ |
3 | // RUN: -analyzer-checker=debug.ExprInspection -std=c++11 |
4 | // RUN: %clang_analyze_cc1 -w -verify %s\ |
5 | // RUN: -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks\ |
6 | // RUN: -analyzer-checker=debug.ExprInspection -std=c++17 |
7 | // RUN: %clang_analyze_cc1 -w -verify %s\ |
8 | // RUN: -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks\ |
9 | // RUN: -analyzer-checker=debug.ExprInspection -std=c++11\ |
10 | // RUN: -DTEST_INLINABLE_ALLOCATORS |
11 | // RUN: %clang_analyze_cc1 -w -verify %s\ |
12 | // RUN: -analyzer-checker=core,unix.Malloc,cplusplus.NewDeleteLeaks\ |
13 | // RUN: -analyzer-checker=debug.ExprInspection -std=c++17\ |
14 | // RUN: -DTEST_INLINABLE_ALLOCATORS |
15 | |
16 | void clang_analyzer_eval(bool); |
17 | |
18 | #include "Inputs/system-header-simulator-cxx.h" |
19 | |
20 | class A { |
21 | int x; |
22 | public: |
23 | A(); |
24 | }; |
25 | |
26 | A::A() : x(0) { |
27 | clang_analyzer_eval(x == 0); // expected-warning{{TRUE}} |
28 | } |
29 | |
30 | |
31 | class DirectMember { |
32 | int x; |
33 | public: |
34 | DirectMember(int value) : x(value) {} |
35 | |
36 | int getX() { return x; } |
37 | }; |
38 | |
39 | void testDirectMember() { |
40 | DirectMember obj(3); |
41 | clang_analyzer_eval(obj.getX() == 3); // expected-warning{{TRUE}} |
42 | } |
43 | |
44 | |
45 | class IndirectMember { |
46 | struct { |
47 | int x; |
48 | }; |
49 | public: |
50 | IndirectMember(int value) : x(value) {} |
51 | |
52 | int getX() { return x; } |
53 | }; |
54 | |
55 | void testIndirectMember() { |
56 | IndirectMember obj(3); |
57 | clang_analyzer_eval(obj.getX() == 3); // expected-warning{{TRUE}} |
58 | } |
59 | |
60 | |
61 | struct DelegatingConstructor { |
62 | int x; |
63 | DelegatingConstructor(int y) { x = y; } |
64 | DelegatingConstructor() : DelegatingConstructor(42) {} |
65 | }; |
66 | |
67 | void testDelegatingConstructor() { |
68 | DelegatingConstructor obj; |
69 | clang_analyzer_eval(obj.x == 42); // expected-warning{{TRUE}} |
70 | } |
71 | |
72 | |
73 | struct RefWrapper { |
74 | RefWrapper(int *p) : x(*p) {} |
75 | RefWrapper(int &r) : x(r) {} |
76 | int &x; |
77 | }; |
78 | |
79 | void testReferenceMember() { |
80 | int *p = 0; |
81 | RefWrapper X(p); // expected-warning@-7 {{Dereference of null pointer}} |
82 | } |
83 | |
84 | void testReferenceMember2() { |
85 | int *p = 0; |
86 | RefWrapper X(*p); // expected-warning {{Forming reference to null pointer}} |
87 | } |
88 | |
89 | |
90 | extern "C" char *strdup(const char *); |
91 | |
92 | class StringWrapper { |
93 | char *str; |
94 | public: |
95 | StringWrapper(const char *input) : str(strdup(input)) {} // no-warning |
96 | }; |
97 | |
98 | |
99 | // PR15070 - Constructing a type containing a non-POD array mistakenly |
100 | // tried to perform a bind instead of relying on the CXXConstructExpr, |
101 | // which caused a cast<> failure in RegionStore. |
102 | namespace DefaultConstructorWithCleanups { |
103 | class Element { |
104 | public: |
105 | int value; |
106 | |
107 | class Helper { |
108 | public: |
109 | ~Helper(); |
110 | }; |
111 | Element(Helper h = Helper()); |
112 | }; |
113 | class Wrapper { |
114 | public: |
115 | Element arr[2]; |
116 | |
117 | Wrapper(); |
118 | }; |
119 | |
120 | Wrapper::Wrapper() /* initializers synthesized */ {} |
121 | |
122 | int test() { |
123 | Wrapper w; |
124 | return w.arr[0].value; // no-warning |
125 | } |
126 | } |
127 | |
128 | namespace DefaultMemberInitializers { |
129 | struct Wrapper { |
130 | int value = 42; |
131 | |
132 | Wrapper() {} |
133 | Wrapper(int x) : value(x) {} |
134 | Wrapper(bool) {} |
135 | }; |
136 | |
137 | void test() { |
138 | Wrapper w1; |
139 | clang_analyzer_eval(w1.value == 42); // expected-warning{{TRUE}} |
140 | |
141 | Wrapper w2(50); |
142 | clang_analyzer_eval(w2.value == 50); // expected-warning{{TRUE}} |
143 | |
144 | Wrapper w3(false); |
145 | clang_analyzer_eval(w3.value == 42); // expected-warning{{TRUE}} |
146 | } |
147 | |
148 | struct StringWrapper { |
149 | const char s[4] = "abc"; |
150 | const char *p = "xyz"; |
151 | |
152 | StringWrapper(bool) {} |
153 | }; |
154 | |
155 | void testString() { |
156 | StringWrapper w(true); |
157 | clang_analyzer_eval(w.s[1] == 'b'); // expected-warning{{TRUE}} |
158 | clang_analyzer_eval(w.p[1] == 'y'); // expected-warning{{TRUE}} |
159 | } |
160 | } |
161 | |
162 | namespace ReferenceInitialization { |
163 | struct OtherStruct { |
164 | OtherStruct(int i); |
165 | ~OtherStruct(); |
166 | }; |
167 | |
168 | struct MyStruct { |
169 | MyStruct(int i); |
170 | MyStruct(OtherStruct os); |
171 | |
172 | void method() const; |
173 | }; |
174 | |
175 | void referenceInitializeLocal() { |
176 | const MyStruct &myStruct(5); |
177 | myStruct.method(); // no-warning |
178 | } |
179 | |
180 | void referenceInitializeMultipleLocals() { |
181 | const MyStruct &myStruct1(5), myStruct2(5), &myStruct3(5); |
182 | myStruct1.method(); // no-warning |
183 | myStruct2.method(); // no-warning |
184 | myStruct3.method(); // no-warning |
185 | } |
186 | |
187 | void referenceInitializeLocalWithCleanup() { |
188 | const MyStruct &myStruct(OtherStruct(5)); |
189 | myStruct.method(); // no-warning |
190 | } |
191 | }; |
192 | |
193 | namespace PR31592 { |
194 | struct C { |
195 | C() : f("}") { } // no-crash |
196 | const char(&f)[2]; |
197 | }; |
198 | } |
199 | |
200 | namespace CXX_initializer_lists { |
201 | struct C { |
202 | C(std::initializer_list<int *> list); |
203 | }; |
204 | void testPointerEscapeIntoLists() { |
205 | C empty{}; // no-crash |
206 | |
207 | // Do not warn that 'x' leaks. It might have been deleted by |
208 | // the destructor of 'c'. |
209 | int *x = new int; |
210 | C c{x}; // no-warning |
211 | } |
212 | |
213 | void testPassListsWithExplicitConstructors() { |
214 | (void)(std::initializer_list<int>){12}; // no-crash |
215 | } |
216 | } |
217 | |
218 | namespace CXX17_aggregate_construction { |
219 | struct A { |
220 | A(); |
221 | }; |
222 | |
223 | struct B: public A { |
224 | }; |
225 | |
226 | struct C: public B { |
227 | }; |
228 | |
229 | struct D: public virtual A { |
230 | }; |
231 | |
232 | // In C++17, classes B and C are aggregates, so they will be constructed |
233 | // without actually calling their trivial constructor. Used to crash. |
234 | void foo() { |
235 | B b = {}; // no-crash |
236 | const B &bl = {}; // no-crash |
237 | B &&br = {}; // no-crash |
238 | |
239 | C c = {}; // no-crash |
240 | const C &cl = {}; // no-crash |
241 | C &&cr = {}; // no-crash |
242 | |
243 | D d = {}; // no-crash |
244 | |
245 | #if __cplusplus >= 201703L |
246 | C cd = {{}}; // no-crash |
247 | const C &cdl = {{}}; // no-crash |
248 | C &&cdr = {{}}; // no-crash |
249 | |
250 | const B &bll = {{}}; // no-crash |
251 | const B &bcl = C({{}}); // no-crash |
252 | B &&bcr = C({{}}); // no-crash |
253 | #endif |
254 | } |
255 | } // namespace CXX17_aggregate_construction |
256 | |
257 | namespace CXX17_transparent_init_list_exprs { |
258 | class A {}; |
259 | |
260 | class B: private A {}; |
261 | |
262 | B boo(); |
263 | void foo1() { |
264 | B b { boo() }; // no-crash |
265 | } |
266 | |
267 | class C: virtual public A {}; |
268 | |
269 | C coo(); |
270 | void foo2() { |
271 | C c { coo() }; // no-crash |
272 | } |
273 | |
274 | B foo_recursive() { |
275 | B b { foo_recursive() }; |
276 | } |
277 | } // namespace CXX17_transparent_init_list_exprs |
278 | |