1 | // RUN: %clang_cc1 -std=c99 -DOPEN_MPI -fsyntax-only -verify %s |
2 | // RUN: %clang_cc1 -std=c99 -DMPICH -fsyntax-only -verify %s |
3 | // RUN: %clang_cc1 -x c++ -std=c++98 -DOPEN_MPI -fsyntax-only -verify %s |
4 | // RUN: %clang_cc1 -x c++ -std=c++98 -DMPICH -fsyntax-only -verify %s |
5 | // |
6 | // RUN: %clang_cc1 -std=c99 -DOPEN_MPI -fno-signed-char -fsyntax-only -verify %s |
7 | // RUN: %clang_cc1 -std=c99 -DMPICH -fno-signed-char -fsyntax-only -verify %s |
8 | |
9 | //===--- limits.h mock ----------------------------------------------------===// |
10 | |
11 | #ifdef __CHAR_UNSIGNED__ |
12 | #define CHAR_MIN 0 |
13 | #define CHAR_MAX (__SCHAR_MAX__*2 +1) |
14 | #else |
15 | #define CHAR_MIN (-__SCHAR_MAX__-1) |
16 | #define CHAR_MAX __SCHAR_MAX__ |
17 | #endif |
18 | |
19 | //===--- mpi.h mock -------------------------------------------------------===// |
20 | |
21 | #define NULL ((void *)0) |
22 | |
23 | #ifdef OPEN_MPI |
24 | typedef struct ompi_datatype_t *MPI_Datatype; |
25 | #endif |
26 | |
27 | #ifdef MPICH |
28 | typedef int MPI_Datatype; |
29 | #endif |
30 | |
31 | int MPI_Send(void *buf, int count, MPI_Datatype datatype) |
32 | __attribute__(( pointer_with_type_tag(mpi,1,3) )); |
33 | |
34 | int MPI_Gather(void *sendbuf, int sendcount, MPI_Datatype sendtype, |
35 | void *recvbuf, int recvcount, MPI_Datatype recvtype) |
36 | __attribute__(( pointer_with_type_tag(mpi,1,3), pointer_with_type_tag(mpi,4,6) )); |
37 | |
38 | #ifdef OPEN_MPI |
39 | // OpenMPI and LAM/MPI-style datatype definitions |
40 | |
41 | #define OMPI_PREDEFINED_GLOBAL(type, global) ((type) &(global)) |
42 | |
43 | #define MPI_DATATYPE_NULL OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_datatype_null) |
44 | #define MPI_FLOAT OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_float) |
45 | #define MPI_INT OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_int) |
46 | #define MPI_LONG OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_long) |
47 | #define MPI_LONG_LONG_INT OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_long_long_int) |
48 | #define MPI_CHAR OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_char) |
49 | |
50 | #define MPI_FLOAT_INT OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_float_int) |
51 | #define MPI_2INT OMPI_PREDEFINED_GLOBAL(MPI_Datatype, ompi_mpi_2int) |
52 | |
53 | #define MPI_IN_PLACE ((void *) 1) |
54 | |
55 | extern struct ompi_predefined_datatype_t ompi_mpi_datatype_null __attribute__(( type_tag_for_datatype(mpi,void,must_be_null) )); |
56 | extern struct ompi_predefined_datatype_t ompi_mpi_float __attribute__(( type_tag_for_datatype(mpi,float) )); |
57 | extern struct ompi_predefined_datatype_t ompi_mpi_int __attribute__(( type_tag_for_datatype(mpi,int) )); |
58 | extern struct ompi_predefined_datatype_t ompi_mpi_long __attribute__(( type_tag_for_datatype(mpi,long) )); |
59 | extern struct ompi_predefined_datatype_t ompi_mpi_long_long_int __attribute__(( type_tag_for_datatype(mpi,long long int) )); |
60 | extern struct ompi_predefined_datatype_t ompi_mpi_char __attribute__(( type_tag_for_datatype(mpi,char) )); |
61 | |
62 | struct ompi_struct_mpi_float_int {float f; int i;}; |
63 | extern struct ompi_predefined_datatype_t ompi_mpi_float_int __attribute__(( type_tag_for_datatype(mpi, struct ompi_struct_mpi_float_int, layout_compatible) )); |
64 | |
65 | struct ompi_struct_mpi_2int {int i1; int i2;}; |
66 | extern struct ompi_predefined_datatype_t ompi_mpi_2int __attribute__(( type_tag_for_datatype(mpi, struct ompi_struct_mpi_2int, layout_compatible) )); |
67 | #endif |
68 | |
69 | #ifdef MPICH |
70 | // MPICH2 and MVAPICH2-style datatype definitions |
71 | |
72 | #define MPI_COMM_WORLD ((MPI_Comm) 0x44000000) |
73 | |
74 | #define MPI_DATATYPE_NULL ((MPI_Datatype) 0xa0000000) |
75 | #define MPI_FLOAT ((MPI_Datatype) 0xa0000001) |
76 | #define MPI_INT ((MPI_Datatype) 0xa0000002) |
77 | #define MPI_LONG ((MPI_Datatype) 0xa0000003) |
78 | #define MPI_LONG_LONG_INT ((MPI_Datatype) 0xa0000004) |
79 | #define MPI_CHAR ((MPI_Datatype) 0xa0000005) |
80 | |
81 | #define MPI_FLOAT_INT ((MPI_Datatype) 0xa0000006) |
82 | #define MPI_2INT ((MPI_Datatype) 0xa0000007) |
83 | |
84 | #define MPI_IN_PLACE (void *) -1 |
85 | |
86 | static const MPI_Datatype mpich_mpi_datatype_null __attribute__(( type_tag_for_datatype(mpi,void,must_be_null) )) = 0xa0000000; |
87 | static const MPI_Datatype mpich_mpi_float __attribute__(( type_tag_for_datatype(mpi,float) )) = 0xa0000001; |
88 | static const MPI_Datatype mpich_mpi_int __attribute__(( type_tag_for_datatype(mpi,int) )) = 0xa0000002; |
89 | static const MPI_Datatype mpich_mpi_long __attribute__(( type_tag_for_datatype(mpi,long) )) = 0xa0000003; |
90 | static const MPI_Datatype mpich_mpi_long_long_int __attribute__(( type_tag_for_datatype(mpi,long long int) )) = 0xa0000004; |
91 | static const MPI_Datatype mpich_mpi_char __attribute__(( type_tag_for_datatype(mpi,char) )) = 0xa0000005; |
92 | |
93 | struct mpich_struct_mpi_float_int { float f; int i; }; |
94 | struct mpich_struct_mpi_2int { int i1; int i2; }; |
95 | static const MPI_Datatype mpich_mpi_float_int __attribute__(( type_tag_for_datatype(mpi, struct mpich_struct_mpi_float_int, layout_compatible) )) = 0xa0000006; |
96 | static const MPI_Datatype mpich_mpi_2int __attribute__(( type_tag_for_datatype(mpi, struct mpich_struct_mpi_2int, layout_compatible) )) = 0xa0000007; |
97 | #endif |
98 | |
99 | //===--- HDF5 headers mock ------------------------------------------------===// |
100 | |
101 | typedef int hid_t; |
102 | void H5open(void); |
103 | |
104 | #ifndef HDF_PRIVATE |
105 | #define H5OPEN H5open(), |
106 | #else |
107 | #define H5OPEN |
108 | #endif |
109 | |
110 | #define H5T_NATIVE_CHAR (CHAR_MIN?H5T_NATIVE_SCHAR:H5T_NATIVE_UCHAR) |
111 | #define H5T_NATIVE_SCHAR (H5OPEN H5T_NATIVE_SCHAR_g) |
112 | #define H5T_NATIVE_UCHAR (H5OPEN H5T_NATIVE_UCHAR_g) |
113 | #define H5T_NATIVE_INT (H5OPEN H5T_NATIVE_INT_g) |
114 | #define H5T_NATIVE_LONG (H5OPEN H5T_NATIVE_LONG_g) |
115 | |
116 | hid_t H5T_NATIVE_SCHAR_g __attribute__(( type_tag_for_datatype(hdf5,signed char) )); |
117 | hid_t H5T_NATIVE_UCHAR_g __attribute__(( type_tag_for_datatype(hdf5,unsigned char) )); |
118 | hid_t H5T_NATIVE_INT_g __attribute__(( type_tag_for_datatype(hdf5,int) )); |
119 | hid_t H5T_NATIVE_LONG_g __attribute__(( type_tag_for_datatype(hdf5,long) )); |
120 | |
121 | void H5Dwrite(hid_t mem_type_id, const void *buf) __attribute__(( pointer_with_type_tag(hdf5,2,1) )); |
122 | |
123 | //===--- Tests ------------------------------------------------------------===// |
124 | |
125 | //===--- MPI |
126 | |
127 | struct pair_float_int |
128 | { |
129 | float f; int i; |
130 | }; |
131 | |
132 | struct pair_int_int |
133 | { |
134 | int i1; int i2; |
135 | }; |
136 | |
137 | void test_mpi_predefined_types( |
138 | int *int_buf, |
139 | long *long_buf1, |
140 | long *long_buf2, |
141 | void *void_buf, |
142 | struct pair_float_int *pfi, |
143 | struct pair_int_int *pii) |
144 | { |
145 | char char_buf[255]; |
146 | |
147 | // Layout-compatible scalar types. |
148 | MPI_Send(int_buf, 1, MPI_INT); // no-warning |
149 | |
150 | // Null pointer constant. |
151 | MPI_Send(0, 0, MPI_INT); // no-warning |
152 | MPI_Send(NULL, 0, MPI_INT); // no-warning |
153 | |
154 | // Layout-compatible class types. |
155 | MPI_Send(pfi, 1, MPI_FLOAT_INT); // no-warning |
156 | MPI_Send(pii, 1, MPI_2INT); // no-warning |
157 | |
158 | // Layout-incompatible scalar types. |
159 | MPI_Send(long_buf1, 1, MPI_INT); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'int *'}} |
160 | |
161 | // Layout-incompatible class types. |
162 | MPI_Send(pii, 1, MPI_FLOAT_INT); // expected-warning {{argument type 'struct pair_int_int *' doesn't match specified 'mpi' type tag}} |
163 | MPI_Send(pfi, 1, MPI_2INT); // expected-warning {{argument type 'struct pair_float_int *' doesn't match specified 'mpi' type tag}} |
164 | |
165 | // Layout-incompatible class-scalar types. |
166 | MPI_Send(long_buf1, 1, MPI_2INT); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag}} |
167 | |
168 | // Function with two buffers. |
169 | MPI_Gather(long_buf1, 1, MPI_INT, // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'int *'}} |
170 | long_buf2, 1, MPI_INT); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'int *'}} |
171 | |
172 | // Array buffers should work like pointer buffers. |
173 | MPI_Send(char_buf, 255, MPI_CHAR); // no-warning |
174 | |
175 | // Explicit casts should not be dropped. |
176 | MPI_Send((int *) char_buf, 255, MPI_INT); // no-warning |
177 | MPI_Send((int *) char_buf, 255, MPI_CHAR); // expected-warning {{argument type 'int *' doesn't match specified 'mpi' type tag that requires 'char *'}} |
178 | |
179 | // `void*' buffer should never warn. |
180 | MPI_Send(void_buf, 255, MPI_CHAR); // no-warning |
181 | |
182 | // We expect that MPI_IN_PLACE is `void*', shouldn't warn. |
183 | MPI_Gather(MPI_IN_PLACE, 0, MPI_INT, |
184 | int_buf, 1, MPI_INT); |
185 | |
186 | // Special handling for MPI_DATATYPE_NULL: buffer pointer should be either |
187 | // a `void*' pointer or a null pointer constant. |
188 | MPI_Gather(NULL, 0, MPI_DATATYPE_NULL, // no-warning |
189 | int_buf, 1, MPI_INT); |
190 | |
191 | MPI_Gather(int_buf, 0, MPI_DATATYPE_NULL, // expected-warning {{specified mpi type tag requires a null pointer}} |
192 | int_buf, 1, MPI_INT); |
193 | } |
194 | |
195 | MPI_Datatype my_int_datatype __attribute__(( type_tag_for_datatype(mpi,int) )); |
196 | |
197 | struct S1 { int a; int b; }; |
198 | MPI_Datatype my_s1_datatype __attribute__(( type_tag_for_datatype(mpi,struct S1) )); |
199 | |
200 | // Layout-compatible to S1, but should be treated as a different type. |
201 | struct S2 { int a; int b; }; |
202 | MPI_Datatype my_s2_datatype __attribute__(( type_tag_for_datatype(mpi,struct S2) )); |
203 | |
204 | enum E1 { Foo }; |
205 | MPI_Datatype my_e1_datatype __attribute__(( type_tag_for_datatype(mpi,enum E1) )); |
206 | |
207 | void test_user_types(int *int_buf, |
208 | long *long_buf, |
209 | struct S1 *s1_buf, |
210 | struct S2 *s2_buf, |
211 | enum E1 *e1_buf) |
212 | { |
213 | MPI_Send(int_buf, 1, my_int_datatype); // no-warning |
214 | MPI_Send(long_buf, 1, my_int_datatype); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'int *'}} |
215 | |
216 | MPI_Send(s1_buf, 1, my_s1_datatype); // no-warning |
217 | MPI_Send(s1_buf, 1, my_s2_datatype); // expected-warning {{argument type 'struct S1 *' doesn't match specified 'mpi' type tag that requires 'struct S2 *'}} |
218 | |
219 | MPI_Send(long_buf, 1, my_s1_datatype); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'struct S1 *'}} |
220 | MPI_Send(s1_buf, 1, MPI_INT); // expected-warning {{argument type 'struct S1 *' doesn't match specified 'mpi' type tag that requires 'int *'}} |
221 | |
222 | MPI_Send(e1_buf, 1, my_e1_datatype); // no-warning |
223 | MPI_Send(e1_buf, 1, MPI_INT); // expected-warning {{argument type 'enum E1 *' doesn't match specified 'mpi' type tag that requires 'int *'}} |
224 | MPI_Send(int_buf, 1, my_e1_datatype); // expected-warning {{argument type 'int *' doesn't match specified 'mpi' type tag that requires 'enum E1 *'}} |
225 | } |
226 | |
227 | MPI_Datatype my_unknown_datatype; |
228 | |
229 | void test_not_annotated(int *int_buf, |
230 | long *long_buf, |
231 | MPI_Datatype type) |
232 | { |
233 | // Using 'MPI_Datatype's without attributes should not produce warnings. |
234 | MPI_Send(long_buf, 1, my_unknown_datatype); // no-warning |
235 | MPI_Send(int_buf, 1, type); // no-warning |
236 | } |
237 | |
238 | struct S1_compat { int a; int b; }; |
239 | MPI_Datatype my_s1_compat_datatype |
240 | __attribute__(( type_tag_for_datatype(mpi, struct S1_compat, layout_compatible) )); |
241 | |
242 | struct S3 { int a; long b; double c; double d; struct S1 s1; }; |
243 | struct S3_compat { int a; long b; double c; double d; struct S2 s2; }; |
244 | MPI_Datatype my_s3_compat_datatype |
245 | __attribute__(( type_tag_for_datatype(mpi, struct S3_compat, layout_compatible) )); |
246 | |
247 | struct S4 { char c; }; |
248 | struct S4_compat { signed char c; }; |
249 | MPI_Datatype my_s4_compat_datatype |
250 | __attribute__(( type_tag_for_datatype(mpi, struct S4_compat, layout_compatible) )); |
251 | |
252 | union U1 { int a; long b; double c; double d; struct S1 s1; }; |
253 | union U1_compat { long b; double c; struct S2 s; int a; double d; }; |
254 | MPI_Datatype my_u1_compat_datatype |
255 | __attribute__(( type_tag_for_datatype(mpi, union U1_compat, layout_compatible) )); |
256 | |
257 | union U2 { int a; long b; double c; struct S1 s1; }; |
258 | MPI_Datatype my_u2_datatype |
259 | __attribute__(( type_tag_for_datatype(mpi, union U2, layout_compatible) )); |
260 | |
261 | void test_layout_compatibility(struct S1 *s1_buf, struct S3 *s3_buf, |
262 | struct S4 *s4_buf, |
263 | union U1 *u1_buf, union U2 *u2_buf) |
264 | { |
265 | MPI_Send(s1_buf, 1, my_s1_compat_datatype); // no-warning |
266 | MPI_Send(s3_buf, 1, my_s3_compat_datatype); // no-warning |
267 | MPI_Send(s1_buf, 1, my_s3_compat_datatype); // expected-warning {{argument type 'struct S1 *' doesn't match specified 'mpi' type tag}} |
268 | MPI_Send(s4_buf, 1, my_s4_compat_datatype); // expected-warning {{argument type 'struct S4 *' doesn't match specified 'mpi' type tag}} |
269 | MPI_Send(u1_buf, 1, my_u1_compat_datatype); // no-warning |
270 | MPI_Send(u1_buf, 1, my_u2_datatype); // expected-warning {{argument type 'union U1 *' doesn't match specified 'mpi' type tag}} |
271 | MPI_Send(u2_buf, 1, my_u1_compat_datatype); // expected-warning {{argument type 'union U2 *' doesn't match specified 'mpi' type tag}} |
272 | } |
273 | |
274 | // There is an MPI_REAL predefined in MPI, but some existing MPI programs do |
275 | // this. |
276 | typedef float real; |
277 | #define MPI_REAL MPI_FLOAT |
278 | |
279 | void test_mpi_real_user_type(real *real_buf, float *float_buf) |
280 | { |
281 | MPI_Send(real_buf, 1, MPI_REAL); // no-warning |
282 | MPI_Send(real_buf, 1, MPI_FLOAT); // no-warning |
283 | MPI_Send(float_buf, 1, MPI_REAL); // no-warning |
284 | MPI_Send(float_buf, 1, MPI_FLOAT); // no-warning |
285 | } |
286 | |
287 | //===--- HDF5 |
288 | |
289 | void test_hdf5(char *char_buf, |
290 | signed char *schar_buf, |
291 | unsigned char *uchar_buf, |
292 | int *int_buf, |
293 | long *long_buf) |
294 | { |
295 | H5Dwrite(H5T_NATIVE_CHAR, char_buf); // no-warning |
296 | #ifdef __CHAR_UNSIGNED__ |
297 | H5Dwrite(H5T_NATIVE_CHAR, schar_buf); // expected-warning {{argument type 'signed char *' doesn't match specified 'hdf5' type tag that requires 'unsigned char *'}} |
298 | H5Dwrite(H5T_NATIVE_CHAR, uchar_buf); // no-warning |
299 | #else |
300 | H5Dwrite(H5T_NATIVE_CHAR, schar_buf); // no-warning |
301 | H5Dwrite(H5T_NATIVE_CHAR, uchar_buf); // expected-warning {{argument type 'unsigned char *' doesn't match specified 'hdf5' type tag that requires 'signed char *'}} |
302 | #endif |
303 | H5Dwrite(H5T_NATIVE_SCHAR, schar_buf); // no-warning |
304 | H5Dwrite(H5T_NATIVE_UCHAR, uchar_buf); // no-warning |
305 | H5Dwrite(H5T_NATIVE_INT, int_buf); // no-warning |
306 | H5Dwrite(H5T_NATIVE_LONG, long_buf); // no-warning |
307 | |
308 | #ifdef __CHAR_UNSIGNED__ |
309 | H5Dwrite(H5T_NATIVE_CHAR, int_buf); // expected-warning {{argument type 'int *' doesn't match specified 'hdf5' type tag that requires 'unsigned char *'}} |
310 | #else |
311 | H5Dwrite(H5T_NATIVE_CHAR, int_buf); // expected-warning {{argument type 'int *' doesn't match specified 'hdf5' type tag that requires 'signed char *'}} |
312 | #endif |
313 | H5Dwrite(H5T_NATIVE_INT, long_buf); // expected-warning {{argument type 'long *' doesn't match specified 'hdf5' type tag that requires 'int *'}} |
314 | |
315 | // FIXME: we should warn here, but it will cause false positives because |
316 | // different kinds may use same magic values. |
317 | //H5Dwrite(MPI_INT, int_buf); |
318 | } |
319 | |
320 | |