1 /* PR 71831 - __builtin_object_size poor results with no optimization
2    Verify that even without optimization __builtin_object_size result
3    is folded into a constant and dead code that depends on it is
4    eliminated.  */
5 /* { dg-do compile } */
6 /* { dg-options "-O0 -fdump-tree-ssa" } */
7 
8 #define concat(a, b)   a ## b
9 #define CAT(a, b)      concat (a, b)
10 
11 /* Create a symbol name unique to each tes and object size type.  */
12 #define SYM(type)      CAT (CAT (CAT (failure_on_line_, __LINE__), _type_), type)
13 
14 /* References to the following undefined symbol which is unique for each
15    test case are expected to be eliminated.  */
16 #define TEST_FAILURE(type)			\
17   do {						\
18     extern void SYM (type)(void);		\
19     SYM (type)();				\
20   } while (0)
21 
22 #define bos(obj, type) __builtin_object_size (obj, type)
23 #define size(obj, n) ((size_t)n == X ? sizeof *obj : (size_t)n)
24 
25 #define test(expect, type, obj)			\
26   do {						\
27     if (bos (obj, type)	!= size (obj, expect))	\
28       TEST_FAILURE (type);			\
29   } while (0)
30 
31 #define FOLD_ALL(r0, r1, r2, r3, obj)		\
32   do {						\
33     test (r0, 0, obj);				\
34     test (r1, 1, obj);				\
35     test (r2, 2, obj);				\
36     test (r3, 3, obj);				\
37   } while (0)
38 
39 #define FOLD_0_2(r0, r1, r2, r3, obj)		\
40   do {						\
41     test (r0, 0, obj);				\
42     test (r2, 2, obj);				\
43   } while (0)
44 
45 /* For convenience.  Substitute for 'sizeof object' in test cases where
46    the size can vary from target to target.  */
47 #define X  (size_t)0xdeadbeef
48 
49 typedef __SIZE_TYPE__ size_t;
50 
51 extern char ax[];
52 char ax2[];               /* { dg-warning "assumed to have one element" } */
53 
54 extern char a0[0];
55 static char a1[1];
56 static char a2[2];
57 static char a9[9];
58 
59 #if __SIZEOF_SHORT__ == 4
60 extern short ia0[0];
61 static short ia1[1];
62 static short ia9[9];
63 #elif __SIZEOF_INT__ == 4
64 extern int ia0[0];
65 static int ia1[1];
66 static int ia9[9];
67 #elif __SIZEOF_LONG__ == 4
68 extern long ia0[0];
69 static long ia1[1];
70 static long ia9[9];
71 #endif
72 
73 static char a2x2[2][2];
74 static char a3x5[3][5];
75 
76 struct Sx { char n, a[]; } sx;
77 struct S0 { char n, a[0]; } s0;
78 struct S1 { char n, a[1]; } s1;
79 struct S2 { char n, a[2]; } s2;
80 struct S9 { char n, a[9]; } s9;
81 
82 struct S2x2 { char n, a[2][2]; } s2x2;
83 struct S3x5 { char n, a[3][5]; } s3x5;
84 
85 static __attribute__ ((noclone, noinline)) void
test_arrays()86 test_arrays ()
87 {
88   FOLD_ALL (     1,       1,       1,       1,   ax2);
89 
90   FOLD_ALL (     1,       1,       1,       1,   a1);
91   FOLD_ALL (     2,       2,       2,       2,   a2);
92   FOLD_ALL (     9,       9,       9,       9,   a9);
93 
94   FOLD_ALL (     0,       0,       0,       0,   a0);
95   FOLD_ALL (     1,       1,       1,       1,   ax2);
96 
97   FOLD_ALL (     0,       0,       0,       0,   ia0);
98   FOLD_ALL (     4,       4,       4,       4,   ia1);
99   FOLD_ALL (    36,      36,      36,      36,   ia9);
100 
101   /* Not all results for multidimensional arrays make sense (see
102      bug 77293).  The expected results below simply reflect those
103      obtained at -O2 (modulo the known limitations at -O1).  */
104   FOLD_ALL (     4,       4,       4,       4,   a2x2);
105   FOLD_ALL (     4,       4,       4,       4,   &a2x2[0]);
106   FOLD_ALL (     4,       2,       4,       2,   &a2x2[0][0]);
107   FOLD_0_2 (     0,  F1  (0),      0,       0,   &a2x2 + 1);
108   FOLD_0_2 (     2,  F1 ( 2),      2,  F3 ( 2),  &a2x2[0] + 1);
109   FOLD_0_2 (     3,  F1 ( 1),      3,  F3 ( 3),  &a2x2[0][0] + 1);
110 
111   FOLD_ALL (    15,      15,      15,      15,   a3x5);
112   FOLD_ALL (    15,       5,      15,       5,   &a3x5[0][0] + 0);
113   FOLD_0_2 (    14,  F1 ( 4),     14,  F3 (14),  &a3x5[0][0] + 1);
114 
115   FOLD_ALL (     1,       1,       1,       1,   a1 + 0);
116   FOLD_0_2 (     0,  F1 ( 0),      0,       0,   &a1 + 1);
117   FOLD_ALL (     2,       2,       2,       2,   a2 + 0);
118   FOLD_0_2 (     1,  F1 ( 1),      1, F3 ( 1),   a2 + 1);
119   FOLD_0_2 (     0,  F1 ( 0),      0,       0,   a2 + 2);
120 }
121 
122 static __attribute__ ((noclone, noinline)) void
test_structs(void)123 test_structs (void)
124 {
125   /* The expected size of a declared object with a flexible array member
126      is sizeof sx in all __builtin_object_size types.  */
127   FOLD_ALL (     X,       X,       X,       X,   &sx);
128 
129   /* The expected size of a flexible array member of a declared object
130      is zero.  */
131   FOLD_ALL (     0,       0,       0,       0,   sx.a);
132 
133   /* The expected size of a declared object with a zero-length array member
134      is sizeof sx in all __builtin_object_size types.  */
135   FOLD_ALL (     X,       X,       X,       X,   &s0);
136 
137   /* The expected size of a zero-length array member of a declared object
138      is zero.  */
139   FOLD_ALL (     0,       0,       0,       0,   s0.a);
140 
141   FOLD_ALL (     X,       X,       X,       X,   &s1);
142   FOLD_ALL (     1,       1,       1,       1,   s1.a);
143   FOLD_0_2 (     0,  F1 (0),       0,       0,   s1.a + 1);
144 
145   FOLD_ALL (     X,       X,       X,       X,   &s9);
146   FOLD_ALL (     9,       9,       9,       9,   s9.a);
147   FOLD_ALL (     9,       9,       9,       9,   s9.a + 0);
148   FOLD_0_2 (     8,  F1 ( 8),      8, F3 (  8),  s9.a + 1);
149   FOLD_0_2 (     7,  F1 ( 7),      7, F3 (  7),  s9.a + 2);
150   FOLD_0_2 (     0,  F1 ( 0),      0, F3 (  0),  s9.a + 9);
151 }
152 
153 int
main()154 main()
155 {
156   test_arrays ();
157   test_structs ();
158 
159   return 0;
160 }
161 
162 /* { dg-final { scan-tree-dump-not "failure_on_line" "ssa" } } */
163