blob: 9c2ee965866d9a23dcd710f86b227fd798bb194e [file] [log] [blame]
Dmitri Gribenko0d5a0692012-08-17 00:08:38 +00001// 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
24typedef struct ompi_datatype_t *MPI_Datatype;
25#endif
26
27#ifdef MPICH
28typedef int MPI_Datatype;
29#endif
30
31int MPI_Send(void *buf, int count, MPI_Datatype datatype)
32 __attribute__(( pointer_with_type_tag(mpi,1,3) ));
33
34int 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
55extern struct ompi_predefined_datatype_t ompi_mpi_datatype_null __attribute__(( type_tag_for_datatype(mpi,void,must_be_null) ));
56extern struct ompi_predefined_datatype_t ompi_mpi_float __attribute__(( type_tag_for_datatype(mpi,float) ));
57extern struct ompi_predefined_datatype_t ompi_mpi_int __attribute__(( type_tag_for_datatype(mpi,int) ));
58extern struct ompi_predefined_datatype_t ompi_mpi_long __attribute__(( type_tag_for_datatype(mpi,long) ));
59extern struct ompi_predefined_datatype_t ompi_mpi_long_long_int __attribute__(( type_tag_for_datatype(mpi,long long int) ));
60extern struct ompi_predefined_datatype_t ompi_mpi_char __attribute__(( type_tag_for_datatype(mpi,char) ));
61
62struct ompi_struct_mpi_float_int {float f; int i;};
63extern struct ompi_predefined_datatype_t ompi_mpi_float_int __attribute__(( type_tag_for_datatype(mpi, struct ompi_struct_mpi_float_int, layout_compatible) ));
64
65struct ompi_struct_mpi_2int {int i1; int i2;};
66extern 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
86static const MPI_Datatype mpich_mpi_datatype_null __attribute__(( type_tag_for_datatype(mpi,void,must_be_null) )) = 0xa0000000;
87static const MPI_Datatype mpich_mpi_float __attribute__(( type_tag_for_datatype(mpi,float) )) = 0xa0000001;
88static const MPI_Datatype mpich_mpi_int __attribute__(( type_tag_for_datatype(mpi,int) )) = 0xa0000002;
89static const MPI_Datatype mpich_mpi_long __attribute__(( type_tag_for_datatype(mpi,long) )) = 0xa0000003;
90static const MPI_Datatype mpich_mpi_long_long_int __attribute__(( type_tag_for_datatype(mpi,long long int) )) = 0xa0000004;
91static const MPI_Datatype mpich_mpi_char __attribute__(( type_tag_for_datatype(mpi,char) )) = 0xa0000005;
92
93struct mpich_struct_mpi_float_int { float f; int i; };
94struct mpich_struct_mpi_2int { int i1; int i2; };
95static const MPI_Datatype mpich_mpi_float_int __attribute__(( type_tag_for_datatype(mpi, struct mpich_struct_mpi_float_int, layout_compatible) )) = 0xa0000006;
96static 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
101typedef int hid_t;
102void 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
116hid_t H5T_NATIVE_SCHAR_g __attribute__(( type_tag_for_datatype(hdf5,signed char) ));
117hid_t H5T_NATIVE_UCHAR_g __attribute__(( type_tag_for_datatype(hdf5,unsigned char) ));
118hid_t H5T_NATIVE_INT_g __attribute__(( type_tag_for_datatype(hdf5,int) ));
119hid_t H5T_NATIVE_LONG_g __attribute__(( type_tag_for_datatype(hdf5,long) ));
120
121void H5Dwrite(hid_t mem_type_id, const void *buf) __attribute__(( pointer_with_type_tag(hdf5,2,1) ));
122
123//===--- Tests ------------------------------------------------------------===//
124
125//===--- MPI
126
127struct pair_float_int
128{
129 float f; int i;
130};
131
132struct pair_int_int
133{
134 int i1; int i2;
135};
136
137void 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 // Layout-compatible class types.
151 MPI_Send(pfi, 1, MPI_FLOAT_INT); // no-warning
152 MPI_Send(pii, 1, MPI_2INT); // no-warning
153
154 // Layout-incompatible scalar types.
155 MPI_Send(long_buf1, 1, MPI_INT); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'int *'}}
156
157 // Layout-incompatible class types.
158 MPI_Send(pii, 1, MPI_FLOAT_INT); // expected-warning {{argument type 'struct pair_int_int *' doesn't match specified 'mpi' type tag}}
159 MPI_Send(pfi, 1, MPI_2INT); // expected-warning {{argument type 'struct pair_float_int *' doesn't match specified 'mpi' type tag}}
160
161 // Layout-incompatible class-scalar types.
162 MPI_Send(long_buf1, 1, MPI_2INT); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag}}
163
164 // Function with two buffers.
165 MPI_Gather(long_buf1, 1, MPI_INT, // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'int *'}}
166 long_buf2, 1, MPI_INT); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'int *'}}
167
168 // Array buffers should work like pointer buffers.
169 MPI_Send(char_buf, 255, MPI_CHAR); // no-warning
170
171 // Explicit casts should not be dropped.
172 MPI_Send((int *) char_buf, 255, MPI_INT); // no-warning
173 MPI_Send((int *) char_buf, 255, MPI_CHAR); // expected-warning {{argument type 'int *' doesn't match specified 'mpi' type tag that requires 'char *'}}
174
175 // `void*' buffer should never warn.
176 MPI_Send(void_buf, 255, MPI_CHAR); // no-warning
177
178 // We expect that MPI_IN_PLACE is `void*', shouldn't warn.
179 MPI_Gather(MPI_IN_PLACE, 0, MPI_INT,
180 int_buf, 1, MPI_INT);
181
182 // Special handling for MPI_DATATYPE_NULL: buffer pointer should be either
183 // a `void*' pointer or a null pointer constant.
184 MPI_Gather(NULL, 0, MPI_DATATYPE_NULL, // no-warning
185 int_buf, 1, MPI_INT);
186
187 MPI_Gather(int_buf, 0, MPI_DATATYPE_NULL, // expected-warning {{specified mpi type tag requires a null pointer}}
188 int_buf, 1, MPI_INT);
189}
190
191MPI_Datatype my_int_datatype __attribute__(( type_tag_for_datatype(mpi,int) ));
192
193struct S1 { int a; int b; };
194MPI_Datatype my_s1_datatype __attribute__(( type_tag_for_datatype(mpi,struct S1) ));
195
196// Layout-compatible to S1, but should be treated as a different type.
197struct S2 { int a; int b; };
198MPI_Datatype my_s2_datatype __attribute__(( type_tag_for_datatype(mpi,struct S2) ));
199
200void test_user_types(int *int_buf,
201 long *long_buf,
202 struct S1 *s1_buf,
203 struct S2 *s2_buf)
204{
205 MPI_Send(int_buf, 1, my_int_datatype); // no-warning
206 MPI_Send(long_buf, 1, my_int_datatype); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'int *'}}
207
208 MPI_Send(s1_buf, 1, my_s1_datatype); // no-warning
209 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 *'}}
210
211 MPI_Send(long_buf, 1, my_s1_datatype); // expected-warning {{argument type 'long *' doesn't match specified 'mpi' type tag that requires 'struct S1 *'}}
212 MPI_Send(s1_buf, 1, MPI_INT); // expected-warning {{argument type 'struct S1 *' doesn't match specified 'mpi' type tag that requires 'int *'}}
213}
214
215MPI_Datatype my_unknown_datatype;
216
217void test_not_annotated(int *int_buf,
218 long *long_buf,
219 MPI_Datatype type)
220{
221 // Using 'MPI_Datatype's without attributes should not produce warnings.
222 MPI_Send(long_buf, 1, my_unknown_datatype); // no-warning
223 MPI_Send(int_buf, 1, type); // no-warning
224}
225
226struct S1_compat { int a; int b; };
227MPI_Datatype my_s1_compat_datatype
228 __attribute__(( type_tag_for_datatype(mpi, struct S1_compat, layout_compatible) ));
229
230struct S3 { int a; long b; double c; double d; struct S1 s1; };
231struct S3_compat { int a; long b; double c; double d; struct S2 s2; };
232MPI_Datatype my_s3_compat_datatype
233 __attribute__(( type_tag_for_datatype(mpi, struct S3_compat, layout_compatible) ));
234
235struct S4 { char c; };
236struct S4_compat { signed char c; };
237MPI_Datatype my_s4_compat_datatype
238 __attribute__(( type_tag_for_datatype(mpi, struct S4_compat, layout_compatible) ));
239
240union U1 { int a; long b; double c; double d; struct S1 s1; };
241union U1_compat { long b; double c; struct S2 s; int a; double d; };
242MPI_Datatype my_u1_compat_datatype
243 __attribute__(( type_tag_for_datatype(mpi, union U1_compat, layout_compatible) ));
244
245union U2 { int a; long b; double c; struct S1 s1; };
246MPI_Datatype my_u2_datatype
247 __attribute__(( type_tag_for_datatype(mpi, union U2, layout_compatible) ));
248
249void test_layout_compatibility(struct S1 *s1_buf, struct S3 *s3_buf,
250 struct S4 *s4_buf,
251 union U1 *u1_buf, union U2 *u2_buf)
252{
253 MPI_Send(s1_buf, 1, my_s1_compat_datatype); // no-warning
254 MPI_Send(s3_buf, 1, my_s3_compat_datatype); // no-warning
255 MPI_Send(s1_buf, 1, my_s3_compat_datatype); // expected-warning {{argument type 'struct S1 *' doesn't match specified 'mpi' type tag}}
256 MPI_Send(s4_buf, 1, my_s4_compat_datatype); // expected-warning {{argument type 'struct S4 *' doesn't match specified 'mpi' type tag}}
257 MPI_Send(u1_buf, 1, my_u1_compat_datatype); // no-warning
258 MPI_Send(u1_buf, 1, my_u2_datatype); // expected-warning {{argument type 'union U1 *' doesn't match specified 'mpi' type tag}}
259 MPI_Send(u2_buf, 1, my_u1_compat_datatype); // expected-warning {{argument type 'union U2 *' doesn't match specified 'mpi' type tag}}
260}
261
262// There is an MPI_REAL predefined in MPI, but some existing MPI programs do
263// this.
264typedef float real;
265#define MPI_REAL MPI_FLOAT
266
267void test_mpi_real_user_type(real *real_buf, float *float_buf)
268{
269 MPI_Send(real_buf, 1, MPI_REAL); // no-warning
270 MPI_Send(real_buf, 1, MPI_FLOAT); // no-warning
271 MPI_Send(float_buf, 1, MPI_REAL); // no-warning
272 MPI_Send(float_buf, 1, MPI_FLOAT); // no-warning
273}
274
275//===--- HDF5
276
277void test_hdf5(char *char_buf,
278 signed char *schar_buf,
279 unsigned char *uchar_buf,
280 int *int_buf,
281 long *long_buf)
282{
283 H5Dwrite(H5T_NATIVE_CHAR, char_buf); // no-warning
284#ifdef __CHAR_UNSIGNED__
285 H5Dwrite(H5T_NATIVE_CHAR, schar_buf); // expected-warning {{argument type 'signed char *' doesn't match specified 'hdf5' type tag that requires 'unsigned char *'}}
286 H5Dwrite(H5T_NATIVE_CHAR, uchar_buf); // no-warning
287#else
288 H5Dwrite(H5T_NATIVE_CHAR, schar_buf); // no-warning
289 H5Dwrite(H5T_NATIVE_CHAR, uchar_buf); // expected-warning {{argument type 'unsigned char *' doesn't match specified 'hdf5' type tag that requires 'signed char *'}}
290#endif
291 H5Dwrite(H5T_NATIVE_SCHAR, schar_buf); // no-warning
292 H5Dwrite(H5T_NATIVE_UCHAR, uchar_buf); // no-warning
293 H5Dwrite(H5T_NATIVE_INT, int_buf); // no-warning
294 H5Dwrite(H5T_NATIVE_LONG, long_buf); // no-warning
295
296#ifdef __CHAR_UNSIGNED__
297 H5Dwrite(H5T_NATIVE_CHAR, int_buf); // expected-warning {{argument type 'int *' doesn't match specified 'hdf5' type tag that requires 'unsigned char *'}}
298#else
299 H5Dwrite(H5T_NATIVE_CHAR, int_buf); // expected-warning {{argument type 'int *' doesn't match specified 'hdf5' type tag that requires 'signed char *'}}
300#endif
301 H5Dwrite(H5T_NATIVE_INT, long_buf); // expected-warning {{argument type 'long *' doesn't match specified 'hdf5' type tag that requires 'int *'}}
302
303 // FIXME: we should warn here, but it will cause false positives because
304 // different kinds may use same magic values.
305 //H5Dwrite(MPI_INT, int_buf);
306}
307