Home | History | Annotate | Download | only in Sema
      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 
    308