1 // RUN: %clang_cc1 -analyze -analyzer-checker=optin.mpi.MPI-Checker -verify %s
2
3 #include "MPIMock.h"
4
matchedWait1()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
matchedWait2()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
matchedWait3()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
missingWait1()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
missingWait2()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
doubleNonblocking()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
doubleNonblocking2()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
doubleNonblocking3()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
doubleNonblocking4()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
tripleNonblocking()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
missingNonBlocking()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
missingNonBlocking2()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
missingNonBlocking3()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
missingNonBlockingMultiple()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
missingNonBlockingWaitall()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
missingNonBlockingWaitall2()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
missingNonBlockingWaitall3()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
missingNonBlockingWaitall4()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
noDoubleRequestUsage()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
noDoubleRequestUsage2()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
nestedRequest()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
singleRequestInWaitall()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
multiRequestUsage()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
multiRequestUsage2()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
callNonblocking(MPI_Request * req)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
callWait(MPI_Request * req)318 void callWait(MPI_Request *req) {
319 MPI_Wait(req, MPI_STATUS_IGNORE);
320 }
321
322 // Call nonblocking, wait wrapper functions.
callWrapperFunctions()323 void callWrapperFunctions() {
324 MPI_Request req;
325 callNonblocking(&req);
326 callWait(&req);
327 } // no error
328
externFunctions1()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
externFunctions2()338 void externFunctions2() {
339 MPI_Request req;
340 void callNonblockingExtern(MPI_Request *req);
341 callNonblockingExtern(&req);
342 }
343