Dmitri Gribenko | 0d5a069 | 2012-08-17 00:08:38 +0000 | [diff] [blame^] | 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 | // 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 | |
| 191 | MPI_Datatype my_int_datatype __attribute__(( type_tag_for_datatype(mpi,int) )); |
| 192 | |
| 193 | struct S1 { int a; int b; }; |
| 194 | MPI_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. |
| 197 | struct S2 { int a; int b; }; |
| 198 | MPI_Datatype my_s2_datatype __attribute__(( type_tag_for_datatype(mpi,struct S2) )); |
| 199 | |
| 200 | void 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 | |
| 215 | MPI_Datatype my_unknown_datatype; |
| 216 | |
| 217 | void 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 | |
| 226 | struct S1_compat { int a; int b; }; |
| 227 | MPI_Datatype my_s1_compat_datatype |
| 228 | __attribute__(( type_tag_for_datatype(mpi, struct S1_compat, layout_compatible) )); |
| 229 | |
| 230 | struct S3 { int a; long b; double c; double d; struct S1 s1; }; |
| 231 | struct S3_compat { int a; long b; double c; double d; struct S2 s2; }; |
| 232 | MPI_Datatype my_s3_compat_datatype |
| 233 | __attribute__(( type_tag_for_datatype(mpi, struct S3_compat, layout_compatible) )); |
| 234 | |
| 235 | struct S4 { char c; }; |
| 236 | struct S4_compat { signed char c; }; |
| 237 | MPI_Datatype my_s4_compat_datatype |
| 238 | __attribute__(( type_tag_for_datatype(mpi, struct S4_compat, layout_compatible) )); |
| 239 | |
| 240 | union U1 { int a; long b; double c; double d; struct S1 s1; }; |
| 241 | union U1_compat { long b; double c; struct S2 s; int a; double d; }; |
| 242 | MPI_Datatype my_u1_compat_datatype |
| 243 | __attribute__(( type_tag_for_datatype(mpi, union U1_compat, layout_compatible) )); |
| 244 | |
| 245 | union U2 { int a; long b; double c; struct S1 s1; }; |
| 246 | MPI_Datatype my_u2_datatype |
| 247 | __attribute__(( type_tag_for_datatype(mpi, union U2, layout_compatible) )); |
| 248 | |
| 249 | void 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. |
| 264 | typedef float real; |
| 265 | #define MPI_REAL MPI_FLOAT |
| 266 | |
| 267 | void 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 | |
| 277 | void 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 | |