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