1 // RUN: %clang_analyze_cc1 -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