1 /* bf-ms-layout.c */
2 
3 /* Test for MS bitfield layout */
4 /* Adapted from Donn Terry <donnte@microsoft.com> testcase
5    posted to GCC-patches
6    http://gcc.gnu.org/ml/gcc-patches/2000-08/msg00577.html */
7 
8 /* { dg-do run { target i?86-*-* x86_64-*-* } } */
9 /* { dg-options "-D_TEST_MS_LAYOUT" } */
10 /* This test uses the attribute instead of the command line option.  */
11 
12 #include <stddef.h>
13 #include <string.h>
14 
15 extern void abort();
16 
17 #pragma pack(8)
18 
19 #ifdef __GNUC__
20 #define ATTR __attribute__ ((ms_struct))
21 #endif
22 
23 struct one {
24   int d;
25   unsigned char a;
26   unsigned short b:7;
27   char c;
28 } ATTR;
29 
30 struct two {
31   int d;
32   unsigned char a;
33   unsigned int b:7;
34   char c;
35 } ATTR;
36 
37 struct three {
38   short d;
39   unsigned short a:3;
40   unsigned short b:9;
41   unsigned char c:7;
42 } ATTR;
43 
44 
45 /* Bitfields of size 0 have some truly odd behaviors. */
46 
47 struct four {
48   unsigned short a:3;
49   unsigned short b:9;
50   unsigned int :0;  /* forces struct alignment to int */
51   unsigned char c:7;
52 } ATTR;
53 
54 struct five {
55   char a;
56   int :0;        /* ignored; prior field is not a bitfield. */
57   char b;
58   char c;
59 } ATTR;
60 
61 struct six {
62   char a :8;
63   int :0;	/* not ignored; prior field IS a bitfield, causes
64 		   struct alignment as well. */
65   char b;
66   char c;
67 } ATTR;
68 
69 struct seven {
70   char a:8;
71   char :0;
72   int  :0;	/* Ignored; prior field is zero size bitfield. */
73   char b;
74   char c;
75 } ATTR;
76 
77 struct eight { /* ms size 4 */
78   short b:3;
79   char  c;
80 } ATTR;
81 
82 #ifdef _MSC_VER
83 #define LONGLONG __int64
84 #else
85 #define LONGLONG long long
86 #endif
87 
88 union nine {   /* ms size 8 */
89   LONGLONG a:3;
90   char  c;
91 } ATTR;
92 
93 struct ten {   /* ms size 16 */
94   LONGLONG a:3;
95   LONGLONG b:3;
96   char  c;
97 } ATTR;
98 
99 
100 #define val(s,f) (s.f)
101 
102 #define check_struct(_X) \
103 { \
104   if (sizeof (struct _X) != exp_sizeof_##_X )	\
105     abort();					\
106   memcpy(&test_##_X, filler, sizeof(test_##_X));\
107   if (val(test_##_X,c) != exp_##_X##_c) 	\
108      abort();					\
109 }
110 
111 #define check_union(_X) \
112 { \
113   if (sizeof (union _X) != exp_sizeof_##_X )	\
114     abort();                                    \
115   memcpy(&test_##_X, filler, sizeof(test_##_X));\
116   if (val(test_##_X,c) != exp_##_X##_c) 	\
117      abort();					\
118 }
119 
120 #define check_struct_size(_X) \
121 { \
122   if (sizeof (struct _X) != exp_sizeof_##_X )	\
123     abort();                                    \
124 }
125 
126 #define check_struct_off(_X) \
127 { \
128   memcpy(&test_##_X, filler, sizeof(test_##_X));\
129   if (val(test_##_X,c) != exp_##_X##_c) 	\
130     abort();                                    \
131 }
132 
133 #define check_union_size(_X) \
134 { \
135   if (sizeof (union _X) != exp_sizeof_##_X )	\
136     abort();                                    \
137 }
138 
139 #define check_union_off(_X) \
140 { \
141   memcpy(&test_##_X, filler, sizeof(test_##_X));\
142   if (val(test_##_X,c) != exp_##_X##_c) 	\
143     abort();                                    \
144 }
145 
main()146 int main(){
147 
148   unsigned char filler[16];
149   struct one test_one;
150   struct two test_two;
151   struct three test_three;
152   struct four test_four;
153   struct five test_five;
154   struct six test_six;
155   struct seven test_seven;
156   struct eight test_eight;
157   union nine test_nine;
158   struct ten test_ten;
159 
160 #if defined (_TEST_MS_LAYOUT) || defined (_MSC_VER)
161   size_t exp_sizeof_one = 12;
162   size_t exp_sizeof_two = 16;
163   size_t exp_sizeof_three =6;
164   size_t exp_sizeof_four = 8;
165   size_t exp_sizeof_five = 3;
166   size_t exp_sizeof_six = 8;
167   size_t exp_sizeof_seven = 3;
168   size_t exp_sizeof_eight = 4;
169   size_t exp_sizeof_nine = 8;
170   size_t exp_sizeof_ten = 16;
171 
172   unsigned char exp_one_c = 8;
173   unsigned char exp_two_c  = 12;
174   unsigned char exp_three_c = 4;
175   unsigned char exp_four_c = 4;
176   char exp_five_c = 2;
177   char exp_six_c = 5;
178   char exp_seven_c = 2;
179   char exp_eight_c = 2;
180   char exp_nine_c = 0;
181   char exp_ten_c = 8;
182 
183 #else /* testing -mno-ms-bitfields */
184 
185   size_t exp_sizeof_one = 8;
186   size_t exp_sizeof_two = 8;
187   size_t exp_sizeof_three = 6;
188   size_t exp_sizeof_four = 6;
189   size_t exp_sizeof_five = 6;
190   size_t exp_sizeof_six = 6;
191   size_t exp_sizeof_seven = 6;
192   size_t exp_sizeof_eight = 2;
193   size_t exp_sizeof_nine = 8;
194   size_t exp_sizeof_ten = 8;
195 
196   unsigned short exp_one_c = 6;
197   unsigned int exp_two_c  = 6;
198   unsigned char exp_three_c = 64;
199   unsigned char exp_four_c = 4;
200   char exp_five_c = 5;
201   char exp_six_c = 5;
202   char exp_seven_c = 5;
203   char exp_eight_c = 1;
204   char exp_nine_c = 0;
205   char exp_ten_c = 1;
206 
207 #endif
208 
209   unsigned char i;
210   for ( i = 0; i < 16; i++ )
211     filler[i] = i;
212 
213   check_struct_off (one);
214   check_struct_off (two);
215   check_struct_off (three);
216   check_struct_off (four);
217   check_struct_off (five);
218   check_struct_off (six);
219   check_struct_off (seven);
220   check_struct_off (eight);
221   check_union_off (nine);
222   check_struct_off (ten);
223 
224   check_struct_size (one);
225   check_struct_size (two);
226   check_struct_size (three);
227   check_struct_size (four);
228   check_struct_size (five);
229   check_struct_size (six);
230   check_struct_size (seven);
231   check_struct_size (eight);
232   check_union_size (nine);
233   check_struct_size (ten);
234 
235   return 0;
236 };
237