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