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