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 {{'pointer_with_type_tag' attribute requires exactly 3 arguments}}
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 {{'pointer_with_type_tag' attribute only applies to non-K&R-style functions}}
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 int ok11(void *, ...)
41     __attribute__(( pointer_with_type_tag(mpi,1,2) ));
42 int wrong11(void *, ...)
43     __attribute__(( pointer_with_type_tag(mpi,2,3) )); // expected-error {{'pointer_with_type_tag' attribute only applies to pointer arguments}}
44 
45 extern struct A datatype_wrong1
46     __attribute__(( type_tag_for_datatype )); // expected-error {{'type_tag_for_datatype' attribute requires parameter 1 to be an identifier}}
47 
48 extern struct A datatype_wrong2
49     __attribute__(( type_tag_for_datatype(mpi,1,2) )); // expected-error {{expected a type}}
50 
51 extern struct A datatype_wrong3
52     __attribute__(( type_tag_for_datatype(mpi,not_a_type) )); // expected-error {{unknown type name 'not_a_type'}}
53 
54 extern struct A datatype_wrong4
55     __attribute__(( type_tag_for_datatype(mpi,int,int) )); // expected-error {{expected identifier}}
56 
57 extern struct A datatype_wrong5
58     __attribute__(( type_tag_for_datatype(mpi,int,not_a_flag) )); // expected-error {{invalid comparison flag 'not_a_flag'}}
59 
60 extern struct A datatype_wrong6
61     __attribute__(( type_tag_for_datatype(mpi,int,layout_compatible,not_a_flag) )); // expected-error {{invalid comparison flag 'not_a_flag'}}
62 
63 
64 void datatype_wrong7(void) __attribute__((type_tag_for_datatype(datatype_wrong7, int))); // expected-error {{'type_tag_for_datatype' attribute only applies to variables}}
65 
66 // Using a tag with kind A in a place where the function requires kind B should
67 // warn.
68 
69 void A_func(void *ptr, void *tag) __attribute__(( pointer_with_type_tag(a,1,2) ));
70 
71 extern struct A A_tag __attribute__(( type_tag_for_datatype(a,int) ));
72 extern struct A B_tag __attribute__(( type_tag_for_datatype(b,int) ));
73 
74 void C_func(void *ptr, int tag) __attribute__(( pointer_with_type_tag(c,1,2) ));
75 
76 static const int C_tag __attribute__(( type_tag_for_datatype(c,int) )) = 10;
77 static const int D_tag __attribute__(( type_tag_for_datatype(d,int) )) = 20;
78 
test_tag_mismatch(int * ptr)79 void test_tag_mismatch(int *ptr)
80 {
81   A_func(ptr, &A_tag); // no-warning
82   A_func(ptr, &B_tag); // expected-warning {{this type tag was not designed to be used with this function}}
83   C_func(ptr, C_tag); // no-warning
84   C_func(ptr, D_tag); // expected-warning {{this type tag was not designed to be used with this function}}
85   C_func(ptr, 10); // no-warning
86   C_func(ptr, 20); // should warn, but may cause false positives
87 }
88 
test_null_pointer()89 void test_null_pointer()
90 {
91   C_func(0, C_tag); // no-warning
92   C_func((void *) 0, C_tag); // no-warning
93   C_func((int *) 0, C_tag); // no-warning
94   C_func((long *) 0, C_tag); // expected-warning {{argument type 'long *' doesn't match specified 'c' type tag that requires 'int *'}}
95 }
96 
97 // Check that we look through typedefs in the special case of allowing 'char'
98 // to be matched with 'signed char' or 'unsigned char'.
99 void E_func(void *ptr, int tag) __attribute__(( pointer_with_type_tag(e,1,2) ));
100 
101 typedef char E_char;
102 typedef char E_char_2;
103 typedef signed char E_char_signed;
104 typedef unsigned char E_char_unsigned;
105 
106 static const int E_tag __attribute__(( type_tag_for_datatype(e,E_char) )) = 10;
107 
test_char_typedef(char * char_buf,E_char_2 * e_char_buf,E_char_signed * e_char_signed_buf,E_char_unsigned * e_char_unsigned_buf)108 void test_char_typedef(char *char_buf,
109                        E_char_2 *e_char_buf,
110                        E_char_signed *e_char_signed_buf,
111                        E_char_unsigned *e_char_unsigned_buf)
112 {
113   E_func(char_buf, E_tag);
114   E_func(e_char_buf, E_tag);
115 #ifdef __CHAR_UNSIGNED__
116   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 *')}}
117   E_func(e_char_unsigned_buf, E_tag);
118 #else
119   E_func(e_char_signed_buf, E_tag);
120   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 *')}}
121 #endif
122 }
123 
124 // Tests for argument_with_type_tag.
125 
126 #define F_DUPFD 10
127 #define F_SETLK 20
128 
129 struct flock { };
130 
131 static const int F_DUPFD_tag __attribute__(( type_tag_for_datatype(fcntl,int) )) = F_DUPFD;
132 static const int F_SETLK_tag __attribute__(( type_tag_for_datatype(fcntl,struct flock *) )) = F_SETLK;
133 
134 int fcntl(int fd, int cmd, ...) __attribute__(( argument_with_type_tag(fcntl,3,2) ));
135 
test_argument_with_type_tag(struct flock * f)136 void test_argument_with_type_tag(struct flock *f)
137 {
138   fcntl(0, F_DUPFD, 10); // no-warning
139   fcntl(0, F_SETLK, f);  // no-warning
140 
141   fcntl(0, F_SETLK, 10); // expected-warning {{argument type 'int' doesn't match specified 'fcntl' type tag that requires 'struct flock *'}}
142   fcntl(0, F_DUPFD, f);  // expected-warning {{argument type 'struct flock *' doesn't match specified 'fcntl' type tag that requires 'int'}}
143 }
144 
test_tag_expresssion(int b)145 void test_tag_expresssion(int b) {
146   fcntl(0, b ? F_DUPFD : F_SETLK, 10); // no-warning
147   fcntl(0, b + F_DUPFD, 10); // no-warning
148   fcntl(0, (b, F_DUPFD), 10); // expected-warning {{expression result unused}}
149 }
150 
151 // Check that using 64-bit magic values as tags works and tag values do not
152 // overflow internally.
153 void F_func(void *ptr, unsigned long long tag) __attribute__((pointer_with_type_tag(f,1,2) ));
154 
155 static const unsigned long long F_tag1 __attribute__(( type_tag_for_datatype(f,int) )) = 0xFFFFFFFFFFFFFFFFULL;
156 static const unsigned long long F_tag2 __attribute__(( type_tag_for_datatype(f,float) )) = 0xFFFFFFFFULL;
157 
test_64bit_magic(int * int_ptr,float * float_ptr)158 void test_64bit_magic(int *int_ptr, float *float_ptr)
159 {
160   F_func(int_ptr,   0xFFFFFFFFFFFFFFFFULL);
161   F_func(int_ptr,   0xFFFFFFFFULL);         // expected-warning {{argument type 'int *' doesn't match specified 'f' type tag that requires 'float *'}}
162   F_func(float_ptr, 0xFFFFFFFFFFFFFFFFULL); // expected-warning {{argument type 'float *' doesn't match specified 'f' type tag that requires 'int *'}}
163   F_func(float_ptr, 0xFFFFFFFFULL);
164 }
165