Home | History | Annotate | Download | only in Sema
      1 // RUN: %clang_cc1 -std=c99 -fsyntax-only -verify %s
      2 // RUN: %clang_cc1 -x c++ -std=c++98 -fsyntax-only -verify %s
      3 // RUN: %clang_cc1 -std=c99 -fno-signed-char -fsyntax-only -verify %s
      4 
      5 struct A {};
      6 
      7 typedef struct A *MPI_Datatype;
      8 
      9 int wrong1(void *buf, MPI_Datatype datatype)
     10     __attribute__(( pointer_with_type_tag )); // expected-error {{attribute requires parameter 1 to be an identifier}}
     11 
     12 int wrong2(void *buf, MPI_Datatype datatype)
     13     __attribute__(( pointer_with_type_tag(mpi,0,7) )); // expected-error {{attribute parameter 2 is out of bounds}}
     14 
     15 int wrong3(void *buf, MPI_Datatype datatype)
     16     __attribute__(( pointer_with_type_tag(mpi,3,7) )); // expected-error {{attribute parameter 2 is out of bounds}}
     17 
     18 int wrong4(void *buf, MPI_Datatype datatype)
     19     __attribute__(( pointer_with_type_tag(mpi,1,0) )); // expected-error {{attribute parameter 3 is out of bounds}}
     20 
     21 int wrong5(void *buf, MPI_Datatype datatype)
     22     __attribute__(( pointer_with_type_tag(mpi,1,3) )); // expected-error {{attribute parameter 3 is out of bounds}}
     23 
     24 int wrong6(void *buf, MPI_Datatype datatype)
     25     __attribute__(( pointer_with_type_tag(mpi,0x8000000000000001ULL,1) )); // expected-error {{attribute parameter 2 is out of bounds}}
     26 
     27 extern int x;
     28 
     29 int wrong7(void *buf, MPI_Datatype datatype)
     30     __attribute__(( pointer_with_type_tag(mpi,x,2) )); // expected-error {{attribute requires parameter 2 to be an integer constant}}
     31 
     32 int wrong8(void *buf, MPI_Datatype datatype)
     33     __attribute__(( pointer_with_type_tag(mpi,1,x) )); // expected-error {{attribute requires parameter 3 to be an integer constant}}
     34 
     35 int wrong9 __attribute__(( pointer_with_type_tag(mpi,1,2) )); // expected-error {{attribute only applies to functions and methods}}
     36 
     37 int wrong10(double buf, MPI_Datatype type)
     38     __attribute__(( pointer_with_type_tag(mpi,1,2) )); // expected-error {{'pointer_with_type_tag' attribute only applies to pointer arguments}}
     39 
     40 
     41 extern struct A datatype_wrong1
     42     __attribute__(( type_tag_for_datatype )); // expected-error {{attribute requires parameter 1 to be an identifier}}
     43 
     44 extern struct A datatype_wrong2
     45     __attribute__(( type_tag_for_datatype(mpi,1,2) )); // expected-error {{expected a type}}
     46 
     47 extern struct A datatype_wrong3
     48     __attribute__(( type_tag_for_datatype(mpi,not_a_type) )); // expected-error {{unknown type name 'not_a_type'}}
     49 
     50 extern struct A datatype_wrong4
     51     __attribute__(( type_tag_for_datatype(mpi,int,int) )); // expected-error {{expected identifier}}
     52 
     53 extern struct A datatype_wrong5
     54     __attribute__(( type_tag_for_datatype(mpi,int,not_a_flag) )); // expected-error {{invalid comparison flag 'not_a_flag'}}
     55 
     56 extern struct A datatype_wrong6
     57     __attribute__(( type_tag_for_datatype(mpi,int,layout_compatible,not_a_flag) )); // expected-error {{invalid comparison flag 'not_a_flag'}}
     58 
     59 
     60 // Using a tag with kind A in a place where the function requires kind B should
     61 // warn.
     62 
     63 void A_func(void *ptr, void *tag) __attribute__(( pointer_with_type_tag(a,1,2) ));
     64 
     65 extern struct A A_tag __attribute__(( type_tag_for_datatype(a,int) ));
     66 extern struct A B_tag __attribute__(( type_tag_for_datatype(b,int) ));
     67 
     68 void C_func(void *ptr, int tag) __attribute__(( pointer_with_type_tag(c,1,2) ));
     69 
     70 static const int C_tag __attribute__(( type_tag_for_datatype(c,int) )) = 10;
     71 static const int D_tag __attribute__(( type_tag_for_datatype(d,int) )) = 20;
     72 
     73 void test_tag_mismatch(int *ptr)
     74 {
     75   A_func(ptr, &A_tag); // no-warning
     76   A_func(ptr, &B_tag); // expected-warning {{this type tag was not designed to be used with this function}}
     77   C_func(ptr, C_tag); // no-warning
     78   C_func(ptr, D_tag); // expected-warning {{this type tag was not designed to be used with this function}}
     79   C_func(ptr, 10); // no-warning
     80   C_func(ptr, 20); // should warn, but may cause false positives
     81 }
     82 
     83 void test_null_pointer()
     84 {
     85   C_func(0, C_tag); // no-warning
     86   C_func((void *) 0, C_tag); // no-warning
     87   C_func((int *) 0, C_tag); // no-warning
     88   C_func((long *) 0, C_tag); // expected-warning {{argument type 'long *' doesn't match specified 'c' type tag that requires 'int *'}}
     89 }
     90 
     91 // Check that we look through typedefs in the special case of allowing 'char'
     92 // to be matched with 'signed char' or 'unsigned char'.
     93 void E_func(void *ptr, int tag) __attribute__(( pointer_with_type_tag(e,1,2) ));
     94 
     95 typedef char E_char;
     96 typedef char E_char_2;
     97 typedef signed char E_char_signed;
     98 typedef unsigned char E_char_unsigned;
     99 
    100 static const int E_tag __attribute__(( type_tag_for_datatype(e,E_char) )) = 10;
    101 
    102 void test_char_typedef(char *char_buf,
    103                        E_char_2 *e_char_buf,
    104                        E_char_signed *e_char_signed_buf,
    105                        E_char_unsigned *e_char_unsigned_buf)
    106 {
    107   E_func(char_buf, E_tag);
    108   E_func(e_char_buf, E_tag);
    109 #ifdef __CHAR_UNSIGNED__
    110   E_func(e_char_signed_buf, E_tag); // expected-warning {{argument type 'E_char_signed *' (aka 'signed char *') doesn't match specified 'e' type tag that requires 'E_char *' (aka 'char *')}}
    111   E_func(e_char_unsigned_buf, E_tag);
    112 #else
    113   E_func(e_char_signed_buf, E_tag);
    114   E_func(e_char_unsigned_buf, E_tag); // expected-warning {{argument type 'E_char_unsigned *' (aka 'unsigned char *') doesn't match specified 'e' type tag that requires 'E_char *' (aka 'char *')}}
    115 #endif
    116 }
    117 
    118 // Tests for argument_with_type_tag.
    119 
    120 #define F_DUPFD 10
    121 #define F_SETLK 20
    122 
    123 struct flock { };
    124 
    125 static const int F_DUPFD_tag __attribute__(( type_tag_for_datatype(fcntl,int) )) = F_DUPFD;
    126 static const int F_SETLK_tag __attribute__(( type_tag_for_datatype(fcntl,struct flock *) )) = F_SETLK;
    127 
    128 int fcntl(int fd, int cmd, ...) __attribute__(( argument_with_type_tag(fcntl,3,2) ));
    129 
    130 void test_argument_with_type_tag(struct flock *f)
    131 {
    132   fcntl(0, F_DUPFD, 10); // no-warning
    133   fcntl(0, F_SETLK, f);  // no-warning
    134 
    135   fcntl(0, F_SETLK, 10); // expected-warning {{argument type 'int' doesn't match specified 'fcntl' type tag that requires 'struct flock *'}}
    136   fcntl(0, F_DUPFD, f);  // expected-warning {{argument type 'struct flock *' doesn't match specified 'fcntl' type tag that requires 'int'}}
    137 }
    138 
    139 void test_tag_expresssion(int b) {
    140   fcntl(0, b ? F_DUPFD : F_SETLK, 10); // no-warning
    141   fcntl(0, b + F_DUPFD, 10); // no-warning
    142   fcntl(0, (b, F_DUPFD), 10); // expected-warning {{expression result unused}}
    143 }
    144 
    145 // Check that using 64-bit magic values as tags works and tag values do not
    146 // overflow internally.
    147 void F_func(void *ptr, unsigned long long tag) __attribute__((pointer_with_type_tag(f,1,2) ));
    148 
    149 static const unsigned long long F_tag1 __attribute__(( type_tag_for_datatype(f,int) )) = 0xFFFFFFFFFFFFFFFFULL;
    150 static const unsigned long long F_tag2 __attribute__(( type_tag_for_datatype(f,float) )) = 0xFFFFFFFFULL;
    151 
    152 void test_64bit_magic(int *int_ptr, float *float_ptr)
    153 {
    154   F_func(int_ptr,   0xFFFFFFFFFFFFFFFFULL);
    155   F_func(int_ptr,   0xFFFFFFFFULL);         // expected-warning {{argument type 'int *' doesn't match specified 'f' type tag that requires 'float *'}}
    156   F_func(float_ptr, 0xFFFFFFFFFFFFFFFFULL); // expected-warning {{argument type 'float *' doesn't match specified 'f' type tag that requires 'int *'}}
    157   F_func(float_ptr, 0xFFFFFFFFULL);
    158 }
    159 
    160 
    161