1 | // RUN: %clang_analyze_cc1 -analyzer-checker=optin.mpi.MPI-Checker -verify %s |
2 | |
3 | #include "MPIMock.h" |
4 | |
5 | void matchedWait1() { |
6 | int rank = 0; |
7 | double buf = 0; |
8 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
9 | if (rank >= 0) { |
10 | MPI_Request sendReq1, recvReq1; |
11 | MPI_Isend(&buf, 1, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD, &sendReq1); |
12 | MPI_Irecv(&buf, 1, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD, &recvReq1); |
13 | |
14 | MPI_Wait(&sendReq1, MPI_STATUS_IGNORE); |
15 | MPI_Wait(&recvReq1, MPI_STATUS_IGNORE); |
16 | } |
17 | } // no error |
18 | |
19 | void matchedWait2() { |
20 | int rank = 0; |
21 | double buf = 0; |
22 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
23 | if (rank >= 0) { |
24 | MPI_Request sendReq1, recvReq1; |
25 | MPI_Isend(&buf, 1, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD, &sendReq1); |
26 | MPI_Irecv(&buf, 1, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD, &recvReq1); |
27 | MPI_Wait(&sendReq1, MPI_STATUS_IGNORE); |
28 | MPI_Wait(&recvReq1, MPI_STATUS_IGNORE); |
29 | } |
30 | } // no error |
31 | |
32 | void matchedWait3() { |
33 | int rank = 0; |
34 | double buf = 0; |
35 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
36 | if (rank >= 0) { |
37 | MPI_Request sendReq1, recvReq1; |
38 | MPI_Isend(&buf, 1, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD, &sendReq1); |
39 | MPI_Irecv(&buf, 1, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD, &recvReq1); |
40 | |
41 | if (rank > 1000) { |
42 | MPI_Wait(&sendReq1, MPI_STATUS_IGNORE); |
43 | MPI_Wait(&recvReq1, MPI_STATUS_IGNORE); |
44 | } else { |
45 | MPI_Wait(&sendReq1, MPI_STATUS_IGNORE); |
46 | MPI_Wait(&recvReq1, MPI_STATUS_IGNORE); |
47 | } |
48 | } |
49 | } // no error |
50 | |
51 | void missingWait1() { // Check missing wait for dead region. |
52 | double buf = 0; |
53 | MPI_Request sendReq1; |
54 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, &sendReq1); |
55 | } // expected-warning{{Request 'sendReq1' has no matching wait.}} |
56 | |
57 | void missingWait2() { |
58 | int rank = 0; |
59 | double buf = 0; |
60 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
61 | if (rank == 0) { |
62 | } else { |
63 | MPI_Request sendReq1, recvReq1; |
64 | |
65 | MPI_Isend(&buf, 1, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD, &sendReq1); |
66 | MPI_Irecv(&buf, 1, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD, &recvReq1); // expected-warning{{Request 'sendReq1' has no matching wait.}} |
67 | MPI_Wait(&recvReq1, MPI_STATUS_IGNORE); |
68 | } |
69 | } |
70 | |
71 | void doubleNonblocking() { |
72 | int rank = 0; |
73 | double buf = 0; |
74 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
75 | if (rank == 1) { |
76 | } else { |
77 | MPI_Request sendReq1; |
78 | |
79 | MPI_Isend(&buf, 1, MPI_DOUBLE, rank + 1, 0, MPI_COMM_WORLD, &sendReq1); |
80 | MPI_Irecv(&buf, 1, MPI_DOUBLE, rank - 1, 0, MPI_COMM_WORLD, &sendReq1); // expected-warning{{Double nonblocking on request 'sendReq1'.}} |
81 | MPI_Wait(&sendReq1, MPI_STATUS_IGNORE); |
82 | } |
83 | } |
84 | |
85 | void doubleNonblocking2() { |
86 | int rank = 0; |
87 | double buf = 0; |
88 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
89 | |
90 | MPI_Request req; |
91 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, &req); |
92 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, &req); // expected-warning{{Double nonblocking on request 'req'.}} |
93 | MPI_Wait(&req, MPI_STATUS_IGNORE); |
94 | } |
95 | |
96 | void doubleNonblocking3() { |
97 | typedef struct { MPI_Request req; } ReqStruct; |
98 | |
99 | ReqStruct rs; |
100 | int rank = 0; |
101 | double buf = 0; |
102 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
103 | |
104 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, &rs.req); |
105 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, &rs.req); // expected-warning{{Double nonblocking on request 'rs.req'.}} |
106 | MPI_Wait(&rs.req, MPI_STATUS_IGNORE); |
107 | } |
108 | |
109 | void doubleNonblocking4() { |
110 | int rank = 0; |
111 | double buf = 0; |
112 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
113 | |
114 | MPI_Request req; |
115 | for (int i = 0; i < 2; ++i) { |
116 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, &req); // expected-warning{{Double nonblocking on request 'req'.}} |
117 | } |
118 | MPI_Wait(&req, MPI_STATUS_IGNORE); |
119 | } |
120 | |
121 | void tripleNonblocking() { |
122 | double buf = 0; |
123 | MPI_Request sendReq; |
124 | MPI_Isend(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq); |
125 | MPI_Irecv(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq); // expected-warning{{Double nonblocking on request 'sendReq'.}} |
126 | MPI_Isend(&buf, 1, MPI_DOUBLE, 0, 0, MPI_COMM_WORLD, &sendReq); // expected-warning{{Double nonblocking on request 'sendReq'.}} |
127 | MPI_Wait(&sendReq, MPI_STATUS_IGNORE); |
128 | } |
129 | |
130 | void missingNonBlocking() { |
131 | int rank = 0; |
132 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
133 | MPI_Request sendReq1[10][10][10]; |
134 | MPI_Wait(&sendReq1[1][7][9], MPI_STATUS_IGNORE); // expected-warning{{Request 'sendReq1[1][7][9]' has no matching nonblocking call.}} |
135 | } |
136 | |
137 | void missingNonBlocking2() { |
138 | int rank = 0; |
139 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
140 | typedef struct { MPI_Request req[2][2]; } ReqStruct; |
141 | ReqStruct rs; |
142 | MPI_Request *r = &rs.req[0][1]; |
143 | MPI_Wait(r, MPI_STATUS_IGNORE); // expected-warning{{Request 'rs.req[0][1]' has no matching nonblocking call.}} |
144 | } |
145 | |
146 | void missingNonBlocking3() { |
147 | int rank = 0; |
148 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
149 | MPI_Request sendReq; |
150 | MPI_Wait(&sendReq, MPI_STATUS_IGNORE); // expected-warning{{Request 'sendReq' has no matching nonblocking call.}} |
151 | } |
152 | |
153 | void missingNonBlockingMultiple() { |
154 | int rank = 0; |
155 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
156 | MPI_Request sendReq[4]; |
157 | for (int i = 0; i < 4; ++i) { |
158 | MPI_Wait(&sendReq[i], MPI_STATUS_IGNORE); // expected-warning-re 1+{{Request {{.*}} has no matching nonblocking call.}} |
159 | } |
160 | } |
161 | |
162 | void missingNonBlockingWaitall() { |
163 | int rank = 0; |
164 | double buf = 0; |
165 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
166 | MPI_Request req[4]; |
167 | |
168 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
169 | &req[0]); |
170 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
171 | &req[1]); |
172 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
173 | &req[3]); |
174 | |
175 | MPI_Waitall(4, req, MPI_STATUSES_IGNORE); // expected-warning{{Request 'req[2]' has no matching nonblocking call.}} |
176 | } |
177 | |
178 | void missingNonBlockingWaitall2() { |
179 | int rank = 0; |
180 | double buf = 0; |
181 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
182 | MPI_Request req[4]; |
183 | |
184 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
185 | &req[0]); |
186 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
187 | &req[3]); |
188 | |
189 | MPI_Waitall(4, req, MPI_STATUSES_IGNORE); // expected-warning-re 2{{Request '{{(.*)[[1-2]](.*)}}' has no matching nonblocking call.}} |
190 | } |
191 | |
192 | void missingNonBlockingWaitall3() { |
193 | int rank = 0; |
194 | double buf = 0; |
195 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
196 | MPI_Request req[4]; |
197 | |
198 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
199 | &req[0]); |
200 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
201 | &req[2]); |
202 | |
203 | MPI_Waitall(4, req, MPI_STATUSES_IGNORE); // expected-warning-re 2{{Request '{{(.*)[[1,3]](.*)}}' has no matching nonblocking call.}} |
204 | } |
205 | |
206 | void missingNonBlockingWaitall4() { |
207 | int rank = 0; |
208 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
209 | MPI_Request req[4]; |
210 | MPI_Waitall(4, req, MPI_STATUSES_IGNORE); // expected-warning-re 4{{Request '{{(.*)[[0-3]](.*)}}' has no matching nonblocking call.}} |
211 | } |
212 | |
213 | void noDoubleRequestUsage() { |
214 | typedef struct { |
215 | MPI_Request req; |
216 | MPI_Request req2; |
217 | } ReqStruct; |
218 | |
219 | ReqStruct rs; |
220 | int rank = 0; |
221 | double buf = 0; |
222 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
223 | |
224 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
225 | &rs.req); |
226 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
227 | &rs.req2); |
228 | MPI_Wait(&rs.req, MPI_STATUS_IGNORE); |
229 | MPI_Wait(&rs.req2, MPI_STATUS_IGNORE); |
230 | } // no error |
231 | |
232 | void noDoubleRequestUsage2() { |
233 | typedef struct { |
234 | MPI_Request req[2]; |
235 | MPI_Request req2; |
236 | } ReqStruct; |
237 | |
238 | ReqStruct rs; |
239 | int rank = 0; |
240 | double buf = 0; |
241 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
242 | |
243 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
244 | &rs.req[0]); |
245 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
246 | &rs.req[1]); |
247 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
248 | &rs.req2); |
249 | MPI_Wait(&rs.req[0], MPI_STATUS_IGNORE); |
250 | MPI_Wait(&rs.req[1], MPI_STATUS_IGNORE); |
251 | MPI_Wait(&rs.req2, MPI_STATUS_IGNORE); |
252 | } // no error |
253 | |
254 | void nestedRequest() { |
255 | typedef struct { |
256 | MPI_Request req[2]; |
257 | MPI_Request req2; |
258 | } ReqStruct; |
259 | |
260 | ReqStruct rs; |
261 | int rank = 0; |
262 | double buf = 0; |
263 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
264 | |
265 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
266 | &rs.req[0]); |
267 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
268 | &rs.req[1]); |
269 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
270 | &rs.req2); |
271 | MPI_Waitall(2, rs.req, MPI_STATUSES_IGNORE); |
272 | MPI_Wait(&rs.req2, MPI_STATUS_IGNORE); |
273 | } // no error |
274 | |
275 | void singleRequestInWaitall() { |
276 | MPI_Request r; |
277 | int rank = 0; |
278 | double buf = 0; |
279 | MPI_Comm_rank(MPI_COMM_WORLD, &rank); |
280 | |
281 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
282 | &r); |
283 | MPI_Waitall(1, &r, MPI_STATUSES_IGNORE); |
284 | } // no error |
285 | |
286 | void multiRequestUsage() { |
287 | double buf = 0; |
288 | MPI_Request req; |
289 | |
290 | MPI_Isend(&buf, 1, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD, &req); |
291 | MPI_Wait(&req, MPI_STATUS_IGNORE); |
292 | |
293 | MPI_Irecv(&buf, 1, MPI_DOUBLE, 1, 0, MPI_COMM_WORLD, &req); |
294 | MPI_Wait(&req, MPI_STATUS_IGNORE); |
295 | } // no error |
296 | |
297 | void multiRequestUsage2() { |
298 | double buf = 0; |
299 | MPI_Request req; |
300 | |
301 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
302 | &req); |
303 | MPI_Wait(&req, MPI_STATUS_IGNORE); |
304 | |
305 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
306 | &req); |
307 | MPI_Wait(&req, MPI_STATUS_IGNORE); |
308 | } // no error |
309 | |
310 | // wrapper function |
311 | void callNonblocking(MPI_Request *req) { |
312 | double buf = 0; |
313 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
314 | req); |
315 | } |
316 | |
317 | // wrapper function |
318 | void callWait(MPI_Request *req) { |
319 | MPI_Wait(req, MPI_STATUS_IGNORE); |
320 | } |
321 | |
322 | // Call nonblocking, wait wrapper functions. |
323 | void callWrapperFunctions() { |
324 | MPI_Request req; |
325 | callNonblocking(&req); |
326 | callWait(&req); |
327 | } // no error |
328 | |
329 | void externFunctions1() { |
330 | double buf = 0; |
331 | MPI_Request req; |
332 | MPI_Ireduce(MPI_IN_PLACE, &buf, 1, MPI_DOUBLE, MPI_SUM, 0, MPI_COMM_WORLD, |
333 | &req); |
334 | void callWaitExtern(MPI_Request *req); |
335 | callWaitExtern(&req); |
336 | } // expected-warning{{Request 'req' has no matching wait.}} |
337 | |
338 | void externFunctions2() { |
339 | MPI_Request req; |
340 | void callNonblockingExtern(MPI_Request *req); |
341 | callNonblockingExtern(&req); |
342 | } |
343 | |