| @@ -1,4868 +1,4805 @@ | | | @@ -1,4868 +1,4805 @@ |
1 | /* $NetBSD: tree.c,v 1.508 2023/04/11 00:03:42 rillig Exp $ */ | | 1 | /* $NetBSD: tree.c,v 1.509 2023/04/11 19:02:19 rillig Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1994, 1995 Jochen Pohl | | 4 | * Copyright (c) 1994, 1995 Jochen Pohl |
5 | * All Rights Reserved. | | 5 | * All Rights Reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * 3. All advertising materials mentioning features or use of this software | | 15 | * 3. All advertising materials mentioning features or use of this software |
16 | * must display the following acknowledgement: | | 16 | * must display the following acknowledgement: |
17 | * This product includes software developed by Jochen Pohl for | | 17 | * This product includes software developed by Jochen Pohl for |
18 | * The NetBSD Project. | | 18 | * The NetBSD Project. |
19 | * 4. The name of the author may not be used to endorse or promote products | | 19 | * 4. The name of the author may not be used to endorse or promote products |
20 | * derived from this software without specific prior written permission. | | 20 | * derived from this software without specific prior written permission. |
21 | * | | 21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #if HAVE_NBTOOL_CONFIG_H | | 34 | #if HAVE_NBTOOL_CONFIG_H |
35 | #include "nbtool_config.h" | | 35 | #include "nbtool_config.h" |
36 | #endif | | 36 | #endif |
37 | | | 37 | |
38 | #include <sys/cdefs.h> | | 38 | #include <sys/cdefs.h> |
39 | #if defined(__RCSID) | | 39 | #if defined(__RCSID) |
40 | __RCSID("$NetBSD: tree.c,v 1.508 2023/04/11 00:03:42 rillig Exp $"); | | 40 | __RCSID("$NetBSD: tree.c,v 1.509 2023/04/11 19:02:19 rillig Exp $"); |
41 | #endif | | 41 | #endif |
42 | | | 42 | |
43 | #include <float.h> | | 43 | #include <float.h> |
44 | #include <limits.h> | | 44 | #include <limits.h> |
45 | #include <math.h> | | 45 | #include <math.h> |
46 | #include <signal.h> | | 46 | #include <signal.h> |
47 | #include <stdlib.h> | | 47 | #include <stdlib.h> |
48 | #include <string.h> | | 48 | #include <string.h> |
49 | | | 49 | |
50 | #include "lint1.h" | | 50 | #include "lint1.h" |
51 | | | 51 | |
52 | | | 52 | |
53 | typedef struct integer_constraints { | | 53 | typedef struct integer_constraints { |
54 | int64_t smin; /* signed minimum */ | | 54 | int64_t smin; /* signed minimum */ |
55 | int64_t smax; /* signed maximum */ | | 55 | int64_t smax; /* signed maximum */ |
56 | uint64_t umin; /* unsigned minimum */ | | 56 | uint64_t umin; /* unsigned minimum */ |
57 | uint64_t umax; /* unsigned maximum */ | | 57 | uint64_t umax; /* unsigned maximum */ |
58 | uint64_t bset; /* bits that are definitely set */ | | 58 | uint64_t bset; /* bits that are definitely set */ |
59 | uint64_t bclr; /* bits that are definitely clear */ | | 59 | uint64_t bclr; /* bits that are definitely clear */ |
60 | } integer_constraints; | | 60 | } integer_constraints; |
61 | | | 61 | |
62 | | | 62 | |
63 | static uint64_t | | 63 | static uint64_t |
64 | u64_fill_right(uint64_t x) | | 64 | u64_fill_right(uint64_t x) |
65 | { | | 65 | { |
66 | x |= x >> 1; | | 66 | x |= x >> 1; |
67 | x |= x >> 2; | | 67 | x |= x >> 2; |
68 | x |= x >> 4; | | 68 | x |= x >> 4; |
69 | x |= x >> 8; | | 69 | x |= x >> 8; |
70 | x |= x >> 16; | | 70 | x |= x >> 16; |
71 | x |= x >> 32; | | 71 | x |= x >> 32; |
72 | return x; | | 72 | return x; |
73 | } | | 73 | } |
74 | | | 74 | |
75 | static bool | | 75 | static bool |
76 | str_endswith(const char *haystack, const char *needle) | | 76 | str_endswith(const char *haystack, const char *needle) |
77 | { | | 77 | { |
78 | size_t hlen = strlen(haystack); | | 78 | size_t hlen = strlen(haystack); |
79 | size_t nlen = strlen(needle); | | 79 | size_t nlen = strlen(needle); |
80 | | | 80 | |
81 | return nlen <= hlen && | | 81 | return nlen <= hlen && |
82 | memcmp(haystack + hlen - nlen, needle, nlen) == 0; | | 82 | memcmp(haystack + hlen - nlen, needle, nlen) == 0; |
83 | } | | 83 | } |
84 | static const char * | | 84 | static const char * |
85 | op_name(op_t op) | | 85 | op_name(op_t op) |
86 | { | | 86 | { |
87 | return modtab[op].m_name; | | 87 | return modtab[op].m_name; |
88 | } | | 88 | } |
89 | | | 89 | |
90 | static unsigned | | 90 | static unsigned |
91 | width_in_bits(const type_t *tp) | | 91 | width_in_bits(const type_t *tp) |
92 | { | | 92 | { |
93 | | | 93 | |
94 | lint_assert(is_integer(tp->t_tspec)); | | 94 | lint_assert(is_integer(tp->t_tspec)); |
95 | return tp->t_bitfield ? tp->t_flen : size_in_bits(tp->t_tspec); | | 95 | return tp->t_bitfield ? tp->t_flen : size_in_bits(tp->t_tspec); |
96 | } | | 96 | } |
97 | | | 97 | |
98 | static bool | | 98 | static bool |
99 | ic_maybe_signed(const type_t *tp, const integer_constraints *ic) | | 99 | ic_maybe_signed(const type_t *tp, const integer_constraints *ic) |
100 | { | | 100 | { |
101 | | | 101 | |
102 | return !is_uinteger(tp->t_tspec) && | | 102 | return !is_uinteger(tp->t_tspec) && |
103 | (ic->bclr & ((uint64_t)1 << 63)) == 0; | | 103 | (ic->bclr & ((uint64_t)1 << 63)) == 0; |
104 | } | | 104 | } |
105 | | | 105 | |
106 | static integer_constraints | | 106 | static integer_constraints |
107 | ic_any(const type_t *tp) | | 107 | ic_any(const type_t *tp) |
108 | { | | 108 | { |
109 | integer_constraints c; | | 109 | integer_constraints c; |
110 | | | 110 | |
111 | uint64_t vbits = value_bits(width_in_bits(tp)); | | 111 | uint64_t vbits = value_bits(width_in_bits(tp)); |
112 | if (is_uinteger(tp->t_tspec)) { | | 112 | if (is_uinteger(tp->t_tspec)) { |
113 | c.smin = INT64_MIN; | | 113 | c.smin = INT64_MIN; |
114 | c.smax = INT64_MAX; | | 114 | c.smax = INT64_MAX; |
115 | c.umin = 0; | | 115 | c.umin = 0; |
116 | c.umax = vbits; | | 116 | c.umax = vbits; |
117 | c.bset = 0; | | 117 | c.bset = 0; |
118 | c.bclr = ~c.umax; | | 118 | c.bclr = ~c.umax; |
119 | } else { | | 119 | } else { |
120 | c.smin = (int64_t)-1 - (int64_t)(vbits >> 1); | | 120 | c.smin = (int64_t)-1 - (int64_t)(vbits >> 1); |
121 | c.smax = (int64_t)(vbits >> 1); | | 121 | c.smax = (int64_t)(vbits >> 1); |
122 | c.umin = 0; | | 122 | c.umin = 0; |
123 | c.umax = UINT64_MAX; | | 123 | c.umax = UINT64_MAX; |
124 | c.bset = 0; | | 124 | c.bset = 0; |
125 | c.bclr = 0; | | 125 | c.bclr = 0; |
126 | } | | 126 | } |
127 | return c; | | 127 | return c; |
128 | } | | 128 | } |
129 | | | 129 | |
130 | static integer_constraints | | 130 | static integer_constraints |
131 | ic_con(const type_t *tp, const val_t *v) | | 131 | ic_con(const type_t *tp, const val_t *v) |
132 | { | | 132 | { |
133 | integer_constraints c; | | 133 | integer_constraints c; |
134 | | | 134 | |
135 | lint_assert(is_integer(tp->t_tspec)); | | 135 | lint_assert(is_integer(tp->t_tspec)); |
136 | int64_t s = v->v_quad; | | 136 | int64_t s = v->v_quad; |
137 | uint64_t u = (uint64_t)s; | | 137 | uint64_t u = (uint64_t)s; |
138 | c.smin = s; | | 138 | c.smin = s; |
139 | c.smax = s; | | 139 | c.smax = s; |
140 | c.umin = u; | | 140 | c.umin = u; |
141 | c.umax = u; | | 141 | c.umax = u; |
142 | c.bset = u; | | 142 | c.bset = u; |
143 | c.bclr = ~u; | | 143 | c.bclr = ~u; |
144 | return c; | | 144 | return c; |
145 | } | | 145 | } |
146 | | | 146 | |
147 | static integer_constraints | | 147 | static integer_constraints |
148 | ic_cvt(const type_t *ntp, const type_t *otp, integer_constraints a) | | 148 | ic_cvt(const type_t *ntp, const type_t *otp, integer_constraints a) |
149 | { | | 149 | { |
150 | | | 150 | |
151 | if (width_in_bits(ntp) > width_in_bits(otp) && | | 151 | if (width_in_bits(ntp) > width_in_bits(otp) && |
152 | is_uinteger(otp->t_tspec)) | | 152 | is_uinteger(otp->t_tspec)) |
153 | return a; | | 153 | return a; |
154 | return ic_any(ntp); | | 154 | return ic_any(ntp); |
155 | } | | 155 | } |
156 | | | 156 | |
157 | static integer_constraints | | 157 | static integer_constraints |
158 | ic_bitand(integer_constraints a, integer_constraints b) | | 158 | ic_bitand(integer_constraints a, integer_constraints b) |
159 | { | | 159 | { |
160 | integer_constraints c; | | 160 | integer_constraints c; |
161 | | | 161 | |
162 | c.smin = INT64_MIN; | | 162 | c.smin = INT64_MIN; |
163 | c.smax = INT64_MAX; | | 163 | c.smax = INT64_MAX; |
164 | c.umin = 0; | | 164 | c.umin = 0; |
165 | c.umax = UINT64_MAX; | | 165 | c.umax = UINT64_MAX; |
166 | c.bset = a.bset & b.bset; | | 166 | c.bset = a.bset & b.bset; |
167 | c.bclr = a.bclr | b.bclr; | | 167 | c.bclr = a.bclr | b.bclr; |
168 | return c; | | 168 | return c; |
169 | } | | 169 | } |
170 | | | 170 | |
171 | static integer_constraints | | 171 | static integer_constraints |
172 | ic_bitor(integer_constraints a, integer_constraints b) | | 172 | ic_bitor(integer_constraints a, integer_constraints b) |
173 | { | | 173 | { |
174 | integer_constraints c; | | 174 | integer_constraints c; |
175 | | | 175 | |
176 | c.smin = INT64_MIN; | | 176 | c.smin = INT64_MIN; |
177 | c.smax = INT64_MAX; | | 177 | c.smax = INT64_MAX; |
178 | c.umin = 0; | | 178 | c.umin = 0; |
179 | c.umax = UINT64_MAX; | | 179 | c.umax = UINT64_MAX; |
180 | c.bset = a.bset | b.bset; | | 180 | c.bset = a.bset | b.bset; |
181 | c.bclr = a.bclr & b.bclr; | | 181 | c.bclr = a.bclr & b.bclr; |
182 | return c; | | 182 | return c; |
183 | } | | 183 | } |
184 | | | 184 | |
185 | static integer_constraints | | 185 | static integer_constraints |
186 | ic_mod(const type_t *tp, integer_constraints a, integer_constraints b) | | 186 | ic_mod(const type_t *tp, integer_constraints a, integer_constraints b) |
187 | { | | 187 | { |
188 | integer_constraints c; | | 188 | integer_constraints c; |
189 | | | 189 | |
190 | if (ic_maybe_signed(tp, &a) || ic_maybe_signed(tp, &b)) | | 190 | if (ic_maybe_signed(tp, &a) || ic_maybe_signed(tp, &b)) |
191 | return ic_any(tp); | | 191 | return ic_any(tp); |
192 | | | 192 | |
193 | c.smin = INT64_MIN; | | 193 | c.smin = INT64_MIN; |
194 | c.smax = INT64_MAX; | | 194 | c.smax = INT64_MAX; |
195 | c.umin = 0; | | 195 | c.umin = 0; |
196 | c.umax = b.umax - 1; | | 196 | c.umax = b.umax - 1; |
197 | c.bset = 0; | | 197 | c.bset = 0; |
198 | c.bclr = ~u64_fill_right(c.umax); | | 198 | c.bclr = ~u64_fill_right(c.umax); |
199 | return c; | | 199 | return c; |
200 | } | | 200 | } |
201 | | | 201 | |
202 | static integer_constraints | | 202 | static integer_constraints |
203 | ic_shl(const type_t *tp, integer_constraints a, integer_constraints b) | | 203 | ic_shl(const type_t *tp, integer_constraints a, integer_constraints b) |
204 | { | | 204 | { |
205 | integer_constraints c; | | 205 | integer_constraints c; |
206 | unsigned int amount; | | 206 | unsigned int amount; |
207 | | | 207 | |
208 | if (ic_maybe_signed(tp, &a)) | | 208 | if (ic_maybe_signed(tp, &a)) |
209 | return ic_any(tp); | | 209 | return ic_any(tp); |
210 | | | 210 | |
211 | if (b.smin == b.smax && b.smin >= 0 && b.smin < 64) | | 211 | if (b.smin == b.smax && b.smin >= 0 && b.smin < 64) |
212 | amount = (unsigned int)b.smin; | | 212 | amount = (unsigned int)b.smin; |
213 | else if (b.umin == b.umax && b.umin < 64) | | 213 | else if (b.umin == b.umax && b.umin < 64) |
214 | amount = (unsigned int)b.umin; | | 214 | amount = (unsigned int)b.umin; |
215 | else | | 215 | else |
216 | return ic_any(tp); | | 216 | return ic_any(tp); |
217 | | | 217 | |
218 | c.smin = INT64_MIN; | | 218 | c.smin = INT64_MIN; |
219 | c.smax = INT64_MAX; | | 219 | c.smax = INT64_MAX; |
220 | c.umin = 0; | | 220 | c.umin = 0; |
221 | c.umax = UINT64_MAX; | | 221 | c.umax = UINT64_MAX; |
222 | c.bset = a.bset << amount; | | 222 | c.bset = a.bset << amount; |
223 | c.bclr = a.bclr << amount | (((uint64_t)1 << amount) - 1); | | 223 | c.bclr = a.bclr << amount | (((uint64_t)1 << amount) - 1); |
224 | return c; | | 224 | return c; |
225 | } | | 225 | } |
226 | | | 226 | |
227 | static integer_constraints | | 227 | static integer_constraints |
228 | ic_shr(const type_t *tp, integer_constraints a, integer_constraints b) | | 228 | ic_shr(const type_t *tp, integer_constraints a, integer_constraints b) |
229 | { | | 229 | { |
230 | integer_constraints c; | | 230 | integer_constraints c; |
231 | unsigned int amount; | | 231 | unsigned int amount; |
232 | | | 232 | |
233 | if (ic_maybe_signed(tp, &a)) | | 233 | if (ic_maybe_signed(tp, &a)) |
234 | return ic_any(tp); | | 234 | return ic_any(tp); |
235 | | | 235 | |
236 | if (b.smin == b.smax && b.smin >= 0 && b.smin < 64) | | 236 | if (b.smin == b.smax && b.smin >= 0 && b.smin < 64) |
237 | amount = (unsigned int)b.smin; | | 237 | amount = (unsigned int)b.smin; |
238 | else if (b.umin == b.umax && b.umin < 64) | | 238 | else if (b.umin == b.umax && b.umin < 64) |
239 | amount = (unsigned int)b.umin; | | 239 | amount = (unsigned int)b.umin; |
240 | else | | 240 | else |
241 | return ic_any(tp); | | 241 | return ic_any(tp); |
242 | | | 242 | |
243 | c.smin = INT64_MIN; | | 243 | c.smin = INT64_MIN; |
244 | c.smax = INT64_MAX; | | 244 | c.smax = INT64_MAX; |
245 | c.umin = 0; | | 245 | c.umin = 0; |
246 | c.umax = UINT64_MAX; | | 246 | c.umax = UINT64_MAX; |
247 | c.bset = a.bset >> amount; | | 247 | c.bset = a.bset >> amount; |
248 | c.bclr = a.bclr >> amount | ~(~(uint64_t)0 >> amount); | | 248 | c.bclr = a.bclr >> amount | ~(~(uint64_t)0 >> amount); |
249 | return c; | | 249 | return c; |
250 | } | | 250 | } |
251 | | | 251 | |
252 | static integer_constraints | | 252 | static integer_constraints |
253 | ic_expr(const tnode_t *tn) | | 253 | ic_expr(const tnode_t *tn) |
254 | { | | 254 | { |
255 | integer_constraints lc, rc; | | 255 | integer_constraints lc, rc; |
256 | | | 256 | |
257 | lint_assert(is_integer(tn->tn_type->t_tspec)); | | 257 | lint_assert(is_integer(tn->tn_type->t_tspec)); |
258 | | | 258 | |
259 | switch (tn->tn_op) { | | 259 | switch (tn->tn_op) { |
260 | case CON: | | 260 | case CON: |
261 | return ic_con(tn->tn_type, tn->tn_val); | | 261 | return ic_con(tn->tn_type, tn->tn_val); |
262 | case CVT: | | 262 | case CVT: |
263 | if (!is_integer(tn->tn_left->tn_type->t_tspec)) | | 263 | if (!is_integer(tn->tn_left->tn_type->t_tspec)) |
264 | return ic_any(tn->tn_type); | | 264 | return ic_any(tn->tn_type); |
265 | lc = ic_expr(tn->tn_left); | | 265 | lc = ic_expr(tn->tn_left); |
266 | return ic_cvt(tn->tn_type, tn->tn_left->tn_type, lc); | | 266 | return ic_cvt(tn->tn_type, tn->tn_left->tn_type, lc); |
267 | case MOD: | | 267 | case MOD: |
268 | lc = ic_expr(before_conversion(tn->tn_left)); | | 268 | lc = ic_expr(before_conversion(tn->tn_left)); |
269 | rc = ic_expr(before_conversion(tn->tn_right)); | | 269 | rc = ic_expr(before_conversion(tn->tn_right)); |
270 | return ic_mod(tn->tn_type, lc, rc); | | 270 | return ic_mod(tn->tn_type, lc, rc); |
271 | case SHL: | | 271 | case SHL: |
272 | lc = ic_expr(tn->tn_left); | | 272 | lc = ic_expr(tn->tn_left); |
273 | rc = ic_expr(tn->tn_right); | | 273 | rc = ic_expr(tn->tn_right); |
274 | return ic_shl(tn->tn_type, lc, rc); | | 274 | return ic_shl(tn->tn_type, lc, rc); |
275 | case SHR: | | 275 | case SHR: |
276 | lc = ic_expr(tn->tn_left); | | 276 | lc = ic_expr(tn->tn_left); |
277 | rc = ic_expr(tn->tn_right); | | 277 | rc = ic_expr(tn->tn_right); |
278 | return ic_shr(tn->tn_type, lc, rc); | | 278 | return ic_shr(tn->tn_type, lc, rc); |
279 | case BITAND: | | 279 | case BITAND: |
280 | lc = ic_expr(tn->tn_left); | | 280 | lc = ic_expr(tn->tn_left); |
281 | rc = ic_expr(tn->tn_right); | | 281 | rc = ic_expr(tn->tn_right); |
282 | return ic_bitand(lc, rc); | | 282 | return ic_bitand(lc, rc); |
283 | case BITOR: | | 283 | case BITOR: |
284 | lc = ic_expr(tn->tn_left); | | 284 | lc = ic_expr(tn->tn_left); |
285 | rc = ic_expr(tn->tn_right); | | 285 | rc = ic_expr(tn->tn_right); |
286 | return ic_bitor(lc, rc); | | 286 | return ic_bitor(lc, rc); |
287 | default: | | 287 | default: |
288 | return ic_any(tn->tn_type); | | 288 | return ic_any(tn->tn_type); |
289 | } | | 289 | } |
290 | } | | 290 | } |
291 | | | 291 | |
292 | /* Build 'pointer to tp', 'array of tp' or 'function returning tp'. */ | | 292 | /* Build 'pointer to tp', 'array of tp' or 'function returning tp'. */ |
293 | type_t * | | 293 | type_t * |
294 | block_derive_type(type_t *tp, tspec_t t) | | 294 | block_derive_type(type_t *tp, tspec_t t) |
295 | { | | 295 | { |
296 | type_t *tp2; | | 296 | type_t *tp2; |
297 | | | 297 | |
298 | tp2 = block_zero_alloc(sizeof(*tp2)); | | 298 | tp2 = block_zero_alloc(sizeof(*tp2)); |
299 | tp2->t_tspec = t; | | 299 | tp2->t_tspec = t; |
300 | tp2->t_subt = tp; | | 300 | tp2->t_subt = tp; |
301 | return tp2; | | 301 | return tp2; |
302 | } | | 302 | } |
303 | | | 303 | |
304 | /* | | 304 | /* |
305 | * Derive 'pointer to tp' or 'function returning tp'. | | 305 | * Derive 'pointer to tp' or 'function returning tp'. |
306 | * The memory is freed at the end of the current expression. | | 306 | * The memory is freed at the end of the current expression. |
307 | */ | | 307 | */ |
308 | type_t * | | 308 | type_t * |
309 | expr_derive_type(type_t *tp, tspec_t t) | | 309 | expr_derive_type(type_t *tp, tspec_t t) |
310 | { | | 310 | { |
311 | type_t *tp2; | | 311 | type_t *tp2; |
312 | | | 312 | |
313 | tp2 = expr_zero_alloc(sizeof(*tp2)); | | 313 | tp2 = expr_zero_alloc(sizeof(*tp2)); |
314 | tp2->t_tspec = t; | | 314 | tp2->t_tspec = t; |
315 | tp2->t_subt = tp; | | 315 | tp2->t_subt = tp; |
316 | return tp2; | | 316 | return tp2; |
317 | } | | 317 | } |
318 | | | 318 | |
319 | /* | | 319 | /* |
320 | * Build and initialize a new node. | | 320 | * Build and initialize a new node. |
321 | */ | | 321 | */ |
322 | static tnode_t * | | 322 | static tnode_t * |
323 | new_tnode(op_t op, bool sys, type_t *type, tnode_t *ln, tnode_t *rn) | | 323 | new_tnode(op_t op, bool sys, type_t *type, tnode_t *ln, tnode_t *rn) |
324 | { | | 324 | { |
325 | | | 325 | |
326 | tnode_t *ntn = expr_alloc_tnode(); | | 326 | tnode_t *ntn = expr_alloc_tnode(); |
327 | ntn->tn_op = op; | | 327 | ntn->tn_op = op; |
328 | ntn->tn_type = type; | | 328 | ntn->tn_type = type; |
329 | ntn->tn_sys = sys; | | 329 | ntn->tn_sys = sys; |
330 | ntn->tn_left = ln; | | 330 | ntn->tn_left = ln; |
331 | ntn->tn_right = rn; | | 331 | ntn->tn_right = rn; |
332 | | | 332 | |
333 | if (op == INDIR || op == FSEL) { | | 333 | if (op == INDIR || op == FSEL) { |
334 | lint_assert(ln->tn_type->t_tspec == PTR); | | 334 | lint_assert(ln->tn_type->t_tspec == PTR); |
335 | tspec_t t = ln->tn_type->t_subt->t_tspec; | | 335 | tspec_t t = ln->tn_type->t_subt->t_tspec; |
336 | if (t != FUNC && t != VOID) | | 336 | if (t != FUNC && t != VOID) |
337 | ntn->tn_lvalue = true; | | 337 | ntn->tn_lvalue = true; |
338 | } | | 338 | } |
339 | | | 339 | |
340 | return ntn; | | 340 | return ntn; |
341 | } | | 341 | } |
342 | | | 342 | |
343 | /* | | 343 | /* |
344 | * Create a node for a constant. | | 344 | * Create a node for a constant. |
345 | */ | | 345 | */ |
346 | tnode_t * | | 346 | tnode_t * |
347 | build_constant(type_t *tp, val_t *v) | | 347 | build_constant(type_t *tp, val_t *v) |
348 | { | | 348 | { |
349 | tnode_t *n; | | 349 | tnode_t *n; |
350 | | | 350 | |
351 | n = expr_alloc_tnode(); | | 351 | n = expr_alloc_tnode(); |
352 | n->tn_op = CON; | | 352 | n->tn_op = CON; |
353 | n->tn_type = tp; | | 353 | n->tn_type = tp; |
354 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); | | 354 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); |
355 | n->tn_val->v_tspec = tp->t_tspec; | | 355 | n->tn_val->v_tspec = tp->t_tspec; |
356 | n->tn_val->v_unsigned_since_c90 = v->v_unsigned_since_c90; | | 356 | n->tn_val->v_unsigned_since_c90 = v->v_unsigned_since_c90; |
357 | n->tn_val->v_u = v->v_u; | | 357 | n->tn_val->v_u = v->v_u; |
358 | free(v); | | 358 | free(v); |
359 | return n; | | 359 | return n; |
360 | } | | 360 | } |
361 | | | 361 | |
362 | static tnode_t * | | 362 | static tnode_t * |
363 | build_integer_constant(tspec_t t, int64_t q) | | 363 | build_integer_constant(tspec_t t, int64_t q) |
364 | { | | 364 | { |
365 | tnode_t *n; | | 365 | tnode_t *n; |
366 | | | 366 | |
367 | n = expr_alloc_tnode(); | | 367 | n = expr_alloc_tnode(); |
368 | n->tn_op = CON; | | 368 | n->tn_op = CON; |
369 | n->tn_type = gettyp(t); | | 369 | n->tn_type = gettyp(t); |
370 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); | | 370 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); |
371 | n->tn_val->v_tspec = t; | | 371 | n->tn_val->v_tspec = t; |
372 | n->tn_val->v_quad = q; | | 372 | n->tn_val->v_quad = q; |
373 | return n; | | 373 | return n; |
374 | } | | 374 | } |
375 | | | 375 | |
376 | static void | | 376 | static void |
377 | fallback_symbol(sym_t *sym) | | 377 | fallback_symbol(sym_t *sym) |
378 | { | | 378 | { |
379 | | | 379 | |
380 | if (Tflag && fallback_symbol_strict_bool(sym)) | | 380 | if (Tflag && fallback_symbol_strict_bool(sym)) |
381 | return; | | 381 | return; |
382 | | | 382 | |
383 | if (block_level > 0 && (strcmp(sym->s_name, "__FUNCTION__") == 0 || | | 383 | if (block_level > 0 && (strcmp(sym->s_name, "__FUNCTION__") == 0 || |
384 | strcmp(sym->s_name, "__PRETTY_FUNCTION__") == 0)) { | | 384 | strcmp(sym->s_name, "__PRETTY_FUNCTION__") == 0)) { |
385 | /* __FUNCTION__/__PRETTY_FUNCTION__ is a GCC extension */ | | 385 | /* __FUNCTION__/__PRETTY_FUNCTION__ is a GCC extension */ |
386 | gnuism(316); | | 386 | gnuism(316); |
387 | sym->s_type = block_derive_type(gettyp(CHAR), PTR); | | 387 | sym->s_type = block_derive_type(gettyp(CHAR), PTR); |
388 | sym->s_type->t_const = true; | | 388 | sym->s_type->t_const = true; |
389 | return; | | 389 | return; |
390 | } | | 390 | } |
391 | | | 391 | |
392 | if (block_level > 0 && strcmp(sym->s_name, "__func__") == 0) { | | 392 | if (block_level > 0 && strcmp(sym->s_name, "__func__") == 0) { |
393 | if (!allow_c99) | | 393 | if (!allow_c99) |
394 | /* __func__ is a C99 feature */ | | 394 | /* __func__ is a C99 feature */ |
395 | warning(317); | | 395 | warning(317); |
396 | /* C11 6.4.2.2 */ | | 396 | /* C11 6.4.2.2 */ |
397 | sym->s_type = block_derive_type(gettyp(CHAR), ARRAY); | | 397 | sym->s_type = block_derive_type(gettyp(CHAR), ARRAY); |
398 | sym->s_type->t_const = true; | | 398 | sym->s_type->t_const = true; |
399 | sym->s_type->t_dim = (int)strlen(funcsym->s_name) + 1; | | 399 | sym->s_type->t_dim = (int)strlen(funcsym->s_name) + 1; |
400 | return; | | 400 | return; |
401 | } | | 401 | } |
402 | | | 402 | |
403 | /* '%s' undefined */ | | 403 | /* '%s' undefined */ |
404 | error(99, sym->s_name); | | 404 | error(99, sym->s_name); |
405 | } | | 405 | } |
406 | | | 406 | |
407 | /* | | 407 | /* |
408 | * Functions that are predeclared by GCC or other compilers can be called | | 408 | * Functions that are predeclared by GCC or other compilers can be called |
409 | * with arbitrary arguments. Since lint usually runs after a successful | | 409 | * with arbitrary arguments. Since lint usually runs after a successful |
410 | * compilation, it's the compiler's job to catch any errors. | | 410 | * compilation, it's the compiler's job to catch any errors. |
411 | */ | | 411 | */ |
412 | bool | | 412 | bool |
413 | is_compiler_builtin(const char *name) | | 413 | is_compiler_builtin(const char *name) |
414 | { | | 414 | { |
415 | /* https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html */ | | 415 | /* https://gcc.gnu.org/onlinedocs/gcc/C-Extensions.html */ |
416 | if (allow_gcc) { | | 416 | if (allow_gcc) { |
417 | if (strncmp(name, "__atomic_", 9) == 0 || | | 417 | if (strncmp(name, "__atomic_", 9) == 0 || |
418 | strncmp(name, "__builtin_", 10) == 0 || | | 418 | strncmp(name, "__builtin_", 10) == 0 || |
419 | strcmp(name, "alloca") == 0 || | | 419 | strcmp(name, "alloca") == 0 || |
420 | /* obsolete but still in use, as of 2021 */ | | 420 | /* obsolete but still in use, as of 2021 */ |
421 | strncmp(name, "__sync_", 7) == 0) | | 421 | strncmp(name, "__sync_", 7) == 0) |
422 | return true; | | 422 | return true; |
423 | } | | 423 | } |
424 | | | 424 | |
425 | /* https://software.intel.com/sites/landingpage/IntrinsicsGuide/ */ | | 425 | /* https://software.intel.com/sites/landingpage/IntrinsicsGuide/ */ |
426 | if (strncmp(name, "_mm_", 4) == 0) | | 426 | if (strncmp(name, "_mm_", 4) == 0) |
427 | return true; | | 427 | return true; |
428 | | | 428 | |
429 | return false; | | 429 | return false; |
430 | } | | 430 | } |
431 | | | 431 | |
432 | /* https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html */ | | 432 | /* https://gcc.gnu.org/onlinedocs/gcc/Integer-Overflow-Builtins.html */ |
433 | static bool | | 433 | static bool |
434 | is_gcc_bool_builtin(const char *name) | | 434 | is_gcc_bool_builtin(const char *name) |
435 | { | | 435 | { |
436 | return strncmp(name, "__builtin_", 10) == 0 && | | 436 | return strncmp(name, "__builtin_", 10) == 0 && |
437 | (str_endswith(name, "_overflow") || | | 437 | (str_endswith(name, "_overflow") || |
438 | str_endswith(name, "_overflow_p")); | | 438 | str_endswith(name, "_overflow_p")); |
439 | } | | 439 | } |
440 | | | 440 | |
441 | static void | | 441 | static void |
442 | build_name_call(sym_t *sym) | | 442 | build_name_call(sym_t *sym) |
443 | { | | 443 | { |
444 | | | 444 | |
445 | if (is_compiler_builtin(sym->s_name)) { | | 445 | if (is_compiler_builtin(sym->s_name)) { |
446 | /* | | 446 | /* |
447 | * Do not warn about these, just assume that | | 447 | * Do not warn about these, just assume that |
448 | * they are regular functions compatible with | | 448 | * they are regular functions compatible with |
449 | * non-prototype calling conventions. | | 449 | * non-prototype calling conventions. |
450 | */ | | 450 | */ |
451 | if (allow_gcc && is_gcc_bool_builtin(sym->s_name)) | | 451 | if (allow_gcc && is_gcc_bool_builtin(sym->s_name)) |
452 | sym->s_type = gettyp(BOOL); | | 452 | sym->s_type = gettyp(BOOL); |
453 | | | 453 | |
454 | } else if (allow_c99) { | | 454 | } else if (allow_c99) { |
455 | /* function '%s' implicitly declared to return int */ | | 455 | /* function '%s' implicitly declared to return int */ |
456 | error(215, sym->s_name); | | 456 | error(215, sym->s_name); |
457 | } else if (!allow_trad) { | | 457 | } else if (!allow_trad) { |
458 | /* function '%s' implicitly declared to return int */ | | 458 | /* function '%s' implicitly declared to return int */ |
459 | warning(215, sym->s_name); | | 459 | warning(215, sym->s_name); |
460 | } | | 460 | } |
461 | | | 461 | |
462 | /* XXX if !allow_c90, the symbol should be exported to level 0 */ | | 462 | /* XXX if !allow_c90, the symbol should be exported to level 0 */ |
463 | sym->s_type = block_derive_type(sym->s_type, FUNC); | | 463 | sym->s_type = block_derive_type(sym->s_type, FUNC); |
464 | } | | 464 | } |
465 | | | 465 | |
466 | /* Create a node for a name (symbol table entry). */ | | 466 | /* Create a node for a name (symbol table entry). */ |
467 | tnode_t * | | 467 | tnode_t * |
468 | build_name(sym_t *sym, bool is_funcname) | | 468 | build_name(sym_t *sym, bool is_funcname) |
469 | { | | 469 | { |
470 | tnode_t *n; | | 470 | tnode_t *n; |
471 | | | 471 | |
472 | if (sym->s_scl == NOSCL && !in_gcc_attribute) { | | 472 | if (sym->s_scl == NOSCL && !in_gcc_attribute) { |
473 | sym->s_scl = EXTERN; | | 473 | sym->s_scl = EXTERN; |
474 | sym->s_def = DECL; | | 474 | sym->s_def = DECL; |
475 | if (is_funcname) | | 475 | if (is_funcname) |
476 | build_name_call(sym); | | 476 | build_name_call(sym); |
477 | else | | 477 | else |
478 | fallback_symbol(sym); | | 478 | fallback_symbol(sym); |
479 | } | | 479 | } |
480 | | | 480 | |
481 | lint_assert(sym->s_kind == FVFT || sym->s_kind == FMEMBER); | | 481 | lint_assert(sym->s_kind == FVFT || sym->s_kind == FMEMBER); |
482 | | | 482 | |
483 | n = expr_alloc_tnode(); | | 483 | n = expr_alloc_tnode(); |
484 | n->tn_type = sym->s_type; | | 484 | n->tn_type = sym->s_type; |
485 | if (sym->s_scl == BOOL_CONST) { | | 485 | if (sym->s_scl == BOOL_CONST) { |
486 | n->tn_op = CON; | | 486 | n->tn_op = CON; |
487 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); | | 487 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); |
488 | n->tn_val->v_tspec = BOOL; | | 488 | n->tn_val->v_tspec = BOOL; |
489 | n->tn_val->v_quad = sym->u.s_bool_constant ? 1 : 0; | | 489 | n->tn_val->v_quad = sym->u.s_bool_constant ? 1 : 0; |
490 | } else if (sym->s_scl == ENUM_CONST) { | | 490 | } else if (sym->s_scl == ENUM_CONST) { |
491 | n->tn_op = CON; | | 491 | n->tn_op = CON; |
492 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); | | 492 | n->tn_val = expr_zero_alloc(sizeof(*n->tn_val)); |
493 | n->tn_val->v_tspec = INT; /* ENUM is in n->tn_type */ | | 493 | n->tn_val->v_tspec = INT; /* ENUM is in n->tn_type */ |
494 | n->tn_val->v_quad = sym->u.s_enum_constant; | | 494 | n->tn_val->v_quad = sym->u.s_enum_constant; |
495 | } else { | | 495 | } else { |
496 | n->tn_op = NAME; | | 496 | n->tn_op = NAME; |
497 | n->tn_sym = sym; | | 497 | n->tn_sym = sym; |
498 | if (sym->s_kind == FVFT && sym->s_type->t_tspec != FUNC) | | 498 | if (sym->s_kind == FVFT && sym->s_type->t_tspec != FUNC) |
499 | n->tn_lvalue = true; | | 499 | n->tn_lvalue = true; |
500 | } | | 500 | } |
501 | | | 501 | |
502 | return n; | | 502 | return n; |
503 | } | | 503 | } |
504 | | | 504 | |
505 | tnode_t * | | 505 | tnode_t * |
506 | build_string(strg_t *strg) | | 506 | build_string(strg_t *strg) |
507 | { | | 507 | { |
508 | size_t len; | | 508 | size_t len; |
509 | tnode_t *n; | | 509 | tnode_t *n; |
510 | type_t *tp; | | 510 | type_t *tp; |
511 | | | 511 | |
512 | len = strg->st_len; | | 512 | len = strg->st_len; |
513 | | | 513 | |
514 | n = expr_alloc_tnode(); | | 514 | n = expr_alloc_tnode(); |
515 | | | 515 | |
516 | tp = expr_zero_alloc(sizeof(*tp)); | | 516 | tp = expr_zero_alloc(sizeof(*tp)); |
517 | tp->t_tspec = ARRAY; | | 517 | tp->t_tspec = ARRAY; |
518 | tp->t_subt = gettyp(strg->st_char ? CHAR : WCHAR); | | 518 | tp->t_subt = gettyp(strg->st_char ? CHAR : WCHAR); |
519 | tp->t_dim = (int)(len + 1); | | 519 | tp->t_dim = (int)(len + 1); |
520 | | | 520 | |
521 | n->tn_op = STRING; | | 521 | n->tn_op = STRING; |
522 | n->tn_type = tp; | | 522 | n->tn_type = tp; |
523 | n->tn_lvalue = true; | | 523 | n->tn_lvalue = true; |
524 | | | 524 | |
525 | n->tn_string = expr_zero_alloc(sizeof(*n->tn_string)); | | 525 | n->tn_string = expr_zero_alloc(sizeof(*n->tn_string)); |
526 | n->tn_string->st_char = strg->st_char; | | 526 | n->tn_string->st_char = strg->st_char; |
527 | n->tn_string->st_len = len; | | 527 | n->tn_string->st_len = len; |
528 | | | 528 | |
529 | size_t chsize = strg->st_char ? sizeof(char) : sizeof(wchar_t); | | 529 | size_t chsize = strg->st_char ? sizeof(char) : sizeof(wchar_t); |
530 | size_t size = (len + 1) * chsize; | | 530 | size_t size = (len + 1) * chsize; |
531 | n->tn_string->st_mem = expr_zero_alloc(size); | | 531 | n->tn_string->st_mem = expr_zero_alloc(size); |
532 | (void)memcpy(n->tn_string->st_mem, strg->st_mem, size); | | 532 | (void)memcpy(n->tn_string->st_mem, strg->st_mem, size); |
533 | free(strg->st_mem); | | 533 | free(strg->st_mem); |
534 | free(strg); | | 534 | free(strg); |
535 | | | 535 | |
536 | return n; | | 536 | return n; |
537 | } | | 537 | } |
538 | | | 538 | |
539 | tnode_t * | | 539 | tnode_t * |
540 | build_generic_selection(const tnode_t *expr, | | 540 | build_generic_selection(const tnode_t *expr, |
541 | struct generic_association *sel) | | 541 | struct generic_association *sel) |
542 | { | | 542 | { |
543 | tnode_t *default_result = NULL; | | 543 | tnode_t *default_result = NULL; |
544 | | | 544 | |
545 | for (; sel != NULL; sel = sel->ga_prev) { | | 545 | for (; sel != NULL; sel = sel->ga_prev) { |
546 | if (expr != NULL && | | 546 | if (expr != NULL && |
547 | types_compatible(sel->ga_arg, expr->tn_type, | | 547 | types_compatible(sel->ga_arg, expr->tn_type, |
548 | false, false, NULL)) | | 548 | false, false, NULL)) |
549 | return sel->ga_result; | | 549 | return sel->ga_result; |
550 | else if (sel->ga_arg == NULL) | | 550 | else if (sel->ga_arg == NULL) |
551 | default_result = sel->ga_result; | | 551 | default_result = sel->ga_result; |
552 | } | | 552 | } |
553 | return default_result; | | 553 | return default_result; |
554 | } | | 554 | } |
555 | | | 555 | |
556 | static bool | | 556 | static bool |
557 | is_out_of_char_range(const tnode_t *tn) | | 557 | is_out_of_char_range(const tnode_t *tn) |
558 | { | | 558 | { |
559 | return tn->tn_op == CON && | | 559 | return tn->tn_op == CON && |
560 | !(0 <= tn->tn_val->v_quad && | | 560 | !(0 <= tn->tn_val->v_quad && |
561 | tn->tn_val->v_quad < 1 << (CHAR_SIZE - 1)); | | 561 | tn->tn_val->v_quad < 1 << (CHAR_SIZE - 1)); |
562 | } | | 562 | } |
563 | | | 563 | |
564 | /* | | 564 | /* |
565 | * Check for ordered comparisons of unsigned values with 0. | | 565 | * Check for ordered comparisons of unsigned values with 0. |
566 | */ | | 566 | */ |
567 | static void | | 567 | static void |
568 | check_integer_comparison(op_t op, tnode_t *ln, tnode_t *rn) | | 568 | check_integer_comparison(op_t op, tnode_t *ln, tnode_t *rn) |
569 | { | | 569 | { |
570 | tspec_t lt, rt; | | 570 | tspec_t lt, rt; |
571 | | | 571 | |
572 | lt = ln->tn_type->t_tspec; | | 572 | lt = ln->tn_type->t_tspec; |
573 | rt = rn->tn_type->t_tspec; | | 573 | rt = rn->tn_type->t_tspec; |
574 | | | 574 | |
575 | if (ln->tn_op != CON && rn->tn_op != CON) | | 575 | if (ln->tn_op != CON && rn->tn_op != CON) |
576 | return; | | 576 | return; |
577 | | | 577 | |
578 | if (!is_integer(lt) || !is_integer(rt)) | | 578 | if (!is_integer(lt) || !is_integer(rt)) |
579 | return; | | 579 | return; |
580 | | | 580 | |
581 | if (hflag || pflag) { | | 581 | if (hflag || pflag) { |
582 | if (lt == CHAR && is_out_of_char_range(rn)) { | | 582 | if (lt == CHAR && is_out_of_char_range(rn)) { |
583 | char buf[128]; | | 583 | char buf[128]; |
584 | (void)snprintf(buf, sizeof(buf), "%s %d", | | 584 | (void)snprintf(buf, sizeof(buf), "%s %d", |
585 | op_name(op), (int)rn->tn_val->v_quad); | | 585 | op_name(op), (int)rn->tn_val->v_quad); |
586 | /* nonportable character comparison '%s' */ | | 586 | /* nonportable character comparison '%s' */ |
587 | warning(230, buf); | | 587 | warning(230, buf); |
588 | return; | | 588 | return; |
589 | } | | 589 | } |
590 | if (rt == CHAR && is_out_of_char_range(ln)) { | | 590 | if (rt == CHAR && is_out_of_char_range(ln)) { |
591 | char buf[128]; | | 591 | char buf[128]; |
592 | (void)snprintf(buf, sizeof(buf), "%d %s ?", | | 592 | (void)snprintf(buf, sizeof(buf), "%d %s ?", |
593 | (int)ln->tn_val->v_quad, op_name(op)); | | 593 | (int)ln->tn_val->v_quad, op_name(op)); |
594 | /* nonportable character comparison '%s' */ | | 594 | /* nonportable character comparison '%s' */ |
595 | warning(230, buf); | | 595 | warning(230, buf); |
596 | return; | | 596 | return; |
597 | } | | 597 | } |
598 | } | | 598 | } |
599 | | | 599 | |
600 | if (is_uinteger(lt) && !is_uinteger(rt) && | | 600 | if (is_uinteger(lt) && !is_uinteger(rt) && |
601 | rn->tn_op == CON && rn->tn_val->v_quad <= 0) { | | 601 | rn->tn_op == CON && rn->tn_val->v_quad <= 0) { |
602 | if (rn->tn_val->v_quad < 0) { | | 602 | if (rn->tn_val->v_quad < 0) { |
603 | /* operator '%s' compares '%s' with '%s' */ | | 603 | /* operator '%s' compares '%s' with '%s' */ |
604 | warning(162, op_name(op), | | 604 | warning(162, op_name(op), |
605 | type_name(ln->tn_type), "negative constant"); | | 605 | type_name(ln->tn_type), "negative constant"); |
606 | } else if (op == LT || op == GE) { | | 606 | } else if (op == LT || op == GE) { |
607 | /* operator '%s' compares '%s' with '%s' */ | | 607 | /* operator '%s' compares '%s' with '%s' */ |
608 | warning(162, op_name(op), type_name(ln->tn_type), "0"); | | 608 | warning(162, op_name(op), type_name(ln->tn_type), "0"); |
609 | } | | 609 | } |
610 | return; | | 610 | return; |
611 | } | | 611 | } |
612 | if (is_uinteger(rt) && !is_uinteger(lt) && | | 612 | if (is_uinteger(rt) && !is_uinteger(lt) && |
613 | ln->tn_op == CON && ln->tn_val->v_quad <= 0) { | | 613 | ln->tn_op == CON && ln->tn_val->v_quad <= 0) { |
614 | if (ln->tn_val->v_quad < 0) { | | 614 | if (ln->tn_val->v_quad < 0) { |
615 | /* operator '%s' compares '%s' with '%s' */ | | 615 | /* operator '%s' compares '%s' with '%s' */ |
616 | warning(162, op_name(op), | | 616 | warning(162, op_name(op), |
617 | "negative constant", type_name(rn->tn_type)); | | 617 | "negative constant", type_name(rn->tn_type)); |
618 | } else if (op == GT || op == LE) { | | 618 | } else if (op == GT || op == LE) { |
619 | /* operator '%s' compares '%s' with '%s' */ | | 619 | /* operator '%s' compares '%s' with '%s' */ |
620 | warning(162, op_name(op), "0", type_name(rn->tn_type)); | | 620 | warning(162, op_name(op), "0", type_name(rn->tn_type)); |
621 | } | | 621 | } |
622 | return; | | 622 | return; |
623 | } | | 623 | } |
624 | } | | 624 | } |
625 | | | 625 | |
626 | static const tspec_t arith_rank[] = { | | 626 | static const tspec_t arith_rank[] = { |
627 | LDOUBLE, DOUBLE, FLOAT, | | 627 | LDOUBLE, DOUBLE, FLOAT, |
628 | #ifdef INT128_SIZE | | 628 | #ifdef INT128_SIZE |
629 | UINT128, INT128, | | 629 | UINT128, INT128, |
630 | #endif | | 630 | #endif |
631 | UQUAD, QUAD, | | 631 | UQUAD, QUAD, |
632 | ULONG, LONG, | | 632 | ULONG, LONG, |
633 | UINT, INT, | | 633 | UINT, INT, |
634 | }; | | 634 | }; |
635 | | | 635 | |
636 | /* Keep unsigned in traditional C */ | | 636 | /* Keep unsigned in traditional C */ |
637 | static tspec_t | | 637 | static tspec_t |
638 | usual_arithmetic_conversion_trad(tspec_t lt, tspec_t rt) | | 638 | usual_arithmetic_conversion_trad(tspec_t lt, tspec_t rt) |
639 | { | | 639 | { |
640 | | | 640 | |
641 | size_t i; | | 641 | size_t i; |
642 | for (i = 0; arith_rank[i] != INT; i++) | | 642 | for (i = 0; arith_rank[i] != INT; i++) |
643 | if (lt == arith_rank[i] || rt == arith_rank[i]) | | 643 | if (lt == arith_rank[i] || rt == arith_rank[i]) |
644 | break; | | 644 | break; |
645 | | | 645 | |
646 | tspec_t t = arith_rank[i]; | | 646 | tspec_t t = arith_rank[i]; |
647 | if (is_uinteger(lt) || is_uinteger(rt)) | | 647 | if (is_uinteger(lt) || is_uinteger(rt)) |
648 | if (is_integer(t) && !is_uinteger(t)) | | 648 | if (is_integer(t) && !is_uinteger(t)) |
649 | return unsigned_type(t); | | 649 | return unsigned_type(t); |
650 | return t; | | 650 | return t; |
651 | } | | 651 | } |
652 | | | 652 | |
653 | static tspec_t | | 653 | static tspec_t |
654 | usual_arithmetic_conversion_c90(tspec_t lt, tspec_t rt) | | 654 | usual_arithmetic_conversion_c90(tspec_t lt, tspec_t rt) |
655 | { | | 655 | { |
656 | | | 656 | |
657 | if (lt == rt) | | 657 | if (lt == rt) |
658 | return lt; | | 658 | return lt; |
659 | | | 659 | |
660 | if (lt == LCOMPLEX || rt == LCOMPLEX) | | 660 | if (lt == LCOMPLEX || rt == LCOMPLEX) |
661 | return LCOMPLEX; | | 661 | return LCOMPLEX; |
662 | if (lt == DCOMPLEX || rt == DCOMPLEX) | | 662 | if (lt == DCOMPLEX || rt == DCOMPLEX) |
663 | return DCOMPLEX; | | 663 | return DCOMPLEX; |
664 | if (lt == FCOMPLEX || rt == FCOMPLEX) | | 664 | if (lt == FCOMPLEX || rt == FCOMPLEX) |
665 | return FCOMPLEX; | | 665 | return FCOMPLEX; |
666 | if (lt == LDOUBLE || rt == LDOUBLE) | | 666 | if (lt == LDOUBLE || rt == LDOUBLE) |
667 | return LDOUBLE; | | 667 | return LDOUBLE; |
668 | if (lt == DOUBLE || rt == DOUBLE) | | 668 | if (lt == DOUBLE || rt == DOUBLE) |
669 | return DOUBLE; | | 669 | return DOUBLE; |
670 | if (lt == FLOAT || rt == FLOAT) | | 670 | if (lt == FLOAT || rt == FLOAT) |
671 | return FLOAT; | | 671 | return FLOAT; |
672 | | | 672 | |
673 | /* | | 673 | /* |
674 | * If type A has more bits than type B, it should be able to hold all | | 674 | * If type A has more bits than type B, it should be able to hold all |
675 | * possible values of type B. | | 675 | * possible values of type B. |
676 | */ | | 676 | */ |
677 | if (size_in_bits(lt) > size_in_bits(rt)) | | 677 | if (size_in_bits(lt) > size_in_bits(rt)) |
678 | return lt; | | 678 | return lt; |
679 | if (size_in_bits(lt) < size_in_bits(rt)) | | 679 | if (size_in_bits(lt) < size_in_bits(rt)) |
680 | return rt; | | 680 | return rt; |
681 | | | 681 | |
682 | size_t i; | | 682 | size_t i; |
683 | for (i = 3; arith_rank[i] != INT; i++) | | 683 | for (i = 3; arith_rank[i] != INT; i++) |
684 | if (arith_rank[i] == lt || arith_rank[i] == rt) | | 684 | if (arith_rank[i] == lt || arith_rank[i] == rt) |
685 | break; | | 685 | break; |
686 | if ((is_uinteger(lt) || is_uinteger(rt)) && | | 686 | if ((is_uinteger(lt) || is_uinteger(rt)) && |
687 | !is_uinteger(arith_rank[i])) | | 687 | !is_uinteger(arith_rank[i])) |
688 | i--; | | 688 | i--; |
689 | return arith_rank[i]; | | 689 | return arith_rank[i]; |
690 | } | | 690 | } |
691 | | | 691 | |
692 | static tnode_t * | | 692 | static tnode_t * |
693 | apply_usual_arithmetic_conversions(op_t op, tnode_t *tn, tspec_t t) | | 693 | apply_usual_arithmetic_conversions(op_t op, tnode_t *tn, tspec_t t) |
694 | { | | 694 | { |
695 | type_t *ntp = expr_dup_type(tn->tn_type); | | 695 | type_t *ntp = expr_dup_type(tn->tn_type); |
696 | ntp->t_tspec = t; | | 696 | ntp->t_tspec = t; |
697 | if (tn->tn_op != CON) { | | 697 | if (tn->tn_op != CON) { |
698 | /* usual arithmetic conversion for '%s' from '%s' to '%s' */ | | 698 | /* usual arithmetic conversion for '%s' from '%s' to '%s' */ |
699 | query_message(4, op_name(op), | | 699 | query_message(4, op_name(op), |
700 | type_name(tn->tn_type), type_name(ntp)); | | 700 | type_name(tn->tn_type), type_name(ntp)); |
701 | } | | 701 | } |
702 | return convert(op, 0, ntp, tn); | | 702 | return convert(op, 0, ntp, tn); |
703 | } | | 703 | } |
704 | | | 704 | |
705 | /* | | 705 | /* |
706 | * Apply the "usual arithmetic conversions" (C99 6.3.1.8), which gives both | | 706 | * Apply the "usual arithmetic conversions" (C99 6.3.1.8), which gives both |
707 | * operands the same type. | | 707 | * operands the same type. |
708 | */ | | 708 | */ |
709 | static void | | 709 | static void |
710 | balance(op_t op, tnode_t **lnp, tnode_t **rnp) | | 710 | balance(op_t op, tnode_t **lnp, tnode_t **rnp) |
711 | { | | 711 | { |
712 | | | 712 | |
713 | tspec_t lt = (*lnp)->tn_type->t_tspec; | | 713 | tspec_t lt = (*lnp)->tn_type->t_tspec; |
714 | tspec_t rt = (*rnp)->tn_type->t_tspec; | | 714 | tspec_t rt = (*rnp)->tn_type->t_tspec; |
715 | if (!is_arithmetic(lt) || !is_arithmetic(rt)) | | 715 | if (!is_arithmetic(lt) || !is_arithmetic(rt)) |
716 | return; | | 716 | return; |
717 | | | 717 | |
718 | tspec_t t = allow_c90 | | 718 | tspec_t t = allow_c90 |
719 | ? usual_arithmetic_conversion_c90(lt, rt) | | 719 | ? usual_arithmetic_conversion_c90(lt, rt) |
720 | : usual_arithmetic_conversion_trad(lt, rt); | | 720 | : usual_arithmetic_conversion_trad(lt, rt); |
721 | | | 721 | |
722 | if (t != lt) | | 722 | if (t != lt) |
723 | *lnp = apply_usual_arithmetic_conversions(op, *lnp, t); | | 723 | *lnp = apply_usual_arithmetic_conversions(op, *lnp, t); |
724 | if (t != rt) | | 724 | if (t != rt) |
725 | *rnp = apply_usual_arithmetic_conversions(op, *rnp, t); | | 725 | *rnp = apply_usual_arithmetic_conversions(op, *rnp, t); |
726 | } | | 726 | } |
727 | | | 727 | |
728 | /* | | 728 | /* |
729 | * Create a tree node for the unary & operator | | 729 | * Create a tree node for the unary & operator |
730 | */ | | 730 | */ |
731 | static tnode_t * | | 731 | static tnode_t * |
732 | build_address(bool sys, tnode_t *tn, bool noign) | | 732 | build_address(bool sys, tnode_t *tn, bool noign) |
733 | { | | 733 | { |
734 | tspec_t t; | | 734 | tspec_t t; |
735 | | | 735 | |
736 | if (!noign && ((t = tn->tn_type->t_tspec) == ARRAY || t == FUNC)) { | | 736 | if (!noign && ((t = tn->tn_type->t_tspec) == ARRAY || t == FUNC)) { |
737 | if (!allow_c90) | | 737 | if (!allow_c90) |
738 | /* '&' before array or function: ignored */ | | 738 | /* '&' before array or function: ignored */ |
739 | warning(127); | | 739 | warning(127); |
740 | return tn; | | 740 | return tn; |
741 | } | | 741 | } |
742 | | | 742 | |
743 | /* eliminate &* */ | | 743 | /* eliminate &* */ |
744 | if (tn->tn_op == INDIR && | | 744 | if (tn->tn_op == INDIR && |
745 | tn->tn_left->tn_type->t_tspec == PTR && | | 745 | tn->tn_left->tn_type->t_tspec == PTR && |
746 | tn->tn_left->tn_type->t_subt == tn->tn_type) { | | 746 | tn->tn_left->tn_type->t_subt == tn->tn_type) { |
747 | return tn->tn_left; | | 747 | return tn->tn_left; |
748 | } | | 748 | } |
749 | | | 749 | |
750 | return new_tnode(ADDR, sys, expr_derive_type(tn->tn_type, PTR), | | 750 | return new_tnode(ADDR, sys, expr_derive_type(tn->tn_type, PTR), |
751 | tn, NULL); | | 751 | tn, NULL); |
752 | } | | 752 | } |
753 | | | 753 | |
754 | /* | | 754 | /* |
755 | * XXX | | 755 | * XXX |
756 | * Note: There appear to be a number of bugs in detecting overflow in | | 756 | * Note: There appear to be a number of bugs in detecting overflow in |
757 | * this function. An audit and a set of proper regression tests are needed. | | 757 | * this function. An audit and a set of proper regression tests are needed. |
758 | * --Perry Metzger, Nov. 16, 2001 | | 758 | * --Perry Metzger, Nov. 16, 2001 |
759 | */ | | 759 | */ |
760 | /* | | 760 | /* |
761 | * Do only as much as necessary to compute constant expressions. | | 761 | * Do only as much as necessary to compute constant expressions. |
762 | * Called only if the operator allows folding and all operands are constants. | | 762 | * Called only if the operator allows folding and all operands are constants. |
763 | */ | | 763 | */ |
764 | static tnode_t * | | 764 | static tnode_t * |
765 | fold(tnode_t *tn) | | 765 | fold(tnode_t *tn) |
766 | { | | 766 | { |
767 | val_t *v; | | 767 | val_t *v; |
768 | tspec_t t; | | 768 | tspec_t t; |
769 | bool utyp, ovfl; | | 769 | bool utyp, ovfl; |
770 | int64_t sl, sr = 0, q = 0, mask; | | 770 | int64_t sl, sr = 0, q = 0, mask; |
771 | uint64_t ul, ur = 0; | | 771 | uint64_t ul, ur = 0; |
772 | tnode_t *cn; | | 772 | tnode_t *cn; |
773 | | | 773 | |
774 | v = xcalloc(1, sizeof(*v)); | | 774 | v = xcalloc(1, sizeof(*v)); |
775 | v->v_tspec = tn->tn_type->t_tspec; | | 775 | v->v_tspec = tn->tn_type->t_tspec; |
776 | | | 776 | |
777 | t = tn->tn_left->tn_type->t_tspec; | | 777 | t = tn->tn_left->tn_type->t_tspec; |
778 | utyp = !is_integer(t) || is_uinteger(t); | | 778 | utyp = !is_integer(t) || is_uinteger(t); |
779 | ul = sl = tn->tn_left->tn_val->v_quad; | | 779 | ul = sl = tn->tn_left->tn_val->v_quad; |
780 | if (is_binary(tn)) | | 780 | if (is_binary(tn)) |
781 | ur = sr = tn->tn_right->tn_val->v_quad; | | 781 | ur = sr = tn->tn_right->tn_val->v_quad; |
782 | | | 782 | |
783 | mask = value_bits(size_in_bits(t)); | | 783 | mask = value_bits(size_in_bits(t)); |
784 | ovfl = false; | | 784 | ovfl = false; |
785 | | | 785 | |
786 | switch (tn->tn_op) { | | 786 | switch (tn->tn_op) { |
787 | case UPLUS: | | 787 | case UPLUS: |
788 | q = sl; | | 788 | q = sl; |
789 | break; | | 789 | break; |
790 | case UMINUS: | | 790 | case UMINUS: |
791 | q = sl == INT64_MIN ? sl : -sl; | | 791 | q = sl == INT64_MIN ? sl : -sl; |
792 | if (sl != 0 && msb(q, t) == msb(sl, t)) | | 792 | if (sl != 0 && msb(q, t) == msb(sl, t)) |
793 | ovfl = true; | | 793 | ovfl = true; |
794 | break; | | 794 | break; |
795 | case COMPL: | | 795 | case COMPL: |
796 | q = ~sl; | | 796 | q = ~sl; |
797 | break; | | 797 | break; |
798 | case MULT: | | 798 | case MULT: |
799 | if (utyp) { | | 799 | if (utyp) { |
800 | q = ul * ur; | | 800 | q = ul * ur; |
801 | if (q != (q & mask)) | | 801 | if (q != (q & mask)) |
802 | ovfl = true; | | 802 | ovfl = true; |
803 | else if ((ul != 0) && ((q / ul) != ur)) | | 803 | else if ((ul != 0) && ((q / ul) != ur)) |
804 | ovfl = true; | | 804 | ovfl = true; |
805 | } else { | | 805 | } else { |
806 | q = sl * sr; | | 806 | q = sl * sr; |
807 | if (msb(q, t) != (msb(sl, t) ^ msb(sr, t))) | | 807 | if (msb(q, t) != (msb(sl, t) ^ msb(sr, t))) |
808 | ovfl = true; | | 808 | ovfl = true; |
809 | } | | 809 | } |
810 | break; | | 810 | break; |
811 | case DIV: | | 811 | case DIV: |
812 | if (sr == 0) { | | 812 | if (sr == 0) { |
813 | /* division by 0 */ | | 813 | /* division by 0 */ |
814 | error(139); | | 814 | error(139); |
815 | q = utyp ? -1 : INT64_MAX; | | 815 | q = utyp ? -1 : INT64_MAX; |
816 | } else { | | 816 | } else { |
817 | q = utyp ? (int64_t)(ul / ur) : sl / sr; | | 817 | q = utyp ? (int64_t)(ul / ur) : sl / sr; |
818 | } | | 818 | } |
819 | break; | | 819 | break; |
820 | case MOD: | | 820 | case MOD: |
821 | if (sr == 0) { | | 821 | if (sr == 0) { |
822 | /* modulus by 0 */ | | 822 | /* modulus by 0 */ |
823 | error(140); | | 823 | error(140); |
824 | q = 0; | | 824 | q = 0; |
825 | } else { | | 825 | } else { |
826 | q = utyp ? (int64_t)(ul % ur) : sl % sr; | | 826 | q = utyp ? (int64_t)(ul % ur) : sl % sr; |
827 | } | | 827 | } |
828 | break; | | 828 | break; |
829 | case PLUS: | | 829 | case PLUS: |
830 | q = utyp ? (int64_t)(ul + ur) : sl + sr; | | 830 | q = utyp ? (int64_t)(ul + ur) : sl + sr; |
831 | if (msb(sl, t) && msb(sr, t) && !msb(q, t)) | | 831 | if (msb(sl, t) && msb(sr, t) && !msb(q, t)) |
832 | ovfl = true; | | 832 | ovfl = true; |
833 | if (!utyp && !msb(sl, t) && !msb(sr, t) && msb(q, t)) | | 833 | if (!utyp && !msb(sl, t) && !msb(sr, t) && msb(q, t)) |
834 | ovfl = true; | | 834 | ovfl = true; |
835 | break; | | 835 | break; |
836 | case MINUS: | | 836 | case MINUS: |
837 | q = utyp ? (int64_t)(ul - ur) : sl - sr; | | 837 | q = utyp ? (int64_t)(ul - ur) : sl - sr; |
838 | if (!utyp && msb(sl, t) && !msb(sr, t) && !msb(q, t)) | | 838 | if (!utyp && msb(sl, t) && !msb(sr, t) && !msb(q, t)) |
839 | ovfl = true; | | 839 | ovfl = true; |
840 | if (!msb(sl, t) && msb(sr, t) && msb(q, t)) | | 840 | if (!msb(sl, t) && msb(sr, t) && msb(q, t)) |
841 | ovfl = true; | | 841 | ovfl = true; |
842 | break; | | 842 | break; |
843 | case SHL: | | 843 | case SHL: |
844 | /* TODO: warn about out-of-bounds 'sr'. */ | | 844 | /* TODO: warn about out-of-bounds 'sr'. */ |
845 | /* TODO: warn about overflow in signed '<<'. */ | | 845 | /* TODO: warn about overflow in signed '<<'. */ |
846 | q = utyp ? (int64_t)(ul << (sr & 63)) : sl << (sr & 63); | | 846 | q = utyp ? (int64_t)(ul << (sr & 63)) : sl << (sr & 63); |
847 | break; | | 847 | break; |
848 | case SHR: | | 848 | case SHR: |
849 | /* | | 849 | /* |
850 | * The sign must be explicitly extended because | | 850 | * The sign must be explicitly extended because |
851 | * shifts of signed values are implementation dependent. | | 851 | * shifts of signed values are implementation dependent. |
852 | */ | | 852 | */ |
853 | /* TODO: warn about out-of-bounds 'sr'. */ | | 853 | /* TODO: warn about out-of-bounds 'sr'. */ |
854 | q = ul >> (sr & 63); | | 854 | q = ul >> (sr & 63); |
855 | q = convert_integer(q, t, size_in_bits(t) - (int)sr); | | 855 | q = convert_integer(q, t, size_in_bits(t) - (int)sr); |
856 | break; | | 856 | break; |
857 | case LT: | | 857 | case LT: |
858 | q = (utyp ? ul < ur : sl < sr) ? 1 : 0; | | 858 | q = (utyp ? ul < ur : sl < sr) ? 1 : 0; |
859 | break; | | 859 | break; |
860 | case LE: | | 860 | case LE: |
861 | q = (utyp ? ul <= ur : sl <= sr) ? 1 : 0; | | 861 | q = (utyp ? ul <= ur : sl <= sr) ? 1 : 0; |
862 | break; | | 862 | break; |
863 | case GE: | | 863 | case GE: |
864 | q = (utyp ? ul >= ur : sl >= sr) ? 1 : 0; | | 864 | q = (utyp ? ul >= ur : sl >= sr) ? 1 : 0; |
865 | break; | | 865 | break; |
866 | case GT: | | 866 | case GT: |
867 | q = (utyp ? ul > ur : sl > sr) ? 1 : 0; | | 867 | q = (utyp ? ul > ur : sl > sr) ? 1 : 0; |
868 | break; | | 868 | break; |
869 | case EQ: | | 869 | case EQ: |
870 | q = (utyp ? ul == ur : sl == sr) ? 1 : 0; | | 870 | q = (utyp ? ul == ur : sl == sr) ? 1 : 0; |
871 | break; | | 871 | break; |
872 | case NE: | | 872 | case NE: |
873 | q = (utyp ? ul != ur : sl != sr) ? 1 : 0; | | 873 | q = (utyp ? ul != ur : sl != sr) ? 1 : 0; |
874 | break; | | 874 | break; |
875 | case BITAND: | | 875 | case BITAND: |
876 | q = utyp ? (int64_t)(ul & ur) : sl & sr; | | 876 | q = utyp ? (int64_t)(ul & ur) : sl & sr; |
877 | break; | | 877 | break; |
878 | case BITXOR: | | 878 | case BITXOR: |
879 | q = utyp ? (int64_t)(ul ^ ur) : sl ^ sr; | | 879 | q = utyp ? (int64_t)(ul ^ ur) : sl ^ sr; |
880 | break; | | 880 | break; |
881 | case BITOR: | | 881 | case BITOR: |
882 | q = utyp ? (int64_t)(ul | ur) : sl | sr; | | 882 | q = utyp ? (int64_t)(ul | ur) : sl | sr; |
883 | break; | | 883 | break; |
884 | default: | | 884 | default: |
885 | lint_assert(/*CONSTCOND*/false); | | 885 | lint_assert(/*CONSTCOND*/false); |
886 | } | | 886 | } |
887 | | | 887 | |
888 | /* XXX does not work for quads. */ | | 888 | /* XXX does not work for quads. */ |
889 | if (ovfl || | | 889 | if (ovfl || |
890 | ((uint64_t)(q | mask) != ~(uint64_t)0 && (q & ~mask) != 0)) { | | 890 | ((uint64_t)(q | mask) != ~(uint64_t)0 && (q & ~mask) != 0)) { |
891 | if (hflag) | | 891 | if (hflag) |
892 | /* integer overflow detected, op '%s' */ | | 892 | /* integer overflow detected, op '%s' */ |
893 | warning(141, op_name(tn->tn_op)); | | 893 | warning(141, op_name(tn->tn_op)); |
894 | } | | 894 | } |
895 | | | 895 | |
896 | v->v_quad = convert_integer(q, t, 0); | | 896 | v->v_quad = convert_integer(q, t, 0); |
897 | | | 897 | |
898 | cn = build_constant(tn->tn_type, v); | | 898 | cn = build_constant(tn->tn_type, v); |
899 | if (tn->tn_left->tn_system_dependent) | | 899 | if (tn->tn_left->tn_system_dependent) |
900 | cn->tn_system_dependent = true; | | 900 | cn->tn_system_dependent = true; |
901 | if (is_binary(tn) && tn->tn_right->tn_system_dependent) | | 901 | if (is_binary(tn) && tn->tn_right->tn_system_dependent) |
902 | cn->tn_system_dependent = true; | | 902 | cn->tn_system_dependent = true; |
903 | | | 903 | |
904 | return cn; | | 904 | return cn; |
905 | } | | 905 | } |
906 | | | 906 | |
907 | /* | | 907 | /* |
908 | * Create a new node for one of the operators POINT and ARROW. | | 908 | * Create a new node for one of the operators POINT and ARROW. |
909 | */ | | 909 | */ |
910 | static tnode_t * | | 910 | static tnode_t * |
911 | build_struct_access(op_t op, bool sys, tnode_t *ln, tnode_t *rn) | | 911 | build_struct_access(op_t op, bool sys, tnode_t *ln, tnode_t *rn) |
912 | { | | 912 | { |
913 | tnode_t *ntn, *ctn; | | 913 | tnode_t *ntn, *ctn; |
914 | bool nolval; | | 914 | bool nolval; |
915 | | | 915 | |
916 | lint_assert(rn->tn_op == NAME); | | 916 | lint_assert(rn->tn_op == NAME); |
917 | lint_assert(is_member(rn->tn_sym)); | | 917 | lint_assert(is_member(rn->tn_sym)); |
918 | | | 918 | |
919 | /* | | 919 | /* |
920 | * Remember if the left operand is an lvalue (structure members | | 920 | * Remember if the left operand is an lvalue (structure members |
921 | * are lvalues if and only if the structure itself is an lvalue). | | 921 | * are lvalues if and only if the structure itself is an lvalue). |
922 | */ | | 922 | */ |
923 | nolval = op == POINT && !ln->tn_lvalue; | | 923 | nolval = op == POINT && !ln->tn_lvalue; |
924 | | | 924 | |
925 | if (op == POINT) { | | 925 | if (op == POINT) { |
926 | ln = build_address(sys, ln, true); | | 926 | ln = build_address(sys, ln, true); |
927 | } else if (ln->tn_type->t_tspec != PTR) { | | 927 | } else if (ln->tn_type->t_tspec != PTR) { |
928 | lint_assert(!allow_c90); | | 928 | lint_assert(!allow_c90); |
929 | lint_assert(is_integer(ln->tn_type->t_tspec)); | | 929 | lint_assert(is_integer(ln->tn_type->t_tspec)); |
930 | ln = convert(NOOP, 0, expr_derive_type(gettyp(VOID), PTR), ln); | | 930 | ln = convert(NOOP, 0, expr_derive_type(gettyp(VOID), PTR), ln); |
931 | } | | 931 | } |
932 | | | 932 | |
933 | ctn = build_integer_constant(PTRDIFF_TSPEC, | | 933 | ctn = build_integer_constant(PTRDIFF_TSPEC, |
934 | rn->tn_sym->u.s_member.sm_offset_in_bits / CHAR_SIZE); | | 934 | rn->tn_sym->u.s_member.sm_offset_in_bits / CHAR_SIZE); |
935 | | | 935 | |
936 | ntn = new_tnode(PLUS, sys, expr_derive_type(rn->tn_type, PTR), | | 936 | ntn = new_tnode(PLUS, sys, expr_derive_type(rn->tn_type, PTR), |
937 | ln, ctn); | | 937 | ln, ctn); |
938 | if (ln->tn_op == CON) | | 938 | if (ln->tn_op == CON) |
939 | ntn = fold(ntn); | | 939 | ntn = fold(ntn); |
940 | | | 940 | |
941 | if (rn->tn_type->t_bitfield) { | | 941 | if (rn->tn_type->t_bitfield) { |
942 | ntn = new_tnode(FSEL, sys, ntn->tn_type->t_subt, ntn, NULL); | | 942 | ntn = new_tnode(FSEL, sys, ntn->tn_type->t_subt, ntn, NULL); |
943 | } else { | | 943 | } else { |
944 | ntn = new_tnode(INDIR, sys, ntn->tn_type->t_subt, ntn, NULL); | | 944 | ntn = new_tnode(INDIR, sys, ntn->tn_type->t_subt, ntn, NULL); |
945 | } | | 945 | } |
946 | | | 946 | |
947 | if (nolval) | | 947 | if (nolval) |
948 | ntn->tn_lvalue = false; | | 948 | ntn->tn_lvalue = false; |
949 | | | 949 | |
950 | return ntn; | | 950 | return ntn; |
951 | } | | 951 | } |
952 | | | 952 | |
953 | /* | | 953 | /* |
954 | * Get the size in bytes of type tp->t_subt, as a constant expression of type | | 954 | * Get the size in bytes of type tp->t_subt, as a constant expression of type |
955 | * ptrdiff_t as seen from the target platform. | | 955 | * ptrdiff_t as seen from the target platform. |
956 | */ | | 956 | */ |
957 | static tnode_t * | | 957 | static tnode_t * |
958 | subt_size_in_bytes(type_t *tp) | | 958 | subt_size_in_bytes(type_t *tp) |
959 | { | | 959 | { |
960 | int elem, elsz_in_bits; | | 960 | int elem, elsz_in_bits; |
961 | | | 961 | |
962 | lint_assert(tp->t_tspec == PTR); | | 962 | lint_assert(tp->t_tspec == PTR); |
963 | tp = tp->t_subt; | | 963 | tp = tp->t_subt; |
964 | | | 964 | |
965 | elem = 1; | | 965 | elem = 1; |
966 | elsz_in_bits = 0; | | 966 | elsz_in_bits = 0; |
967 | | | 967 | |
968 | while (tp->t_tspec == ARRAY) { | | 968 | while (tp->t_tspec == ARRAY) { |
969 | elem *= tp->t_dim; | | 969 | elem *= tp->t_dim; |
970 | tp = tp->t_subt; | | 970 | tp = tp->t_subt; |
971 | } | | 971 | } |
972 | | | 972 | |
973 | switch (tp->t_tspec) { | | 973 | switch (tp->t_tspec) { |
974 | case FUNC: | | 974 | case FUNC: |
975 | /* pointer to function is not allowed here */ | | 975 | /* pointer to function is not allowed here */ |
976 | error(110); | | 976 | error(110); |
977 | break; | | 977 | break; |
978 | case VOID: | | 978 | case VOID: |
979 | /* cannot do pointer arithmetic on operand of unknown size */ | | 979 | /* cannot do pointer arithmetic on operand of unknown size */ |
980 | gnuism(136); | | 980 | gnuism(136); |
981 | break; | | 981 | break; |
982 | case STRUCT: | | 982 | case STRUCT: |
983 | case UNION: | | 983 | case UNION: |
984 | if ((elsz_in_bits = tp->t_str->sou_size_in_bits) == 0) | | 984 | if ((elsz_in_bits = tp->t_str->sou_size_in_bits) == 0) |
985 | /* cannot do pointer arithmetic on operand of ... */ | | 985 | /* cannot do pointer arithmetic on operand of ... */ |
986 | error(136); | | 986 | error(136); |
987 | break; | | 987 | break; |
988 | case ENUM: | | 988 | case ENUM: |
989 | if (is_incomplete(tp)) { | | 989 | if (is_incomplete(tp)) { |
990 | /* cannot do pointer arithmetic on operand of ... */ | | 990 | /* cannot do pointer arithmetic on operand of ... */ |
991 | warning(136); | | 991 | warning(136); |
992 | } | | 992 | } |
993 | /* FALLTHROUGH */ | | 993 | /* FALLTHROUGH */ |
994 | default: | | 994 | default: |
995 | if ((elsz_in_bits = size_in_bits(tp->t_tspec)) == 0) { | | 995 | if ((elsz_in_bits = size_in_bits(tp->t_tspec)) == 0) { |
996 | /* cannot do pointer arithmetic on operand of ... */ | | 996 | /* cannot do pointer arithmetic on operand of ... */ |
997 | error(136); | | 997 | error(136); |
998 | } else { | | 998 | } else { |
999 | lint_assert(elsz_in_bits != -1); | | 999 | lint_assert(elsz_in_bits != -1); |
1000 | } | | 1000 | } |
1001 | break; | | 1001 | break; |
1002 | } | | 1002 | } |
1003 | | | 1003 | |
1004 | if (elem == 0 && elsz_in_bits != 0) { | | 1004 | if (elem == 0 && elsz_in_bits != 0) { |
1005 | /* cannot do pointer arithmetic on operand of unknown size */ | | 1005 | /* cannot do pointer arithmetic on operand of unknown size */ |
1006 | error(136); | | 1006 | error(136); |
1007 | } | | 1007 | } |
1008 | | | 1008 | |
1009 | if (elsz_in_bits == 0) | | 1009 | if (elsz_in_bits == 0) |
1010 | elsz_in_bits = CHAR_SIZE; | | 1010 | elsz_in_bits = CHAR_SIZE; |
1011 | | | 1011 | |
1012 | return build_integer_constant(PTRDIFF_TSPEC, | | 1012 | return build_integer_constant(PTRDIFF_TSPEC, |
1013 | (int64_t)(elem * elsz_in_bits / CHAR_SIZE)); | | 1013 | (int64_t)(elem * elsz_in_bits / CHAR_SIZE)); |
1014 | } | | 1014 | } |
1015 | | | 1015 | |
1016 | /* | | 1016 | /* |
1017 | * Create a node for INCAFT, INCBEF, DECAFT and DECBEF. | | 1017 | * Create a node for INCAFT, INCBEF, DECAFT and DECBEF. |
1018 | */ | | 1018 | */ |
1019 | static tnode_t * | | 1019 | static tnode_t * |
1020 | build_prepost_incdec(op_t op, bool sys, tnode_t *ln) | | 1020 | build_prepost_incdec(op_t op, bool sys, tnode_t *ln) |
1021 | { | | 1021 | { |
1022 | tnode_t *cn, *ntn; | | 1022 | tnode_t *cn, *ntn; |
1023 | | | 1023 | |
1024 | lint_assert(ln != NULL); | | 1024 | lint_assert(ln != NULL); |
1025 | | | 1025 | |
1026 | if (ln->tn_type->t_tspec == PTR) { | | 1026 | if (ln->tn_type->t_tspec == PTR) { |
1027 | cn = subt_size_in_bytes(ln->tn_type); | | 1027 | cn = subt_size_in_bytes(ln->tn_type); |
1028 | } else { | | 1028 | } else { |
1029 | cn = build_integer_constant(INT, (int64_t)1); | | 1029 | cn = build_integer_constant(INT, (int64_t)1); |
1030 | } | | 1030 | } |
1031 | ntn = new_tnode(op, sys, ln->tn_type, ln, cn); | | 1031 | ntn = new_tnode(op, sys, ln->tn_type, ln, cn); |
1032 | | | 1032 | |
1033 | return ntn; | | 1033 | return ntn; |
1034 | } | | 1034 | } |
1035 | | | 1035 | |
1036 | static void | | 1036 | static void |
1037 | check_enum_array_index(const tnode_t *ln, const tnode_t *rn) | | 1037 | check_enum_array_index(const tnode_t *ln, const tnode_t *rn) |
1038 | { | | 1038 | { |
1039 | int max_array_index; | | 1039 | int max_array_index; |
1040 | int64_t max_enum_value; | | 1040 | int64_t max_enum_value; |
1041 | const struct sym *ec, *max_ec; | | 1041 | const struct sym *ec, *max_ec; |
1042 | const type_t *lt, *rt; | | 1042 | const type_t *lt, *rt; |
1043 | | | 1043 | |
1044 | if (ln->tn_op != ADDR || ln->tn_left->tn_op != NAME) | | 1044 | if (ln->tn_op != ADDR || ln->tn_left->tn_op != NAME) |
1045 | return; | | 1045 | return; |
1046 | | | 1046 | |
1047 | lt = ln->tn_left->tn_type; | | 1047 | lt = ln->tn_left->tn_type; |
1048 | if (lt->t_tspec != ARRAY || lt->t_incomplete_array) | | 1048 | if (lt->t_tspec != ARRAY || lt->t_incomplete_array) |
1049 | return; | | 1049 | return; |
1050 | | | 1050 | |
1051 | if (rn->tn_op != CVT || !rn->tn_type->t_is_enum) | | 1051 | if (rn->tn_op != CVT || !rn->tn_type->t_is_enum) |
1052 | return; | | 1052 | return; |
1053 | if (rn->tn_left->tn_op != LOAD) | | 1053 | if (rn->tn_left->tn_op != LOAD) |
1054 | return; | | 1054 | return; |
1055 | | | 1055 | |
1056 | rt = rn->tn_left->tn_type; | | 1056 | rt = rn->tn_left->tn_type; |
1057 | ec = rt->t_enum->en_first_enumerator; | | 1057 | ec = rt->t_enum->en_first_enumerator; |
1058 | max_ec = ec; | | 1058 | max_ec = ec; |
1059 | lint_assert(ec != NULL); | | 1059 | lint_assert(ec != NULL); |
1060 | for (ec = ec->s_next; ec != NULL; ec = ec->s_next) | | 1060 | for (ec = ec->s_next; ec != NULL; ec = ec->s_next) |
1061 | if (ec->u.s_enum_constant > max_ec->u.s_enum_constant) | | 1061 | if (ec->u.s_enum_constant > max_ec->u.s_enum_constant) |
1062 | max_ec = ec; | | 1062 | max_ec = ec; |
1063 | | | 1063 | |
1064 | max_enum_value = max_ec->u.s_enum_constant; | | 1064 | max_enum_value = max_ec->u.s_enum_constant; |
1065 | lint_assert(INT_MIN <= max_enum_value && max_enum_value <= INT_MAX); | | 1065 | lint_assert(INT_MIN <= max_enum_value && max_enum_value <= INT_MAX); |
1066 | | | 1066 | |
1067 | max_array_index = lt->t_dim - 1; | | 1067 | max_array_index = lt->t_dim - 1; |
1068 | if (max_enum_value == max_array_index) | | 1068 | if (max_enum_value == max_array_index) |
1069 | return; | | 1069 | return; |
1070 | | | 1070 | |
1071 | /* | | 1071 | /* |
1072 | * If the name of the largest enum constant contains 'MAX' or 'NUM', | | 1072 | * If the name of the largest enum constant contains 'MAX' or 'NUM', |
1073 | * that constant is typically not part of the allowed enum values but | | 1073 | * that constant is typically not part of the allowed enum values but |
1074 | * a marker for the number of actual enum values. | | 1074 | * a marker for the number of actual enum values. |
1075 | */ | | 1075 | */ |
1076 | if (max_enum_value == max_array_index + 1 && | | 1076 | if (max_enum_value == max_array_index + 1 && |
1077 | (strstr(max_ec->s_name, "MAX") != NULL || | | 1077 | (strstr(max_ec->s_name, "MAX") != NULL || |
1078 | strstr(max_ec->s_name, "max") != NULL || | | 1078 | strstr(max_ec->s_name, "max") != NULL || |
1079 | strstr(max_ec->s_name, "NUM") != NULL || | | 1079 | strstr(max_ec->s_name, "NUM") != NULL || |
1080 | strstr(max_ec->s_name, "num") != NULL)) | | 1080 | strstr(max_ec->s_name, "num") != NULL)) |
1081 | return; | | 1081 | return; |
1082 | | | 1082 | |
1083 | /* maximum value %d of '%s' does not match maximum array index %d */ | | 1083 | /* maximum value %d of '%s' does not match maximum array index %d */ |
1084 | warning(348, (int)max_enum_value, type_name(rt), max_array_index); | | 1084 | warning(348, (int)max_enum_value, type_name(rt), max_array_index); |
1085 | print_previous_declaration(max_ec); | | 1085 | print_previous_declaration(max_ec); |
1086 | } | | 1086 | } |
1087 | | | 1087 | |
1088 | /* | | 1088 | /* |
1089 | * Create a node for operators PLUS and MINUS. | | 1089 | * Create a node for operators PLUS and MINUS. |
1090 | */ | | 1090 | */ |
1091 | static tnode_t * | | 1091 | static tnode_t * |
1092 | build_plus_minus(op_t op, bool sys, tnode_t *ln, tnode_t *rn) | | 1092 | build_plus_minus(op_t op, bool sys, tnode_t *ln, tnode_t *rn) |
1093 | { | | 1093 | { |
1094 | | | 1094 | |
1095 | /* If pointer and integer, then pointer to the lhs. */ | | 1095 | /* If pointer and integer, then pointer to the lhs. */ |
1096 | if (rn->tn_type->t_tspec == PTR && is_integer(ln->tn_type->t_tspec)) { | | 1096 | if (rn->tn_type->t_tspec == PTR && is_integer(ln->tn_type->t_tspec)) { |
1097 | tnode_t *tmp = ln; | | 1097 | tnode_t *tmp = ln; |
1098 | ln = rn; | | 1098 | ln = rn; |
1099 | rn = tmp; | | 1099 | rn = tmp; |
1100 | /* pointer addition has integer on the left-hand side */ | | 1100 | /* pointer addition has integer on the left-hand side */ |
1101 | query_message(5); | | 1101 | query_message(5); |
1102 | } | | 1102 | } |
1103 | | | 1103 | |
1104 | /* pointer +- integer */ | | 1104 | /* pointer +- integer */ |
1105 | if (ln->tn_type->t_tspec == PTR && rn->tn_type->t_tspec != PTR) { | | 1105 | if (ln->tn_type->t_tspec == PTR && rn->tn_type->t_tspec != PTR) { |
1106 | lint_assert(is_integer(rn->tn_type->t_tspec)); | | 1106 | lint_assert(is_integer(rn->tn_type->t_tspec)); |
1107 | | | 1107 | |
1108 | check_ctype_macro_invocation(ln, rn); | | 1108 | check_ctype_macro_invocation(ln, rn); |
1109 | check_enum_array_index(ln, rn); | | 1109 | check_enum_array_index(ln, rn); |
1110 | | | 1110 | |
1111 | tnode_t *elsz = subt_size_in_bytes(ln->tn_type); | | 1111 | tnode_t *elsz = subt_size_in_bytes(ln->tn_type); |
1112 | if (rn->tn_type->t_tspec != elsz->tn_type->t_tspec) | | 1112 | if (rn->tn_type->t_tspec != elsz->tn_type->t_tspec) |
1113 | rn = convert(NOOP, 0, elsz->tn_type, rn); | | 1113 | rn = convert(NOOP, 0, elsz->tn_type, rn); |
1114 | | | 1114 | |
1115 | tnode_t *prod = new_tnode(MULT, sys, rn->tn_type, rn, elsz); | | 1115 | tnode_t *prod = new_tnode(MULT, sys, rn->tn_type, rn, elsz); |
1116 | if (rn->tn_op == CON) | | 1116 | if (rn->tn_op == CON) |
1117 | prod = fold(prod); | | 1117 | prod = fold(prod); |
1118 | | | 1118 | |
1119 | return new_tnode(op, sys, ln->tn_type, ln, prod); | | 1119 | return new_tnode(op, sys, ln->tn_type, ln, prod); |
1120 | } | | 1120 | } |
1121 | | | 1121 | |
1122 | /* pointer - pointer */ | | 1122 | /* pointer - pointer */ |
1123 | if (rn->tn_type->t_tspec == PTR) { | | 1123 | if (rn->tn_type->t_tspec == PTR) { |
1124 | lint_assert(ln->tn_type->t_tspec == PTR); | | 1124 | lint_assert(ln->tn_type->t_tspec == PTR); |
1125 | lint_assert(op == MINUS); | | 1125 | lint_assert(op == MINUS); |
1126 | | | 1126 | |
1127 | type_t *ptrdiff = gettyp(PTRDIFF_TSPEC); | | 1127 | type_t *ptrdiff = gettyp(PTRDIFF_TSPEC); |
1128 | tnode_t *raw_diff = new_tnode(op, sys, ptrdiff, ln, rn); | | 1128 | tnode_t *raw_diff = new_tnode(op, sys, ptrdiff, ln, rn); |
1129 | if (ln->tn_op == CON && rn->tn_op == CON) | | 1129 | if (ln->tn_op == CON && rn->tn_op == CON) |
1130 | raw_diff = fold(raw_diff); | | 1130 | raw_diff = fold(raw_diff); |
1131 | | | 1131 | |
1132 | tnode_t *elsz = subt_size_in_bytes(ln->tn_type); | | 1132 | tnode_t *elsz = subt_size_in_bytes(ln->tn_type); |
1133 | balance(NOOP, &raw_diff, &elsz); | | 1133 | balance(NOOP, &raw_diff, &elsz); |
1134 | | | 1134 | |
1135 | return new_tnode(DIV, sys, ptrdiff, raw_diff, elsz); | | 1135 | return new_tnode(DIV, sys, ptrdiff, raw_diff, elsz); |
1136 | } | | 1136 | } |
1137 | | | 1137 | |
1138 | return new_tnode(op, sys, ln->tn_type, ln, rn); | | 1138 | return new_tnode(op, sys, ln->tn_type, ln, rn); |
1139 | } | | 1139 | } |
1140 | | | 1140 | |
1141 | /* | | 1141 | /* |
1142 | * Create a node for operators SHL and SHR. | | 1142 | * Create a node for operators SHL and SHR. |
1143 | */ | | 1143 | */ |
1144 | static tnode_t * | | 1144 | static tnode_t * |
1145 | build_bit_shift(op_t op, bool sys, tnode_t *ln, tnode_t *rn) | | 1145 | build_bit_shift(op_t op, bool sys, tnode_t *ln, tnode_t *rn) |
1146 | { | | 1146 | { |
1147 | | | 1147 | |
1148 | if (!allow_c90 && rn->tn_type->t_tspec != INT) | | 1148 | if (!allow_c90 && rn->tn_type->t_tspec != INT) |
1149 | rn = convert(NOOP, 0, gettyp(INT), rn); | | 1149 | rn = convert(NOOP, 0, gettyp(INT), rn); |
1150 | return new_tnode(op, sys, ln->tn_type, ln, rn); | | 1150 | return new_tnode(op, sys, ln->tn_type, ln, rn); |
1151 | } | | 1151 | } |
1152 | | | 1152 | |
1153 | static bool | | 1153 | static bool |
1154 | is_null_pointer(const tnode_t *tn) | | 1154 | is_null_pointer(const tnode_t *tn) |
1155 | { | | 1155 | { |
1156 | tspec_t t = tn->tn_type->t_tspec; | | 1156 | tspec_t t = tn->tn_type->t_tspec; |
1157 | | | 1157 | |
1158 | return ((t == PTR && tn->tn_type->t_subt->t_tspec == VOID) || | | 1158 | return ((t == PTR && tn->tn_type->t_subt->t_tspec == VOID) || |
1159 | is_integer(t)) | | 1159 | is_integer(t)) |
1160 | && (tn->tn_op == CON && tn->tn_val->v_quad == 0); | | 1160 | && (tn->tn_op == CON && tn->tn_val->v_quad == 0); |
1161 | } | | 1161 | } |
1162 | | | 1162 | |
1163 | /* Return a type based on tp1, with added qualifiers from tp2. */ | | 1163 | /* Return a type based on tp1, with added qualifiers from tp2. */ |
1164 | static type_t * | | 1164 | static type_t * |
1165 | merge_qualifiers(type_t *tp1, const type_t *tp2) | | 1165 | merge_qualifiers(type_t *tp1, const type_t *tp2) |
1166 | { | | 1166 | { |
1167 | type_t *ntp, *nstp; | | 1167 | type_t *ntp, *nstp; |
1168 | bool c1, c2, v1, v2; | | 1168 | bool c1, c2, v1, v2; |
1169 | | | 1169 | |
1170 | lint_assert(tp1->t_tspec == PTR); | | 1170 | lint_assert(tp1->t_tspec == PTR); |
1171 | lint_assert(tp2->t_tspec == PTR); | | 1171 | lint_assert(tp2->t_tspec == PTR); |
1172 | | | 1172 | |
1173 | c1 = tp1->t_subt->t_const; | | 1173 | c1 = tp1->t_subt->t_const; |
1174 | c2 = tp2->t_subt->t_const; | | 1174 | c2 = tp2->t_subt->t_const; |
1175 | v1 = tp1->t_subt->t_volatile; | | 1175 | v1 = tp1->t_subt->t_volatile; |
1176 | v2 = tp2->t_subt->t_volatile; | | 1176 | v2 = tp2->t_subt->t_volatile; |
1177 | | | 1177 | |
1178 | if (c1 == (c1 | c2) && v1 == (v1 | v2)) | | 1178 | if (c1 == (c1 | c2) && v1 == (v1 | v2)) |
1179 | return tp1; | | 1179 | return tp1; |
1180 | | | 1180 | |
1181 | nstp = expr_dup_type(tp1->t_subt); | | 1181 | nstp = expr_dup_type(tp1->t_subt); |
1182 | nstp->t_const |= c2; | | 1182 | nstp->t_const |= c2; |
1183 | nstp->t_volatile |= v2; | | 1183 | nstp->t_volatile |= v2; |
1184 | | | 1184 | |
1185 | ntp = expr_dup_type(tp1); | | 1185 | ntp = expr_dup_type(tp1); |
1186 | ntp->t_subt = nstp; | | 1186 | ntp->t_subt = nstp; |
1187 | return ntp; | | 1187 | return ntp; |
1188 | } | | 1188 | } |
1189 | | | 1189 | |
1190 | /* See C99 6.5.15 "Conditional operator". */ | | 1190 | /* See C99 6.5.15 "Conditional operator". */ |
1191 | static tnode_t * | | 1191 | static tnode_t * |
1192 | build_colon(bool sys, tnode_t *ln, tnode_t *rn) | | 1192 | build_colon(bool sys, tnode_t *ln, tnode_t *rn) |
1193 | { | | 1193 | { |
1194 | tspec_t lt, rt; | | 1194 | tspec_t lt, rt; |
1195 | type_t *tp; | | 1195 | type_t *tp; |
1196 | | | 1196 | |
1197 | lt = ln->tn_type->t_tspec; | | 1197 | lt = ln->tn_type->t_tspec; |
1198 | rt = rn->tn_type->t_tspec; | | 1198 | rt = rn->tn_type->t_tspec; |
1199 | | | 1199 | |
1200 | if (is_arithmetic(lt) && is_arithmetic(rt)) { | | 1200 | if (is_arithmetic(lt) && is_arithmetic(rt)) { |
1201 | /* The operands were already balanced in build_binary. */ | | 1201 | /* The operands were already balanced in build_binary. */ |
1202 | tp = ln->tn_type; | | 1202 | tp = ln->tn_type; |
1203 | } else if (lt == BOOL && rt == BOOL) { | | 1203 | } else if (lt == BOOL && rt == BOOL) { |
1204 | tp = ln->tn_type; | | 1204 | tp = ln->tn_type; |
1205 | } else if (lt == VOID || rt == VOID) { | | 1205 | } else if (lt == VOID || rt == VOID) { |
1206 | tp = gettyp(VOID); | | 1206 | tp = gettyp(VOID); |
1207 | } else if (is_struct_or_union(lt)) { | | 1207 | } else if (is_struct_or_union(lt)) { |
1208 | /* Both types must be identical. */ | | 1208 | /* Both types must be identical. */ |
1209 | lint_assert(is_struct_or_union(rt)); | | 1209 | lint_assert(is_struct_or_union(rt)); |
1210 | lint_assert(ln->tn_type->t_str == rn->tn_type->t_str); | | 1210 | lint_assert(ln->tn_type->t_str == rn->tn_type->t_str); |
1211 | if (is_incomplete(ln->tn_type)) { | | 1211 | if (is_incomplete(ln->tn_type)) { |
1212 | /* unknown operand size, op '%s' */ | | 1212 | /* unknown operand size, op '%s' */ |
1213 | error(138, op_name(COLON)); | | 1213 | error(138, op_name(COLON)); |
1214 | return NULL; | | 1214 | return NULL; |
1215 | } | | 1215 | } |
1216 | tp = ln->tn_type; | | 1216 | tp = ln->tn_type; |
1217 | } else if (lt == PTR && is_integer(rt)) { | | 1217 | } else if (lt == PTR && is_integer(rt)) { |
1218 | if (rt != PTRDIFF_TSPEC) | | 1218 | if (rt != PTRDIFF_TSPEC) |
1219 | rn = convert(NOOP, 0, gettyp(PTRDIFF_TSPEC), rn); | | 1219 | rn = convert(NOOP, 0, gettyp(PTRDIFF_TSPEC), rn); |
1220 | tp = ln->tn_type; | | 1220 | tp = ln->tn_type; |
1221 | } else if (rt == PTR && is_integer(lt)) { | | 1221 | } else if (rt == PTR && is_integer(lt)) { |
1222 | if (lt != PTRDIFF_TSPEC) | | 1222 | if (lt != PTRDIFF_TSPEC) |
1223 | ln = convert(NOOP, 0, gettyp(PTRDIFF_TSPEC), ln); | | 1223 | ln = convert(NOOP, 0, gettyp(PTRDIFF_TSPEC), ln); |
1224 | tp = rn->tn_type; | | 1224 | tp = rn->tn_type; |
1225 | } else if (lt == PTR && is_null_pointer(rn)) { | | 1225 | } else if (lt == PTR && is_null_pointer(rn)) { |
1226 | tp = merge_qualifiers(ln->tn_type, rn->tn_type); | | 1226 | tp = merge_qualifiers(ln->tn_type, rn->tn_type); |
1227 | } else if (rt == PTR && is_null_pointer(ln)) { | | 1227 | } else if (rt == PTR && is_null_pointer(ln)) { |
1228 | tp = merge_qualifiers(rn->tn_type, ln->tn_type); | | 1228 | tp = merge_qualifiers(rn->tn_type, ln->tn_type); |
1229 | } else if (lt == PTR && ln->tn_type->t_subt->t_tspec == VOID) { | | 1229 | } else if (lt == PTR && ln->tn_type->t_subt->t_tspec == VOID) { |
1230 | tp = merge_qualifiers(ln->tn_type, rn->tn_type); | | 1230 | tp = merge_qualifiers(ln->tn_type, rn->tn_type); |
1231 | } else if (rt == PTR && rn->tn_type->t_subt->t_tspec == VOID) { | | 1231 | } else if (rt == PTR && rn->tn_type->t_subt->t_tspec == VOID) { |
1232 | tp = merge_qualifiers(rn->tn_type, ln->tn_type); | | 1232 | tp = merge_qualifiers(rn->tn_type, ln->tn_type); |
1233 | } else { | | 1233 | } else { |
1234 | /* | | 1234 | /* |
1235 | * XXX For now we simply take the left type. This is | | 1235 | * XXX For now we simply take the left type. This is |
1236 | * probably wrong, if one type contains a function prototype | | 1236 | * probably wrong, if one type contains a function prototype |
1237 | * and the other one, at the same place, only an old-style | | 1237 | * and the other one, at the same place, only an old-style |
1238 | * declaration. | | 1238 | * declaration. |
1239 | */ | | 1239 | */ |
1240 | tp = merge_qualifiers(ln->tn_type, rn->tn_type); | | 1240 | tp = merge_qualifiers(ln->tn_type, rn->tn_type); |
1241 | } | | 1241 | } |
1242 | | | 1242 | |
1243 | return new_tnode(COLON, sys, tp, ln, rn); | | 1243 | return new_tnode(COLON, sys, tp, ln, rn); |
1244 | } | | 1244 | } |
1245 | | | 1245 | |
1246 | /* TODO: check for varargs */ | | 1246 | /* TODO: check for varargs */ |
1247 | static bool | | 1247 | static bool |
1248 | is_cast_redundant(const tnode_t *tn) | | 1248 | is_cast_redundant(const tnode_t *tn) |
1249 | { | | 1249 | { |
1250 | const type_t *ntp = tn->tn_type, *otp = tn->tn_left->tn_type; | | 1250 | const type_t *ntp = tn->tn_type, *otp = tn->tn_left->tn_type; |
1251 | tspec_t nt = ntp->t_tspec, ot = otp->t_tspec; | | 1251 | tspec_t nt = ntp->t_tspec, ot = otp->t_tspec; |
1252 | | | 1252 | |
1253 | if (nt == BOOL || ot == BOOL) | | 1253 | if (nt == BOOL || ot == BOOL) |
1254 | return nt == BOOL && ot == BOOL; | | 1254 | return nt == BOOL && ot == BOOL; |
1255 | | | 1255 | |
1256 | if (is_integer(nt) && is_integer(ot)) { | | 1256 | if (is_integer(nt) && is_integer(ot)) { |
1257 | unsigned int nw = width_in_bits(ntp), ow = width_in_bits(otp); | | 1257 | unsigned int nw = width_in_bits(ntp), ow = width_in_bits(otp); |
1258 | if (is_uinteger(nt) == is_uinteger(ot)) | | 1258 | if (is_uinteger(nt) == is_uinteger(ot)) |
1259 | return nw >= ow; | | 1259 | return nw >= ow; |
1260 | return is_uinteger(ot) && nw > ow; | | 1260 | return is_uinteger(ot) && nw > ow; |
1261 | } | | 1261 | } |
1262 | | | 1262 | |
1263 | if (is_complex(nt) || is_complex(ot)) | | 1263 | if (is_complex(nt) || is_complex(ot)) |
1264 | return is_complex(nt) && is_complex(ot) && | | 1264 | return is_complex(nt) && is_complex(ot) && |
1265 | size_in_bits(nt) >= size_in_bits(ot); | | 1265 | size_in_bits(nt) >= size_in_bits(ot); |
1266 | | | 1266 | |
1267 | if (is_floating(nt) && is_floating(ot)) | | 1267 | if (is_floating(nt) && is_floating(ot)) |
1268 | return size_in_bits(nt) >= size_in_bits(ot); | | 1268 | return size_in_bits(nt) >= size_in_bits(ot); |
1269 | | | 1269 | |
1270 | if (nt == PTR && ot == PTR) { | | 1270 | if (nt == PTR && ot == PTR) { |
1271 | if (!ntp->t_subt->t_const && otp->t_subt->t_const) | | 1271 | if (!ntp->t_subt->t_const && otp->t_subt->t_const) |
1272 | return false; | | 1272 | return false; |
1273 | if (!ntp->t_subt->t_volatile && otp->t_subt->t_volatile) | | 1273 | if (!ntp->t_subt->t_volatile && otp->t_subt->t_volatile) |
1274 | return false; | | 1274 | return false; |
1275 | | | 1275 | |
1276 | if (ntp->t_subt->t_tspec == VOID || | | 1276 | if (ntp->t_subt->t_tspec == VOID || |
1277 | otp->t_subt->t_tspec == VOID || | | 1277 | otp->t_subt->t_tspec == VOID || |
1278 | types_compatible(ntp->t_subt, otp->t_subt, | | 1278 | types_compatible(ntp->t_subt, otp->t_subt, |
1279 | false, false, NULL)) | | 1279 | false, false, NULL)) |
1280 | return true; | | 1280 | return true; |
1281 | } | | 1281 | } |
1282 | | | 1282 | |
1283 | return false; | | 1283 | return false; |
1284 | } | | 1284 | } |
1285 | | | 1285 | |
1286 | /* | | 1286 | /* |
1287 | * Create a node for an assignment operator (both = and op= ). | | 1287 | * Create a node for an assignment operator (both = and op= ). |
1288 | */ | | 1288 | */ |
1289 | static tnode_t * | | 1289 | static tnode_t * |
1290 | build_assignment(op_t op, bool sys, tnode_t *ln, tnode_t *rn) | | 1290 | build_assignment(op_t op, bool sys, tnode_t *ln, tnode_t *rn) |
1291 | { | | 1291 | { |
1292 | tspec_t lt, rt; | | 1292 | tspec_t lt, rt; |
1293 | tnode_t *ntn, *ctn; | | 1293 | tnode_t *ntn, *ctn; |
1294 | | | 1294 | |
1295 | lint_assert(ln != NULL); | | 1295 | lint_assert(ln != NULL); |
1296 | lint_assert(rn != NULL); | | 1296 | lint_assert(rn != NULL); |
1297 | | | 1297 | |
1298 | lt = ln->tn_type->t_tspec; | | 1298 | lt = ln->tn_type->t_tspec; |
1299 | rt = rn->tn_type->t_tspec; | | 1299 | rt = rn->tn_type->t_tspec; |
1300 | | | 1300 | |
1301 | if ((op == ADDASS || op == SUBASS) && lt == PTR) { | | 1301 | if ((op == ADDASS || op == SUBASS) && lt == PTR) { |
1302 | lint_assert(is_integer(rt)); | | 1302 | lint_assert(is_integer(rt)); |
1303 | ctn = subt_size_in_bytes(ln->tn_type); | | 1303 | ctn = subt_size_in_bytes(ln->tn_type); |
1304 | if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) | | 1304 | if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) |
1305 | rn = convert(NOOP, 0, ctn->tn_type, rn); | | 1305 | rn = convert(NOOP, 0, ctn->tn_type, rn); |
1306 | rn = new_tnode(MULT, sys, rn->tn_type, rn, ctn); | | 1306 | rn = new_tnode(MULT, sys, rn->tn_type, rn, ctn); |
1307 | if (rn->tn_left->tn_op == CON) | | 1307 | if (rn->tn_left->tn_op == CON) |
1308 | rn = fold(rn); | | 1308 | rn = fold(rn); |
1309 | } | | 1309 | } |
1310 | | | 1310 | |
1311 | if ((op == ASSIGN || op == RETURN || op == INIT) && | | 1311 | if ((op == ASSIGN || op == RETURN || op == INIT) && |
1312 | (lt == STRUCT || rt == STRUCT)) { | | 1312 | (lt == STRUCT || rt == STRUCT)) { |
1313 | lint_assert(lt == rt); | | 1313 | lint_assert(lt == rt); |
1314 | lint_assert(ln->tn_type->t_str == rn->tn_type->t_str); | | 1314 | lint_assert(ln->tn_type->t_str == rn->tn_type->t_str); |
1315 | if (is_incomplete(ln->tn_type)) { | | 1315 | if (is_incomplete(ln->tn_type)) { |
1316 | if (op == RETURN) { | | 1316 | if (op == RETURN) { |
1317 | /* cannot return incomplete type */ | | 1317 | /* cannot return incomplete type */ |
1318 | error(212); | | 1318 | error(212); |
1319 | } else { | | 1319 | } else { |
1320 | /* unknown operand size, op '%s' */ | | 1320 | /* unknown operand size, op '%s' */ |
1321 | error(138, op_name(op)); | | 1321 | error(138, op_name(op)); |
1322 | } | | 1322 | } |
1323 | return NULL; | | 1323 | return NULL; |
1324 | } | | 1324 | } |
1325 | } | | 1325 | } |
1326 | | | 1326 | |
1327 | if (op == SHLASS) { | | 1327 | if (op == SHLASS) { |
1328 | if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { | | 1328 | if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { |
1329 | if (hflag) | | 1329 | if (hflag) |
1330 | /* semantics of '%s' change in ANSI C; ... */ | | 1330 | /* semantics of '%s' change in ANSI C; ... */ |
1331 | warning(118, "<<="); | | 1331 | warning(118, "<<="); |
1332 | } | | 1332 | } |
1333 | } else if (op != SHRASS) { | | 1333 | } else if (op != SHRASS) { |
1334 | if (op == ASSIGN || lt != PTR) { | | 1334 | if (op == ASSIGN || lt != PTR) { |
1335 | if (lt != rt || | | 1335 | if (lt != rt || |
1336 | (ln->tn_type->t_bitfield && rn->tn_op == CON)) { | | 1336 | (ln->tn_type->t_bitfield && rn->tn_op == CON)) { |
1337 | rn = convert(op, 0, ln->tn_type, rn); | | 1337 | rn = convert(op, 0, ln->tn_type, rn); |
1338 | rt = lt; | | 1338 | rt = lt; |
1339 | } | | 1339 | } |
1340 | } | | 1340 | } |
1341 | } | | 1341 | } |
1342 | | | 1342 | |
1343 | if (any_query_enabled && rn->tn_op == CVT && rn->tn_cast && | | 1343 | if (any_query_enabled && rn->tn_op == CVT && rn->tn_cast && |
1344 | types_compatible(ln->tn_type, rn->tn_type, false, false, NULL) && | | 1344 | types_compatible(ln->tn_type, rn->tn_type, false, false, NULL) && |
1345 | is_cast_redundant(rn)) { | | 1345 | is_cast_redundant(rn)) { |
1346 | /* redundant cast from '%s' to '%s' before assignment */ | | 1346 | /* redundant cast from '%s' to '%s' before assignment */ |
1347 | query_message(7, | | 1347 | query_message(7, |
1348 | type_name(rn->tn_left->tn_type), type_name(rn->tn_type)); | | 1348 | type_name(rn->tn_left->tn_type), type_name(rn->tn_type)); |
1349 | } | | 1349 | } |
1350 | | | 1350 | |
1351 | ntn = new_tnode(op, sys, ln->tn_type, ln, rn); | | 1351 | ntn = new_tnode(op, sys, ln->tn_type, ln, rn); |
1352 | | | 1352 | |
1353 | return ntn; | | 1353 | return ntn; |
1354 | } | | 1354 | } |
1355 | | | 1355 | |
1356 | /* | | 1356 | /* |
1357 | * Create a node for REAL, IMAG | | 1357 | * Create a node for REAL, IMAG |
1358 | */ | | 1358 | */ |
1359 | static tnode_t * | | 1359 | static tnode_t * |
1360 | build_real_imag(op_t op, bool sys, tnode_t *ln) | | 1360 | build_real_imag(op_t op, bool sys, tnode_t *ln) |
1361 | { | | 1361 | { |
1362 | tnode_t *cn, *ntn; | | 1362 | tnode_t *cn, *ntn; |
1363 | | | 1363 | |
1364 | lint_assert(ln != NULL); | | 1364 | lint_assert(ln != NULL); |
1365 | | | 1365 | |
1366 | if (ln->tn_op == NAME) { | | 1366 | if (ln->tn_op == NAME) { |
1367 | /* | | 1367 | /* |
1368 | * This may be too much, but it avoids wrong warnings. | | 1368 | * This may be too much, but it avoids wrong warnings. |
1369 | * See d_c99_complex_split.c. | | 1369 | * See d_c99_complex_split.c. |
1370 | */ | | 1370 | */ |
1371 | mark_as_used(ln->tn_sym, false, false); | | 1371 | mark_as_used(ln->tn_sym, false, false); |
1372 | mark_as_set(ln->tn_sym); | | 1372 | mark_as_set(ln->tn_sym); |
1373 | } | | 1373 | } |
1374 | | | 1374 | |
1375 | switch (ln->tn_type->t_tspec) { | | 1375 | switch (ln->tn_type->t_tspec) { |
1376 | case LCOMPLEX: | | 1376 | case LCOMPLEX: |
1377 | /* XXX: integer and LDOUBLE don't match. */ | | 1377 | /* XXX: integer and LDOUBLE don't match. */ |
1378 | cn = build_integer_constant(LDOUBLE, (int64_t)1); | | 1378 | cn = build_integer_constant(LDOUBLE, (int64_t)1); |
1379 | break; | | 1379 | break; |
1380 | case DCOMPLEX: | | 1380 | case DCOMPLEX: |
1381 | /* XXX: integer and DOUBLE don't match. */ | | 1381 | /* XXX: integer and DOUBLE don't match. */ |
1382 | cn = build_integer_constant(DOUBLE, (int64_t)1); | | 1382 | cn = build_integer_constant(DOUBLE, (int64_t)1); |
1383 | break; | | 1383 | break; |
1384 | case FCOMPLEX: | | 1384 | case FCOMPLEX: |
1385 | /* XXX: integer and FLOAT don't match. */ | | 1385 | /* XXX: integer and FLOAT don't match. */ |
1386 | cn = build_integer_constant(FLOAT, (int64_t)1); | | 1386 | cn = build_integer_constant(FLOAT, (int64_t)1); |
1387 | break; | | 1387 | break; |
1388 | default: | | 1388 | default: |
1389 | /* '__%s__' is illegal for type '%s' */ | | 1389 | /* '__%s__' is illegal for type '%s' */ |
1390 | error(276, op == REAL ? "real" : "imag", | | 1390 | error(276, op == REAL ? "real" : "imag", |
1391 | type_name(ln->tn_type)); | | 1391 | type_name(ln->tn_type)); |
1392 | return NULL; | | 1392 | return NULL; |
1393 | } | | 1393 | } |
1394 | ntn = new_tnode(op, sys, cn->tn_type, ln, cn); | | 1394 | ntn = new_tnode(op, sys, cn->tn_type, ln, cn); |
1395 | ntn->tn_lvalue = true; | | 1395 | ntn->tn_lvalue = true; |
1396 | | | 1396 | |
1397 | return ntn; | | 1397 | return ntn; |
1398 | } | | 1398 | } |
1399 | | | 1399 | |
1400 | static bool | | 1400 | static bool |
1401 | is_confusing_precedence(op_t op, op_t lop, bool lparen, op_t rop, bool rparen) | | 1401 | is_confusing_precedence(op_t op, op_t lop, bool lparen, op_t rop, bool rparen) |
1402 | { | | 1402 | { |
1403 | | | 1403 | |
1404 | if (op == SHL || op == SHR) { | | 1404 | if (op == SHL || op == SHR) { |
1405 | if (!lparen && (lop == PLUS || lop == MINUS)) | | 1405 | if (!lparen && (lop == PLUS || lop == MINUS)) |
1406 | return true; | | 1406 | return true; |
1407 | if (!rparen && (rop == PLUS || rop == MINUS)) | | 1407 | if (!rparen && (rop == PLUS || rop == MINUS)) |
1408 | return true; | | 1408 | return true; |
1409 | return false; | | 1409 | return false; |
1410 | } | | 1410 | } |
1411 | | | 1411 | |
1412 | if (op == LOGOR) { | | 1412 | if (op == LOGOR) { |
1413 | if (!lparen && lop == LOGAND) | | 1413 | if (!lparen && lop == LOGAND) |
1414 | return true; | | 1414 | return true; |
1415 | if (!rparen && rop == LOGAND) | | 1415 | if (!rparen && rop == LOGAND) |
1416 | return true; | | 1416 | return true; |
1417 | return false; | | 1417 | return false; |
1418 | } | | 1418 | } |
1419 | | | 1419 | |
1420 | lint_assert(op == BITAND || op == BITXOR || op == BITOR); | | 1420 | lint_assert(op == BITAND || op == BITXOR || op == BITOR); |
1421 | if (!lparen && lop != op) { | | 1421 | if (!lparen && lop != op) { |
1422 | if (lop == PLUS || lop == MINUS) | | 1422 | if (lop == PLUS || lop == MINUS) |
1423 | return true; | | 1423 | return true; |
1424 | if (lop == BITAND || lop == BITXOR) | | 1424 | if (lop == BITAND || lop == BITXOR) |
1425 | return true; | | 1425 | return true; |
1426 | } | | 1426 | } |
1427 | if (!rparen && rop != op) { | | 1427 | if (!rparen && rop != op) { |
1428 | if (rop == PLUS || rop == MINUS) | | 1428 | if (rop == PLUS || rop == MINUS) |
1429 | return true; | | 1429 | return true; |
1430 | if (rop == BITAND || rop == BITXOR) | | 1430 | if (rop == BITAND || rop == BITXOR) |
1431 | return true; | | 1431 | return true; |
1432 | } | | 1432 | } |
1433 | return false; | | 1433 | return false; |
1434 | } | | 1434 | } |
1435 | | | 1435 | |
1436 | /* | | 1436 | /* |
1437 | * Print a warning if the given node has operands which should be | | 1437 | * Print a warning if the given node has operands which should be |
1438 | * parenthesized. | | 1438 | * parenthesized. |
1439 | * | | 1439 | * |
1440 | * XXX Does not work if an operand is a constant expression. Constant | | 1440 | * XXX Does not work if an operand is a constant expression. Constant |
1441 | * expressions are already folded. | | 1441 | * expressions are already folded. |
1442 | */ | | 1442 | */ |
1443 | static void | | 1443 | static void |
1444 | check_precedence_confusion(tnode_t *tn) | | 1444 | check_precedence_confusion(tnode_t *tn) |
1445 | { | | 1445 | { |
1446 | tnode_t *ln, *rn; | | 1446 | tnode_t *ln, *rn; |
1447 | | | 1447 | |
1448 | if (!hflag) | | 1448 | if (!hflag) |
1449 | return; | | 1449 | return; |
1450 | | | 1450 | |
1451 | debug_node(tn); | | 1451 | debug_node(tn); |
1452 | | | 1452 | |
1453 | lint_assert(is_binary(tn)); | | 1453 | lint_assert(is_binary(tn)); |
1454 | for (ln = tn->tn_left; ln->tn_op == CVT; ln = ln->tn_left) | | 1454 | for (ln = tn->tn_left; ln->tn_op == CVT; ln = ln->tn_left) |
1455 | continue; | | 1455 | continue; |
1456 | for (rn = tn->tn_right; rn->tn_op == CVT; rn = rn->tn_left) | | 1456 | for (rn = tn->tn_right; rn->tn_op == CVT; rn = rn->tn_left) |
1457 | continue; | | 1457 | continue; |
1458 | | | 1458 | |
1459 | if (is_confusing_precedence(tn->tn_op, | | 1459 | if (is_confusing_precedence(tn->tn_op, |
1460 | ln->tn_op, ln->tn_parenthesized, | | 1460 | ln->tn_op, ln->tn_parenthesized, |
1461 | rn->tn_op, rn->tn_parenthesized)) { | | 1461 | rn->tn_op, rn->tn_parenthesized)) { |
1462 | /* precedence confusion possible: parenthesize! */ | | 1462 | /* precedence confusion possible: parenthesize! */ |
1463 | warning(169); | | 1463 | warning(169); |
1464 | } | | 1464 | } |
1465 | } | | 1465 | } |
1466 | | | 1466 | |
1467 | /* | | 1467 | /* |
1468 | * Fold constant nodes, as much as is needed for comparing the value with 0. | | 1468 | * Fold constant nodes, as much as is needed for comparing the value with 0. |
1469 | */ | | 1469 | */ |
1470 | static tnode_t * | | 1470 | static tnode_t * |
1471 | fold_bool(tnode_t *tn) | | 1471 | fold_bool(tnode_t *tn) |
1472 | { | | 1472 | { |
1473 | bool l, r; | | 1473 | bool l, r; |
1474 | val_t *v; | | 1474 | val_t *v; |
1475 | | | 1475 | |
1476 | v = xcalloc(1, sizeof(*v)); | | 1476 | v = xcalloc(1, sizeof(*v)); |
1477 | v->v_tspec = tn->tn_type->t_tspec; | | 1477 | v->v_tspec = tn->tn_type->t_tspec; |
1478 | lint_assert(v->v_tspec == INT || (Tflag && v->v_tspec == BOOL)); | | 1478 | lint_assert(v->v_tspec == INT || (Tflag && v->v_tspec == BOOL)); |
1479 | | | 1479 | |
1480 | l = constant_is_nonzero(tn->tn_left); | | 1480 | l = constant_is_nonzero(tn->tn_left); |
1481 | r = is_binary(tn) && constant_is_nonzero(tn->tn_right); | | 1481 | r = is_binary(tn) && constant_is_nonzero(tn->tn_right); |
1482 | | | 1482 | |
1483 | switch (tn->tn_op) { | | 1483 | switch (tn->tn_op) { |
1484 | case NOT: | | 1484 | case NOT: |
1485 | if (hflag && !constcond_flag) | | 1485 | if (hflag && !constcond_flag) |
1486 | /* constant argument to '!' */ | | 1486 | /* constant argument to '!' */ |
1487 | warning(239); | | 1487 | warning(239); |
1488 | v->v_quad = !l ? 1 : 0; | | 1488 | v->v_quad = !l ? 1 : 0; |
1489 | break; | | 1489 | break; |
1490 | case LOGAND: | | 1490 | case LOGAND: |
1491 | v->v_quad = l && r ? 1 : 0; | | 1491 | v->v_quad = l && r ? 1 : 0; |
1492 | break; | | 1492 | break; |
1493 | case LOGOR: | | 1493 | case LOGOR: |
1494 | v->v_quad = l || r ? 1 : 0; | | 1494 | v->v_quad = l || r ? 1 : 0; |
1495 | break; | | 1495 | break; |
1496 | default: | | 1496 | default: |
1497 | lint_assert(/*CONSTCOND*/false); | | 1497 | lint_assert(/*CONSTCOND*/false); |
1498 | } | | 1498 | } |
1499 | | | 1499 | |
1500 | return build_constant(tn->tn_type, v); | | 1500 | return build_constant(tn->tn_type, v); |
1501 | } | | 1501 | } |
1502 | | | 1502 | |
1503 | static ldbl_t | | 1503 | static ldbl_t |
1504 | floating_error_value(tspec_t t, ldbl_t lv) | | 1504 | floating_error_value(tspec_t t, ldbl_t lv) |
1505 | { | | 1505 | { |
1506 | if (t == FLOAT) { | | 1506 | if (t == FLOAT) |
1507 | return lv < 0 ? -FLT_MAX : FLT_MAX; | | 1507 | return lv < 0 ? -FLT_MAX : FLT_MAX; |
1508 | } else if (t == DOUBLE) { | | 1508 | if (t == DOUBLE) |
1509 | return lv < 0 ? -DBL_MAX : DBL_MAX; | | 1509 | return lv < 0 ? -DBL_MAX : DBL_MAX; |
1510 | } else { | | 1510 | |
1511 | /* LINTED 248: floating-point constant out of range */ | | 1511 | /* FIXME: Remove the '(double)' cast near 'isfinite'. */ |
1512 | ldbl_t max = LDBL_MAX; | | 1512 | /* FIXME: Inlining the variable 'max' produces a wrong warning. */ |
1513 | return lv < 0 ? -max : max; | | 1513 | /* LINTED 248: floating-point constant out of range */ |
1514 | } | | 1514 | ldbl_t max = LDBL_MAX; |
| | | 1515 | return lv < 0 ? -max : max; |
1515 | } | | 1516 | } |
1516 | | | 1517 | |
1517 | /* | | 1518 | /* |
1518 | * Fold constant nodes having operands with floating point type. | | 1519 | * Fold constant nodes having operands with floating point type. |
1519 | */ | | 1520 | */ |
1520 | static tnode_t * | | 1521 | static tnode_t * |
1521 | fold_float(tnode_t *tn) | | 1522 | fold_float(tnode_t *tn) |
1522 | { | | 1523 | { |
1523 | val_t *v; | | 1524 | val_t *v; |
1524 | tspec_t t; | | 1525 | tspec_t t; |
1525 | ldbl_t lv, rv = 0; | | 1526 | ldbl_t lv, rv = 0; |
1526 | | | 1527 | |
1527 | fpe = 0; | | 1528 | fpe = 0; |
1528 | v = xcalloc(1, sizeof(*v)); | | 1529 | v = xcalloc(1, sizeof(*v)); |
1529 | v->v_tspec = t = tn->tn_type->t_tspec; | | 1530 | v->v_tspec = t = tn->tn_type->t_tspec; |
1530 | | | 1531 | |
1531 | lint_assert(is_floating(t)); | | 1532 | lint_assert(is_floating(t)); |
1532 | lint_assert(t == tn->tn_left->tn_type->t_tspec); | | 1533 | lint_assert(t == tn->tn_left->tn_type->t_tspec); |
1533 | lint_assert(!is_binary(tn) || t == tn->tn_right->tn_type->t_tspec); | | 1534 | lint_assert(!is_binary(tn) || t == tn->tn_right->tn_type->t_tspec); |
1534 | | | 1535 | |
1535 | lv = tn->tn_left->tn_val->v_ldbl; | | 1536 | lv = tn->tn_left->tn_val->v_ldbl; |
1536 | if (is_binary(tn)) | | 1537 | if (is_binary(tn)) |
1537 | rv = tn->tn_right->tn_val->v_ldbl; | | 1538 | rv = tn->tn_right->tn_val->v_ldbl; |
1538 | | | 1539 | |
1539 | switch (tn->tn_op) { | | 1540 | switch (tn->tn_op) { |
1540 | case UPLUS: | | 1541 | case UPLUS: |
1541 | v->v_ldbl = lv; | | 1542 | v->v_ldbl = lv; |
1542 | break; | | 1543 | break; |
1543 | case UMINUS: | | 1544 | case UMINUS: |
1544 | v->v_ldbl = -lv; | | 1545 | v->v_ldbl = -lv; |
1545 | break; | | 1546 | break; |
1546 | case MULT: | | 1547 | case MULT: |
1547 | v->v_ldbl = lv * rv; | | 1548 | v->v_ldbl = lv * rv; |
1548 | break; | | 1549 | break; |
1549 | case DIV: | | 1550 | case DIV: |
1550 | if (rv == 0.0) { | | 1551 | if (rv == 0.0) { |
1551 | /* division by 0 */ | | 1552 | /* division by 0 */ |
1552 | error(139); | | 1553 | error(139); |
1553 | v->v_ldbl = floating_error_value(t, lv); | | 1554 | v->v_ldbl = floating_error_value(t, lv); |
1554 | } else { | | 1555 | } else { |
1555 | v->v_ldbl = lv / rv; | | 1556 | v->v_ldbl = lv / rv; |
1556 | } | | 1557 | } |
1557 | break; | | 1558 | break; |
1558 | case PLUS: | | 1559 | case PLUS: |
1559 | v->v_ldbl = lv + rv; | | 1560 | v->v_ldbl = lv + rv; |
1560 | break; | | 1561 | break; |
1561 | case MINUS: | | 1562 | case MINUS: |
1562 | v->v_ldbl = lv - rv; | | 1563 | v->v_ldbl = lv - rv; |
1563 | break; | | 1564 | break; |
1564 | case LT: | | 1565 | case LT: |
1565 | v->v_quad = lv < rv ? 1 : 0; | | 1566 | v->v_quad = lv < rv ? 1 : 0; |
1566 | break; | | 1567 | break; |
1567 | case LE: | | 1568 | case LE: |
1568 | v->v_quad = lv <= rv ? 1 : 0; | | 1569 | v->v_quad = lv <= rv ? 1 : 0; |
1569 | break; | | 1570 | break; |
1570 | case GE: | | 1571 | case GE: |
1571 | v->v_quad = lv >= rv ? 1 : 0; | | 1572 | v->v_quad = lv >= rv ? 1 : 0; |
1572 | break; | | 1573 | break; |
1573 | case GT: | | 1574 | case GT: |
1574 | v->v_quad = lv > rv ? 1 : 0; | | 1575 | v->v_quad = lv > rv ? 1 : 0; |
1575 | break; | | 1576 | break; |
1576 | case EQ: | | 1577 | case EQ: |
1577 | v->v_quad = lv == rv ? 1 : 0; | | 1578 | v->v_quad = lv == rv ? 1 : 0; |
1578 | break; | | 1579 | break; |
1579 | case NE: | | 1580 | case NE: |
1580 | v->v_quad = lv != rv ? 1 : 0; | | 1581 | v->v_quad = lv != rv ? 1 : 0; |
1581 | break; | | 1582 | break; |
1582 | default: | | 1583 | default: |
1583 | lint_assert(/*CONSTCOND*/false); | | 1584 | lint_assert(/*CONSTCOND*/false); |
1584 | } | | 1585 | } |
1585 | | | 1586 | |
1586 | lint_assert(fpe != 0 || isnan((double)v->v_ldbl) == 0); | | 1587 | lint_assert(fpe != 0 || isnan((double)v->v_ldbl) == 0); |
1587 | if (is_complex(v->v_tspec)) { | | 1588 | if (is_complex(v->v_tspec)) { |
1588 | /* | | 1589 | /* |
1589 | * Don't warn, as lint doesn't model the imaginary part of | | 1590 | * Don't warn, as lint doesn't model the imaginary part of |
1590 | * complex numbers. | | 1591 | * complex numbers. |
1591 | */ | | 1592 | */ |
1592 | fpe = 0; | | 1593 | fpe = 0; |
1593 | } else if (fpe != 0 || isfinite((double)v->v_ldbl) == 0 || | | 1594 | } else if (fpe != 0 || isfinite((double)v->v_ldbl) == 0 || |
1594 | (t == FLOAT && | | 1595 | (t == FLOAT && |
1595 | (v->v_ldbl > FLT_MAX || v->v_ldbl < -FLT_MAX)) || | | 1596 | (v->v_ldbl > FLT_MAX || v->v_ldbl < -FLT_MAX)) || |
1596 | (t == DOUBLE && | | 1597 | (t == DOUBLE && |
1597 | (v->v_ldbl > DBL_MAX || v->v_ldbl < -DBL_MAX))) { | | 1598 | (v->v_ldbl > DBL_MAX || v->v_ldbl < -DBL_MAX))) { |
1598 | /* floating point overflow on operator '%s' */ | | 1599 | /* floating point overflow on operator '%s' */ |
1599 | warning(142, op_name(tn->tn_op)); | | 1600 | warning(142, op_name(tn->tn_op)); |
1600 | v->v_ldbl = floating_error_value(t, v->v_ldbl); | | 1601 | v->v_ldbl = floating_error_value(t, v->v_ldbl); |
1601 | fpe = 0; | | 1602 | fpe = 0; |
1602 | } | | 1603 | } |
1603 | | | 1604 | |
1604 | return build_constant(tn->tn_type, v); | | 1605 | return build_constant(tn->tn_type, v); |
1605 | } | | 1606 | } |
1606 | | | 1607 | |
1607 | /* | | 1608 | /* |
1608 | * Create a tree node for a binary operator and its two operands. Also called | | 1609 | * Create a tree node for a binary operator and its two operands. Also called |
1609 | * for unary operators; in that case rn is NULL. | | 1610 | * for unary operators; in that case rn is NULL. |
1610 | * | | 1611 | * |
1611 | * Function calls, sizeof and casts are handled elsewhere. | | 1612 | * Function calls, sizeof and casts are handled elsewhere. |
1612 | */ | | 1613 | */ |
1613 | tnode_t * | | 1614 | tnode_t * |
1614 | build_binary(tnode_t *ln, op_t op, bool sys, tnode_t *rn) | | 1615 | build_binary(tnode_t *ln, op_t op, bool sys, tnode_t *rn) |
1615 | { | | 1616 | { |
1616 | const mod_t *mp; | | 1617 | const mod_t *mp; |
1617 | tnode_t *ntn; | | 1618 | tnode_t *ntn; |
1618 | type_t *rettp; | | 1619 | type_t *rettp; |
1619 | | | 1620 | |
1620 | mp = &modtab[op]; | | 1621 | mp = &modtab[op]; |
1621 | | | 1622 | |
1622 | /* If there was an error in one of the operands, return. */ | | 1623 | /* If there was an error in one of the operands, return. */ |
1623 | if (ln == NULL || (mp->m_binary && rn == NULL)) | | 1624 | if (ln == NULL || (mp->m_binary && rn == NULL)) |
1624 | return NULL; | | 1625 | return NULL; |
1625 | | | 1626 | |
1626 | /* | | 1627 | /* |
1627 | * Apply class conversions to the left operand, but only if its | | 1628 | * Apply class conversions to the left operand, but only if its |
1628 | * value is needed or it is compared with zero. | | 1629 | * value is needed or it is compared with zero. |
1629 | */ | | 1630 | */ |
1630 | if (mp->m_value_context || mp->m_compares_with_zero) | | 1631 | if (mp->m_value_context || mp->m_compares_with_zero) |
1631 | ln = cconv(ln); | | 1632 | ln = cconv(ln); |
1632 | /* | | 1633 | /* |
1633 | * The right operand is almost always in a test or value context, | | 1634 | * The right operand is almost always in a test or value context, |
1634 | * except if it is a struct or union member. | | 1635 | * except if it is a struct or union member. |
1635 | */ | | 1636 | */ |
1636 | if (mp->m_binary && op != ARROW && op != POINT) | | 1637 | if (mp->m_binary && op != ARROW && op != POINT) |
1637 | rn = cconv(rn); | | 1638 | rn = cconv(rn); |
1638 | | | 1639 | |
1639 | /* | | 1640 | /* |
1640 | * Print some warnings for comparisons of unsigned values with | | 1641 | * Print some warnings for comparisons of unsigned values with |
1641 | * constants lower than or equal to null. This must be done | | 1642 | * constants lower than or equal to null. This must be done |
1642 | * before promote() because otherwise unsigned char and unsigned | | 1643 | * before promote() because otherwise unsigned char and unsigned |
1643 | * short would be promoted to int. Types are also tested to be | | 1644 | * short would be promoted to int. Types are also tested to be |
1644 | * CHAR, which would also become int. | | 1645 | * CHAR, which would also become int. |
1645 | */ | | 1646 | */ |
1646 | if (mp->m_comparison) | | 1647 | if (mp->m_comparison) |
1647 | check_integer_comparison(op, ln, rn); | | 1648 | check_integer_comparison(op, ln, rn); |
1648 | | | 1649 | |
1649 | if (mp->m_value_context || mp->m_compares_with_zero) | | 1650 | if (mp->m_value_context || mp->m_compares_with_zero) |
1650 | ln = promote(op, false, ln); | | 1651 | ln = promote(op, false, ln); |
1651 | if (mp->m_binary && op != ARROW && op != POINT && | | 1652 | if (mp->m_binary && op != ARROW && op != POINT && |
1652 | op != ASSIGN && op != RETURN && op != INIT) { | | 1653 | op != ASSIGN && op != RETURN && op != INIT) { |
1653 | rn = promote(op, false, rn); | | 1654 | rn = promote(op, false, rn); |
1654 | } | | 1655 | } |
1655 | | | 1656 | |
1656 | /* | | 1657 | /* |
1657 | * If the result of the operation is different for signed or | | 1658 | * If the result of the operation is different for signed or |
1658 | * unsigned operands and one of the operands is signed only in | | 1659 | * unsigned operands and one of the operands is signed only in |
1659 | * ANSI C, print a warning. | | 1660 | * ANSI C, print a warning. |
1660 | */ | | 1661 | */ |
1661 | if (mp->m_warn_if_left_unsigned_in_c90 && | | 1662 | if (mp->m_warn_if_left_unsigned_in_c90 && |
1662 | ln->tn_op == CON && ln->tn_val->v_unsigned_since_c90) { | | 1663 | ln->tn_op == CON && ln->tn_val->v_unsigned_since_c90) { |
1663 | /* ANSI C treats constant as unsigned, op '%s' */ | | 1664 | /* ANSI C treats constant as unsigned, op '%s' */ |
1664 | warning(218, mp->m_name); | | 1665 | warning(218, mp->m_name); |
1665 | ln->tn_val->v_unsigned_since_c90 = false; | | 1666 | ln->tn_val->v_unsigned_since_c90 = false; |
1666 | } | | 1667 | } |
1667 | if (mp->m_warn_if_right_unsigned_in_c90 && | | 1668 | if (mp->m_warn_if_right_unsigned_in_c90 && |
1668 | rn->tn_op == CON && rn->tn_val->v_unsigned_since_c90) { | | 1669 | rn->tn_op == CON && rn->tn_val->v_unsigned_since_c90) { |
1669 | /* ANSI C treats constant as unsigned, op '%s' */ | | 1670 | /* ANSI C treats constant as unsigned, op '%s' */ |
1670 | warning(218, mp->m_name); | | 1671 | warning(218, mp->m_name); |
1671 | rn->tn_val->v_unsigned_since_c90 = false; | | 1672 | rn->tn_val->v_unsigned_since_c90 = false; |
1672 | } | | 1673 | } |
1673 | | | 1674 | |
1674 | /* Make sure both operands are of the same type */ | | 1675 | /* Make sure both operands are of the same type */ |
1675 | if (mp->m_balance_operands || (!allow_c90 && (op == SHL || op == SHR))) | | 1676 | if (mp->m_balance_operands || (!allow_c90 && (op == SHL || op == SHR))) |
1676 | balance(op, &ln, &rn); | | 1677 | balance(op, &ln, &rn); |
1677 | | | 1678 | |
1678 | /* | | 1679 | /* |
1679 | * Check types for compatibility with the operation and mutual | | 1680 | * Check types for compatibility with the operation and mutual |
1680 | * compatibility. Return if there are serious problems. | | 1681 | * compatibility. Return if there are serious problems. |
1681 | */ | | 1682 | */ |
1682 | if (!typeok(op, 0, ln, rn)) | | 1683 | if (!typeok(op, 0, ln, rn)) |
1683 | return NULL; | | 1684 | return NULL; |
1684 | | | 1685 | |
1685 | /* And now create the node. */ | | 1686 | /* And now create the node. */ |
1686 | switch (op) { | | 1687 | switch (op) { |
1687 | case POINT: | | 1688 | case POINT: |
1688 | case ARROW: | | 1689 | case ARROW: |
1689 | ntn = build_struct_access(op, sys, ln, rn); | | 1690 | ntn = build_struct_access(op, sys, ln, rn); |
1690 | break; | | 1691 | break; |
1691 | case INCAFT: | | 1692 | case INCAFT: |
1692 | case DECAFT: | | 1693 | case DECAFT: |
1693 | case INCBEF: | | 1694 | case INCBEF: |
1694 | case DECBEF: | | 1695 | case DECBEF: |
1695 | ntn = build_prepost_incdec(op, sys, ln); | | 1696 | ntn = build_prepost_incdec(op, sys, ln); |
1696 | break; | | 1697 | break; |
1697 | case ADDR: | | 1698 | case ADDR: |
1698 | ntn = build_address(sys, ln, false); | | 1699 | ntn = build_address(sys, ln, false); |
1699 | break; | | 1700 | break; |
1700 | case INDIR: | | 1701 | case INDIR: |
1701 | ntn = new_tnode(INDIR, sys, ln->tn_type->t_subt, ln, NULL); | | 1702 | ntn = new_tnode(INDIR, sys, ln->tn_type->t_subt, ln, NULL); |
1702 | break; | | 1703 | break; |
1703 | case PLUS: | | 1704 | case PLUS: |
1704 | case MINUS: | | 1705 | case MINUS: |
1705 | ntn = build_plus_minus(op, sys, ln, rn); | | 1706 | ntn = build_plus_minus(op, sys, ln, rn); |
1706 | break; | | 1707 | break; |
1707 | case SHL: | | 1708 | case SHL: |
1708 | case SHR: | | 1709 | case SHR: |
1709 | ntn = build_bit_shift(op, sys, ln, rn); | | 1710 | ntn = build_bit_shift(op, sys, ln, rn); |
1710 | break; | | 1711 | break; |
1711 | case COLON: | | 1712 | case COLON: |
1712 | ntn = build_colon(sys, ln, rn); | | 1713 | ntn = build_colon(sys, ln, rn); |
1713 | break; | | 1714 | break; |
1714 | case ASSIGN: | | 1715 | case ASSIGN: |
1715 | case MULASS: | | 1716 | case MULASS: |
1716 | case DIVASS: | | 1717 | case DIVASS: |
1717 | case MODASS: | | 1718 | case MODASS: |
1718 | case ADDASS: | | 1719 | case ADDASS: |
1719 | case SUBASS: | | 1720 | case SUBASS: |
1720 | case SHLASS: | | 1721 | case SHLASS: |
1721 | case SHRASS: | | 1722 | case SHRASS: |
1722 | case ANDASS: | | 1723 | case ANDASS: |
1723 | case XORASS: | | 1724 | case XORASS: |
1724 | case ORASS: | | 1725 | case ORASS: |
1725 | case RETURN: | | 1726 | case RETURN: |
1726 | case INIT: | | 1727 | case INIT: |
1727 | ntn = build_assignment(op, sys, ln, rn); | | 1728 | ntn = build_assignment(op, sys, ln, rn); |
1728 | break; | | 1729 | break; |
1729 | case COMMA: | | 1730 | case COMMA: |
1730 | case QUEST: | | 1731 | case QUEST: |
1731 | ntn = new_tnode(op, sys, rn->tn_type, ln, rn); | | 1732 | ntn = new_tnode(op, sys, rn->tn_type, ln, rn); |
1732 | break; | | 1733 | break; |
1733 | case REAL: | | 1734 | case REAL: |
1734 | case IMAG: | | 1735 | case IMAG: |
1735 | ntn = build_real_imag(op, sys, ln); | | 1736 | ntn = build_real_imag(op, sys, ln); |
1736 | break; | | 1737 | break; |
1737 | default: | | 1738 | default: |
1738 | rettp = mp->m_returns_bool | | 1739 | rettp = mp->m_returns_bool |
1739 | ? gettyp(Tflag ? BOOL : INT) : ln->tn_type; | | 1740 | ? gettyp(Tflag ? BOOL : INT) : ln->tn_type; |
1740 | lint_assert(mp->m_binary == (rn != NULL)); | | 1741 | lint_assert(mp->m_binary == (rn != NULL)); |
1741 | ntn = new_tnode(op, sys, rettp, ln, rn); | | 1742 | ntn = new_tnode(op, sys, rettp, ln, rn); |
1742 | break; | | 1743 | break; |
1743 | } | | 1744 | } |
1744 | | | 1745 | |
1745 | /* Return if an error occurred. */ | | 1746 | /* Return if an error occurred. */ |
1746 | if (ntn == NULL) | | 1747 | if (ntn == NULL) |
1747 | return NULL; | | 1748 | return NULL; |
1748 | | | 1749 | |
1749 | /* Print a warning if precedence confusion is possible */ | | 1750 | /* Print a warning if precedence confusion is possible */ |
1750 | if (mp->m_possible_precedence_confusion) | | 1751 | if (mp->m_possible_precedence_confusion) |
1751 | check_precedence_confusion(ntn); | | 1752 | check_precedence_confusion(ntn); |
1752 | | | 1753 | |
1753 | /* | | 1754 | /* |
1754 | * Print a warning if one of the operands is in a context where | | 1755 | * Print a warning if one of the operands is in a context where |
1755 | * it is compared with zero and if this operand is a constant. | | 1756 | * it is compared with zero and if this operand is a constant. |
1756 | */ | | 1757 | */ |
1757 | if (hflag && !constcond_flag && | | 1758 | if (hflag && !constcond_flag && |
1758 | mp->m_compares_with_zero && | | 1759 | mp->m_compares_with_zero && |
1759 | (ln->tn_op == CON || | | 1760 | (ln->tn_op == CON || |
1760 | ((mp->m_binary && op != QUEST) && rn->tn_op == CON)) && | | 1761 | ((mp->m_binary && op != QUEST) && rn->tn_op == CON)) && |
1761 | /* XXX: rn->tn_system_dependent should be checked as well */ | | 1762 | /* XXX: rn->tn_system_dependent should be checked as well */ |
1762 | !ln->tn_system_dependent) { | | 1763 | !ln->tn_system_dependent) { |
1763 | /* constant in conditional context */ | | 1764 | /* constant in conditional context */ |
1764 | warning(161); | | 1765 | warning(161); |
1765 | } | | 1766 | } |
1766 | | | 1767 | |
1767 | /* Fold if the operator requires it */ | | 1768 | /* Fold if the operator requires it */ |
1768 | if (mp->m_fold_constant_operands) { | | 1769 | if (mp->m_fold_constant_operands) { |
1769 | if (ln->tn_op == CON && (!mp->m_binary || rn->tn_op == CON)) { | | 1770 | if (ln->tn_op == CON && (!mp->m_binary || rn->tn_op == CON)) { |
1770 | if (mp->m_compares_with_zero) { | | 1771 | if (mp->m_compares_with_zero) { |
1771 | ntn = fold_bool(ntn); | | 1772 | ntn = fold_bool(ntn); |
1772 | } else if (is_floating(ntn->tn_type->t_tspec)) { | | 1773 | } else if (is_floating(ntn->tn_type->t_tspec)) { |
1773 | ntn = fold_float(ntn); | | 1774 | ntn = fold_float(ntn); |
1774 | } else { | | 1775 | } else { |
1775 | ntn = fold(ntn); | | 1776 | ntn = fold(ntn); |
1776 | } | | 1777 | } |
1777 | } else if (op == QUEST && ln->tn_op == CON) { | | 1778 | } else if (op == QUEST && ln->tn_op == CON) { |
1778 | ntn = ln->tn_val->v_quad != 0 | | 1779 | ntn = ln->tn_val->v_quad != 0 |
1779 | ? rn->tn_left : rn->tn_right; | | 1780 | ? rn->tn_left : rn->tn_right; |
1780 | } | | 1781 | } |
1781 | } | | 1782 | } |
1782 | | | 1783 | |
1783 | return ntn; | | 1784 | return ntn; |
1784 | } | | 1785 | } |
1785 | | | 1786 | |
1786 | tnode_t * | | 1787 | tnode_t * |
1787 | build_unary(op_t op, bool sys, tnode_t *tn) | | 1788 | build_unary(op_t op, bool sys, tnode_t *tn) |
1788 | { | | 1789 | { |
1789 | return build_binary(tn, op, sys, NULL); | | 1790 | return build_binary(tn, op, sys, NULL); |
1790 | } | | 1791 | } |
1791 | | | 1792 | |
1792 | /* | | 1793 | /* |
1793 | * Return whether all struct/union members with the same name have the same | | 1794 | * Return whether all struct/union members with the same name have the same |
1794 | * type and offset. | | 1795 | * type and offset. |
1795 | */ | | 1796 | */ |
1796 | static bool | | 1797 | static bool |
1797 | all_members_compatible(const sym_t *msym) | | 1798 | all_members_compatible(const sym_t *msym) |
1798 | { | | 1799 | { |
1799 | for (const sym_t *csym = msym; | | 1800 | for (const sym_t *csym = msym; |
1800 | csym != NULL; csym = csym->s_symtab_next) { | | 1801 | csym != NULL; csym = csym->s_symtab_next) { |
1801 | if (!is_member(csym)) | | 1802 | if (!is_member(csym)) |
1802 | continue; | | 1803 | continue; |
1803 | if (strcmp(msym->s_name, csym->s_name) != 0) | | 1804 | if (strcmp(msym->s_name, csym->s_name) != 0) |
1804 | continue; | | 1805 | continue; |
1805 | | | 1806 | |
1806 | for (const sym_t *sym = csym->s_symtab_next; | | 1807 | for (const sym_t *sym = csym->s_symtab_next; |
1807 | sym != NULL; sym = sym->s_symtab_next) { | | 1808 | sym != NULL; sym = sym->s_symtab_next) { |
1808 | | | 1809 | |
1809 | if (!is_member(sym)) | | 1810 | if (!is_member(sym)) |
1810 | continue; | | 1811 | continue; |
1811 | if (strcmp(csym->s_name, sym->s_name) != 0) | | 1812 | if (strcmp(csym->s_name, sym->s_name) != 0) |
1812 | continue; | | 1813 | continue; |
1813 | if (csym->u.s_member.sm_offset_in_bits != | | 1814 | if (csym->u.s_member.sm_offset_in_bits != |
1814 | sym->u.s_member.sm_offset_in_bits) | | 1815 | sym->u.s_member.sm_offset_in_bits) |
1815 | return false; | | 1816 | return false; |
1816 | | | 1817 | |
1817 | bool w = false; | | 1818 | bool w = false; |
1818 | if (!types_compatible(csym->s_type, sym->s_type, | | 1819 | if (!types_compatible(csym->s_type, sym->s_type, |
1819 | false, false, &w) && !w) | | 1820 | false, false, &w) && !w) |
1820 | return false; | | 1821 | return false; |
1821 | if (csym->s_bitfield != sym->s_bitfield) | | 1822 | if (csym->s_bitfield != sym->s_bitfield) |
1822 | return false; | | 1823 | return false; |
1823 | if (csym->s_bitfield) { | | 1824 | if (csym->s_bitfield) { |
1824 | type_t *tp1 = csym->s_type; | | 1825 | type_t *tp1 = csym->s_type; |
1825 | type_t *tp2 = sym->s_type; | | 1826 | type_t *tp2 = sym->s_type; |
1826 | if (tp1->t_flen != tp2->t_flen) | | 1827 | if (tp1->t_flen != tp2->t_flen) |
1827 | return false; | | 1828 | return false; |
1828 | if (tp1->t_foffs != tp2->t_foffs) | | 1829 | if (tp1->t_foffs != tp2->t_foffs) |
1829 | return false; | | 1830 | return false; |
1830 | } | | 1831 | } |
1831 | } | | 1832 | } |
1832 | } | | 1833 | } |
1833 | return true; | | 1834 | return true; |
1834 | } | | 1835 | } |
1835 | | | 1836 | |
1836 | /* | | 1837 | /* |
1837 | * Returns a symbol which has the same name as the msym argument and is a | | 1838 | * Returns a symbol which has the same name as the msym argument and is a |
1838 | * member of the struct or union specified by the tn argument. | | 1839 | * member of the struct or union specified by the tn argument. |
1839 | */ | | 1840 | */ |
1840 | static sym_t * | | 1841 | static sym_t * |
1841 | struct_or_union_member(tnode_t *tn, op_t op, sym_t *msym) | | 1842 | struct_or_union_member(tnode_t *tn, op_t op, sym_t *msym) |
1842 | { | | 1843 | { |
1843 | struct_or_union *str; | | 1844 | struct_or_union *str; |
1844 | type_t *tp; | | 1845 | type_t *tp; |
1845 | tspec_t t; | | 1846 | tspec_t t; |
1846 | | | 1847 | |
1847 | /* | | 1848 | /* |
1848 | * Remove the member if it was unknown until now, which means | | 1849 | * Remove the member if it was unknown until now, which means |
1849 | * that no defined struct or union has a member with the same name. | | 1850 | * that no defined struct or union has a member with the same name. |
1850 | */ | | 1851 | */ |
1851 | if (msym->s_scl == NOSCL) { | | 1852 | if (msym->s_scl == NOSCL) { |
1852 | /* type '%s' does not have member '%s' */ | | 1853 | /* type '%s' does not have member '%s' */ |
1853 | error(101, type_name(tn->tn_type), msym->s_name); | | 1854 | error(101, type_name(tn->tn_type), msym->s_name); |
1854 | rmsym(msym); | | 1855 | rmsym(msym); |
1855 | msym->s_kind = FMEMBER; | | 1856 | msym->s_kind = FMEMBER; |
1856 | msym->s_scl = STRUCT_MEMBER; | | 1857 | msym->s_scl = STRUCT_MEMBER; |
1857 | | | 1858 | |
1858 | struct_or_union *sou = expr_zero_alloc(sizeof(*sou)); | | 1859 | struct_or_union *sou = expr_zero_alloc(sizeof(*sou)); |
1859 | sou->sou_tag = expr_zero_alloc(sizeof(*sou->sou_tag)); | | 1860 | sou->sou_tag = expr_zero_alloc(sizeof(*sou->sou_tag)); |
1860 | sou->sou_tag->s_name = unnamed; | | 1861 | sou->sou_tag->s_name = unnamed; |
1861 | | | 1862 | |
1862 | msym->u.s_member.sm_sou_type = sou; | | 1863 | msym->u.s_member.sm_sou_type = sou; |
1863 | /* | | 1864 | /* |
1864 | * The member sm_offset_in_bits is not needed here since this | | 1865 | * The member sm_offset_in_bits is not needed here since this |
1865 | * symbol can only be used for error reporting. | | 1866 | * symbol can only be used for error reporting. |
1866 | */ | | 1867 | */ |
1867 | return msym; | | 1868 | return msym; |
1868 | } | | 1869 | } |
1869 | | | 1870 | |
1870 | /* Set str to the tag of which msym is expected to be a member. */ | | 1871 | /* Set str to the tag of which msym is expected to be a member. */ |
1871 | str = NULL; | | 1872 | str = NULL; |
1872 | t = (tp = tn->tn_type)->t_tspec; | | 1873 | t = (tp = tn->tn_type)->t_tspec; |
1873 | if (op == POINT) { | | 1874 | if (op == POINT) { |
1874 | if (is_struct_or_union(t)) | | 1875 | if (is_struct_or_union(t)) |
1875 | str = tp->t_str; | | 1876 | str = tp->t_str; |
1876 | } else if (op == ARROW && t == PTR) { | | 1877 | } else if (op == ARROW && t == PTR) { |
1877 | t = (tp = tp->t_subt)->t_tspec; | | 1878 | t = (tp = tp->t_subt)->t_tspec; |
1878 | if (is_struct_or_union(t)) | | 1879 | if (is_struct_or_union(t)) |
1879 | str = tp->t_str; | | 1880 | str = tp->t_str; |
1880 | } | | 1881 | } |
1881 | | | 1882 | |
1882 | /* | | 1883 | /* |
1883 | * If this struct/union has a member with the name of msym, return it. | | 1884 | * If this struct/union has a member with the name of msym, return it. |
1884 | */ | | 1885 | */ |
1885 | if (str != NULL) { | | 1886 | if (str != NULL) { |
1886 | for (sym_t *sym = msym; | | 1887 | for (sym_t *sym = msym; |
1887 | sym != NULL; sym = sym->s_symtab_next) { | | 1888 | sym != NULL; sym = sym->s_symtab_next) { |
1888 | if (!is_member(sym)) | | 1889 | if (is_member(sym) && |
1889 | continue; | | 1890 | sym->u.s_member.sm_sou_type == str && |
1890 | if (sym->u.s_member.sm_sou_type != str) | | 1891 | strcmp(sym->s_name, msym->s_name) == 0) |
1891 | continue; | | 1892 | return sym; |
1892 | if (strcmp(sym->s_name, msym->s_name) != 0) | | | |
1893 | continue; | | | |
1894 | return sym; | | | |
1895 | } | | 1893 | } |
1896 | } | | 1894 | } |
1897 | | | 1895 | |
1898 | bool eq = all_members_compatible(msym); | | 1896 | bool eq = all_members_compatible(msym); |
1899 | | | 1897 | |
1900 | /* | | 1898 | /* |
1901 | * Now handle the case in which the left operand refers really | | 1899 | * Now handle the case in which the left operand refers really |
1902 | * to a struct/union, but the right operand is not member of it. | | 1900 | * to a struct/union, but the right operand is not member of it. |
1903 | */ | | 1901 | */ |
1904 | if (str != NULL) { | | 1902 | if (str != NULL) { |
1905 | if (eq && !allow_c90) { | | 1903 | if (eq && !allow_c90) { |
1906 | /* illegal use of member '%s' */ | | 1904 | /* illegal use of member '%s' */ |
1907 | warning(102, msym->s_name); | | 1905 | warning(102, msym->s_name); |
1908 | } else { | | 1906 | } else { |
1909 | /* illegal use of member '%s' */ | | 1907 | /* illegal use of member '%s' */ |
1910 | error(102, msym->s_name); | | 1908 | error(102, msym->s_name); |
1911 | } | | 1909 | } |
1912 | return msym; | | 1910 | return msym; |
1913 | } | | 1911 | } |
1914 | | | 1912 | |
1915 | /* | | 1913 | /* |
1916 | * Now the left operand of ARROW does not point to a struct/union | | 1914 | * Now the left operand of ARROW does not point to a struct/union |
1917 | * or the left operand of POINT is no struct/union. | | 1915 | * or the left operand of POINT is no struct/union. |
1918 | */ | | 1916 | */ |
1919 | if (eq) { | | 1917 | if (eq) { |
1920 | if (op == POINT) { | | 1918 | if (op == POINT) { |
1921 | if (!allow_c90) { | | 1919 | if (!allow_c90) { |
1922 | /* left operand of '.' must be struct ... */ | | 1920 | /* left operand of '.' must be struct ... */ |
1923 | warning(103, type_name(tn->tn_type)); | | 1921 | warning(103, type_name(tn->tn_type)); |
1924 | } else { | | 1922 | } else { |
1925 | /* left operand of '.' must be struct ... */ | | 1923 | /* left operand of '.' must be struct ... */ |
1926 | error(103, type_name(tn->tn_type)); | | 1924 | error(103, type_name(tn->tn_type)); |
1927 | } | | 1925 | } |
1928 | } else { | | 1926 | } else { |
1929 | if (!allow_c90 && tn->tn_type->t_tspec == PTR) { | | 1927 | if (!allow_c90 && tn->tn_type->t_tspec == PTR) { |
1930 | /* left operand of '->' must be pointer ... */ | | 1928 | /* left operand of '->' must be pointer ... */ |
1931 | warning(104, type_name(tn->tn_type)); | | 1929 | warning(104, type_name(tn->tn_type)); |
1932 | } else { | | 1930 | } else { |
1933 | /* left operand of '->' must be pointer ... */ | | 1931 | /* left operand of '->' must be pointer ... */ |
1934 | error(104, type_name(tn->tn_type)); | | 1932 | error(104, type_name(tn->tn_type)); |
1935 | } | | 1933 | } |
1936 | } | | 1934 | } |
1937 | } else { | | 1935 | } else { |
1938 | if (!allow_c90) { | | 1936 | if (!allow_c90) { |
1939 | /* non-unique member requires struct/union %s */ | | 1937 | /* non-unique member requires struct/union %s */ |
1940 | error(105, op == POINT ? "object" : "pointer"); | | 1938 | error(105, op == POINT ? "object" : "pointer"); |
1941 | } else { | | 1939 | } else { |
1942 | /* unacceptable operand of '%s' */ | | 1940 | /* unacceptable operand of '%s' */ |
1943 | error(111, op_name(op)); | | 1941 | error(111, op_name(op)); |
1944 | } | | 1942 | } |
1945 | } | | 1943 | } |
1946 | | | 1944 | |
1947 | return msym; | | 1945 | return msym; |
1948 | } | | 1946 | } |
1949 | | | 1947 | |
1950 | tnode_t * | | 1948 | tnode_t * |
1951 | build_member_access(tnode_t *ln, op_t op, bool sys, sbuf_t *member) | | 1949 | build_member_access(tnode_t *ln, op_t op, bool sys, sbuf_t *member) |
1952 | { | | 1950 | { |
1953 | sym_t *msym; | | 1951 | sym_t *msym; |
1954 | | | 1952 | |
1955 | if (ln == NULL) | | 1953 | if (ln == NULL) |
1956 | return NULL; | | 1954 | return NULL; |
1957 | | | 1955 | |
1958 | if (op == ARROW) { | | 1956 | if (op == ARROW) { |
1959 | /* must do this before struct_or_union_member is called */ | | 1957 | /* must do this before struct_or_union_member is called */ |
1960 | ln = cconv(ln); | | 1958 | ln = cconv(ln); |
1961 | } | | 1959 | } |
1962 | msym = struct_or_union_member(ln, op, getsym(member)); | | 1960 | msym = struct_or_union_member(ln, op, getsym(member)); |
1963 | return build_binary(ln, op, sys, build_name(msym, false)); | | 1961 | return build_binary(ln, op, sys, build_name(msym, false)); |
1964 | } | | 1962 | } |
1965 | | | 1963 | |
1966 | /* | | 1964 | /* |
1967 | * Perform class conversions. | | 1965 | * Perform class conversions. |
1968 | * | | 1966 | * |
1969 | * Arrays of type T are converted into pointers to type T. | | 1967 | * Arrays of type T are converted into pointers to type T. |
1970 | * Functions are converted to pointers to functions. | | 1968 | * Functions are converted to pointers to functions. |
1971 | * Lvalues are converted to rvalues. | | 1969 | * Lvalues are converted to rvalues. |
1972 | * | | 1970 | * |
1973 | * C99 6.3 "Conversions" | | 1971 | * C99 6.3 "Conversions" |
1974 | * C99 6.3.2 "Other operands" | | 1972 | * C99 6.3.2 "Other operands" |
1975 | * C99 6.3.2.1 "Lvalues, arrays, and function designators" | | 1973 | * C99 6.3.2.1 "Lvalues, arrays, and function designators" |
1976 | */ | | 1974 | */ |
1977 | tnode_t * | | 1975 | tnode_t * |
1978 | cconv(tnode_t *tn) | | 1976 | cconv(tnode_t *tn) |
1979 | { | | 1977 | { |
1980 | type_t *tp; | | | |
1981 | | | | |
1982 | /* | | 1978 | /* |
1983 | * Array-lvalue (array of type T) is converted into rvalue | | 1979 | * Array-lvalue (array of type T) is converted into rvalue |
1984 | * (pointer to type T) | | 1980 | * (pointer to type T) |
1985 | */ | | 1981 | */ |
1986 | if (tn->tn_type->t_tspec == ARRAY) { | | 1982 | if (tn->tn_type->t_tspec == ARRAY) { |
1987 | if (!tn->tn_lvalue) { | | 1983 | if (!tn->tn_lvalue) { |
1988 | /* XXX print correct operator */ | | 1984 | /* XXX print correct operator */ |
1989 | /* %soperand of '%s' must be lvalue */ | | 1985 | /* %soperand of '%s' must be lvalue */ |
1990 | gnuism(114, "", op_name(ADDR)); | | 1986 | gnuism(114, "", op_name(ADDR)); |
1991 | } | | 1987 | } |
1992 | tn = new_tnode(ADDR, tn->tn_sys, | | 1988 | tn = new_tnode(ADDR, tn->tn_sys, |
1993 | expr_derive_type(tn->tn_type->t_subt, PTR), tn, NULL); | | 1989 | expr_derive_type(tn->tn_type->t_subt, PTR), tn, NULL); |
1994 | } | | 1990 | } |
1995 | | | 1991 | |
1996 | /* | | 1992 | /* |
1997 | * Expression of type function (function with return value of type T) | | 1993 | * Expression of type function (function with return value of type T) |
1998 | * in rvalue-expression (pointer to function with return value | | 1994 | * in rvalue-expression (pointer to function with return value |
1999 | * of type T) | | 1995 | * of type T) |
2000 | */ | | 1996 | */ |
2001 | if (tn->tn_type->t_tspec == FUNC) | | 1997 | if (tn->tn_type->t_tspec == FUNC) |
2002 | tn = build_address(tn->tn_sys, tn, true); | | 1998 | tn = build_address(tn->tn_sys, tn, true); |
2003 | | | 1999 | |
2004 | /* lvalue to rvalue */ | | 2000 | /* lvalue to rvalue */ |
2005 | if (tn->tn_lvalue) { | | 2001 | if (tn->tn_lvalue) { |
2006 | tp = expr_dup_type(tn->tn_type); | | 2002 | type_t *tp = expr_dup_type(tn->tn_type); |
2007 | /* C99 6.3.2.1p2 sentence 2 says to remove the qualifiers. */ | | 2003 | /* C99 6.3.2.1p2 sentence 2 says to remove the qualifiers. */ |
2008 | tp->t_const = tp->t_volatile = false; | | 2004 | tp->t_const = tp->t_volatile = false; |
2009 | tn = new_tnode(LOAD, tn->tn_sys, tp, tn, NULL); | | 2005 | tn = new_tnode(LOAD, tn->tn_sys, tp, tn, NULL); |
2010 | } | | 2006 | } |
2011 | | | 2007 | |
2012 | return tn; | | 2008 | return tn; |
2013 | } | | 2009 | } |
2014 | | | 2010 | |
2015 | const tnode_t * | | 2011 | const tnode_t * |
2016 | before_conversion(const tnode_t *tn) | | 2012 | before_conversion(const tnode_t *tn) |
2017 | { | | 2013 | { |
2018 | while (tn->tn_op == CVT && !tn->tn_cast) | | 2014 | while (tn->tn_op == CVT && !tn->tn_cast) |
2019 | tn = tn->tn_left; | | 2015 | tn = tn->tn_left; |
2020 | return tn; | | 2016 | return tn; |
2021 | } | | 2017 | } |
2022 | | | 2018 | |
2023 | /* | | 2019 | /* |
2024 | * Most errors required by ANSI C are reported in struct_or_union_member(). | | 2020 | * Most errors required by ANSI C are reported in struct_or_union_member(). |
2025 | * Here we only check for totally wrong things. | | 2021 | * Here we only check for totally wrong things. |
2026 | */ | | 2022 | */ |
2027 | static bool | | 2023 | static bool |
2028 | typeok_point(const tnode_t *ln, const type_t *ltp, tspec_t lt) | | 2024 | typeok_point(const tnode_t *ln, const type_t *ltp, tspec_t lt) |
2029 | { | | 2025 | { |
2030 | if (is_struct_or_union(lt)) | | 2026 | if (is_struct_or_union(lt)) |
2031 | return true; | | 2027 | return true; |
2032 | | | 2028 | |
2033 | if (lt == FUNC || lt == VOID || ltp->t_bitfield) | | 2029 | if (lt == FUNC || lt == VOID || ltp->t_bitfield) |
2034 | goto wrong; | | 2030 | goto wrong; |
2035 | | | 2031 | |
2036 | /* | | 2032 | /* |
2037 | * Some C dialects from before C90 tolerated any lvalue on the | | 2033 | * Some C dialects from before C90 tolerated any lvalue on the |
2038 | * left-hand side of the '.' operator, allowing things like | | 2034 | * left-hand side of the '.' operator, allowing things like |
2039 | * char st[100]; st.st_mtime, assuming that the member 'st_mtime' | | 2035 | * char st[100]; st.st_mtime, assuming that the member 'st_mtime' |
2040 | * only occurred in a single struct; see typeok_arrow. | | 2036 | * only occurred in a single struct; see typeok_arrow. |
2041 | */ | | 2037 | */ |
2042 | if (ln->tn_lvalue) | | 2038 | if (ln->tn_lvalue) |
2043 | return true; | | 2039 | return true; |
2044 | | | 2040 | |
2045 | wrong: | | 2041 | wrong: |
2046 | /* With allow_c90 we already got an error */ | | 2042 | /* With allow_c90 we already got an error */ |
2047 | if (!allow_c90) | | 2043 | if (!allow_c90) |
2048 | /* unacceptable operand of '%s' */ | | 2044 | /* unacceptable operand of '%s' */ |
2049 | error(111, op_name(POINT)); | | 2045 | error(111, op_name(POINT)); |
2050 | | | 2046 | |
2051 | return false; | | 2047 | return false; |
2052 | } | | 2048 | } |
2053 | | | 2049 | |
2054 | static bool | | 2050 | static bool |
2055 | typeok_arrow(tspec_t lt) | | 2051 | typeok_arrow(tspec_t lt) |
2056 | { | | 2052 | { |
2057 | /* | | 2053 | /* |
2058 | * C1978 Appendix A 14.1 says: <quote>In fact, any lvalue is allowed | | 2054 | * C1978 Appendix A 14.1 says: <quote>In fact, any lvalue is allowed |
2059 | * before '.', and that lvalue is then assumed to have the form of | | 2055 | * before '.', and that lvalue is then assumed to have the form of |
2060 | * the structure of which the name of the right is a member. [...] | | 2056 | * the structure of which the name of the right is a member. [...] |
2061 | * Such constructions are non-portable.</quote> | | 2057 | * Such constructions are non-portable.</quote> |
2062 | */ | | 2058 | */ |
2063 | if (lt == PTR || (!allow_c90 && is_integer(lt))) | | 2059 | if (lt == PTR || (!allow_c90 && is_integer(lt))) |
2064 | return true; | | 2060 | return true; |
2065 | | | 2061 | |
2066 | /* With allow_c90 we already got an error */ | | 2062 | /* With allow_c90 we already got an error */ |
2067 | if (!allow_c90) | | 2063 | if (!allow_c90) |
2068 | /* unacceptable operand of '%s' */ | | 2064 | /* unacceptable operand of '%s' */ |
2069 | error(111, op_name(ARROW)); | | 2065 | error(111, op_name(ARROW)); |
2070 | return false; | | 2066 | return false; |
2071 | } | | 2067 | } |
2072 | | | 2068 | |
2073 | static bool | | 2069 | static bool |
2074 | typeok_incdec(op_t op, const tnode_t *tn, const type_t *tp) | | 2070 | typeok_incdec(op_t op, const tnode_t *tn, const type_t *tp) |
2075 | { | | 2071 | { |
2076 | /* operand has scalar type (checked in typeok) */ | | 2072 | /* operand has scalar type (checked in typeok) */ |
2077 | if (!tn->tn_lvalue) { | | 2073 | if (!tn->tn_lvalue) { |
2078 | if (tn->tn_op == CVT && tn->tn_cast && | | 2074 | if (tn->tn_op == CVT && tn->tn_cast && |
2079 | tn->tn_left->tn_op == LOAD) { | | 2075 | tn->tn_left->tn_op == LOAD) { |
2080 | /* a cast does not yield an lvalue */ | | 2076 | /* a cast does not yield an lvalue */ |
2081 | error(163); | | 2077 | error(163); |
2082 | } | | 2078 | } |
2083 | /* %soperand of '%s' must be lvalue */ | | 2079 | /* %soperand of '%s' must be lvalue */ |
2084 | error(114, "", op_name(op)); | | 2080 | error(114, "", op_name(op)); |
2085 | return false; | | 2081 | return false; |
2086 | } else if (tp->t_const) { | | 2082 | } |
2087 | if (allow_c90) | | 2083 | if (tp->t_const && allow_c90) { |
2088 | /* %soperand of '%s' must be modifiable lvalue */ | | 2084 | /* %soperand of '%s' must be modifiable lvalue */ |
2089 | warning(115, "", op_name(op)); | | 2085 | warning(115, "", op_name(op)); |
2090 | } | | 2086 | } |
2091 | return true; | | 2087 | return true; |
2092 | } | | 2088 | } |
2093 | | | 2089 | |
2094 | static bool | | 2090 | static bool |
2095 | typeok_address(const mod_t *mp, | | 2091 | typeok_address(const mod_t *mp, |
2096 | const tnode_t *tn, const type_t *tp, tspec_t t) | | 2092 | const tnode_t *tn, const type_t *tp, tspec_t t) |
2097 | { | | 2093 | { |
2098 | if (t == ARRAY || t == FUNC) { | | 2094 | if (t == ARRAY || t == FUNC) { |
2099 | /* ok, a warning comes later (in build_address()) */ | | 2095 | /* ok, a warning comes later (in build_address()) */ |
2100 | } else if (!tn->tn_lvalue) { | | 2096 | } else if (!tn->tn_lvalue) { |
2101 | if (tn->tn_op == CVT && tn->tn_cast && | | 2097 | if (tn->tn_op == CVT && tn->tn_cast && |
2102 | tn->tn_left->tn_op == LOAD) { | | 2098 | tn->tn_left->tn_op == LOAD) { |
2103 | /* a cast does not yield an lvalue */ | | 2099 | /* a cast does not yield an lvalue */ |
2104 | error(163); | | 2100 | error(163); |
2105 | } | | 2101 | } |
2106 | /* %soperand of '%s' must be lvalue */ | | 2102 | /* %soperand of '%s' must be lvalue */ |
2107 | error(114, "", mp->m_name); | | 2103 | error(114, "", mp->m_name); |
2108 | return false; | | 2104 | return false; |
2109 | } else if (is_scalar(t)) { | | 2105 | } else if (is_scalar(t)) { |
2110 | if (tp->t_bitfield) { | | 2106 | if (tp->t_bitfield) { |
2111 | /* cannot take address of bit-field */ | | 2107 | /* cannot take address of bit-field */ |
2112 | error(112); | | 2108 | error(112); |
2113 | return false; | | 2109 | return false; |
2114 | } | | 2110 | } |
2115 | } else if (t != STRUCT && t != UNION) { | | 2111 | } else if (t != STRUCT && t != UNION) { |
2116 | /* unacceptable operand of '%s' */ | | 2112 | /* unacceptable operand of '%s' */ |
2117 | error(111, mp->m_name); | | 2113 | error(111, mp->m_name); |
2118 | return false; | | 2114 | return false; |
2119 | } | | 2115 | } |
2120 | if (tn->tn_op == NAME && tn->tn_sym->s_register) { | | 2116 | if (tn->tn_op == NAME && tn->tn_sym->s_register) { |
2121 | /* cannot take address of register '%s' */ | | 2117 | /* cannot take address of register '%s' */ |
2122 | error(113, tn->tn_sym->s_name); | | 2118 | error(113, tn->tn_sym->s_name); |
2123 | return false; | | 2119 | return false; |
2124 | } | | 2120 | } |
2125 | return true; | | 2121 | return true; |
2126 | } | | 2122 | } |
2127 | | | 2123 | |
2128 | static bool | | 2124 | static bool |
2129 | typeok_indir(const type_t *tp, tspec_t t) | | 2125 | typeok_indir(const type_t *tp, tspec_t t) |
2130 | { | | 2126 | { |
2131 | | | 2127 | |
2132 | if (t != PTR) { | | 2128 | if (t != PTR) { |
2133 | /* cannot dereference non-pointer type '%s' */ | | 2129 | /* cannot dereference non-pointer type '%s' */ |
2134 | error(96, type_name(tp)); | | 2130 | error(96, type_name(tp)); |
2135 | return false; | | 2131 | return false; |
2136 | } | | 2132 | } |
2137 | return true; | | 2133 | return true; |
2138 | } | | 2134 | } |
2139 | | | 2135 | |
2140 | /* | | | |
2141 | * Called if incompatible types were detected. | | | |
2142 | * Prints a appropriate warning. | | | |
2143 | */ | | | |
2144 | static void | | 2136 | static void |
2145 | warn_incompatible_types(op_t op, | | 2137 | warn_incompatible_types(op_t op, |
2146 | const type_t *ltp, tspec_t lt, | | 2138 | const type_t *ltp, tspec_t lt, |
2147 | const type_t *rtp, tspec_t rt) | | 2139 | const type_t *rtp, tspec_t rt) |
2148 | { | | 2140 | { |
2149 | const mod_t *mp; | | 2141 | const mod_t *mp = &modtab[op]; |
2150 | | | | |
2151 | mp = &modtab[op]; | | | |
2152 | | | 2142 | |
2153 | if (lt == VOID || (mp->m_binary && rt == VOID)) { | | 2143 | if (lt == VOID || (mp->m_binary && rt == VOID)) { |
2154 | /* void type illegal in expression */ | | 2144 | /* void type illegal in expression */ |
2155 | error(109); | | 2145 | error(109); |
2156 | } else if (op == ASSIGN) { | | 2146 | } else if (op == ASSIGN) { |
2157 | /* cannot assign to '%s' from '%s' */ | | 2147 | /* cannot assign to '%s' from '%s' */ |
2158 | error(171, type_name(ltp), type_name(rtp)); | | 2148 | error(171, type_name(ltp), type_name(rtp)); |
2159 | } else if (mp->m_binary) { | | 2149 | } else if (mp->m_binary) { |
2160 | /* operands of '%s' have incompatible types '%s' and '%s' */ | | 2150 | /* operands of '%s' have incompatible types '%s' and '%s' */ |
2161 | error(107, mp->m_name, tspec_name(lt), tspec_name(rt)); | | 2151 | error(107, mp->m_name, tspec_name(lt), tspec_name(rt)); |
2162 | } else { | | 2152 | } else { |
2163 | lint_assert(rt == NOTSPEC); | | 2153 | lint_assert(rt == NOTSPEC); |
2164 | /* operand of '%s' has invalid type '%s' */ | | 2154 | /* operand of '%s' has invalid type '%s' */ |
2165 | error(108, mp->m_name, type_name(ltp)); | | 2155 | error(108, mp->m_name, type_name(ltp)); |
2166 | } | | 2156 | } |
2167 | } | | 2157 | } |
2168 | | | 2158 | |
2169 | static bool | | 2159 | static bool |
2170 | typeok_plus(op_t op, | | 2160 | typeok_plus(op_t op, |
2171 | const type_t *ltp, tspec_t lt, | | 2161 | const type_t *ltp, tspec_t lt, |
2172 | const type_t *rtp, tspec_t rt) | | 2162 | const type_t *rtp, tspec_t rt) |
2173 | { | | 2163 | { |
2174 | /* operands have scalar types (checked in typeok) */ | | 2164 | /* operands have scalar types (checked in typeok) */ |
2175 | if ((lt == PTR && !is_integer(rt)) || (rt == PTR && !is_integer(lt))) { | | 2165 | if ((lt == PTR && !is_integer(rt)) || (rt == PTR && !is_integer(lt))) { |
2176 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 2166 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
2177 | return false; | | 2167 | return false; |
2178 | } | | 2168 | } |
2179 | return true; | | 2169 | return true; |
2180 | } | | 2170 | } |
2181 | | | 2171 | |
2182 | static bool | | 2172 | static bool |
2183 | typeok_minus(op_t op, | | 2173 | typeok_minus(op_t op, |
2184 | const type_t *ltp, tspec_t lt, | | 2174 | const type_t *ltp, tspec_t lt, |
2185 | const type_t *rtp, tspec_t rt) | | 2175 | const type_t *rtp, tspec_t rt) |
2186 | { | | 2176 | { |
2187 | /* operands have scalar types (checked in typeok) */ | | 2177 | /* operands have scalar types (checked in typeok) */ |
2188 | if ((lt == PTR && rt != PTR && !is_integer(rt)) || | | 2178 | if ((lt == PTR && rt != PTR && !is_integer(rt)) || |
2189 | (lt != PTR && rt == PTR)) { | | 2179 | (lt != PTR && rt == PTR)) { |
2190 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 2180 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
2191 | return false; | | 2181 | return false; |
2192 | } | | 2182 | } |
2193 | if (lt == PTR && rt == PTR) { | | 2183 | if (lt == PTR && rt == PTR && |
2194 | if (!types_compatible(ltp->t_subt, rtp->t_subt, | | 2184 | !types_compatible(ltp->t_subt, rtp->t_subt, true, false, NULL)) { |
2195 | true, false, NULL)) { | | 2185 | /* illegal pointer subtraction */ |
2196 | /* illegal pointer subtraction */ | | 2186 | error(116); |
2197 | error(116); | | | |
2198 | } | | | |
2199 | } | | 2187 | } |
2200 | return true; | | 2188 | return true; |
2201 | } | | 2189 | } |
2202 | | | 2190 | |
2203 | static void | | 2191 | static void |
2204 | typeok_shr(const mod_t *mp, | | 2192 | typeok_shr(const mod_t *mp, |
2205 | const tnode_t *ln, tspec_t lt, | | 2193 | const tnode_t *ln, tspec_t lt, |
2206 | const tnode_t *rn, tspec_t rt) | | 2194 | const tnode_t *rn, tspec_t rt) |
2207 | { | | 2195 | { |
2208 | tspec_t olt, ort; | | 2196 | tspec_t olt, ort; |
2209 | | | 2197 | |
2210 | olt = before_conversion(ln)->tn_type->t_tspec; | | 2198 | olt = before_conversion(ln)->tn_type->t_tspec; |
2211 | ort = before_conversion(rn)->tn_type->t_tspec; | | 2199 | ort = before_conversion(rn)->tn_type->t_tspec; |
2212 | | | 2200 | |
2213 | /* operands have integer types (checked in typeok) */ | | 2201 | /* operands have integer types (checked in typeok) */ |
2214 | if (pflag && !is_uinteger(olt)) { | | 2202 | if (pflag && !is_uinteger(olt)) { |
2215 | integer_constraints lc = ic_expr(ln); | | 2203 | integer_constraints lc = ic_expr(ln); |
2216 | if (!ic_maybe_signed(ln->tn_type, &lc)) | | 2204 | if (!ic_maybe_signed(ln->tn_type, &lc)) |
2217 | return; | | 2205 | return; |
2218 | | | 2206 | |
2219 | /* | | 2207 | /* |
2220 | * The left operand is signed. This means that | | 2208 | * The left operand is signed. This means that |
2221 | * the operation is (possibly) nonportable. | | 2209 | * the operation is (possibly) nonportable. |
2222 | */ | | 2210 | */ |
2223 | if (ln->tn_op != CON) { | | 2211 | if (ln->tn_op != CON) { |
2224 | /* bitwise '%s' on signed value possibly nonportable */ | | 2212 | /* bitwise '%s' on signed value possibly nonportable */ |
2225 | warning(117, mp->m_name); | | 2213 | warning(117, mp->m_name); |
2226 | } else if (ln->tn_val->v_quad < 0) { | | 2214 | } else if (ln->tn_val->v_quad < 0) { |
2227 | /* bitwise '%s' on signed value nonportable */ | | 2215 | /* bitwise '%s' on signed value nonportable */ |
2228 | warning(120, mp->m_name); | | 2216 | warning(120, mp->m_name); |
2229 | } | | 2217 | } |
2230 | } else if (allow_trad && allow_c90 && | | 2218 | } else if (allow_trad && allow_c90 && |
2231 | !is_uinteger(olt) && is_uinteger(ort)) { | | 2219 | !is_uinteger(olt) && is_uinteger(ort)) { |
2232 | /* | | 2220 | /* The left operand would become unsigned in traditional C. */ |
2233 | * The left operand would become unsigned in | | | |
2234 | * traditional C. | | | |
2235 | */ | | | |
2236 | if (hflag && (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { | | 2221 | if (hflag && (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { |
2237 | /* semantics of '%s' change in ANSI C; use ... */ | | 2222 | /* semantics of '%s' change in ANSI C; use ... */ |
2238 | warning(118, mp->m_name); | | 2223 | warning(118, mp->m_name); |
2239 | } | | 2224 | } |
2240 | } else if (allow_trad && allow_c90 && | | 2225 | } else if (allow_trad && allow_c90 && |
2241 | !is_uinteger(olt) && !is_uinteger(ort) && | | 2226 | !is_uinteger(olt) && !is_uinteger(ort) && |
2242 | portable_size_in_bits(lt) < portable_size_in_bits(rt)) { | | 2227 | portable_size_in_bits(lt) < portable_size_in_bits(rt)) { |
2243 | /* | | 2228 | /* |
2244 | * In traditional C the left operand would be extended | | 2229 | * In traditional C the left operand would be extended |
2245 | * (possibly sign-extended) and then shifted. | | 2230 | * (possibly sign-extended) and then shifted. |
2246 | */ | | 2231 | */ |
2247 | if (hflag && (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { | | 2232 | if (hflag && (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { |
2248 | /* semantics of '%s' change in ANSI C; use ... */ | | 2233 | /* semantics of '%s' change in ANSI C; use ... */ |
2249 | warning(118, mp->m_name); | | 2234 | warning(118, mp->m_name); |
2250 | } | | 2235 | } |
2251 | } | | 2236 | } |
2252 | } | | 2237 | } |
2253 | | | 2238 | |
2254 | static void | | 2239 | static void |
2255 | typeok_shl(const mod_t *mp, tspec_t lt, tspec_t rt) | | 2240 | typeok_shl(const mod_t *mp, tspec_t lt, tspec_t rt) |
2256 | { | | 2241 | { |
2257 | /* | | 2242 | /* |
2258 | * C90 does not perform balancing for shift operations, | | 2243 | * C90 does not perform balancing for shift operations, |
2259 | * but traditional C does. If the width of the right operand | | 2244 | * but traditional C does. If the width of the right operand |
2260 | * is greater than the width of the left operand, then in | | 2245 | * is greater than the width of the left operand, then in |
2261 | * traditional C the left operand would be extended to the | | 2246 | * traditional C the left operand would be extended to the |
2262 | * width of the right operand. For SHL this may result in | | 2247 | * width of the right operand. For SHL this may result in |
2263 | * different results. | | 2248 | * different results. |
2264 | */ | | 2249 | */ |
2265 | if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { | | 2250 | if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { |
2266 | /* | | 2251 | /* |
2267 | * XXX If both operands are constant, make sure | | 2252 | * XXX If both operands are constant, make sure |
2268 | * that there is really a difference between | | 2253 | * that there is really a difference between |
2269 | * ANSI C and traditional C. | | 2254 | * ANSI C and traditional C. |
2270 | */ | | 2255 | */ |
2271 | if (hflag && !allow_c99) | | 2256 | if (hflag && !allow_c99) |
2272 | /* semantics of '%s' change in ANSI C; use ... */ | | 2257 | /* semantics of '%s' change in ANSI C; use ... */ |
2273 | warning(118, mp->m_name); | | 2258 | warning(118, mp->m_name); |
2274 | } | | 2259 | } |
2275 | } | | 2260 | } |
2276 | | | 2261 | |
2277 | static void | | 2262 | static void |
2278 | typeok_shift(const type_t *ltp, tspec_t lt, const tnode_t *rn, tspec_t rt) | | 2263 | typeok_shift(const type_t *ltp, tspec_t lt, const tnode_t *rn, tspec_t rt) |
2279 | { | | 2264 | { |
2280 | if (rn->tn_op != CON) | | 2265 | if (rn->tn_op != CON) |
2281 | return; | | 2266 | return; |
2282 | | | 2267 | |
2283 | if (!is_uinteger(rt) && rn->tn_val->v_quad < 0) { | | 2268 | if (!is_uinteger(rt) && rn->tn_val->v_quad < 0) { |
2284 | /* negative shift */ | | 2269 | /* negative shift */ |
2285 | warning(121); | | 2270 | warning(121); |
2286 | } else if ((uint64_t)rn->tn_val->v_quad == | | 2271 | } else if ((uint64_t)rn->tn_val->v_quad == |
2287 | (uint64_t)size_in_bits(lt)) { | | 2272 | (uint64_t)size_in_bits(lt)) { |
2288 | /* shift amount %u equals bit-size of '%s' */ | | 2273 | /* shift amount %u equals bit-size of '%s' */ |
2289 | warning(267, (unsigned)rn->tn_val->v_quad, type_name(ltp)); | | 2274 | warning(267, (unsigned)rn->tn_val->v_quad, type_name(ltp)); |
2290 | } else if ((uint64_t)rn->tn_val->v_quad > (uint64_t)size_in_bits(lt)) { | | 2275 | } else if ((uint64_t)rn->tn_val->v_quad > (uint64_t)size_in_bits(lt)) { |
2291 | /* shift amount %llu is greater than bit-size %llu of '%s' */ | | 2276 | /* shift amount %llu is greater than bit-size %llu of '%s' */ |
2292 | warning(122, (unsigned long long)rn->tn_val->v_quad, | | 2277 | warning(122, (unsigned long long)rn->tn_val->v_quad, |
2293 | (unsigned long long)size_in_bits(lt), | | 2278 | (unsigned long long)size_in_bits(lt), |
2294 | tspec_name(lt)); | | 2279 | tspec_name(lt)); |
2295 | } | | 2280 | } |
2296 | } | | 2281 | } |
2297 | | | 2282 | |
2298 | static bool | | 2283 | static bool |
2299 | is_typeok_eq(const tnode_t *ln, tspec_t lt, const tnode_t *rn, tspec_t rt) | | 2284 | is_typeok_eq(const tnode_t *ln, tspec_t lt, const tnode_t *rn, tspec_t rt) |
2300 | { | | 2285 | { |
2301 | if (lt == PTR && is_null_pointer(rn)) | | 2286 | if (lt == PTR && is_null_pointer(rn)) |
2302 | return true; | | 2287 | return true; |
2303 | if (rt == PTR && is_null_pointer(ln)) | | 2288 | if (rt == PTR && is_null_pointer(ln)) |
2304 | return true; | | 2289 | return true; |
2305 | return false; | | 2290 | return false; |
2306 | } | | 2291 | } |
2307 | | | 2292 | |
2308 | /* | | 2293 | /* |
2309 | * Called if incompatible pointer types are detected. | | 2294 | * Called if incompatible pointer types are detected. |
2310 | * Print an appropriate warning. | | 2295 | * Print an appropriate warning. |
2311 | */ | | 2296 | */ |
2312 | static void | | 2297 | static void |
2313 | warn_incompatible_pointers(const mod_t *mp, | | 2298 | warn_incompatible_pointers(const mod_t *mp, |
2314 | const type_t *ltp, const type_t *rtp) | | 2299 | const type_t *ltp, const type_t *rtp) |
2315 | { | | 2300 | { |
2316 | tspec_t lt, rt; | | | |
2317 | | | | |
2318 | lint_assert(ltp->t_tspec == PTR); | | 2301 | lint_assert(ltp->t_tspec == PTR); |
2319 | lint_assert(rtp->t_tspec == PTR); | | 2302 | lint_assert(rtp->t_tspec == PTR); |
2320 | | | 2303 | |
2321 | lt = ltp->t_subt->t_tspec; | | 2304 | tspec_t lt = ltp->t_subt->t_tspec; |
2322 | rt = rtp->t_subt->t_tspec; | | 2305 | tspec_t rt = rtp->t_subt->t_tspec; |
2323 | | | 2306 | |
2324 | if (is_struct_or_union(lt) && is_struct_or_union(rt)) { | | 2307 | if (is_struct_or_union(lt) && is_struct_or_union(rt)) { |
2325 | if (mp == NULL) { | | 2308 | if (mp == NULL) { |
2326 | /* illegal structure pointer combination */ | | 2309 | /* illegal structure pointer combination */ |
2327 | warning(244); | | 2310 | warning(244); |
2328 | } else { | | 2311 | } else { |
2329 | /* incompatible structure pointers: '%s' '%s' '%s' */ | | 2312 | /* incompatible structure pointers: '%s' '%s' '%s' */ |
2330 | warning(245, type_name(ltp), mp->m_name, type_name(rtp)); | | 2313 | warning(245, type_name(ltp), mp->m_name, type_name(rtp)); |
2331 | } | | 2314 | } |
2332 | } else { | | 2315 | } else { |
2333 | if (mp == NULL) { | | 2316 | if (mp == NULL) { |
2334 | /* illegal combination of '%s' and '%s' */ | | 2317 | /* illegal combination of '%s' and '%s' */ |
2335 | warning(184, type_name(ltp), type_name(rtp)); | | 2318 | warning(184, type_name(ltp), type_name(rtp)); |
2336 | } else { | | 2319 | } else { |
2337 | /* illegal combination of '%s' and '%s', op '%s' */ | | 2320 | /* illegal combination of '%s' and '%s', op '%s' */ |
2338 | warning(124, | | 2321 | warning(124, |
2339 | type_name(ltp), type_name(rtp), mp->m_name); | | 2322 | type_name(ltp), type_name(rtp), mp->m_name); |
2340 | } | | 2323 | } |
2341 | } | | 2324 | } |
2342 | } | | 2325 | } |
2343 | | | 2326 | |
2344 | static void | | 2327 | static void |
2345 | check_pointer_comparison(op_t op, const tnode_t *ln, const tnode_t *rn) | | 2328 | check_pointer_comparison(op_t op, const tnode_t *ln, const tnode_t *rn) |
2346 | { | | 2329 | { |
2347 | type_t *ltp, *rtp; | | 2330 | type_t *ltp = ln->tn_type, *rtp = rn->tn_type; |
2348 | tspec_t lst, rst; | | 2331 | tspec_t lst = ltp->t_subt->t_tspec, rst = rtp->t_subt->t_tspec; |
2349 | const char *lsts, *rsts; | | | |
2350 | | | | |
2351 | lst = (ltp = ln->tn_type)->t_subt->t_tspec; | | | |
2352 | rst = (rtp = rn->tn_type)->t_subt->t_tspec; | | | |
2353 | | | 2332 | |
2354 | if (lst == VOID || rst == VOID) { | | 2333 | if (lst == VOID || rst == VOID) { |
2355 | /* TODO: C99 behaves like C90 here. */ | | 2334 | /* TODO: C99 behaves like C90 here. */ |
2356 | if ((!allow_trad && !allow_c99) && | | 2335 | if ((!allow_trad && !allow_c99) && |
2357 | (lst == FUNC || rst == FUNC)) { | | 2336 | (lst == FUNC || rst == FUNC)) { |
2358 | /* (void *)0 already handled in typeok() */ | | 2337 | /* (void *)0 is already handled in typeok() */ |
| | | 2338 | const char *lsts, *rsts; |
2359 | *(lst == FUNC ? &lsts : &rsts) = "function pointer"; | | 2339 | *(lst == FUNC ? &lsts : &rsts) = "function pointer"; |
2360 | *(lst == VOID ? &lsts : &rsts) = "'void *'"; | | 2340 | *(lst == VOID ? &lsts : &rsts) = "'void *'"; |
2361 | /* ANSI C forbids comparison of %s with %s */ | | 2341 | /* ANSI C forbids comparison of %s with %s */ |
2362 | warning(274, lsts, rsts); | | 2342 | warning(274, lsts, rsts); |
2363 | } | | 2343 | } |
2364 | return; | | 2344 | return; |
2365 | } | | 2345 | } |
2366 | | | 2346 | |
2367 | if (!types_compatible(ltp->t_subt, rtp->t_subt, true, false, NULL)) { | | 2347 | if (!types_compatible(ltp->t_subt, rtp->t_subt, true, false, NULL)) { |
2368 | warn_incompatible_pointers(&modtab[op], ltp, rtp); | | 2348 | warn_incompatible_pointers(&modtab[op], ltp, rtp); |
2369 | return; | | 2349 | return; |
2370 | } | | 2350 | } |
2371 | | | 2351 | |
2372 | if (lst == FUNC && rst == FUNC) { | | 2352 | if (lst == FUNC && rst == FUNC) { |
2373 | /* TODO: C99 behaves like C90 here, see C99 6.5.8p2. */ | | 2353 | /* TODO: C99 behaves like C90 here, see C99 6.5.8p2. */ |
2374 | if ((!allow_trad && !allow_c99) && op != EQ && op != NE) | | 2354 | if ((!allow_trad && !allow_c99) && op != EQ && op != NE) |
2375 | /* ANSI C forbids ordered comparisons of ... */ | | 2355 | /* ANSI C forbids ordered comparisons of ... */ |
2376 | warning(125); | | 2356 | warning(125); |
2377 | } | | 2357 | } |
2378 | } | | 2358 | } |
2379 | | | 2359 | |
2380 | static bool | | 2360 | static bool |
2381 | typeok_compare(op_t op, | | 2361 | typeok_compare(op_t op, |
2382 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | | 2362 | const tnode_t *ln, const type_t *ltp, tspec_t lt, |
2383 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | | 2363 | const tnode_t *rn, const type_t *rtp, tspec_t rt) |
2384 | { | | 2364 | { |
2385 | const char *lx, *rx; | | | |
2386 | | | | |
2387 | if (lt == PTR && rt == PTR) { | | 2365 | if (lt == PTR && rt == PTR) { |
2388 | check_pointer_comparison(op, ln, rn); | | 2366 | check_pointer_comparison(op, ln, rn); |
2389 | return true; | | 2367 | return true; |
2390 | } | | 2368 | } |
2391 | | | 2369 | |
2392 | if (lt != PTR && rt != PTR) | | 2370 | if (lt != PTR && rt != PTR) |
2393 | return true; | | 2371 | return true; |
2394 | | | 2372 | |
2395 | if (!is_integer(lt) && !is_integer(rt)) { | | 2373 | if (!is_integer(lt) && !is_integer(rt)) { |
2396 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 2374 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
2397 | return false; | | 2375 | return false; |
2398 | } | | 2376 | } |
2399 | | | 2377 | |
2400 | lx = lt == PTR ? "pointer" : "integer"; | | 2378 | const char *lx = lt == PTR ? "pointer" : "integer"; |
2401 | rx = rt == PTR ? "pointer" : "integer"; | | 2379 | const char *rx = rt == PTR ? "pointer" : "integer"; |
2402 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ | | 2380 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ |
2403 | warning(123, lx, type_name(ltp), rx, type_name(rtp), op_name(op)); | | 2381 | warning(123, lx, type_name(ltp), rx, type_name(rtp), op_name(op)); |
2404 | return true; | | 2382 | return true; |
2405 | } | | 2383 | } |
2406 | | | 2384 | |
2407 | static bool | | 2385 | static bool |
2408 | typeok_quest(tspec_t lt, const tnode_t *rn) | | 2386 | typeok_quest(tspec_t lt, const tnode_t *rn) |
2409 | { | | 2387 | { |
2410 | if (!is_scalar(lt)) { | | 2388 | if (!is_scalar(lt)) { |
2411 | /* first operand must have scalar type, op ? : */ | | 2389 | /* first operand must have scalar type, op ? : */ |
2412 | error(170); | | 2390 | error(170); |
2413 | return false; | | 2391 | return false; |
2414 | } | | 2392 | } |
2415 | lint_assert(before_conversion(rn)->tn_op == COLON); | | 2393 | lint_assert(before_conversion(rn)->tn_op == COLON); |
2416 | return true; | | 2394 | return true; |
2417 | } | | 2395 | } |
2418 | | | 2396 | |
2419 | static void | | 2397 | static void |
2420 | typeok_colon_pointer(const mod_t *mp, const type_t *ltp, const type_t *rtp) | | 2398 | typeok_colon_pointer(const mod_t *mp, const type_t *ltp, const type_t *rtp) |
2421 | { | | 2399 | { |
2422 | type_t *lstp = ltp->t_subt; | | 2400 | type_t *lstp = ltp->t_subt; |
2423 | type_t *rstp = rtp->t_subt; | | 2401 | type_t *rstp = rtp->t_subt; |
2424 | tspec_t lst = lstp->t_tspec; | | 2402 | tspec_t lst = lstp->t_tspec; |
2425 | tspec_t rst = rstp->t_tspec; | | 2403 | tspec_t rst = rstp->t_tspec; |
2426 | | | 2404 | |
2427 | if ((lst == VOID && rst == FUNC) || (lst == FUNC && rst == VOID)) { | | 2405 | if ((lst == VOID && rst == FUNC) || (lst == FUNC && rst == VOID)) { |
2428 | /* (void *)0 is handled in typeok_colon */ | | 2406 | /* (void *)0 is handled in typeok_colon */ |
2429 | /* TODO: C99 behaves like C90 here. */ | | 2407 | /* TODO: C99 behaves like C90 here. */ |
2430 | if (!allow_trad && !allow_c99) | | 2408 | if (!allow_trad && !allow_c99) |
2431 | /* ANSI C forbids conversion of %s to %s, op %s */ | | 2409 | /* ANSI C forbids conversion of %s to %s, op %s */ |
2432 | warning(305, "function pointer", "'void *'", | | 2410 | warning(305, "function pointer", "'void *'", |
2433 | mp->m_name); | | 2411 | mp->m_name); |
2434 | return; | | 2412 | return; |
2435 | } | | 2413 | } |
2436 | | | 2414 | |
2437 | if (pointer_types_are_compatible(lstp, rstp, true)) | | 2415 | if (pointer_types_are_compatible(lstp, rstp, true)) |
2438 | return; | | 2416 | return; |
2439 | if (!types_compatible(lstp, rstp, true, false, NULL)) | | 2417 | if (!types_compatible(lstp, rstp, true, false, NULL)) |
2440 | warn_incompatible_pointers(mp, ltp, rtp); | | 2418 | warn_incompatible_pointers(mp, ltp, rtp); |
2441 | } | | 2419 | } |
2442 | | | 2420 | |
2443 | static bool | | 2421 | static bool |
2444 | typeok_colon(const mod_t *mp, | | 2422 | typeok_colon(const mod_t *mp, |
2445 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | | 2423 | const tnode_t *ln, const type_t *ltp, tspec_t lt, |
2446 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | | 2424 | const tnode_t *rn, const type_t *rtp, tspec_t rt) |
2447 | { | | 2425 | { |
2448 | | | 2426 | |
2449 | if (is_arithmetic(lt) && is_arithmetic(rt)) | | 2427 | if (is_arithmetic(lt) && is_arithmetic(rt)) |
2450 | return true; | | 2428 | return true; |
2451 | if (lt == BOOL && rt == BOOL) | | 2429 | if (lt == BOOL && rt == BOOL) |
2452 | return true; | | 2430 | return true; |
2453 | | | 2431 | |
2454 | if (lt == STRUCT && rt == STRUCT && ltp->t_str == rtp->t_str) | | 2432 | if (lt == STRUCT && rt == STRUCT && ltp->t_str == rtp->t_str) |
2455 | return true; | | 2433 | return true; |
2456 | if (lt == UNION && rt == UNION && ltp->t_str == rtp->t_str) | | 2434 | if (lt == UNION && rt == UNION && ltp->t_str == rtp->t_str) |
2457 | return true; | | 2435 | return true; |
2458 | | | 2436 | |
2459 | if (lt == PTR && is_null_pointer(rn)) | | 2437 | if (lt == PTR && is_null_pointer(rn)) |
2460 | return true; | | 2438 | return true; |
2461 | if (rt == PTR && is_null_pointer(ln)) | | 2439 | if (rt == PTR && is_null_pointer(ln)) |
2462 | return true; | | 2440 | return true; |
2463 | | | 2441 | |
2464 | if ((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)) { | | 2442 | if ((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)) { |
2465 | const char *lx = lt == PTR ? "pointer" : "integer"; | | 2443 | const char *lx = lt == PTR ? "pointer" : "integer"; |
2466 | const char *rx = rt == PTR ? "pointer" : "integer"; | | 2444 | const char *rx = rt == PTR ? "pointer" : "integer"; |
2467 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ | | 2445 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ |
2468 | warning(123, lx, type_name(ltp), | | 2446 | warning(123, lx, type_name(ltp), |
2469 | rx, type_name(rtp), mp->m_name); | | 2447 | rx, type_name(rtp), mp->m_name); |
2470 | return true; | | 2448 | return true; |
2471 | } | | 2449 | } |
2472 | | | 2450 | |
2473 | if (lt == VOID || rt == VOID) { | | 2451 | if (lt == VOID || rt == VOID) { |
2474 | if (lt != VOID || rt != VOID) | | 2452 | if (lt != VOID || rt != VOID) |
2475 | /* incompatible types '%s' and '%s' in conditional */ | | 2453 | /* incompatible types '%s' and '%s' in conditional */ |
2476 | warning(126, type_name(ltp), type_name(rtp)); | | 2454 | warning(126, type_name(ltp), type_name(rtp)); |
2477 | return true; | | 2455 | return true; |
2478 | } | | 2456 | } |
2479 | | | 2457 | |
2480 | if (lt == PTR && rt == PTR) { | | 2458 | if (lt == PTR && rt == PTR) { |
2481 | typeok_colon_pointer(mp, ltp, rtp); | | 2459 | typeok_colon_pointer(mp, ltp, rtp); |
2482 | return true; | | 2460 | return true; |
2483 | } | | 2461 | } |
2484 | | | 2462 | |
2485 | /* incompatible types '%s' and '%s' in conditional */ | | 2463 | /* incompatible types '%s' and '%s' in conditional */ |
2486 | error(126, type_name(ltp), type_name(rtp)); | | 2464 | error(126, type_name(ltp), type_name(rtp)); |
2487 | return false; | | 2465 | return false; |
2488 | } | | 2466 | } |
2489 | | | 2467 | |
2490 | /* | | 2468 | /* |
2491 | * Returns true if the given structure or union has a constant member | | 2469 | * Returns true if the given structure or union has a constant member |
2492 | * (maybe recursively). | | 2470 | * (maybe recursively). |
2493 | */ | | 2471 | */ |
2494 | static bool | | 2472 | static bool |
2495 | has_constant_member(const type_t *tp) | | 2473 | has_constant_member(const type_t *tp) |
2496 | { | | 2474 | { |
2497 | sym_t *m; | | | |
2498 | | | | |
2499 | lint_assert(is_struct_or_union(tp->t_tspec)); | | 2475 | lint_assert(is_struct_or_union(tp->t_tspec)); |
2500 | | | 2476 | |
2501 | for (m = tp->t_str->sou_first_member; m != NULL; m = m->s_next) { | | 2477 | for (sym_t *m = tp->t_str->sou_first_member; |
| | | 2478 | m != NULL; m = m->s_next) { |
2502 | const type_t *mtp = m->s_type; | | 2479 | const type_t *mtp = m->s_type; |
2503 | if (mtp->t_const) | | 2480 | if (mtp->t_const) |
2504 | return true; | | 2481 | return true; |
2505 | if (is_struct_or_union(mtp->t_tspec) && | | 2482 | if (is_struct_or_union(mtp->t_tspec) && |
2506 | has_constant_member(mtp)) | | 2483 | has_constant_member(mtp)) |
2507 | return true; | | 2484 | return true; |
2508 | } | | 2485 | } |
2509 | return false; | | 2486 | return false; |
2510 | } | | 2487 | } |
2511 | | | 2488 | |
2512 | static bool | | 2489 | static bool |
2513 | typeok_assign(op_t op, const tnode_t *ln, const type_t *ltp, tspec_t lt) | | 2490 | typeok_assign(op_t op, const tnode_t *ln, const type_t *ltp, tspec_t lt) |
2514 | { | | 2491 | { |
2515 | if (op == RETURN || op == INIT || op == FARG) | | 2492 | if (op == RETURN || op == INIT || op == FARG) |
2516 | return true; | | 2493 | return true; |
2517 | | | 2494 | |
2518 | if (!ln->tn_lvalue) { | | 2495 | if (!ln->tn_lvalue) { |
2519 | if (ln->tn_op == CVT && ln->tn_cast && | | 2496 | if (ln->tn_op == CVT && ln->tn_cast && |
2520 | ln->tn_left->tn_op == LOAD) { | | 2497 | ln->tn_left->tn_op == LOAD) { |
2521 | /* a cast does not yield an lvalue */ | | 2498 | /* a cast does not yield an lvalue */ |
2522 | error(163); | | 2499 | error(163); |
2523 | } | | 2500 | } |
2524 | /* %soperand of '%s' must be lvalue */ | | 2501 | /* %soperand of '%s' must be lvalue */ |
2525 | error(114, "left ", op_name(op)); | | 2502 | error(114, "left ", op_name(op)); |
2526 | return false; | | 2503 | return false; |
2527 | } else if (ltp->t_const || (is_struct_or_union(lt) && | | 2504 | } else if (ltp->t_const || (is_struct_or_union(lt) && |
2528 | has_constant_member(ltp))) { | | 2505 | has_constant_member(ltp))) { |
2529 | if (allow_c90) | | 2506 | if (allow_c90) |
2530 | /* %soperand of '%s' must be modifiable lvalue */ | | 2507 | /* %soperand of '%s' must be modifiable lvalue */ |
2531 | warning(115, "left ", op_name(op)); | | 2508 | warning(115, "left ", op_name(op)); |
2532 | } | | 2509 | } |
2533 | return true; | | 2510 | return true; |
2534 | } | | 2511 | } |
2535 | | | 2512 | |
2536 | /* Check the types using the information from modtab[]. */ | | 2513 | /* Check the types using the information from modtab[]. */ |
2537 | static bool | | 2514 | static bool |
2538 | typeok_scalar(op_t op, const mod_t *mp, | | 2515 | typeok_scalar(op_t op, const mod_t *mp, |
2539 | const type_t *ltp, tspec_t lt, | | 2516 | const type_t *ltp, tspec_t lt, |
2540 | const type_t *rtp, tspec_t rt) | | 2517 | const type_t *rtp, tspec_t rt) |
2541 | { | | 2518 | { |
2542 | if (mp->m_takes_bool && lt == BOOL && rt == BOOL) | | 2519 | if (mp->m_takes_bool && lt == BOOL && rt == BOOL) |
2543 | return true; | | 2520 | return true; |
2544 | if (mp->m_requires_integer) { | | 2521 | if (mp->m_requires_integer) { |
2545 | if (!is_integer(lt) || (mp->m_binary && !is_integer(rt))) { | | 2522 | if (!is_integer(lt) || (mp->m_binary && !is_integer(rt))) { |
2546 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 2523 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
2547 | return false; | | 2524 | return false; |
2548 | } | | 2525 | } |
2549 | } else if (mp->m_requires_integer_or_complex) { | | 2526 | } else if (mp->m_requires_integer_or_complex) { |
2550 | if ((!is_integer(lt) && !is_complex(lt)) || | | 2527 | if ((!is_integer(lt) && !is_complex(lt)) || |
2551 | (mp->m_binary && (!is_integer(rt) && !is_complex(rt)))) { | | 2528 | (mp->m_binary && (!is_integer(rt) && !is_complex(rt)))) { |
2552 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 2529 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
2553 | return false; | | 2530 | return false; |
2554 | } | | 2531 | } |
2555 | } else if (mp->m_requires_scalar) { | | 2532 | } else if (mp->m_requires_scalar) { |
2556 | if (!is_scalar(lt) || (mp->m_binary && !is_scalar(rt))) { | | 2533 | if (!is_scalar(lt) || (mp->m_binary && !is_scalar(rt))) { |
2557 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 2534 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
2558 | return false; | | 2535 | return false; |
2559 | } | | 2536 | } |
2560 | } else if (mp->m_requires_arith) { | | 2537 | } else if (mp->m_requires_arith) { |
2561 | if (!is_arithmetic(lt) || | | 2538 | if (!is_arithmetic(lt) || |
2562 | (mp->m_binary && !is_arithmetic(rt))) { | | 2539 | (mp->m_binary && !is_arithmetic(rt))) { |
2563 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 2540 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
2564 | return false; | | 2541 | return false; |
2565 | } | | 2542 | } |
2566 | } | | 2543 | } |
2567 | return true; | | 2544 | return true; |
2568 | } | | 2545 | } |
2569 | | | 2546 | |
2570 | static void | | 2547 | static void |
2571 | check_assign_void_pointer(op_t op, int arg, | | 2548 | check_assign_void_pointer(op_t op, int arg, |
2572 | tspec_t lt, tspec_t lst, | | 2549 | tspec_t lt, tspec_t lst, |
2573 | tspec_t rt, tspec_t rst) | | 2550 | tspec_t rt, tspec_t rst) |
2574 | { | | 2551 | { |
2575 | const char *lts, *rts; | | | |
2576 | | | 2552 | |
2577 | if (!(lt == PTR && rt == PTR && (lst == VOID || rst == VOID))) | | 2553 | if (!(lt == PTR && rt == PTR && (lst == VOID || rst == VOID))) |
2578 | return; | | 2554 | return; |
2579 | /* two pointers, at least one pointer to void */ | | 2555 | /* two pointers, at least one pointer to void */ |
2580 | | | 2556 | |
2581 | /* TODO: C99 behaves like C90 here. */ | | 2557 | /* TODO: C99 behaves like C90 here. */ |
2582 | if (!((!allow_trad && !allow_c99) && (lst == FUNC || rst == FUNC))) | | 2558 | if (!((!allow_trad && !allow_c99) && (lst == FUNC || rst == FUNC))) |
2583 | return; | | 2559 | return; |
2584 | /* comb. of ptr to func and ptr to void */ | | 2560 | /* comb. of ptr to func and ptr to void */ |
2585 | | | 2561 | |
| | | 2562 | const char *lts, *rts; |
2586 | *(lst == FUNC ? <s : &rts) = "function pointer"; | | 2563 | *(lst == FUNC ? <s : &rts) = "function pointer"; |
2587 | *(lst == VOID ? <s : &rts) = "'void *'"; | | 2564 | *(lst == VOID ? <s : &rts) = "'void *'"; |
2588 | | | 2565 | |
2589 | switch (op) { | | 2566 | switch (op) { |
2590 | case INIT: | | 2567 | case INIT: |
2591 | case RETURN: | | 2568 | case RETURN: |
2592 | /* ANSI C forbids conversion of %s to %s */ | | 2569 | /* ANSI C forbids conversion of %s to %s */ |
2593 | warning(303, rts, lts); | | 2570 | warning(303, rts, lts); |
2594 | break; | | 2571 | break; |
2595 | case FARG: | | 2572 | case FARG: |
2596 | /* ANSI C forbids conversion of %s to %s, arg #%d */ | | 2573 | /* ANSI C forbids conversion of %s to %s, arg #%d */ |
2597 | warning(304, rts, lts, arg); | | 2574 | warning(304, rts, lts, arg); |
2598 | break; | | 2575 | break; |
2599 | default: | | 2576 | default: |
2600 | /* ANSI C forbids conversion of %s to %s, op %s */ | | 2577 | /* ANSI C forbids conversion of %s to %s, op %s */ |
2601 | warning(305, rts, lts, op_name(op)); | | 2578 | warning(305, rts, lts, op_name(op)); |
2602 | break; | | 2579 | break; |
2603 | } | | 2580 | } |
2604 | } | | 2581 | } |
2605 | | | 2582 | |
2606 | static bool | | 2583 | static bool |
2607 | is_direct_function_call(const tnode_t *tn, const char **out_name) | | 2584 | is_direct_function_call(const tnode_t *tn, const char **out_name) |
2608 | { | | 2585 | { |
2609 | | | 2586 | |
2610 | if (!(tn->tn_op == CALL && | | 2587 | if (!(tn->tn_op == CALL && |
2611 | tn->tn_left->tn_op == ADDR && | | 2588 | tn->tn_left->tn_op == ADDR && |
2612 | tn->tn_left->tn_left->tn_op == NAME)) | | 2589 | tn->tn_left->tn_left->tn_op == NAME)) |
2613 | return false; | | 2590 | return false; |
2614 | | | 2591 | |
2615 | *out_name = tn->tn_left->tn_left->tn_sym->s_name; | | 2592 | *out_name = tn->tn_left->tn_left->tn_sym->s_name; |
2616 | return true; | | 2593 | return true; |
2617 | } | | 2594 | } |
2618 | | | 2595 | |
2619 | static bool | | 2596 | static bool |
2620 | is_unconst_function(const char *name) | | 2597 | is_unconst_function(const char *name) |
2621 | { | | 2598 | { |
2622 | | | 2599 | |
2623 | return strcmp(name, "memchr") == 0 || | | 2600 | return strcmp(name, "memchr") == 0 || |
2624 | strcmp(name, "strchr") == 0 || | | 2601 | strcmp(name, "strchr") == 0 || |
2625 | strcmp(name, "strpbrk") == 0 || | | 2602 | strcmp(name, "strpbrk") == 0 || |
2626 | strcmp(name, "strrchr") == 0 || | | 2603 | strcmp(name, "strrchr") == 0 || |
2627 | strcmp(name, "strstr") == 0; | | 2604 | strcmp(name, "strstr") == 0; |
2628 | } | | 2605 | } |
2629 | | | 2606 | |
2630 | static bool | | 2607 | static bool |
2631 | is_const_char_pointer(const tnode_t *tn) | | 2608 | is_const_char_pointer(const tnode_t *tn) |
2632 | { | | 2609 | { |
2633 | const type_t *tp; | | | |
2634 | | | | |
2635 | /* | | 2610 | /* |
2636 | * For traditional reasons, C99 6.4.5p5 defines that string literals | | 2611 | * For traditional reasons, C99 6.4.5p5 defines that string literals |
2637 | * have type 'char[]'. They are often implicitly converted to | | 2612 | * have type 'char[]'. They are often implicitly converted to |
2638 | * 'char *', for example when they are passed as function arguments. | | 2613 | * 'char *', for example when they are passed as function arguments. |
2639 | * | | 2614 | * |
2640 | * C99 6.4.5p6 further defines that modifying a string that is | | 2615 | * C99 6.4.5p6 further defines that modifying a string that is |
2641 | * constructed from a string literal invokes undefined behavior. | | 2616 | * constructed from a string literal invokes undefined behavior. |
2642 | * | | 2617 | * |
2643 | * Out of these reasons, string literals are treated as 'effectively | | 2618 | * Out of these reasons, string literals are treated as 'effectively |
2644 | * const' here. | | 2619 | * const' here. |
2645 | */ | | 2620 | */ |
2646 | if (tn->tn_op == CVT && | | 2621 | if (tn->tn_op == CVT && |
2647 | tn->tn_left->tn_op == ADDR && | | 2622 | tn->tn_left->tn_op == ADDR && |
2648 | tn->tn_left->tn_left->tn_op == STRING) | | 2623 | tn->tn_left->tn_left->tn_op == STRING) |
2649 | return true; | | 2624 | return true; |
2650 | | | 2625 | |
2651 | tp = before_conversion(tn)->tn_type; | | 2626 | const type_t *tp = before_conversion(tn)->tn_type; |
2652 | return tp->t_tspec == PTR && | | 2627 | return tp->t_tspec == PTR && |
2653 | tp->t_subt->t_tspec == CHAR && | | 2628 | tp->t_subt->t_tspec == CHAR && |
2654 | tp->t_subt->t_const; | | 2629 | tp->t_subt->t_const; |
2655 | } | | 2630 | } |
2656 | | | 2631 | |
2657 | static bool | | 2632 | static bool |
2658 | is_first_arg_const_char_pointer(const tnode_t *tn) | | 2633 | is_first_arg_const_char_pointer(const tnode_t *tn) |
2659 | { | | 2634 | { |
2660 | const tnode_t *an; | | 2635 | const tnode_t *an = tn->tn_right; |
2661 | | | | |
2662 | an = tn->tn_right; | | | |
2663 | if (an == NULL) | | 2636 | if (an == NULL) |
2664 | return false; | | 2637 | return false; |
2665 | | | 2638 | |
2666 | while (an->tn_right != NULL) | | 2639 | while (an->tn_right != NULL) |
2667 | an = an->tn_right; | | 2640 | an = an->tn_right; |
2668 | return is_const_char_pointer(an->tn_left); | | 2641 | return is_const_char_pointer(an->tn_left); |
2669 | } | | 2642 | } |
2670 | | | 2643 | |
2671 | static bool | | 2644 | static bool |
2672 | is_const_pointer(const tnode_t *tn) | | 2645 | is_const_pointer(const tnode_t *tn) |
2673 | { | | 2646 | { |
2674 | const type_t *tp; | | 2647 | const type_t *tp = before_conversion(tn)->tn_type; |
2675 | | | | |
2676 | tp = before_conversion(tn)->tn_type; | | | |
2677 | return tp->t_tspec == PTR && tp->t_subt->t_const; | | 2648 | return tp->t_tspec == PTR && tp->t_subt->t_const; |
2678 | } | | 2649 | } |
2679 | | | 2650 | |
2680 | static bool | | 2651 | static bool |
2681 | is_second_arg_const_pointer(const tnode_t *tn) | | 2652 | is_second_arg_const_pointer(const tnode_t *tn) |
2682 | { | | 2653 | { |
2683 | const tnode_t *an; | | 2654 | const tnode_t *an = tn->tn_right; |
2684 | | | | |
2685 | an = tn->tn_right; | | | |
2686 | if (an == NULL || an->tn_right == NULL) | | 2655 | if (an == NULL || an->tn_right == NULL) |
2687 | return false; | | 2656 | return false; |
2688 | | | 2657 | |
2689 | while (an->tn_right->tn_right != NULL) | | 2658 | while (an->tn_right->tn_right != NULL) |
2690 | an = an->tn_right; | | 2659 | an = an->tn_right; |
2691 | return is_const_pointer(an->tn_left); | | 2660 | return is_const_pointer(an->tn_left); |
2692 | } | | 2661 | } |
2693 | | | 2662 | |
2694 | static void | | 2663 | static void |
2695 | check_unconst_function(const type_t *lstp, const tnode_t *rn) | | 2664 | check_unconst_function(const type_t *lstp, const tnode_t *rn) |
2696 | { | | 2665 | { |
2697 | const char *function_name; | | 2666 | const char *function_name; |
2698 | | | 2667 | |
2699 | if (lstp->t_tspec == CHAR && !lstp->t_const && | | 2668 | if (lstp->t_tspec == CHAR && !lstp->t_const && |
2700 | is_direct_function_call(rn, &function_name) && | | 2669 | is_direct_function_call(rn, &function_name) && |
2701 | is_unconst_function(function_name) && | | 2670 | is_unconst_function(function_name) && |
2702 | is_first_arg_const_char_pointer(rn)) { | | 2671 | is_first_arg_const_char_pointer(rn)) { |
2703 | /* call to '%s' effectively discards 'const' from argument */ | | 2672 | /* call to '%s' effectively discards 'const' from argument */ |
2704 | warning(346, function_name); | | 2673 | warning(346, function_name); |
2705 | } | | 2674 | } |
2706 | | | 2675 | |
2707 | if (!lstp->t_const && | | 2676 | if (!lstp->t_const && |
2708 | is_direct_function_call(rn, &function_name) && | | 2677 | is_direct_function_call(rn, &function_name) && |
2709 | strcmp(function_name, "bsearch") == 0 && | | 2678 | strcmp(function_name, "bsearch") == 0 && |
2710 | is_second_arg_const_pointer(rn)) { | | 2679 | is_second_arg_const_pointer(rn)) { |
2711 | /* call to '%s' effectively discards 'const' from argument */ | | 2680 | /* call to '%s' effectively discards 'const' from argument */ |
2712 | warning(346, function_name); | | 2681 | warning(346, function_name); |
2713 | } | | 2682 | } |
2714 | } | | 2683 | } |
2715 | | | 2684 | |
2716 | static bool | | 2685 | static bool |
2717 | check_assign_void_pointer_compat(op_t op, int arg, | | 2686 | check_assign_void_pointer_compat(op_t op, int arg, |
2718 | const type_t *const ltp, tspec_t const lt, | | 2687 | const type_t *const ltp, tspec_t const lt, |
2719 | const type_t *const lstp, tspec_t const lst, | | 2688 | const type_t *const lstp, tspec_t const lst, |
2720 | const tnode_t *const rn, | | 2689 | const tnode_t *const rn, |
2721 | const type_t *const rtp, tspec_t const rt, | | 2690 | const type_t *const rtp, tspec_t const rt, |
2722 | const type_t *const rstp, tspec_t const rst) | | 2691 | const type_t *const rstp, tspec_t const rst) |
2723 | { | | 2692 | { |
2724 | if (!(lt == PTR && rt == PTR && (lst == VOID || rst == VOID || | | 2693 | if (!(lt == PTR && rt == PTR && (lst == VOID || rst == VOID || |
2725 | types_compatible(lstp, rstp, | | 2694 | types_compatible(lstp, rstp, |
2726 | true, false, NULL)))) | | 2695 | true, false, NULL)))) |
2727 | return false; | | 2696 | return false; |
2728 | | | 2697 | |
2729 | /* compatible pointer types (qualifiers ignored) */ | | 2698 | /* compatible pointer types (qualifiers ignored) */ |
2730 | if (allow_c90 && | | 2699 | if (allow_c90 && |
2731 | ((!lstp->t_const && rstp->t_const) || | | 2700 | ((!lstp->t_const && rstp->t_const) || |
2732 | (!lstp->t_volatile && rstp->t_volatile))) { | | 2701 | (!lstp->t_volatile && rstp->t_volatile))) { |
2733 | /* left side has not all qualifiers of right */ | | 2702 | /* left side has not all qualifiers of right */ |
2734 | switch (op) { | | 2703 | switch (op) { |
2735 | case INIT: | | 2704 | case INIT: |
2736 | case RETURN: | | 2705 | case RETURN: |
2737 | /* incompatible pointer types to '%s' and '%s' */ | | 2706 | /* incompatible pointer types to '%s' and '%s' */ |
2738 | warning(182, type_name(lstp), type_name(rstp)); | | 2707 | warning(182, type_name(lstp), type_name(rstp)); |
2739 | break; | | 2708 | break; |
2740 | case FARG: | | 2709 | case FARG: |
2741 | /* converting '%s' to incompatible '%s' ... */ | | 2710 | /* converting '%s' to incompatible '%s' ... */ |
2742 | warning(153, | | 2711 | warning(153, |
2743 | type_name(rtp), type_name(ltp), arg); | | 2712 | type_name(rtp), type_name(ltp), arg); |
2744 | break; | | 2713 | break; |
2745 | default: | | 2714 | default: |
2746 | /* operands of '%s' have incompatible pointer ... */ | | 2715 | /* operands of '%s' have incompatible pointer ... */ |
2747 | warning(128, op_name(op), | | 2716 | warning(128, op_name(op), |
2748 | type_name(lstp), type_name(rstp)); | | 2717 | type_name(lstp), type_name(rstp)); |
2749 | break; | | 2718 | break; |
2750 | } | | 2719 | } |
2751 | } | | 2720 | } |
2752 | | | 2721 | |
2753 | if (allow_c90) | | 2722 | if (allow_c90) |
2754 | check_unconst_function(lstp, rn); | | 2723 | check_unconst_function(lstp, rn); |
2755 | | | 2724 | |
2756 | return true; | | 2725 | return true; |
2757 | } | | 2726 | } |
2758 | | | 2727 | |
2759 | static bool | | 2728 | static bool |
2760 | check_assign_pointer_integer(op_t op, int arg, | | 2729 | check_assign_pointer_integer(op_t op, int arg, |
2761 | const type_t *const ltp, tspec_t const lt, | | 2730 | const type_t *const ltp, tspec_t const lt, |
2762 | const type_t *const rtp, tspec_t const rt) | | 2731 | const type_t *const rtp, tspec_t const rt) |
2763 | { | | 2732 | { |
2764 | const char *lx, *rx; | | 2733 | const char *lx, *rx; |
2765 | | | 2734 | |
2766 | if (!((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR))) | | 2735 | if (!((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR))) |
2767 | return false; | | 2736 | return false; |
2768 | | | 2737 | |
2769 | lx = lt == PTR ? "pointer" : "integer"; | | 2738 | lx = lt == PTR ? "pointer" : "integer"; |
2770 | rx = rt == PTR ? "pointer" : "integer"; | | 2739 | rx = rt == PTR ? "pointer" : "integer"; |
2771 | | | 2740 | |
2772 | switch (op) { | | 2741 | switch (op) { |
2773 | case INIT: | | 2742 | case INIT: |
2774 | case RETURN: | | 2743 | case RETURN: |
2775 | /* illegal combination of %s '%s' and %s '%s' */ | | 2744 | /* illegal combination of %s '%s' and %s '%s' */ |
2776 | warning(183, lx, type_name(ltp), rx, type_name(rtp)); | | 2745 | warning(183, lx, type_name(ltp), rx, type_name(rtp)); |
2777 | break; | | 2746 | break; |
2778 | case FARG: | | 2747 | case FARG: |
2779 | /* illegal combination of %s '%s' and %s '%s', arg #%d */ | | 2748 | /* illegal combination of %s '%s' and %s '%s', arg #%d */ |
2780 | warning(154, | | 2749 | warning(154, |
2781 | lx, type_name(ltp), rx, type_name(rtp), arg); | | 2750 | lx, type_name(ltp), rx, type_name(rtp), arg); |
2782 | break; | | 2751 | break; |
2783 | default: | | 2752 | default: |
2784 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ | | 2753 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ |
2785 | warning(123, | | 2754 | warning(123, |
2786 | lx, type_name(ltp), rx, type_name(rtp), op_name(op)); | | 2755 | lx, type_name(ltp), rx, type_name(rtp), op_name(op)); |
2787 | break; | | 2756 | break; |
2788 | } | | 2757 | } |
2789 | return true; | | 2758 | return true; |
2790 | } | | 2759 | } |
2791 | | | 2760 | |
2792 | static bool | | 2761 | static bool |
2793 | check_assign_pointer(op_t op, int arg, | | 2762 | check_assign_pointer(op_t op, int arg, |
2794 | const type_t *ltp, tspec_t lt, | | 2763 | const type_t *ltp, tspec_t lt, |
2795 | const type_t *rtp, tspec_t rt) | | 2764 | const type_t *rtp, tspec_t rt) |
2796 | { | | 2765 | { |
2797 | if (!(lt == PTR && rt == PTR)) | | 2766 | if (!(lt == PTR && rt == PTR)) |
2798 | return false; | | 2767 | return false; |
2799 | | | 2768 | |
2800 | switch (op) { | | 2769 | switch (op) { |
2801 | case RETURN: | | 2770 | case RETURN: |
2802 | warn_incompatible_pointers(NULL, ltp, rtp); | | 2771 | warn_incompatible_pointers(NULL, ltp, rtp); |
2803 | break; | | 2772 | break; |
2804 | case FARG: | | 2773 | case FARG: |
2805 | /* converting '%s' to incompatible '%s' for ... */ | | 2774 | /* converting '%s' to incompatible '%s' for ... */ |
2806 | warning(153, type_name(rtp), type_name(ltp), arg); | | 2775 | warning(153, type_name(rtp), type_name(ltp), arg); |
2807 | break; | | 2776 | break; |
2808 | default: | | 2777 | default: |
2809 | warn_incompatible_pointers(&modtab[op], ltp, rtp); | | 2778 | warn_incompatible_pointers(&modtab[op], ltp, rtp); |
2810 | break; | | 2779 | break; |
2811 | } | | 2780 | } |
2812 | return true; | | 2781 | return true; |
2813 | } | | 2782 | } |
2814 | | | 2783 | |
2815 | static void | | 2784 | static void |
2816 | warn_assign(op_t op, int arg, | | 2785 | warn_assign(op_t op, int arg, |
2817 | const type_t *ltp, tspec_t lt, | | 2786 | const type_t *ltp, tspec_t lt, |
2818 | const type_t *rtp, tspec_t rt) | | 2787 | const type_t *rtp, tspec_t rt) |
2819 | { | | 2788 | { |
2820 | switch (op) { | | 2789 | switch (op) { |
2821 | case INIT: | | 2790 | case INIT: |
2822 | /* cannot initialize '%s' from '%s' */ | | 2791 | /* cannot initialize '%s' from '%s' */ |
2823 | error(185, type_name(ltp), type_name(rtp)); | | 2792 | error(185, type_name(ltp), type_name(rtp)); |
2824 | break; | | 2793 | break; |
2825 | case RETURN: | | 2794 | case RETURN: |
2826 | /* function has return type '%s' but returns '%s' */ | | 2795 | /* function has return type '%s' but returns '%s' */ |
2827 | error(211, type_name(ltp), type_name(rtp)); | | 2796 | error(211, type_name(ltp), type_name(rtp)); |
2828 | break; | | 2797 | break; |
2829 | case FARG: | | 2798 | case FARG: |
2830 | /* passing '%s' to incompatible '%s', arg #%d */ | | 2799 | /* passing '%s' to incompatible '%s', arg #%d */ |
2831 | warning(155, type_name(rtp), type_name(ltp), arg); | | 2800 | warning(155, type_name(rtp), type_name(ltp), arg); |
2832 | break; | | 2801 | break; |
2833 | default: | | 2802 | default: |
2834 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 2803 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
2835 | break; | | 2804 | break; |
2836 | } | | 2805 | } |
2837 | } | | 2806 | } |
2838 | | | 2807 | |
2839 | /* | | 2808 | /* |
2840 | * Checks type compatibility for ASSIGN, INIT, FARG and RETURN | | 2809 | * Checks type compatibility for ASSIGN, INIT, FARG and RETURN |
2841 | * and prints warnings/errors if necessary. | | 2810 | * and prints warnings/errors if necessary. |
2842 | * Returns whether the types are (almost) compatible. | | 2811 | * Returns whether the types are (almost) compatible. |
2843 | */ | | 2812 | */ |
2844 | static bool | | 2813 | static bool |
2845 | check_assign_types_compatible(op_t op, int arg, | | 2814 | check_assign_types_compatible(op_t op, int arg, |
2846 | const tnode_t *ln, const tnode_t *rn) | | 2815 | const tnode_t *ln, const tnode_t *rn) |
2847 | { | | 2816 | { |
2848 | tspec_t lt, rt, lst = NOTSPEC, rst = NOTSPEC; | | 2817 | tspec_t lt, rt, lst = NOTSPEC, rst = NOTSPEC; |
2849 | type_t *ltp, *rtp, *lstp = NULL, *rstp = NULL; | | 2818 | type_t *ltp, *rtp, *lstp = NULL, *rstp = NULL; |
2850 | | | 2819 | |
2851 | if ((lt = (ltp = ln->tn_type)->t_tspec) == PTR) | | 2820 | if ((lt = (ltp = ln->tn_type)->t_tspec) == PTR) |
2852 | lst = (lstp = ltp->t_subt)->t_tspec; | | 2821 | lst = (lstp = ltp->t_subt)->t_tspec; |
2853 | if ((rt = (rtp = rn->tn_type)->t_tspec) == PTR) | | 2822 | if ((rt = (rtp = rn->tn_type)->t_tspec) == PTR) |
2854 | rst = (rstp = rtp->t_subt)->t_tspec; | | 2823 | rst = (rstp = rtp->t_subt)->t_tspec; |
2855 | | | 2824 | |
2856 | if (lt == BOOL && is_scalar(rt)) /* C99 6.3.1.2 */ | | 2825 | if (lt == BOOL && is_scalar(rt)) /* C99 6.3.1.2 */ |
2857 | return true; | | 2826 | return true; |
2858 | | | 2827 | |
2859 | if (is_arithmetic(lt) && (is_arithmetic(rt) || rt == BOOL)) | | 2828 | if (is_arithmetic(lt) && (is_arithmetic(rt) || rt == BOOL)) |
2860 | return true; | | 2829 | return true; |
2861 | | | 2830 | |
2862 | if (is_struct_or_union(lt) && is_struct_or_union(rt)) | | 2831 | if (is_struct_or_union(lt) && is_struct_or_union(rt)) |
2863 | /* both are struct or union */ | | 2832 | /* both are struct or union */ |
2864 | return ltp->t_str == rtp->t_str; | | 2833 | return ltp->t_str == rtp->t_str; |
2865 | | | 2834 | |
2866 | /* a null pointer may be assigned to any pointer */ | | 2835 | /* a null pointer may be assigned to any pointer */ |
2867 | if (lt == PTR && is_null_pointer(rn)) | | 2836 | if (lt == PTR && is_null_pointer(rn)) |
2868 | return true; | | 2837 | return true; |
2869 | | | 2838 | |
2870 | check_assign_void_pointer(op, arg, lt, lst, rt, rst); | | 2839 | check_assign_void_pointer(op, arg, lt, lst, rt, rst); |
2871 | | | 2840 | |
2872 | if (check_assign_void_pointer_compat(op, arg, | | 2841 | if (check_assign_void_pointer_compat(op, arg, |
2873 | ltp, lt, lstp, lst, rn, rtp, rt, rstp, rst)) | | 2842 | ltp, lt, lstp, lst, rn, rtp, rt, rstp, rst)) |
2874 | return true; | | 2843 | return true; |
2875 | | | 2844 | |
2876 | if (check_assign_pointer_integer(op, arg, ltp, lt, rtp, rt)) | | 2845 | if (check_assign_pointer_integer(op, arg, ltp, lt, rtp, rt)) |
2877 | return true; | | 2846 | return true; |
2878 | | | 2847 | |
2879 | if (check_assign_pointer(op, arg, ltp, lt, rtp, rt)) | | 2848 | if (check_assign_pointer(op, arg, ltp, lt, rtp, rt)) |
2880 | return true; | | 2849 | return true; |
2881 | | | 2850 | |
2882 | warn_assign(op, arg, ltp, lt, rtp, rt); | | 2851 | warn_assign(op, arg, ltp, lt, rtp, rt); |
2883 | return false; | | 2852 | return false; |
2884 | } | | 2853 | } |
2885 | | | 2854 | |
2886 | static bool | | 2855 | static bool |
2887 | has_side_effect(const tnode_t *tn) /* NOLINT(misc-no-recursion) */ | | 2856 | has_side_effect(const tnode_t *tn) /* NOLINT(misc-no-recursion) */ |
2888 | { | | 2857 | { |
2889 | op_t op = tn->tn_op; | | 2858 | op_t op = tn->tn_op; |
2890 | | | 2859 | |
2891 | if (modtab[op].m_has_side_effect) | | 2860 | if (modtab[op].m_has_side_effect) |
2892 | return true; | | 2861 | return true; |
2893 | | | 2862 | |
2894 | if (op == CVT && tn->tn_type->t_tspec == VOID) | | 2863 | if (op == CVT && tn->tn_type->t_tspec == VOID) |
2895 | return has_side_effect(tn->tn_left); | | 2864 | return has_side_effect(tn->tn_left); |
2896 | | | 2865 | |
2897 | /* XXX: Why not has_side_effect(tn->tn_left) as well? */ | | 2866 | /* XXX: Why not has_side_effect(tn->tn_left) as well? */ |
2898 | if (op == LOGAND || op == LOGOR) | | 2867 | if (op == LOGAND || op == LOGOR) |
2899 | return has_side_effect(tn->tn_right); | | 2868 | return has_side_effect(tn->tn_right); |
2900 | | | 2869 | |
2901 | /* XXX: Why not has_side_effect(tn->tn_left) as well? */ | | 2870 | /* XXX: Why not has_side_effect(tn->tn_left) as well? */ |
2902 | if (op == QUEST) | | 2871 | if (op == QUEST) |
2903 | return has_side_effect(tn->tn_right); | | 2872 | return has_side_effect(tn->tn_right); |
2904 | | | 2873 | |
2905 | if (op == COLON || op == COMMA) { | | 2874 | if (op == COLON || op == COMMA) { |
2906 | return has_side_effect(tn->tn_left) || | | 2875 | return has_side_effect(tn->tn_left) || |
2907 | has_side_effect(tn->tn_right); | | 2876 | has_side_effect(tn->tn_right); |
2908 | } | | 2877 | } |
2909 | | | 2878 | |
2910 | return false; | | 2879 | return false; |
2911 | } | | 2880 | } |
2912 | | | 2881 | |
2913 | static bool | | 2882 | static bool |
2914 | is_void_cast(const tnode_t *tn) | | 2883 | is_void_cast(const tnode_t *tn) |
2915 | { | | 2884 | { |
2916 | | | 2885 | |
2917 | return tn->tn_op == CVT && tn->tn_cast && | | 2886 | return tn->tn_op == CVT && tn->tn_cast && |
2918 | tn->tn_type->t_tspec == VOID; | | 2887 | tn->tn_type->t_tspec == VOID; |
2919 | } | | 2888 | } |
2920 | | | 2889 | |
2921 | static bool | | 2890 | static bool |
2922 | is_local_symbol(const tnode_t *tn) | | 2891 | is_local_symbol(const tnode_t *tn) |
2923 | { | | 2892 | { |
2924 | | | 2893 | |
2925 | return tn->tn_op == LOAD && | | 2894 | return tn->tn_op == LOAD && |
2926 | tn->tn_left->tn_op == NAME && | | 2895 | tn->tn_left->tn_op == NAME && |
2927 | tn->tn_left->tn_sym->s_scl == AUTO; | | 2896 | tn->tn_left->tn_sym->s_scl == AUTO; |
2928 | } | | 2897 | } |
2929 | | | 2898 | |
2930 | static bool | | 2899 | static bool |
2931 | is_int_constant_zero(const tnode_t *tn) | | 2900 | is_int_constant_zero(const tnode_t *tn) |
2932 | { | | 2901 | { |
2933 | | | 2902 | |
2934 | return tn->tn_op == CON && | | 2903 | return tn->tn_op == CON && |
2935 | tn->tn_type->t_tspec == INT && | | 2904 | tn->tn_type->t_tspec == INT && |
2936 | tn->tn_val->v_quad == 0; | | 2905 | tn->tn_val->v_quad == 0; |
2937 | } | | 2906 | } |
2938 | | | 2907 | |
2939 | static void | | 2908 | static void |
2940 | check_null_effect(const tnode_t *tn) | | 2909 | check_null_effect(const tnode_t *tn) |
2941 | { | | 2910 | { |
2942 | | | 2911 | |
2943 | if (!hflag) | | 2912 | if (hflag && |
2944 | return; | | 2913 | !has_side_effect(tn) && |
2945 | if (has_side_effect(tn)) | | 2914 | !(is_void_cast(tn) && is_local_symbol(tn->tn_left)) && |
2946 | return; | | 2915 | !(is_void_cast(tn) && is_int_constant_zero(tn->tn_left))) { |
2947 | if (is_void_cast(tn) && is_local_symbol(tn->tn_left)) | | 2916 | /* expression has null effect */ |
2948 | return; | | 2917 | warning(129); |
2949 | if (is_void_cast(tn) && is_int_constant_zero(tn->tn_left)) | | 2918 | } |
2950 | return; | | | |
2951 | | | | |
2952 | /* expression has null effect */ | | | |
2953 | warning(129); | | | |
2954 | } | | 2919 | } |
2955 | | | 2920 | |
2956 | /* | | 2921 | /* |
2957 | * Check the types for specific operators and type combinations. | | 2922 | * Check the types for specific operators and type combinations. |
2958 | * | | 2923 | * |
2959 | * At this point, the operands already conform to the type requirements of | | 2924 | * At this point, the operands already conform to the type requirements of |
2960 | * the operator, such as being integer, floating or scalar. | | 2925 | * the operator, such as being integer, floating or scalar. |
2961 | */ | | 2926 | */ |
2962 | static bool | | 2927 | static bool |
2963 | typeok_op(op_t op, const mod_t *mp, int arg, | | 2928 | typeok_op(op_t op, const mod_t *mp, int arg, |
2964 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | | 2929 | const tnode_t *ln, const type_t *ltp, tspec_t lt, |
2965 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | | 2930 | const tnode_t *rn, const type_t *rtp, tspec_t rt) |
2966 | { | | 2931 | { |
2967 | switch (op) { | | 2932 | switch (op) { |
2968 | case ARROW: | | 2933 | case ARROW: |
2969 | return typeok_arrow(lt); | | 2934 | return typeok_arrow(lt); |
2970 | case POINT: | | 2935 | case POINT: |
2971 | return typeok_point(ln, ltp, lt); | | 2936 | return typeok_point(ln, ltp, lt); |
2972 | case INCBEF: | | 2937 | case INCBEF: |
2973 | case DECBEF: | | 2938 | case DECBEF: |
2974 | case INCAFT: | | 2939 | case INCAFT: |
2975 | case DECAFT: | | 2940 | case DECAFT: |
2976 | return typeok_incdec(op, ln, ltp); | | 2941 | return typeok_incdec(op, ln, ltp); |
2977 | case INDIR: | | 2942 | case INDIR: |
2978 | return typeok_indir(ltp, lt); | | 2943 | return typeok_indir(ltp, lt); |
2979 | case ADDR: | | 2944 | case ADDR: |
2980 | return typeok_address(mp, ln, ltp, lt); | | 2945 | return typeok_address(mp, ln, ltp, lt); |
2981 | case PLUS: | | 2946 | case PLUS: |
2982 | return typeok_plus(op, ltp, lt, rtp, rt); | | 2947 | return typeok_plus(op, ltp, lt, rtp, rt); |
2983 | case MINUS: | | 2948 | case MINUS: |
2984 | return typeok_minus(op, ltp, lt, rtp, rt); | | 2949 | return typeok_minus(op, ltp, lt, rtp, rt); |
2985 | case SHL: | | 2950 | case SHL: |
2986 | typeok_shl(mp, lt, rt); | | 2951 | typeok_shl(mp, lt, rt); |
2987 | goto shift; | | 2952 | goto shift; |
2988 | case SHR: | | 2953 | case SHR: |
2989 | typeok_shr(mp, ln, lt, rn, rt); | | 2954 | typeok_shr(mp, ln, lt, rn, rt); |
2990 | shift: | | 2955 | shift: |
2991 | typeok_shift(ltp, lt, rn, rt); | | 2956 | typeok_shift(ltp, lt, rn, rt); |
2992 | break; | | 2957 | break; |
2993 | case LT: | | 2958 | case LT: |
2994 | case LE: | | 2959 | case LE: |
2995 | case GT: | | 2960 | case GT: |
2996 | case GE: | | 2961 | case GE: |
2997 | compare: | | 2962 | compare: |
2998 | return typeok_compare(op, ln, ltp, lt, rn, rtp, rt); | | 2963 | return typeok_compare(op, ln, ltp, lt, rn, rtp, rt); |
2999 | case EQ: | | 2964 | case EQ: |
3000 | case NE: | | 2965 | case NE: |
3001 | if (is_typeok_eq(ln, lt, rn, rt)) | | 2966 | if (is_typeok_eq(ln, lt, rn, rt)) |
3002 | break; | | 2967 | break; |
3003 | goto compare; | | 2968 | goto compare; |
3004 | case QUEST: | | 2969 | case QUEST: |
3005 | return typeok_quest(lt, rn); | | 2970 | return typeok_quest(lt, rn); |
3006 | case COLON: | | 2971 | case COLON: |
3007 | return typeok_colon(mp, ln, ltp, lt, rn, rtp, rt); | | 2972 | return typeok_colon(mp, ln, ltp, lt, rn, rtp, rt); |
3008 | case ASSIGN: | | 2973 | case ASSIGN: |
3009 | case INIT: | | 2974 | case INIT: |
3010 | case FARG: | | 2975 | case FARG: |
3011 | case RETURN: | | 2976 | case RETURN: |
3012 | if (!check_assign_types_compatible(op, arg, ln, rn)) | | 2977 | if (!check_assign_types_compatible(op, arg, ln, rn)) |
3013 | return false; | | 2978 | return false; |
3014 | goto assign; | | 2979 | goto assign; |
3015 | case MULASS: | | 2980 | case MULASS: |
3016 | case DIVASS: | | 2981 | case DIVASS: |
3017 | case MODASS: | | 2982 | case MODASS: |
3018 | goto assign; | | 2983 | goto assign; |
3019 | case ADDASS: | | 2984 | case ADDASS: |
3020 | case SUBASS: | | 2985 | case SUBASS: |
3021 | if ((lt == PTR && !is_integer(rt)) || rt == PTR) { | | 2986 | if ((lt == PTR && !is_integer(rt)) || rt == PTR) { |
3022 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 2987 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
3023 | return false; | | 2988 | return false; |
3024 | } | | 2989 | } |
3025 | goto assign; | | 2990 | goto assign; |
3026 | case SHLASS: | | 2991 | case SHLASS: |
3027 | goto assign; | | 2992 | goto assign; |
3028 | case SHRASS: | | 2993 | case SHRASS: |
3029 | if (pflag && !is_uinteger(lt) && | | 2994 | if (pflag && !is_uinteger(lt) && |
3030 | !(!allow_c90 && is_uinteger(rt))) { | | 2995 | !(!allow_c90 && is_uinteger(rt))) { |
3031 | /* bitwise '%s' on signed value possibly nonportable */ | | 2996 | /* bitwise '%s' on signed value possibly nonportable */ |
3032 | warning(117, mp->m_name); | | 2997 | warning(117, mp->m_name); |
3033 | } | | 2998 | } |
3034 | goto assign; | | 2999 | goto assign; |
3035 | case ANDASS: | | 3000 | case ANDASS: |
3036 | case XORASS: | | 3001 | case XORASS: |
3037 | case ORASS: | | 3002 | case ORASS: |
3038 | assign: | | 3003 | assign: |
3039 | return typeok_assign(op, ln, ltp, lt); | | 3004 | return typeok_assign(op, ln, ltp, lt); |
3040 | case COMMA: | | 3005 | case COMMA: |
3041 | if (!modtab[ln->tn_op].m_has_side_effect) | | 3006 | if (!modtab[ln->tn_op].m_has_side_effect) |
3042 | check_null_effect(ln); | | 3007 | check_null_effect(ln); |
3043 | break; | | 3008 | break; |
3044 | default: | | 3009 | default: |
3045 | break; | | 3010 | break; |
3046 | } | | 3011 | } |
3047 | return true; | | 3012 | return true; |
3048 | } | | 3013 | } |
3049 | | | 3014 | |
3050 | /* Prints a warning if a strange operator is used on an enum type. */ | | 3015 | /* Prints a warning if a strange operator is used on an enum type. */ |
3051 | static void | | 3016 | static void |
3052 | check_bad_enum_operation(op_t op, const tnode_t *ln, const tnode_t *rn) | | 3017 | check_bad_enum_operation(op_t op, const tnode_t *ln, const tnode_t *rn) |
3053 | { | | 3018 | { |
3054 | | | 3019 | |
3055 | if (!eflag) | | 3020 | if (!eflag) |
3056 | return; | | 3021 | return; |
3057 | | | 3022 | |
3058 | /* | | 3023 | /* |
3059 | * Enum as offset to a pointer is an exception (otherwise enums | | 3024 | * Enum as offset to a pointer is an exception (otherwise enums |
3060 | * could not be used as array indices). | | 3025 | * could not be used as array indices). |
3061 | */ | | 3026 | */ |
3062 | if (op == PLUS && | | 3027 | if (op == PLUS && |
3063 | ((ln->tn_type->t_is_enum && rn->tn_type->t_tspec == PTR) || | | 3028 | ((ln->tn_type->t_is_enum && rn->tn_type->t_tspec == PTR) || |
3064 | (rn->tn_type->t_is_enum && ln->tn_type->t_tspec == PTR))) { | | 3029 | (rn->tn_type->t_is_enum && ln->tn_type->t_tspec == PTR))) { |
3065 | return; | | 3030 | return; |
3066 | } | | 3031 | } |
3067 | | | 3032 | |
3068 | /* dubious operation on enum, op '%s' */ | | 3033 | /* dubious operation on enum, op '%s' */ |
3069 | warning(241, op_name(op)); | | 3034 | warning(241, op_name(op)); |
3070 | } | | 3035 | } |
3071 | | | 3036 | |
3072 | /* | | 3037 | /* |
3073 | * Prints a warning if an operator is applied to two different enum types. | | 3038 | * Prints a warning if an operator is applied to two different enum types. |
3074 | */ | | 3039 | */ |
3075 | static void | | 3040 | static void |
3076 | check_enum_type_mismatch(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) | | 3041 | check_enum_type_mismatch(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) |
3077 | { | | 3042 | { |
3078 | const mod_t *mp; | | 3043 | const mod_t *mp = &modtab[op]; |
3079 | | | | |
3080 | mp = &modtab[op]; | | | |
3081 | | | 3044 | |
3082 | if (ln->tn_type->t_enum != rn->tn_type->t_enum) { | | 3045 | if (ln->tn_type->t_enum != rn->tn_type->t_enum) { |
3083 | switch (op) { | | 3046 | switch (op) { |
3084 | case INIT: | | 3047 | case INIT: |
3085 | /* enum type mismatch between '%s' and '%s' in ... */ | | 3048 | /* enum type mismatch between '%s' and '%s' in ... */ |
3086 | warning(210, | | 3049 | warning(210, |
3087 | type_name(ln->tn_type), type_name(rn->tn_type)); | | 3050 | type_name(ln->tn_type), type_name(rn->tn_type)); |
3088 | break; | | 3051 | break; |
3089 | case FARG: | | 3052 | case FARG: |
3090 | /* function expects '%s', passing '%s' for arg #%d */ | | 3053 | /* function expects '%s', passing '%s' for arg #%d */ |
3091 | warning(156, | | 3054 | warning(156, |
3092 | type_name(ln->tn_type), type_name(rn->tn_type), | | 3055 | type_name(ln->tn_type), type_name(rn->tn_type), |
3093 | arg); | | 3056 | arg); |
3094 | break; | | 3057 | break; |
3095 | case RETURN: | | 3058 | case RETURN: |
3096 | /* function has return type '%s' but returns '%s' */ | | 3059 | /* function has return type '%s' but returns '%s' */ |
3097 | warning(211, | | 3060 | warning(211, |
3098 | type_name(ln->tn_type), type_name(rn->tn_type)); | | 3061 | type_name(ln->tn_type), type_name(rn->tn_type)); |
3099 | break; | | 3062 | break; |
3100 | default: | | 3063 | default: |
3101 | /* enum type mismatch: '%s' '%s' '%s' */ | | 3064 | /* enum type mismatch: '%s' '%s' '%s' */ |
3102 | warning(130, type_name(ln->tn_type), mp->m_name, | | 3065 | warning(130, type_name(ln->tn_type), mp->m_name, |
3103 | type_name(rn->tn_type)); | | 3066 | type_name(rn->tn_type)); |
3104 | break; | | 3067 | break; |
3105 | } | | 3068 | } |
3106 | } else if (Pflag && mp->m_comparison && op != EQ && op != NE) { | | 3069 | } else if (Pflag && mp->m_comparison && op != EQ && op != NE) { |
3107 | if (eflag) | | 3070 | if (eflag) |
3108 | /* dubious comparison of enums, op '%s' */ | | 3071 | /* dubious comparison of enums, op '%s' */ |
3109 | warning(243, mp->m_name); | | 3072 | warning(243, mp->m_name); |
3110 | } | | 3073 | } |
3111 | } | | 3074 | } |
3112 | | | 3075 | |
3113 | /* Prints a warning if the operands mix between enum and integer. */ | | 3076 | /* Prints a warning if the operands mix between enum and integer. */ |
3114 | static void | | 3077 | static void |
3115 | check_enum_int_mismatch(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) | | 3078 | check_enum_int_mismatch(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) |
3116 | { | | 3079 | { |
3117 | | | 3080 | |
3118 | if (!eflag) | | 3081 | if (!eflag) |
3119 | return; | | 3082 | return; |
3120 | | | 3083 | |
3121 | switch (op) { | | 3084 | switch (op) { |
3122 | case INIT: | | 3085 | case INIT: |
3123 | /* | | 3086 | /* |
3124 | * Initialization with 0 is allowed. Otherwise, all implicit | | 3087 | * Initialization with 0 is allowed. Otherwise, all implicit |
3125 | * initializations would need to be warned upon as well. | | 3088 | * initializations would need to be warned upon as well. |
3126 | */ | | 3089 | */ |
3127 | if (!rn->tn_type->t_is_enum && rn->tn_op == CON && | | 3090 | if (!rn->tn_type->t_is_enum && rn->tn_op == CON && |
3128 | is_integer(rn->tn_type->t_tspec) && | | 3091 | is_integer(rn->tn_type->t_tspec) && |
3129 | rn->tn_val->v_quad == 0) { | | 3092 | rn->tn_val->v_quad == 0) { |
3130 | return; | | 3093 | return; |
3131 | } | | 3094 | } |
3132 | /* initialization of '%s' with '%s' */ | | 3095 | /* initialization of '%s' with '%s' */ |
3133 | warning(277, type_name(ln->tn_type), type_name(rn->tn_type)); | | 3096 | warning(277, type_name(ln->tn_type), type_name(rn->tn_type)); |
3134 | break; | | 3097 | break; |
3135 | case FARG: | | 3098 | case FARG: |
3136 | /* combination of '%s' and '%s', arg #%d */ | | 3099 | /* combination of '%s' and '%s', arg #%d */ |
3137 | warning(278, | | 3100 | warning(278, |
3138 | type_name(ln->tn_type), type_name(rn->tn_type), arg); | | 3101 | type_name(ln->tn_type), type_name(rn->tn_type), arg); |
3139 | break; | | 3102 | break; |
3140 | case RETURN: | | 3103 | case RETURN: |
3141 | /* combination of '%s' and '%s' in return */ | | 3104 | /* combination of '%s' and '%s' in return */ |
3142 | warning(279, type_name(ln->tn_type), type_name(rn->tn_type)); | | 3105 | warning(279, type_name(ln->tn_type), type_name(rn->tn_type)); |
3143 | break; | | 3106 | break; |
3144 | default: | | 3107 | default: |
3145 | /* combination of '%s' and '%s', op '%s' */ | | 3108 | /* combination of '%s' and '%s', op '%s' */ |
3146 | warning(242, type_name(ln->tn_type), type_name(rn->tn_type), | | 3109 | warning(242, type_name(ln->tn_type), type_name(rn->tn_type), |
3147 | op_name(op)); | | 3110 | op_name(op)); |
3148 | break; | | 3111 | break; |
3149 | } | | 3112 | } |
3150 | } | | 3113 | } |
3151 | | | 3114 | |
3152 | static void | | 3115 | static void |
3153 | typeok_enum(op_t op, const mod_t *mp, int arg, | | 3116 | typeok_enum(op_t op, const mod_t *mp, int arg, |
3154 | const tnode_t *ln, const type_t *ltp, | | 3117 | const tnode_t *ln, const type_t *ltp, |
3155 | const tnode_t *rn, const type_t *rtp) | | 3118 | const tnode_t *rn, const type_t *rtp) |
3156 | { | | 3119 | { |
3157 | if (mp->m_bad_on_enum && | | 3120 | if (mp->m_bad_on_enum && |
3158 | (ltp->t_is_enum || (mp->m_binary && rtp->t_is_enum))) { | | 3121 | (ltp->t_is_enum || (mp->m_binary && rtp->t_is_enum))) { |
3159 | check_bad_enum_operation(op, ln, rn); | | 3122 | check_bad_enum_operation(op, ln, rn); |
3160 | } else if (mp->m_valid_on_enum && | | 3123 | } else if (mp->m_valid_on_enum && |
3161 | (ltp->t_is_enum && rtp != NULL && rtp->t_is_enum)) { | | 3124 | (ltp->t_is_enum && rtp != NULL && rtp->t_is_enum)) { |
3162 | check_enum_type_mismatch(op, arg, ln, rn); | | 3125 | check_enum_type_mismatch(op, arg, ln, rn); |
3163 | } else if (mp->m_valid_on_enum && | | 3126 | } else if (mp->m_valid_on_enum && |
3164 | (ltp->t_is_enum || (rtp != NULL && rtp->t_is_enum))) { | | 3127 | (ltp->t_is_enum || (rtp != NULL && rtp->t_is_enum))) { |
3165 | check_enum_int_mismatch(op, arg, ln, rn); | | 3128 | check_enum_int_mismatch(op, arg, ln, rn); |
3166 | } | | 3129 | } |
3167 | } | | 3130 | } |
3168 | | | 3131 | |
3169 | /* Perform most type checks. Return whether the types are ok. */ | | 3132 | /* Perform most type checks. Return whether the types are ok. */ |
3170 | bool | | 3133 | bool |
3171 | typeok(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) | | 3134 | typeok(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) |
3172 | { | | 3135 | { |
3173 | const mod_t *mp; | | | |
3174 | tspec_t lt, rt; | | 3136 | tspec_t lt, rt; |
3175 | type_t *ltp, *rtp; | | 3137 | type_t *ltp, *rtp; |
3176 | | | 3138 | |
3177 | mp = &modtab[op]; | | 3139 | const mod_t *mp = &modtab[op]; |
3178 | | | 3140 | |
3179 | lint_assert((ltp = ln->tn_type) != NULL); | | 3141 | lint_assert((ltp = ln->tn_type) != NULL); |
3180 | lt = ltp->t_tspec; | | 3142 | lt = ltp->t_tspec; |
3181 | | | 3143 | |
3182 | if (mp->m_binary) { | | 3144 | if (mp->m_binary) { |
3183 | lint_assert((rtp = rn->tn_type) != NULL); | | 3145 | lint_assert((rtp = rn->tn_type) != NULL); |
3184 | rt = rtp->t_tspec; | | 3146 | rt = rtp->t_tspec; |
3185 | } else { | | 3147 | } else { |
3186 | rtp = NULL; | | 3148 | rtp = NULL; |
3187 | rt = NOTSPEC; | | 3149 | rt = NOTSPEC; |
3188 | } | | 3150 | } |
3189 | | | 3151 | |
3190 | if (Tflag && !typeok_scalar_strict_bool(op, mp, arg, ln, rn)) | | 3152 | if (Tflag && !typeok_scalar_strict_bool(op, mp, arg, ln, rn)) |
3191 | return false; | | 3153 | return false; |
3192 | if (!typeok_scalar(op, mp, ltp, lt, rtp, rt)) | | 3154 | if (!typeok_scalar(op, mp, ltp, lt, rtp, rt)) |
3193 | return false; | | 3155 | return false; |
3194 | | | 3156 | |
3195 | if (!typeok_op(op, mp, arg, ln, ltp, lt, rn, rtp, rt)) | | 3157 | if (!typeok_op(op, mp, arg, ln, ltp, lt, rn, rtp, rt)) |
3196 | return false; | | 3158 | return false; |
3197 | | | 3159 | |
3198 | typeok_enum(op, mp, arg, ln, ltp, rn, rtp); | | 3160 | typeok_enum(op, mp, arg, ln, ltp, rn, rtp); |
3199 | return true; | | 3161 | return true; |
3200 | } | | 3162 | } |
3201 | | | 3163 | |
3202 | /* In traditional C, keep unsigned and promote FLOAT to DOUBLE. */ | | 3164 | /* In traditional C, keep unsigned and promote FLOAT to DOUBLE. */ |
3203 | static tspec_t | | 3165 | static tspec_t |
3204 | promote_trad(tspec_t t) | | 3166 | promote_trad(tspec_t t) |
3205 | { | | 3167 | { |
3206 | | | 3168 | |
3207 | if (t == UCHAR || t == USHORT) | | 3169 | if (t == UCHAR || t == USHORT) |
3208 | return UINT; | | 3170 | return UINT; |
3209 | if (t == CHAR || t == SCHAR || t == SHORT) | | 3171 | if (t == CHAR || t == SCHAR || t == SHORT) |
3210 | return INT; | | 3172 | return INT; |
3211 | if (t == FLOAT) | | 3173 | if (t == FLOAT) |
3212 | return DOUBLE; | | 3174 | return DOUBLE; |
3213 | if (t == ENUM) | | 3175 | if (t == ENUM) |
3214 | return INT; | | 3176 | return INT; |
3215 | return t; | | 3177 | return t; |
3216 | } | | 3178 | } |
3217 | | | 3179 | |
3218 | /* | | 3180 | /* |
3219 | * C99 6.3.1.1p2 requires for types with lower rank than int that "If an int | | 3181 | * C99 6.3.1.1p2 requires for types with lower rank than int that "If an int |
3220 | * can represent all the values of the original type, the value is converted | | 3182 | * can represent all the values of the original type, the value is converted |
3221 | * to an int; otherwise it is converted to an unsigned int", and that "All | | 3183 | * to an int; otherwise it is converted to an unsigned int", and that "All |
3222 | * other types are unchanged by the integer promotions". | | 3184 | * other types are unchanged by the integer promotions". |
3223 | */ | | 3185 | */ |
3224 | static tspec_t | | 3186 | static tspec_t |
3225 | promote_c90(const tnode_t *tn, tspec_t t, bool farg) | | 3187 | promote_c90(const tnode_t *tn, tspec_t t, bool farg) |
3226 | { | | 3188 | { |
3227 | if (tn->tn_type->t_bitfield) { | | 3189 | if (tn->tn_type->t_bitfield) { |
3228 | unsigned int len = tn->tn_type->t_flen; | | 3190 | unsigned int len = tn->tn_type->t_flen; |
3229 | if (len < size_in_bits(INT)) | | 3191 | if (len < size_in_bits(INT)) |
3230 | return INT; | | 3192 | return INT; |
3231 | if (len == size_in_bits(INT)) | | 3193 | if (len == size_in_bits(INT)) |
3232 | return is_uinteger(t) ? UINT : INT; | | 3194 | return is_uinteger(t) ? UINT : INT; |
3233 | return t; | | 3195 | return t; |
3234 | } | | 3196 | } |
3235 | | | 3197 | |
3236 | if (t == CHAR || t == SCHAR) | | 3198 | if (t == CHAR || t == SCHAR) |
3237 | return INT; | | 3199 | return INT; |
3238 | if (t == UCHAR) | | 3200 | if (t == UCHAR) |
3239 | return size_in_bits(CHAR) < size_in_bits(INT) ? INT : UINT; | | 3201 | return size_in_bits(CHAR) < size_in_bits(INT) ? INT : UINT; |
3240 | if (t == SHORT) | | 3202 | if (t == SHORT) |
3241 | return INT; | | 3203 | return INT; |
3242 | if (t == USHORT) | | 3204 | if (t == USHORT) |
3243 | return size_in_bits(SHORT) < size_in_bits(INT) ? INT : UINT; | | 3205 | return size_in_bits(SHORT) < size_in_bits(INT) ? INT : UINT; |
3244 | if (t == ENUM) | | 3206 | if (t == ENUM) |
3245 | return INT; | | 3207 | return INT; |
3246 | if (farg && t == FLOAT) | | 3208 | if (farg && t == FLOAT) |
3247 | return DOUBLE; | | 3209 | return DOUBLE; |
3248 | return t; | | 3210 | return t; |
3249 | } | | 3211 | } |
3250 | | | 3212 | |
3251 | /* | | 3213 | /* |
3252 | * Performs the "integer promotions" (C99 6.3.1.1p2), which convert small | | 3214 | * Performs the "integer promotions" (C99 6.3.1.1p2), which convert small |
3253 | * integer types to either int or unsigned int. | | 3215 | * integer types to either int or unsigned int. |
3254 | * | | 3216 | * |
3255 | * If allow_c90 is unset or the operand is a function argument with no type | | 3217 | * If allow_c90 is unset or the operand is a function argument with no type |
3256 | * information (no prototype or variable # of args), converts float to double. | | 3218 | * information (no prototype or variable # of args), converts float to double. |
3257 | */ | | 3219 | */ |
3258 | tnode_t * | | 3220 | tnode_t * |
3259 | promote(op_t op, bool farg, tnode_t *tn) | | 3221 | promote(op_t op, bool farg, tnode_t *tn) |
3260 | { | | 3222 | { |
3261 | | | 3223 | |
3262 | tspec_t ot = tn->tn_type->t_tspec; | | 3224 | tspec_t ot = tn->tn_type->t_tspec; |
3263 | if (!is_arithmetic(ot)) | | 3225 | if (!is_arithmetic(ot)) |
3264 | return tn; | | 3226 | return tn; |
3265 | | | 3227 | |
3266 | tspec_t nt = allow_c90 ? promote_c90(tn, ot, farg) : promote_trad(ot); | | 3228 | tspec_t nt = allow_c90 ? promote_c90(tn, ot, farg) : promote_trad(ot); |
3267 | if (nt == ot) | | 3229 | if (nt == ot) |
3268 | return tn; | | 3230 | return tn; |
3269 | | | 3231 | |
3270 | type_t *ntp = expr_dup_type(tn->tn_type); | | 3232 | type_t *ntp = expr_dup_type(tn->tn_type); |
3271 | ntp->t_tspec = nt; | | 3233 | ntp->t_tspec = nt; |
3272 | /* | | 3234 | /* |
3273 | * Keep t_is_enum even though t_tspec gets converted from | | 3235 | * Keep t_is_enum even though t_tspec gets converted from |
3274 | * ENUM to INT, so we are later able to check compatibility | | 3236 | * ENUM to INT, so we are later able to check compatibility |
3275 | * of enum types. | | 3237 | * of enum types. |
3276 | */ | | 3238 | */ |
3277 | return convert(op, 0, ntp, tn); | | 3239 | return convert(op, 0, ntp, tn); |
3278 | } | | 3240 | } |
3279 | | | 3241 | |
3280 | static void | | 3242 | static void |
3281 | convert_integer_from_floating(op_t op, const type_t *tp, const tnode_t *tn) | | 3243 | convert_integer_from_floating(op_t op, const type_t *tp, const tnode_t *tn) |
3282 | { | | 3244 | { |
3283 | | | 3245 | |
3284 | if (op == CVT) | | 3246 | if (op == CVT) |
3285 | /* cast from floating point '%s' to integer '%s' */ | | 3247 | /* cast from floating point '%s' to integer '%s' */ |
3286 | query_message(2, type_name(tn->tn_type), type_name(tp)); | | 3248 | query_message(2, type_name(tn->tn_type), type_name(tp)); |
3287 | else | | 3249 | else |
3288 | /* implicit conversion from floating point '%s' to ... */ | | 3250 | /* implicit conversion from floating point '%s' to ... */ |
3289 | query_message(1, type_name(tn->tn_type), type_name(tp)); | | 3251 | query_message(1, type_name(tn->tn_type), type_name(tp)); |
3290 | } | | 3252 | } |
3291 | | | 3253 | |
3292 | static bool | | 3254 | static bool |
3293 | should_warn_about_prototype_conversion(tspec_t nt, | | 3255 | should_warn_about_prototype_conversion(tspec_t nt, |
3294 | tspec_t ot, const tnode_t *ptn) | | 3256 | tspec_t ot, const tnode_t *ptn) |
3295 | { | | 3257 | { |
3296 | | | 3258 | |
3297 | if (nt == ot) | | 3259 | if (nt == ot) |
3298 | return false; | | 3260 | return false; |
3299 | | | 3261 | |
3300 | if (nt == ENUM && ot == INT) | | 3262 | if (nt == ENUM && ot == INT) |
3301 | return false; | | 3263 | return false; |
3302 | | | 3264 | |
3303 | if (is_floating(nt) != is_floating(ot) || | | 3265 | if (is_floating(nt) != is_floating(ot) || |
3304 | portable_size_in_bits(nt) != portable_size_in_bits(ot)) { | | 3266 | portable_size_in_bits(nt) != portable_size_in_bits(ot)) { |
3305 | /* representation and/or width change */ | | 3267 | /* representation and/or width change */ |
3306 | if (!is_integer(ot)) | | 3268 | if (!is_integer(ot)) |
3307 | return true; | | 3269 | return true; |
3308 | /* | | 3270 | /* |
3309 | * XXX: Investigate whether this rule makes sense; see | | 3271 | * XXX: Investigate whether this rule makes sense; see |
3310 | * tests/usr.bin/xlint/lint1/platform_long.c. | | 3272 | * tests/usr.bin/xlint/lint1/platform_long.c. |
3311 | */ | | 3273 | */ |
3312 | return portable_size_in_bits(ot) > portable_size_in_bits(INT); | | 3274 | return portable_size_in_bits(ot) > portable_size_in_bits(INT); |
3313 | } | | 3275 | } |
3314 | | | 3276 | |
3315 | if (!hflag) | | 3277 | if (!hflag) |
3316 | return false; | | 3278 | return false; |
3317 | | | 3279 | |
3318 | /* | | 3280 | /* |
3319 | * If the types differ only in sign and the argument has the same | | 3281 | * If the types differ only in sign and the argument has the same |
3320 | * representation in both types, print no warning. | | 3282 | * representation in both types, print no warning. |
3321 | */ | | 3283 | */ |
3322 | if (ptn->tn_op == CON && is_integer(nt) && | | 3284 | if (ptn->tn_op == CON && is_integer(nt) && |
3323 | signed_type(nt) == signed_type(ot) && | | 3285 | signed_type(nt) == signed_type(ot) && |
3324 | !msb(ptn->tn_val->v_quad, ot)) | | 3286 | !msb(ptn->tn_val->v_quad, ot)) |
3325 | return false; | | 3287 | return false; |
3326 | | | 3288 | |
3327 | return true; | | 3289 | return true; |
3328 | } | | 3290 | } |
3329 | | | 3291 | |
3330 | /* | | 3292 | /* |
3331 | * Warn if a prototype causes a type conversion that is different from what | | 3293 | * Warn if a prototype causes a type conversion that is different from what |
3332 | * would happen to the same argument in the absence of a prototype. This | | 3294 | * would happen to the same argument in the absence of a prototype. This |
3333 | * check is intended for code that needs to stay compatible with pre-C90 C. | | 3295 | * check is intended for code that needs to stay compatible with pre-C90 C. |
3334 | * | | 3296 | * |
3335 | * Errors/warnings about illegal type combinations are already printed | | 3297 | * Errors/warnings about illegal type combinations are already printed |
3336 | * in check_assign_types_compatible(). | | 3298 | * in check_assign_types_compatible(). |
3337 | */ | | 3299 | */ |
3338 | static void | | 3300 | static void |
3339 | check_prototype_conversion(int arg, tspec_t nt, tspec_t ot, type_t *tp, | | 3301 | check_prototype_conversion(int arg, tspec_t nt, tspec_t ot, type_t *tp, |
3340 | tnode_t *tn) | | 3302 | tnode_t *tn) |
3341 | { | | 3303 | { |
3342 | tnode_t *ptn; | | | |
3343 | | | 3304 | |
3344 | if (!is_arithmetic(nt) || !is_arithmetic(ot)) | | 3305 | if (!is_arithmetic(nt) || !is_arithmetic(ot)) |
3345 | return; | | 3306 | return; |
3346 | | | 3307 | |
3347 | /* | | 3308 | /* |
3348 | * If the type of the formal parameter is char/short, a warning | | 3309 | * If the type of the formal parameter is char/short, a warning |
3349 | * would be useless, because functions declared the old style | | 3310 | * would be useless, because functions declared the old style |
3350 | * can't expect char/short arguments. | | 3311 | * can't expect char/short arguments. |
3351 | */ | | 3312 | */ |
3352 | if (nt == CHAR || nt == SCHAR || nt == UCHAR || | | 3313 | if (nt == CHAR || nt == SCHAR || nt == UCHAR || |
3353 | nt == SHORT || nt == USHORT) | | 3314 | nt == SHORT || nt == USHORT) |
3354 | return; | | 3315 | return; |
3355 | | | 3316 | |
3356 | /* apply the default promotion */ | | 3317 | /* apply the default promotion */ |
3357 | ptn = promote(NOOP, true, tn); | | 3318 | tnode_t *ptn = promote(NOOP, true, tn); |
3358 | ot = ptn->tn_type->t_tspec; | | 3319 | ot = ptn->tn_type->t_tspec; |
3359 | | | 3320 | |
3360 | if (should_warn_about_prototype_conversion(nt, ot, ptn)) { | | 3321 | if (should_warn_about_prototype_conversion(nt, ot, ptn)) { |
3361 | /* argument #%d is converted from '%s' to '%s' ... */ | | 3322 | /* argument #%d is converted from '%s' to '%s' ... */ |
3362 | warning(259, arg, type_name(tn->tn_type), type_name(tp)); | | 3323 | warning(259, arg, type_name(tn->tn_type), type_name(tp)); |
3363 | } | | 3324 | } |
3364 | } | | 3325 | } |
3365 | | | 3326 | |
3366 | /* | | 3327 | /* |
3367 | * When converting a large integer type to a small integer type, in some | | 3328 | * When converting a large integer type to a small integer type, in some |
3368 | * cases the value of the actual expression is further restricted than the | | 3329 | * cases the value of the actual expression is further restricted than the |
3369 | * type bounds, such as in (expr & 0xFF) or (expr % 100) or (expr >> 24). | | 3330 | * type bounds, such as in (expr & 0xFF) or (expr % 100) or (expr >> 24). |
3370 | */ | | 3331 | */ |
3371 | static bool | | 3332 | static bool |
3372 | can_represent(const type_t *tp, const tnode_t *tn) | | 3333 | can_represent(const type_t *tp, const tnode_t *tn) |
3373 | { | | 3334 | { |
3374 | | | 3335 | |
3375 | debug_step("%s: type '%s'", __func__, type_name(tp)); | | 3336 | debug_step("%s: type '%s'", __func__, type_name(tp)); |
3376 | debug_node(tn); | | 3337 | debug_node(tn); |
3377 | | | 3338 | |
3378 | uint64_t nmask = value_bits(width_in_bits(tp)); | | 3339 | uint64_t nmask = value_bits(width_in_bits(tp)); |
3379 | if (!is_uinteger(tp->t_tspec)) | | 3340 | if (!is_uinteger(tp->t_tspec)) |
3380 | nmask >>= 1; | | 3341 | nmask >>= 1; |
3381 | | | 3342 | |
3382 | integer_constraints c = ic_expr(tn); | | 3343 | integer_constraints c = ic_expr(tn); |
3383 | if ((~c.bclr & ~nmask) == 0) | | 3344 | if ((~c.bclr & ~nmask) == 0) |
3384 | return true; | | 3345 | return true; |
3385 | | | 3346 | |
3386 | return false; | | 3347 | return false; |
3387 | } | | 3348 | } |
3388 | | | 3349 | |
3389 | static void | | 3350 | static void |
3390 | convert_integer_from_integer(op_t op, int arg, tspec_t nt, tspec_t ot, | | 3351 | convert_integer_from_integer(op_t op, int arg, tspec_t nt, tspec_t ot, |
3391 | type_t *tp, tnode_t *tn) | | 3352 | type_t *tp, tnode_t *tn) |
3392 | { | | 3353 | { |
3393 | | | 3354 | |
3394 | if (tn->tn_op == CON) | | 3355 | if (tn->tn_op == CON) |
3395 | return; | | 3356 | return; |
3396 | | | 3357 | |
3397 | if (op == CVT) | | 3358 | if (op == CVT) |
3398 | return; | | 3359 | return; |
3399 | | | 3360 | |
3400 | if (Pflag && pflag && aflag > 0 && | | 3361 | if (Pflag && pflag && aflag > 0 && |
3401 | portable_size_in_bits(nt) > portable_size_in_bits(ot) && | | 3362 | portable_size_in_bits(nt) > portable_size_in_bits(ot) && |
3402 | is_uinteger(nt) != is_uinteger(ot)) { | | 3363 | is_uinteger(nt) != is_uinteger(ot)) { |
3403 | if (op == FARG) { | | 3364 | if (op == FARG) { |
3404 | /* conversion to '%s' may sign-extend ... */ | | 3365 | /* conversion to '%s' may sign-extend ... */ |
3405 | warning(297, type_name(tp), arg); | | 3366 | warning(297, type_name(tp), arg); |
3406 | } else { | | 3367 | } else { |
3407 | /* conversion to '%s' may sign-extend ... */ | | 3368 | /* conversion to '%s' may sign-extend ... */ |
3408 | warning(131, type_name(tp)); | | 3369 | warning(131, type_name(tp)); |
3409 | } | | 3370 | } |
3410 | } | | 3371 | } |
3411 | | | 3372 | |
3412 | if (Pflag && portable_size_in_bits(nt) > portable_size_in_bits(ot) && | | 3373 | if (Pflag && portable_size_in_bits(nt) > portable_size_in_bits(ot) && |
3413 | (tn->tn_op == PLUS || tn->tn_op == MINUS || tn->tn_op == MULT || | | 3374 | (tn->tn_op == PLUS || tn->tn_op == MINUS || tn->tn_op == MULT || |
3414 | tn->tn_op == SHL)) { | | 3375 | tn->tn_op == SHL)) { |
3415 | /* suggest cast from '%s' to '%s' on op '%s' to ... */ | | 3376 | /* suggest cast from '%s' to '%s' on op '%s' to ... */ |
3416 | warning(324, type_name(gettyp(ot)), type_name(tp), | | 3377 | warning(324, type_name(gettyp(ot)), type_name(tp), |
3417 | op_name(tn->tn_op)); | | 3378 | op_name(tn->tn_op)); |
3418 | } | | 3379 | } |
3419 | | | 3380 | |
3420 | if (aflag > 0 && | | 3381 | if (aflag > 0 && |
3421 | portable_size_in_bits(nt) < portable_size_in_bits(ot) && | | 3382 | portable_size_in_bits(nt) < portable_size_in_bits(ot) && |
3422 | (ot == LONG || ot == ULONG || ot == QUAD || ot == UQUAD || | | 3383 | (ot == LONG || ot == ULONG || ot == QUAD || ot == UQUAD || |
3423 | aflag > 1) && | | 3384 | aflag > 1) && |
3424 | !can_represent(tp, tn)) { | | 3385 | !can_represent(tp, tn)) { |
3425 | if (op == FARG) { | | 3386 | if (op == FARG) { |
3426 | /* conversion from '%s' to '%s' may lose ... */ | | 3387 | /* conversion from '%s' to '%s' may lose ... */ |
3427 | warning(298, | | 3388 | warning(298, |
3428 | type_name(tn->tn_type), type_name(tp), arg); | | 3389 | type_name(tn->tn_type), type_name(tp), arg); |
3429 | } else { | | 3390 | } else { |
3430 | /* conversion from '%s' to '%s' may lose accuracy */ | | 3391 | /* conversion from '%s' to '%s' may lose accuracy */ |
3431 | warning(132, | | 3392 | warning(132, |
3432 | type_name(tn->tn_type), type_name(tp)); | | 3393 | type_name(tn->tn_type), type_name(tp)); |
3433 | } | | 3394 | } |
3434 | } | | 3395 | } |
3435 | | | 3396 | |
3436 | if (is_uinteger(nt) != is_uinteger(ot)) | | 3397 | if (is_uinteger(nt) != is_uinteger(ot)) |
3437 | /* implicit conversion changes sign from '%s' to '%s' */ | | 3398 | /* implicit conversion changes sign from '%s' to '%s' */ |
3438 | query_message(3, type_name(tn->tn_type), type_name(tp)); | | 3399 | query_message(3, type_name(tn->tn_type), type_name(tp)); |
3439 | } | | 3400 | } |
3440 | | | 3401 | |
3441 | static void | | 3402 | static void |
3442 | convert_integer_from_pointer(op_t op, tspec_t nt, type_t *tp, tnode_t *tn) | | 3403 | convert_integer_from_pointer(op_t op, tspec_t nt, type_t *tp, tnode_t *tn) |
3443 | { | | 3404 | { |
3444 | | | 3405 | |
3445 | if (tn->tn_op == CON) | | 3406 | if (tn->tn_op == CON) |
3446 | return; | | 3407 | return; |
3447 | if (op != CVT) | | 3408 | if (op != CVT) |
3448 | return; /* We got already an error. */ | | 3409 | return; /* We got already an error. */ |
3449 | if (portable_size_in_bits(nt) >= portable_size_in_bits(PTR)) | | 3410 | if (portable_size_in_bits(nt) >= portable_size_in_bits(PTR)) |
3450 | return; | | 3411 | return; |
3451 | | | 3412 | |
3452 | if (pflag && size_in_bits(nt) >= size_in_bits(PTR)) { | | 3413 | if (pflag && size_in_bits(nt) >= size_in_bits(PTR)) { |
3453 | /* conversion of pointer to '%s' may lose bits */ | | 3414 | /* conversion of pointer to '%s' may lose bits */ |
3454 | warning(134, type_name(tp)); | | 3415 | warning(134, type_name(tp)); |
3455 | } else { | | 3416 | } else { |
3456 | /* conversion of pointer to '%s' loses bits */ | | 3417 | /* conversion of pointer to '%s' loses bits */ |
3457 | warning(133, type_name(tp)); | | 3418 | warning(133, type_name(tp)); |
3458 | } | | 3419 | } |
3459 | } | | 3420 | } |
3460 | | | 3421 | |
3461 | static bool | | 3422 | static bool |
3462 | struct_starts_with(const type_t *struct_tp, const type_t *member_tp) | | 3423 | struct_starts_with(const type_t *struct_tp, const type_t *member_tp) |
3463 | { | | 3424 | { |
3464 | | | 3425 | |
3465 | return struct_tp->t_str->sou_first_member != NULL && | | 3426 | return struct_tp->t_str->sou_first_member != NULL && |
3466 | types_compatible(struct_tp->t_str->sou_first_member->s_type, | | 3427 | types_compatible(struct_tp->t_str->sou_first_member->s_type, |
3467 | member_tp, true, false, NULL); | | 3428 | member_tp, true, false, NULL); |
3468 | } | | 3429 | } |
3469 | | | 3430 | |
3470 | static bool | | 3431 | static bool |
3471 | is_byte_array(const type_t *tp) | | 3432 | is_byte_array(const type_t *tp) |
3472 | { | | 3433 | { |
3473 | | | 3434 | |
3474 | return tp->t_tspec == ARRAY && | | 3435 | return tp->t_tspec == ARRAY && |
3475 | (tp->t_subt->t_tspec == CHAR || tp->t_subt->t_tspec == UCHAR); | | 3436 | (tp->t_subt->t_tspec == CHAR || tp->t_subt->t_tspec == UCHAR); |
3476 | } | | 3437 | } |
3477 | | | 3438 | |
3478 | static bool | | 3439 | static bool |
3479 | should_warn_about_pointer_cast(const type_t *nstp, tspec_t nst, | | 3440 | should_warn_about_pointer_cast(const type_t *nstp, tspec_t nst, |
3480 | const type_t *ostp, tspec_t ost) | | 3441 | const type_t *ostp, tspec_t ost) |
3481 | { | | 3442 | { |
3482 | | | 3443 | |
3483 | while (nst == ARRAY) | | 3444 | while (nst == ARRAY) |
3484 | nstp = nstp->t_subt, nst = nstp->t_tspec; | | 3445 | nstp = nstp->t_subt, nst = nstp->t_tspec; |
3485 | while (ost == ARRAY) | | 3446 | while (ost == ARRAY) |
3486 | ostp = ostp->t_subt, ost = ostp->t_tspec; | | 3447 | ostp = ostp->t_subt, ost = ostp->t_tspec; |
3487 | | | 3448 | |
3488 | if (nst == STRUCT && ost == STRUCT && | | 3449 | if (nst == STRUCT && ost == STRUCT && |
3489 | (struct_starts_with(nstp, ostp) || | | 3450 | (struct_starts_with(nstp, ostp) || |
3490 | struct_starts_with(ostp, nstp))) | | 3451 | struct_starts_with(ostp, nstp))) |
3491 | return false; | | 3452 | return false; |
3492 | | | 3453 | |
3493 | if (is_incomplete(nstp) || is_incomplete(ostp)) | | 3454 | if (is_incomplete(nstp) || is_incomplete(ostp)) |
3494 | return false; | | 3455 | return false; |
3495 | | | 3456 | |
3496 | if (nst == CHAR || nst == UCHAR) | | 3457 | if (nst == CHAR || nst == UCHAR) |
3497 | return false; /* for the sake of traditional C code */ | | 3458 | return false; /* for the sake of traditional C code */ |
3498 | if (ost == CHAR || ost == UCHAR) | | 3459 | if (ost == CHAR || ost == UCHAR) |
3499 | return false; /* for the sake of traditional C code */ | | 3460 | return false; /* for the sake of traditional C code */ |
3500 | | | 3461 | |
3501 | /* Allow cast between pointers to sockaddr variants. */ | | 3462 | /* Allow cast between pointers to sockaddr variants. */ |
3502 | if (nst == STRUCT && ost == STRUCT) { | | 3463 | if (nst == STRUCT && ost == STRUCT) { |
3503 | debug_type(nstp); | | 3464 | debug_type(nstp); |
3504 | debug_type(ostp); | | 3465 | debug_type(ostp); |
3505 | const sym_t *nmem = nstp->t_str->sou_first_member; | | 3466 | const sym_t *nmem = nstp->t_str->sou_first_member; |
3506 | const sym_t *omem = ostp->t_str->sou_first_member; | | 3467 | const sym_t *omem = ostp->t_str->sou_first_member; |
3507 | while (nmem != NULL && omem != NULL && | | 3468 | while (nmem != NULL && omem != NULL && |
3508 | types_compatible(nmem->s_type, omem->s_type, | | 3469 | types_compatible(nmem->s_type, omem->s_type, |
3509 | true, false, NULL)) | | 3470 | true, false, NULL)) |
3510 | nmem = nmem->s_next, omem = omem->s_next; | | 3471 | nmem = nmem->s_next, omem = omem->s_next; |
3511 | if (nmem != NULL && is_byte_array(nmem->s_type)) | | 3472 | if (nmem != NULL && is_byte_array(nmem->s_type)) |
3512 | return false; | | 3473 | return false; |
3513 | if (omem != NULL && is_byte_array(omem->s_type)) | | 3474 | if (omem != NULL && is_byte_array(omem->s_type)) |
3514 | return false; | | 3475 | return false; |
3515 | if (nmem == NULL && omem == NULL) | | 3476 | if (nmem == NULL && omem == NULL) |
3516 | return false; | | 3477 | return false; |
3517 | } | | 3478 | } |
3518 | | | 3479 | |
3519 | if (is_struct_or_union(nst) && nstp->t_str != ostp->t_str) | | 3480 | if (is_struct_or_union(nst) && nstp->t_str != ostp->t_str) |
3520 | return true; | | 3481 | return true; |
3521 | | | 3482 | |
3522 | return portable_size_in_bits(nst) != portable_size_in_bits(ost); | | 3483 | return portable_size_in_bits(nst) != portable_size_in_bits(ost); |
3523 | } | | 3484 | } |
3524 | | | 3485 | |
3525 | static void | | 3486 | static void |
3526 | convert_pointer_from_pointer(type_t *ntp, tnode_t *tn) | | 3487 | convert_pointer_from_pointer(type_t *ntp, tnode_t *tn) |
3527 | { | | 3488 | { |
3528 | const type_t *nstp, *otp, *ostp; | | 3489 | const type_t *nstp = ntp->t_subt; |
3529 | tspec_t nst, ost; | | 3490 | const type_t *otp = tn->tn_type; |
3530 | const char *nts, *ots; | | 3491 | const type_t *ostp = otp->t_subt; |
3531 | | | 3492 | tspec_t nst = nstp->t_tspec; |
3532 | nstp = ntp->t_subt; | | 3493 | tspec_t ost = ostp->t_tspec; |
3533 | otp = tn->tn_type; | | | |
3534 | ostp = otp->t_subt; | | | |
3535 | nst = nstp->t_tspec; | | | |
3536 | ost = ostp->t_tspec; | | | |
3537 | | | 3494 | |
3538 | if (nst == VOID || ost == VOID) { | | 3495 | if (nst == VOID || ost == VOID) { |
3539 | /* TODO: C99 behaves like C90 here. */ | | 3496 | /* TODO: C99 behaves like C90 here. */ |
3540 | if ((!allow_trad && !allow_c99) && (nst == FUNC || ost == FUNC)) { | | 3497 | if ((!allow_trad && !allow_c99) && (nst == FUNC || ost == FUNC)) { |
| | | 3498 | const char *nts, *ots; |
3541 | /* null pointers are already handled in convert() */ | | 3499 | /* null pointers are already handled in convert() */ |
3542 | *(nst == FUNC ? &nts : &ots) = "function pointer"; | | 3500 | *(nst == FUNC ? &nts : &ots) = "function pointer"; |
3543 | *(nst == VOID ? &nts : &ots) = "'void *'"; | | 3501 | *(nst == VOID ? &nts : &ots) = "'void *'"; |
3544 | /* ANSI C forbids conversion of %s to %s */ | | 3502 | /* ANSI C forbids conversion of %s to %s */ |
3545 | warning(303, ots, nts); | | 3503 | warning(303, ots, nts); |
3546 | } | | 3504 | } |
3547 | return; | | 3505 | return; |
3548 | } else if (nst == FUNC && ost == FUNC) { | | 3506 | } |
| | | 3507 | if (nst == FUNC && ost == FUNC) |
3549 | return; | | 3508 | return; |
3550 | } else if (nst == FUNC || ost == FUNC) { | | 3509 | if (nst == FUNC || ost == FUNC) { |
3551 | /* converting '%s' to '%s' is questionable */ | | 3510 | /* converting '%s' to '%s' is questionable */ |
3552 | warning(229, type_name(otp), type_name(ntp)); | | 3511 | warning(229, type_name(otp), type_name(ntp)); |
3553 | return; | | 3512 | return; |
3554 | } | | 3513 | } |
3555 | | | 3514 | |
3556 | if (hflag && alignment_in_bits(nstp) > alignment_in_bits(ostp) && | | 3515 | if (hflag && alignment_in_bits(nstp) > alignment_in_bits(ostp) && |
3557 | ost != CHAR && ost != UCHAR && | | 3516 | ost != CHAR && ost != UCHAR && |
3558 | !is_incomplete(ostp)) { | | 3517 | !is_incomplete(ostp)) { |
3559 | /* converting '%s' to '%s' increases alignment ... */ | | 3518 | /* converting '%s' to '%s' increases alignment ... */ |
3560 | warning(135, type_name(otp), type_name(ntp), | | 3519 | warning(135, type_name(otp), type_name(ntp), |
3561 | alignment_in_bits(ostp) / CHAR_SIZE, | | 3520 | alignment_in_bits(ostp) / CHAR_SIZE, |
3562 | alignment_in_bits(nstp) / CHAR_SIZE); | | 3521 | alignment_in_bits(nstp) / CHAR_SIZE); |
3563 | } | | 3522 | } |
3564 | | | 3523 | |
3565 | if (cflag && should_warn_about_pointer_cast(nstp, nst, ostp, ost)) { | | 3524 | if (cflag && should_warn_about_pointer_cast(nstp, nst, ostp, ost)) { |
3566 | /* pointer cast from '%s' to '%s' may be troublesome */ | | 3525 | /* pointer cast from '%s' to '%s' may be troublesome */ |
3567 | warning(247, type_name(otp), type_name(ntp)); | | 3526 | warning(247, type_name(otp), type_name(ntp)); |
3568 | } | | 3527 | } |
3569 | } | | 3528 | } |
3570 | | | 3529 | |
3571 | /* | | 3530 | /* |
3572 | * Insert a conversion operator, which converts the type of the node | | 3531 | * Insert a conversion operator, which converts the type of the node |
3573 | * to another given type. | | 3532 | * to another given type. |
3574 | * | | 3533 | * |
3575 | * Possible values for 'op': | | 3534 | * Possible values for 'op': |
3576 | * CVT a cast-expression | | 3535 | * CVT a cast-expression |
3577 | * binary integer promotion for one of the operands, or a usual | | 3536 | * binary integer promotion for one of the operands, or a usual |
3578 | * arithmetic conversion | | 3537 | * arithmetic conversion |
3579 | * binary plain or compound assignments to bit-fields | | 3538 | * binary plain or compound assignments to bit-fields |
3580 | * FARG 'arg' is the number of the argument (used for warnings) | | 3539 | * FARG 'arg' is the number of the argument (used for warnings) |
3581 | * NOOP several other implicit conversions | | 3540 | * NOOP several other implicit conversions |
3582 | * ... | | 3541 | * ... |
3583 | */ | | 3542 | */ |
3584 | tnode_t * | | 3543 | tnode_t * |
3585 | convert(op_t op, int arg, type_t *tp, tnode_t *tn) | | 3544 | convert(op_t op, int arg, type_t *tp, tnode_t *tn) |
3586 | { | | 3545 | { |
3587 | tnode_t *ntn; | | 3546 | tspec_t nt = tp->t_tspec; |
3588 | tspec_t nt, ot; | | 3547 | tspec_t ot = tn->tn_type->t_tspec; |
3589 | | | | |
3590 | nt = tp->t_tspec; | | | |
3591 | ot = tn->tn_type->t_tspec; | | | |
3592 | | | 3548 | |
3593 | if (allow_trad && allow_c90 && op == FARG) | | 3549 | if (allow_trad && allow_c90 && op == FARG) |
3594 | check_prototype_conversion(arg, nt, ot, tp, tn); | | 3550 | check_prototype_conversion(arg, nt, ot, tp, tn); |
3595 | | | 3551 | |
3596 | if (nt == BOOL) { | | 3552 | if (nt == BOOL) { |
3597 | /* No further checks. */ | | 3553 | /* No further checks. */ |
3598 | | | 3554 | |
3599 | } else if (is_integer(nt)) { | | 3555 | } else if (is_integer(nt)) { |
3600 | if (ot == BOOL) { | | 3556 | if (ot == BOOL) { |
3601 | /* No further checks. */ | | 3557 | /* No further checks. */ |
3602 | } else if (is_integer(ot)) { | | 3558 | } else if (is_integer(ot)) { |
3603 | convert_integer_from_integer(op, arg, nt, ot, tp, tn); | | 3559 | convert_integer_from_integer(op, arg, nt, ot, tp, tn); |
3604 | } else if (is_floating(ot)) { | | 3560 | } else if (is_floating(ot)) { |
3605 | convert_integer_from_floating(op, tp, tn); | | 3561 | convert_integer_from_floating(op, tp, tn); |
3606 | } else if (ot == PTR) { | | 3562 | } else if (ot == PTR) { |
3607 | convert_integer_from_pointer(op, nt, tp, tn); | | 3563 | convert_integer_from_pointer(op, nt, tp, tn); |
3608 | } | | 3564 | } |
3609 | | | 3565 | |
3610 | } else if (is_floating(nt)) { | | 3566 | } else if (is_floating(nt)) { |
3611 | /* No further checks. */ | | 3567 | /* No further checks. */ |
3612 | | | 3568 | |
3613 | } else if (nt == PTR) { | | 3569 | } else if (nt == PTR) { |
3614 | if (is_null_pointer(tn)) { | | 3570 | if (is_null_pointer(tn)) { |
3615 | /* a null pointer may be assigned to any pointer. */ | | 3571 | /* a null pointer may be assigned to any pointer. */ |
3616 | } else if (ot == PTR && op == CVT) { | | 3572 | } else if (ot == PTR && op == CVT) { |
3617 | convert_pointer_from_pointer(tp, tn); | | 3573 | convert_pointer_from_pointer(tp, tn); |
3618 | } | | 3574 | } |
3619 | } | | 3575 | } |
3620 | | | 3576 | |
3621 | ntn = expr_alloc_tnode(); | | 3577 | tnode_t *ntn = expr_alloc_tnode(); |
3622 | ntn->tn_op = CVT; | | 3578 | ntn->tn_op = CVT; |
3623 | ntn->tn_type = tp; | | 3579 | ntn->tn_type = tp; |
3624 | ntn->tn_cast = op == CVT; | | 3580 | ntn->tn_cast = op == CVT; |
3625 | ntn->tn_sys |= tn->tn_sys; | | 3581 | ntn->tn_sys |= tn->tn_sys; |
3626 | ntn->tn_right = NULL; | | 3582 | ntn->tn_right = NULL; |
3627 | if (tn->tn_op != CON || nt == VOID) { | | 3583 | if (tn->tn_op != CON || nt == VOID) { |
3628 | ntn->tn_left = tn; | | 3584 | ntn->tn_left = tn; |
3629 | } else { | | 3585 | } else { |
3630 | ntn->tn_op = CON; | | 3586 | ntn->tn_op = CON; |
3631 | ntn->tn_val = expr_zero_alloc(sizeof(*ntn->tn_val)); | | 3587 | ntn->tn_val = expr_zero_alloc(sizeof(*ntn->tn_val)); |
3632 | convert_constant(op, arg, ntn->tn_type, ntn->tn_val, | | 3588 | convert_constant(op, arg, ntn->tn_type, ntn->tn_val, |
3633 | tn->tn_val); | | 3589 | tn->tn_val); |
3634 | } | | 3590 | } |
3635 | | | 3591 | |
3636 | return ntn; | | 3592 | return ntn; |
3637 | } | | 3593 | } |
3638 | | | 3594 | |
3639 | static void | | 3595 | static void |
3640 | convert_constant_floating(op_t op, int arg, tspec_t ot, const type_t *tp, | | 3596 | convert_constant_floating(op_t op, int arg, tspec_t ot, const type_t *tp, |
3641 | tspec_t nt, val_t *v, val_t *nv) | | 3597 | tspec_t nt, val_t *v, val_t *nv) |
3642 | { | | 3598 | { |
3643 | ldbl_t max = 0.0, min = 0.0; | | 3599 | ldbl_t max = 0.0, min = 0.0; |
3644 | | | 3600 | |
3645 | switch (nt) { | | 3601 | switch (nt) { |
3646 | case CHAR: | | 3602 | case CHAR: |
3647 | max = TARG_CHAR_MAX; min = TARG_CHAR_MIN; break; | | 3603 | max = TARG_CHAR_MAX; min = TARG_CHAR_MIN; break; |
3648 | case UCHAR: | | 3604 | case UCHAR: |
3649 | max = TARG_UCHAR_MAX; min = 0; break; | | 3605 | max = TARG_UCHAR_MAX; min = 0; break; |
3650 | case SCHAR: | | 3606 | case SCHAR: |
3651 | max = TARG_SCHAR_MAX; min = TARG_SCHAR_MIN; break; | | 3607 | max = TARG_SCHAR_MAX; min = TARG_SCHAR_MIN; break; |
3652 | case SHORT: | | 3608 | case SHORT: |
3653 | max = TARG_SHRT_MAX; min = TARG_SHRT_MIN; break; | | 3609 | max = TARG_SHRT_MAX; min = TARG_SHRT_MIN; break; |
3654 | case USHORT: | | 3610 | case USHORT: |
3655 | max = TARG_USHRT_MAX; min = 0; break; | | 3611 | max = TARG_USHRT_MAX; min = 0; break; |
3656 | case ENUM: | | 3612 | case ENUM: |
3657 | case INT: | | 3613 | case INT: |
3658 | max = TARG_INT_MAX; min = TARG_INT_MIN; break; | | 3614 | max = TARG_INT_MAX; min = TARG_INT_MIN; break; |
3659 | case UINT: | | 3615 | case UINT: |
3660 | max = TARG_UINT_MAX; min = 0; break; | | 3616 | max = TARG_UINT_MAX; min = 0; break; |
3661 | case LONG: | | 3617 | case LONG: |
3662 | max = TARG_LONG_MAX; min = TARG_LONG_MIN; break; | | 3618 | max = TARG_LONG_MAX; min = TARG_LONG_MIN; break; |
3663 | case ULONG: | | 3619 | case ULONG: |
3664 | max = TARG_ULONG_MAX; min = 0; break; | | 3620 | max = TARG_ULONG_MAX; min = 0; break; |
3665 | case QUAD: | | 3621 | case QUAD: |
3666 | max = QUAD_MAX; min = QUAD_MIN; break; | | 3622 | max = QUAD_MAX; min = QUAD_MIN; break; |
3667 | case UQUAD: | | 3623 | case UQUAD: |
3668 | max = UQUAD_MAX; min = 0; break; | | 3624 | max = UQUAD_MAX; min = 0; break; |
3669 | case FLOAT: | | 3625 | case FLOAT: |
3670 | case FCOMPLEX: | | 3626 | case FCOMPLEX: |
3671 | max = FLT_MAX; min = -FLT_MAX; break; | | 3627 | max = FLT_MAX; min = -FLT_MAX; break; |
3672 | case DOUBLE: | | 3628 | case DOUBLE: |
3673 | case DCOMPLEX: | | 3629 | case DCOMPLEX: |
3674 | max = DBL_MAX; min = -DBL_MAX; break; | | 3630 | max = DBL_MAX; min = -DBL_MAX; break; |
3675 | case PTR: | | 3631 | case PTR: |
3676 | /* Got already an error because of float --> ptr */ | | 3632 | /* Got already an error because of float --> ptr */ |
3677 | case LDOUBLE: | | 3633 | case LDOUBLE: |
3678 | case LCOMPLEX: | | 3634 | case LCOMPLEX: |
3679 | /* LINTED 248 */ | | 3635 | /* LINTED 248 */ |
3680 | max = LDBL_MAX; min = -max; break; | | 3636 | max = LDBL_MAX; min = -max; break; |
3681 | default: | | 3637 | default: |
3682 | lint_assert(/*CONSTCOND*/false); | | 3638 | lint_assert(/*CONSTCOND*/false); |
3683 | } | | 3639 | } |
3684 | if (v->v_ldbl > max || v->v_ldbl < min) { | | 3640 | if (v->v_ldbl > max || v->v_ldbl < min) { |
3685 | lint_assert(nt != LDOUBLE); | | 3641 | lint_assert(nt != LDOUBLE); |
3686 | if (op == FARG) { | | 3642 | if (op == FARG) { |
3687 | /* conversion of '%s' to '%s' is out of range, ... */ | | 3643 | /* conversion of '%s' to '%s' is out of range, ... */ |
3688 | warning(295, | | 3644 | warning(295, |
3689 | type_name(gettyp(ot)), type_name(tp), arg); | | 3645 | type_name(gettyp(ot)), type_name(tp), arg); |
3690 | } else { | | 3646 | } else { |
3691 | /* conversion of '%s' to '%s' is out of range */ | | 3647 | /* conversion of '%s' to '%s' is out of range */ |
3692 | warning(119, | | 3648 | warning(119, |
3693 | type_name(gettyp(ot)), type_name(tp)); | | 3649 | type_name(gettyp(ot)), type_name(tp)); |
3694 | } | | 3650 | } |
3695 | v->v_ldbl = v->v_ldbl > 0 ? max : min; | | 3651 | v->v_ldbl = v->v_ldbl > 0 ? max : min; |
3696 | } | | 3652 | } |
3697 | | | 3653 | |
3698 | if (nt == FLOAT) { | | 3654 | if (nt == FLOAT) { |
3699 | nv->v_ldbl = (float)v->v_ldbl; | | 3655 | nv->v_ldbl = (float)v->v_ldbl; |
3700 | } else if (nt == DOUBLE) { | | 3656 | } else if (nt == DOUBLE) { |
3701 | nv->v_ldbl = (double)v->v_ldbl; | | 3657 | nv->v_ldbl = (double)v->v_ldbl; |
3702 | } else if (nt == LDOUBLE) { | | 3658 | } else if (nt == LDOUBLE) { |
3703 | nv->v_ldbl = v->v_ldbl; | | 3659 | nv->v_ldbl = v->v_ldbl; |
3704 | } else { | | 3660 | } else { |
3705 | nv->v_quad = (int64_t)v->v_ldbl; | | 3661 | nv->v_quad = (int64_t)v->v_ldbl; |
3706 | } | | 3662 | } |
3707 | } | | 3663 | } |
3708 | | | 3664 | |
3709 | static bool | | 3665 | static bool |
3710 | convert_constant_to_floating(tspec_t nt, val_t *nv, | | 3666 | convert_constant_to_floating(tspec_t nt, val_t *nv, |
3711 | tspec_t ot, const val_t *v) | | 3667 | tspec_t ot, const val_t *v) |
3712 | { | | 3668 | { |
3713 | if (nt == FLOAT) { | | 3669 | if (nt == FLOAT) { |
3714 | nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? | | 3670 | nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? |
3715 | (float)(uint64_t)v->v_quad : (float)v->v_quad; | | 3671 | (float)(uint64_t)v->v_quad : (float)v->v_quad; |
3716 | } else if (nt == DOUBLE) { | | 3672 | } else if (nt == DOUBLE) { |
3717 | nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? | | 3673 | nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? |
3718 | (double)(uint64_t)v->v_quad : (double)v->v_quad; | | 3674 | (double)(uint64_t)v->v_quad : (double)v->v_quad; |
3719 | } else if (nt == LDOUBLE) { | | 3675 | } else if (nt == LDOUBLE) { |
3720 | nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? | | 3676 | nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? |
3721 | (ldbl_t)(uint64_t)v->v_quad : (ldbl_t)v->v_quad; | | 3677 | (ldbl_t)(uint64_t)v->v_quad : (ldbl_t)v->v_quad; |
3722 | } else | | 3678 | } else |
3723 | return false; | | 3679 | return false; |
3724 | return true; | | 3680 | return true; |
3725 | } | | 3681 | } |
3726 | | | 3682 | |
3727 | /* | | 3683 | /* |
3728 | * Print a warning if bits which were set are lost due to the conversion. | | 3684 | * Print a warning if bits which were set are lost due to the conversion. |
3729 | * This can happen with operator ORASS only. | | 3685 | * This can happen with operator ORASS only. |
3730 | */ | | 3686 | */ |
3731 | static void | | 3687 | static void |
3732 | convert_constant_check_range_bitor(size_t nsz, size_t osz, const val_t *v, | | 3688 | convert_constant_check_range_bitor(size_t nsz, size_t osz, const val_t *v, |
3733 | uint64_t xmask, op_t op) | | 3689 | uint64_t xmask, op_t op) |
3734 | { | | 3690 | { |
3735 | if (nsz < osz && (v->v_quad & xmask) != 0) { | | 3691 | if (nsz < osz && (v->v_quad & xmask) != 0) { |
3736 | /* constant truncated by conversion, op '%s' */ | | 3692 | /* constant truncated by conversion, op '%s' */ |
3737 | warning(306, op_name(op)); | | 3693 | warning(306, op_name(op)); |
3738 | } | | 3694 | } |
3739 | } | | 3695 | } |
3740 | | | 3696 | |
3741 | /* | | 3697 | /* |
3742 | * Print a warning if additional bits are not all 1 | | 3698 | * Print a warning if additional bits are not all 1 |
3743 | * and the most significant bit of the old value is 1, | | 3699 | * and the most significant bit of the old value is 1, |
3744 | * or if at least one (but not all) removed bit was 0. | | 3700 | * or if at least one (but not all) removed bit was 0. |
3745 | */ | | 3701 | */ |
3746 | static void | | 3702 | static void |
3747 | convert_constant_check_range_bitand(size_t nsz, size_t osz, | | 3703 | convert_constant_check_range_bitand(size_t nsz, size_t osz, |
3748 | uint64_t xmask, const val_t *nv, | | 3704 | uint64_t xmask, const val_t *nv, |
3749 | tspec_t ot, const val_t *v, | | 3705 | tspec_t ot, const val_t *v, |
3750 | const type_t *tp, op_t op) | | 3706 | const type_t *tp, op_t op) |
3751 | { | | 3707 | { |
3752 | if (nsz > osz && | | 3708 | if (nsz > osz && |
3753 | (nv->v_quad & bit((unsigned int)(osz - 1))) != 0 && | | 3709 | (nv->v_quad & bit((unsigned int)(osz - 1))) != 0 && |
3754 | (nv->v_quad & xmask) != xmask) { | | 3710 | (nv->v_quad & xmask) != xmask) { |
3755 | /* extra bits set to 0 in conversion of '%s' to '%s', ... */ | | 3711 | /* extra bits set to 0 in conversion of '%s' to '%s', ... */ |
3756 | warning(309, type_name(gettyp(ot)), | | 3712 | warning(309, type_name(gettyp(ot)), |
3757 | type_name(tp), op_name(op)); | | 3713 | type_name(tp), op_name(op)); |
3758 | } else if (nsz < osz && | | 3714 | } else if (nsz < osz && |
3759 | (v->v_quad & xmask) != xmask && | | 3715 | (v->v_quad & xmask) != xmask && |
3760 | (v->v_quad & xmask) != 0) { | | 3716 | (v->v_quad & xmask) != 0) { |
3761 | /* constant truncated by conversion, op '%s' */ | | 3717 | /* constant truncated by conversion, op '%s' */ |
3762 | warning(306, op_name(op)); | | 3718 | warning(306, op_name(op)); |
3763 | } | | 3719 | } |
3764 | } | | 3720 | } |
3765 | | | 3721 | |
3766 | static void | | 3722 | static void |
3767 | convert_constant_check_range_signed(op_t op, int arg) | | 3723 | convert_constant_check_range_signed(op_t op, int arg) |
3768 | { | | 3724 | { |
3769 | if (op == ASSIGN) { | | 3725 | if (op == ASSIGN) { |
3770 | /* assignment of negative constant to unsigned type */ | | 3726 | /* assignment of negative constant to unsigned type */ |
3771 | warning(164); | | 3727 | warning(164); |
3772 | } else if (op == INIT) { | | 3728 | } else if (op == INIT) { |
3773 | /* initialization of unsigned with negative constant */ | | 3729 | /* initialization of unsigned with negative constant */ |
3774 | warning(221); | | 3730 | warning(221); |
3775 | } else if (op == FARG) { | | 3731 | } else if (op == FARG) { |
3776 | /* conversion of negative constant to unsigned type, ... */ | | 3732 | /* conversion of negative constant to unsigned type, ... */ |
3777 | warning(296, arg); | | 3733 | warning(296, arg); |
3778 | } else if (modtab[op].m_comparison) { | | 3734 | } else if (modtab[op].m_comparison) { |
3779 | /* handled by check_integer_comparison() */ | | 3735 | /* handled by check_integer_comparison() */ |
3780 | } else { | | 3736 | } else { |
3781 | /* conversion of negative constant to unsigned type */ | | 3737 | /* conversion of negative constant to unsigned type */ |
3782 | warning(222); | | 3738 | warning(222); |
3783 | } | | 3739 | } |
3784 | } | | 3740 | } |
3785 | | | 3741 | |
3786 | /* | | 3742 | /* |
3787 | * Loss of significant bit(s). All truncated bits | | 3743 | * Loss of significant bit(s). All truncated bits of unsigned types or all |
3788 | * of unsigned types or all truncated bits plus the | | 3744 | * truncated bits plus the msb of the target for signed types are considered |
3789 | * msb of the target for signed types are considered | | 3745 | * to be significant bits. Loss of significant bits means that at least one |
3790 | * to be significant bits. Loss of significant bits | | 3746 | * of the bits was set in an unsigned type or that at least one but not all |
3791 | * means that at least one of the bits was set in an | | 3747 | * of the bits was set in a signed type. Loss of significant bits means that |
3792 | * unsigned type or that at least one but not all of | | 3748 | * it is not possible, also not with necessary casts, to convert back to the |
3793 | * the bits was set in a signed type. | | 3749 | * original type. A example for a necessary cast is: |
3794 | * Loss of significant bits means that it is not | | | |
3795 | * possible, also not with necessary casts, to convert | | | |
3796 | * back to the original type. A example for a | | | |
3797 | * necessary cast is: | | | |
3798 | * char c; int i; c = 128; | | 3750 | * char c; int i; c = 128; |
3799 | * i = c; ** yields -128 ** | | 3751 | * i = c; ** yields -128 ** |
3800 | * i = (unsigned char)c; ** yields 128 ** | | 3752 | * i = (unsigned char)c; ** yields 128 ** |
3801 | */ | | 3753 | */ |
3802 | static void | | 3754 | static void |
3803 | convert_constant_check_range_truncated(op_t op, int arg, const type_t *tp, | | 3755 | convert_constant_check_range_truncated(op_t op, int arg, const type_t *tp, |
3804 | tspec_t ot) | | 3756 | tspec_t ot) |
3805 | { | | 3757 | { |
3806 | if (op == ASSIGN && tp->t_bitfield) { | | 3758 | if (op == ASSIGN && tp->t_bitfield) { |
3807 | /* precision lost in bit-field assignment */ | | 3759 | /* precision lost in bit-field assignment */ |
3808 | warning(166); | | 3760 | warning(166); |
3809 | } else if (op == ASSIGN) { | | 3761 | } else if (op == ASSIGN) { |
3810 | /* constant truncated by assignment */ | | 3762 | /* constant truncated by assignment */ |
3811 | warning(165); | | 3763 | warning(165); |
3812 | } else if (op == INIT && tp->t_bitfield) { | | 3764 | } else if (op == INIT && tp->t_bitfield) { |
3813 | /* bit-field initializer does not fit */ | | 3765 | /* bit-field initializer does not fit */ |
3814 | warning(180); | | 3766 | warning(180); |
3815 | } else if (op == INIT) { | | 3767 | } else if (op == INIT) { |
3816 | /* initializer does not fit */ | | 3768 | /* initializer does not fit */ |
3817 | warning(178); | | 3769 | warning(178); |
3818 | } else if (op == CASE) { | | 3770 | } else if (op == CASE) { |
3819 | /* case label affected by conversion */ | | 3771 | /* case label affected by conversion */ |
3820 | warning(196); | | 3772 | warning(196); |
3821 | } else if (op == FARG) { | | 3773 | } else if (op == FARG) { |
3822 | /* conversion of '%s' to '%s' is out of range, arg #%d */ | | 3774 | /* conversion of '%s' to '%s' is out of range, arg #%d */ |
3823 | warning(295, | | 3775 | warning(295, |
3824 | type_name(gettyp(ot)), type_name(tp), arg); | | 3776 | type_name(gettyp(ot)), type_name(tp), arg); |
3825 | } else { | | 3777 | } else { |
3826 | /* conversion of '%s' to '%s' is out of range */ | | 3778 | /* conversion of '%s' to '%s' is out of range */ |
3827 | warning(119, | | 3779 | warning(119, |
3828 | type_name(gettyp(ot)), type_name(tp)); | | 3780 | type_name(gettyp(ot)), type_name(tp)); |
3829 | } | | 3781 | } |
3830 | } | | 3782 | } |
3831 | | | 3783 | |
3832 | static void | | 3784 | static void |
3833 | convert_constant_check_range_loss(op_t op, int arg, const type_t *tp, | | 3785 | convert_constant_check_range_loss(op_t op, int arg, const type_t *tp, |
3834 | tspec_t ot) | | 3786 | tspec_t ot) |
3835 | { | | 3787 | { |
3836 | if (op == ASSIGN && tp->t_bitfield) { | | 3788 | if (op == ASSIGN && tp->t_bitfield) { |
3837 | /* precision lost in bit-field assignment */ | | 3789 | /* precision lost in bit-field assignment */ |
3838 | warning(166); | | 3790 | warning(166); |
3839 | } else if (op == INIT && tp->t_bitfield) { | | 3791 | } else if (op == INIT && tp->t_bitfield) { |
3840 | /* bit-field initializer out of range */ | | 3792 | /* bit-field initializer out of range */ |
3841 | warning(11); | | 3793 | warning(11); |
3842 | } else if (op == CASE) { | | 3794 | } else if (op == CASE) { |
3843 | /* case label affected by conversion */ | | 3795 | /* case label affected by conversion */ |
3844 | warning(196); | | 3796 | warning(196); |
3845 | } else if (op == FARG) { | | 3797 | } else if (op == FARG) { |
3846 | /* conversion of '%s' to '%s' is out of range, arg #%d */ | | 3798 | /* conversion of '%s' to '%s' is out of range, arg #%d */ |
3847 | warning(295, | | 3799 | warning(295, type_name(gettyp(ot)), type_name(tp), arg); |
3848 | type_name(gettyp(ot)), type_name(tp), arg); | | | |
3849 | } else { | | 3800 | } else { |
3850 | /* conversion of '%s' to '%s' is out of range */ | | 3801 | /* conversion of '%s' to '%s' is out of range */ |
3851 | warning(119, | | 3802 | warning(119, type_name(gettyp(ot)), type_name(tp)); |
3852 | type_name(gettyp(ot)), type_name(tp)); | | | |
3853 | } | | 3803 | } |
3854 | } | | 3804 | } |
3855 | | | 3805 | |
3856 | static void | | 3806 | static void |
3857 | convert_constant_check_range(tspec_t ot, const type_t *tp, tspec_t nt, | | 3807 | convert_constant_check_range(tspec_t ot, const type_t *tp, tspec_t nt, |
3858 | op_t op, int arg, const val_t *v, val_t *nv) | | 3808 | op_t op, int arg, const val_t *v, val_t *nv) |
3859 | { | | 3809 | { |
3860 | unsigned int obitsz, nbitsz; | | 3810 | unsigned int obitsz, nbitsz; |
3861 | uint64_t xmask, xmsk1; | | 3811 | uint64_t xmask, xmsk1; |
3862 | | | 3812 | |
3863 | obitsz = size_in_bits(ot); | | 3813 | obitsz = size_in_bits(ot); |
3864 | nbitsz = tp->t_bitfield ? tp->t_flen : size_in_bits(nt); | | 3814 | nbitsz = tp->t_bitfield ? tp->t_flen : size_in_bits(nt); |
3865 | xmask = value_bits(nbitsz) ^ value_bits(obitsz); | | 3815 | xmask = value_bits(nbitsz) ^ value_bits(obitsz); |
3866 | xmsk1 = value_bits(nbitsz) ^ value_bits(obitsz - 1); | | 3816 | xmsk1 = value_bits(nbitsz) ^ value_bits(obitsz - 1); |
3867 | /* | | 3817 | /* |
3868 | * For bitwise operations we are not interested in the arithmetic | | 3818 | * For bitwise operations we are not interested in the arithmetic |
3869 | * value, but in the bits itself. | | 3819 | * value, but in the bits itself. |
3870 | */ | | 3820 | */ |
3871 | if (op == ORASS || op == BITOR || op == BITXOR) { | | 3821 | if (op == ORASS || op == BITOR || op == BITXOR) { |
3872 | convert_constant_check_range_bitor( | | 3822 | convert_constant_check_range_bitor( |
3873 | nbitsz, obitsz, v, xmask, op); | | 3823 | nbitsz, obitsz, v, xmask, op); |
3874 | } else if (op == ANDASS || op == BITAND) { | | 3824 | } else if (op == ANDASS || op == BITAND) { |
3875 | convert_constant_check_range_bitand( | | 3825 | convert_constant_check_range_bitand( |
3876 | nbitsz, obitsz, xmask, nv, ot, v, tp, op); | | 3826 | nbitsz, obitsz, xmask, nv, ot, v, tp, op); |
3877 | } else if ((nt != PTR && is_uinteger(nt)) && | | 3827 | } else if ((nt != PTR && is_uinteger(nt)) && |
3878 | (ot != PTR && !is_uinteger(ot)) && | | 3828 | (ot != PTR && !is_uinteger(ot)) && |
3879 | v->v_quad < 0) { | | 3829 | v->v_quad < 0) { |
3880 | convert_constant_check_range_signed(op, arg); | | 3830 | convert_constant_check_range_signed(op, arg); |
3881 | } else if (nv->v_quad != v->v_quad && nbitsz <= obitsz && | | 3831 | } else if (nv->v_quad != v->v_quad && nbitsz <= obitsz && |
3882 | (v->v_quad & xmask) != 0 && | | 3832 | (v->v_quad & xmask) != 0 && |
3883 | (is_uinteger(ot) || (v->v_quad & xmsk1) != xmsk1)) { | | 3833 | (is_uinteger(ot) || (v->v_quad & xmsk1) != xmsk1)) { |
3884 | convert_constant_check_range_truncated(op, arg, tp, ot); | | 3834 | convert_constant_check_range_truncated(op, arg, tp, ot); |
3885 | } else if (nv->v_quad != v->v_quad) { | | 3835 | } else if (nv->v_quad != v->v_quad) { |
3886 | convert_constant_check_range_loss(op, arg, tp, ot); | | 3836 | convert_constant_check_range_loss(op, arg, tp, ot); |
3887 | } | | 3837 | } |
3888 | } | | 3838 | } |
3889 | | | 3839 | |
3890 | /* | | 3840 | /* |
3891 | * Converts a typed constant to a constant of another type. | | 3841 | * Converts a typed constant to a constant of another type. |
3892 | * | | 3842 | * |
3893 | * op operator which requires conversion | | 3843 | * op operator which requires conversion |
3894 | * arg if op is FARG, # of argument | | 3844 | * arg if op is FARG, # of argument |
3895 | * tp type in which to convert the constant | | 3845 | * tp type in which to convert the constant |
3896 | * nv new constant | | 3846 | * nv new constant |
3897 | * v old constant | | 3847 | * v old constant |
3898 | */ | | 3848 | */ |
3899 | void | | 3849 | void |
3900 | convert_constant(op_t op, int arg, const type_t *tp, val_t *nv, val_t *v) | | 3850 | convert_constant(op_t op, int arg, const type_t *tp, val_t *nv, val_t *v) |
3901 | { | | 3851 | { |
3902 | tspec_t ot, nt; | | | |
3903 | unsigned int sz; | | | |
3904 | bool range_check; | | | |
3905 | | | | |
3906 | /* | | 3852 | /* |
3907 | * TODO: make 'v' const; the name of this function does not suggest | | 3853 | * TODO: make 'v' const; the name of this function does not suggest |
3908 | * that it modifies 'v'. | | 3854 | * that it modifies 'v'. |
3909 | */ | | 3855 | */ |
3910 | ot = v->v_tspec; | | 3856 | tspec_t ot = v->v_tspec; |
3911 | nt = nv->v_tspec = tp->t_tspec; | | 3857 | tspec_t nt = nv->v_tspec = tp->t_tspec; |
3912 | range_check = false; | | 3858 | bool range_check = false; |
3913 | | | 3859 | |
3914 | if (nt == BOOL) { /* C99 6.3.1.2 */ | | 3860 | if (nt == BOOL) { /* C99 6.3.1.2 */ |
3915 | nv->v_unsigned_since_c90 = false; | | 3861 | nv->v_unsigned_since_c90 = false; |
3916 | nv->v_quad = is_nonzero_val(v) ? 1 : 0; | | 3862 | nv->v_quad = is_nonzero_val(v) ? 1 : 0; |
3917 | return; | | 3863 | return; |
3918 | } | | 3864 | } |
3919 | | | 3865 | |
3920 | if (ot == FLOAT || ot == DOUBLE || ot == LDOUBLE) { | | 3866 | if (ot == FLOAT || ot == DOUBLE || ot == LDOUBLE) { |
3921 | convert_constant_floating(op, arg, ot, tp, nt, v, nv); | | 3867 | convert_constant_floating(op, arg, ot, tp, nt, v, nv); |
3922 | } else if (!convert_constant_to_floating(nt, nv, ot, v)) { | | 3868 | } else if (!convert_constant_to_floating(nt, nv, ot, v)) { |
3923 | range_check = true; /* Check for lost precision. */ | | 3869 | range_check = true; /* Check for lost precision. */ |
3924 | nv->v_quad = v->v_quad; | | 3870 | nv->v_quad = v->v_quad; |
3925 | } | | 3871 | } |
3926 | | | 3872 | |
3927 | if (allow_trad && allow_c90 && v->v_unsigned_since_c90 && | | 3873 | if (allow_trad && allow_c90 && v->v_unsigned_since_c90 && |
3928 | (is_floating(nt) || ( | | 3874 | (is_floating(nt) || ( |
3929 | (is_integer(nt) && !is_uinteger(nt) && | | 3875 | (is_integer(nt) && !is_uinteger(nt) && |
3930 | portable_size_in_bits(nt) > portable_size_in_bits(ot))))) { | | 3876 | portable_size_in_bits(nt) > portable_size_in_bits(ot))))) { |
3931 | /* ANSI C treats constant as unsigned */ | | 3877 | /* ANSI C treats constant as unsigned */ |
3932 | warning(157); | | 3878 | warning(157); |
3933 | v->v_unsigned_since_c90 = false; | | 3879 | v->v_unsigned_since_c90 = false; |
3934 | } | | 3880 | } |
3935 | | | 3881 | |
3936 | if (is_integer(nt)) { | | 3882 | if (is_integer(nt)) { |
3937 | sz = tp->t_bitfield ? tp->t_flen : size_in_bits(nt); | | 3883 | nv->v_quad = convert_integer(nv->v_quad, nt, |
3938 | nv->v_quad = convert_integer(nv->v_quad, nt, sz); | | 3884 | tp->t_bitfield ? tp->t_flen : size_in_bits(nt)); |
3939 | } | | 3885 | } |
3940 | | | 3886 | |
3941 | if (range_check && op != CVT) | | 3887 | if (range_check && op != CVT) |
3942 | convert_constant_check_range(ot, tp, nt, op, arg, v, nv); | | 3888 | convert_constant_check_range(ot, tp, nt, op, arg, v, nv); |
3943 | } | | 3889 | } |
3944 | | | 3890 | |
3945 | /* | | 3891 | /* |
3946 | * Create a constant node for sizeof. | | 3892 | * Create a constant node for sizeof. |
3947 | */ | | 3893 | */ |
3948 | tnode_t * | | 3894 | tnode_t * |
3949 | build_sizeof(const type_t *tp) | | 3895 | build_sizeof(const type_t *tp) |
3950 | { | | 3896 | { |
3951 | unsigned int size_in_bytes = type_size_in_bits(tp) / CHAR_SIZE; | | 3897 | unsigned int size_in_bytes = type_size_in_bits(tp) / CHAR_SIZE; |
3952 | tnode_t *tn = build_integer_constant(SIZEOF_TSPEC, size_in_bytes); | | 3898 | tnode_t *tn = build_integer_constant(SIZEOF_TSPEC, size_in_bytes); |
3953 | tn->tn_system_dependent = true; | | 3899 | tn->tn_system_dependent = true; |
3954 | debug_step("build_sizeof '%s' = %u", type_name(tp), size_in_bytes); | | 3900 | debug_step("build_sizeof '%s' = %u", type_name(tp), size_in_bytes); |
3955 | return tn; | | 3901 | return tn; |
3956 | } | | 3902 | } |
3957 | | | 3903 | |
3958 | /* | | 3904 | /* |
3959 | * Create a constant node for offsetof. | | 3905 | * Create a constant node for offsetof. |
3960 | */ | | 3906 | */ |
3961 | /* ARGSUSED */ /* FIXME: See implementation comments. */ | | 3907 | /* ARGSUSED */ /* FIXME: See implementation comments. */ |
3962 | tnode_t * | | 3908 | tnode_t * |
3963 | build_offsetof(const type_t *tp, const sym_t *sym) | | 3909 | build_offsetof(const type_t *tp, const sym_t *sym) |
3964 | { | | 3910 | { |
3965 | unsigned int offset_in_bytes; | | 3911 | unsigned int offset_in_bytes; |
3966 | tnode_t *tn; | | 3912 | tnode_t *tn; |
3967 | | | 3913 | |
3968 | if (!is_struct_or_union(tp->t_tspec)) | | 3914 | if (!is_struct_or_union(tp->t_tspec)) |
3969 | /* unacceptable operand of '%s' */ | | 3915 | /* unacceptable operand of '%s' */ |
3970 | error(111, "offsetof"); | | 3916 | error(111, "offsetof"); |
3971 | | | 3917 | |
3972 | /* FIXME: Don't wrongly use the size of the whole type, use sym. */ | | 3918 | /* FIXME: Don't wrongly use the size of the whole type, use sym. */ |
3973 | offset_in_bytes = type_size_in_bits(tp) / CHAR_SIZE; | | 3919 | offset_in_bytes = type_size_in_bits(tp) / CHAR_SIZE; |
3974 | tn = build_integer_constant(SIZEOF_TSPEC, offset_in_bytes); | | 3920 | tn = build_integer_constant(SIZEOF_TSPEC, offset_in_bytes); |
3975 | tn->tn_system_dependent = true; | | 3921 | tn->tn_system_dependent = true; |
3976 | return tn; | | 3922 | return tn; |
3977 | } | | 3923 | } |
3978 | | | 3924 | |
3979 | unsigned int | | 3925 | unsigned int |
3980 | type_size_in_bits(const type_t *tp) | | 3926 | type_size_in_bits(const type_t *tp) |
3981 | { | | 3927 | { |
3982 | unsigned int elem, elsz; | | 3928 | unsigned int elsz; |
3983 | bool flex; | | | |
3984 | | | 3929 | |
3985 | elem = 1; | | 3930 | unsigned int elem = 1; |
3986 | flex = false; | | 3931 | bool flex = false; |
3987 | lint_assert(tp != NULL); | | 3932 | lint_assert(tp != NULL); |
3988 | while (tp->t_tspec == ARRAY) { | | 3933 | while (tp->t_tspec == ARRAY) { |
3989 | flex = true; /* allow c99 flex arrays [] [0] */ | | 3934 | flex = true; /* allow c99 flex arrays [] [0] */ |
3990 | elem *= tp->t_dim; | | 3935 | elem *= tp->t_dim; |
3991 | tp = tp->t_subt; | | 3936 | tp = tp->t_subt; |
3992 | } | | 3937 | } |
3993 | if (elem == 0) { | | 3938 | if (elem == 0) { |
3994 | if (!flex) { | | 3939 | if (!flex) { |
3995 | /* cannot take size/alignment of incomplete type */ | | 3940 | /* cannot take size/alignment of incomplete type */ |
3996 | error(143); | | 3941 | error(143); |
3997 | elem = 1; | | 3942 | elem = 1; |
3998 | } | | 3943 | } |
3999 | } | | 3944 | } |
4000 | switch (tp->t_tspec) { | | 3945 | switch (tp->t_tspec) { |
4001 | case FUNC: | | 3946 | case FUNC: |
4002 | /* cannot take size/alignment of function type '%s' */ | | 3947 | /* cannot take size/alignment of function type '%s' */ |
4003 | error(144, type_name(tp)); | | 3948 | error(144, type_name(tp)); |
4004 | elsz = 1; | | 3949 | elsz = 1; |
4005 | break; | | 3950 | break; |
4006 | case STRUCT: | | 3951 | case STRUCT: |
4007 | case UNION: | | 3952 | case UNION: |
4008 | if (is_incomplete(tp)) { | | 3953 | if (is_incomplete(tp)) { |
4009 | /* cannot take size/alignment of incomplete type */ | | 3954 | /* cannot take size/alignment of incomplete type */ |
4010 | error(143); | | 3955 | error(143); |
4011 | elsz = 1; | | 3956 | elsz = 1; |
4012 | } else { | | 3957 | } else { |
4013 | elsz = tp->t_str->sou_size_in_bits; | | 3958 | elsz = tp->t_str->sou_size_in_bits; |
4014 | } | | 3959 | } |
4015 | break; | | 3960 | break; |
4016 | case ENUM: | | 3961 | case ENUM: |
4017 | if (is_incomplete(tp)) { | | 3962 | if (is_incomplete(tp)) { |
4018 | /* cannot take size/alignment of incomplete type */ | | 3963 | /* cannot take size/alignment of incomplete type */ |
4019 | warning(143); | | 3964 | warning(143); |
4020 | } | | 3965 | } |
4021 | /* FALLTHROUGH */ | | 3966 | /* FALLTHROUGH */ |
4022 | default: | | 3967 | default: |
4023 | if (tp->t_bitfield) { | | 3968 | if (tp->t_bitfield) { |
4024 | /* cannot take size/alignment of bit-field */ | | 3969 | /* cannot take size/alignment of bit-field */ |
4025 | error(145); | | 3970 | error(145); |
4026 | } | | 3971 | } |
4027 | if (tp->t_tspec == VOID) { | | 3972 | if (tp->t_tspec == VOID) { |
4028 | /* cannot take size/alignment of void */ | | 3973 | /* cannot take size/alignment of void */ |
4029 | error(146); | | 3974 | error(146); |
4030 | elsz = 1; | | 3975 | elsz = 1; |
4031 | } else { | | 3976 | } else { |
4032 | elsz = size_in_bits(tp->t_tspec); | | 3977 | elsz = size_in_bits(tp->t_tspec); |
4033 | lint_assert(elsz > 0); | | 3978 | lint_assert(elsz > 0); |
4034 | } | | 3979 | } |
4035 | break; | | 3980 | break; |
4036 | } | | 3981 | } |
4037 | | | 3982 | |
4038 | return elem * elsz; | | 3983 | return elem * elsz; |
4039 | } | | 3984 | } |
4040 | | | 3985 | |
4041 | tnode_t * | | 3986 | tnode_t * |
4042 | build_alignof(const type_t *tp) | | 3987 | build_alignof(const type_t *tp) |
4043 | { | | 3988 | { |
4044 | switch (tp->t_tspec) { | | 3989 | switch (tp->t_tspec) { |
4045 | case ARRAY: | | 3990 | case ARRAY: |
4046 | break; | | 3991 | break; |
4047 | | | 3992 | |
4048 | case FUNC: | | 3993 | case FUNC: |
4049 | /* cannot take size/alignment of function type '%s' */ | | 3994 | /* cannot take size/alignment of function type '%s' */ |
4050 | error(144, type_name(tp)); | | 3995 | error(144, type_name(tp)); |
4051 | return 0; | | 3996 | return 0; |
4052 | | | 3997 | |
4053 | case STRUCT: | | 3998 | case STRUCT: |
4054 | case UNION: | | 3999 | case UNION: |
4055 | if (is_incomplete(tp)) { | | 4000 | if (is_incomplete(tp)) { |
4056 | /* cannot take size/alignment of incomplete type */ | | 4001 | /* cannot take size/alignment of incomplete type */ |
4057 | error(143); | | 4002 | error(143); |
4058 | return 0; | | 4003 | return 0; |
4059 | } | | 4004 | } |
4060 | break; | | 4005 | break; |
4061 | case ENUM: | | 4006 | case ENUM: |
4062 | break; | | 4007 | break; |
4063 | default: | | 4008 | default: |
4064 | if (tp->t_bitfield) { | | 4009 | if (tp->t_bitfield) { |
4065 | /* cannot take size/alignment of bit-field */ | | 4010 | /* cannot take size/alignment of bit-field */ |
4066 | error(145); | | 4011 | error(145); |
4067 | return 0; | | 4012 | return 0; |
4068 | } | | 4013 | } |
4069 | if (tp->t_tspec == VOID) { | | 4014 | if (tp->t_tspec == VOID) { |
4070 | /* cannot take size/alignment of void */ | | 4015 | /* cannot take size/alignment of void */ |
4071 | error(146); | | 4016 | error(146); |
4072 | return 0; | | 4017 | return 0; |
4073 | } | | 4018 | } |
4074 | break; | | 4019 | break; |
4075 | } | | 4020 | } |
4076 | | | 4021 | |
4077 | return build_integer_constant(SIZEOF_TSPEC, | | 4022 | return build_integer_constant(SIZEOF_TSPEC, |
4078 | (int64_t)alignment_in_bits(tp) / CHAR_SIZE); | | 4023 | (int64_t)alignment_in_bits(tp) / CHAR_SIZE); |
4079 | } | | 4024 | } |
4080 | | | 4025 | |
4081 | static tnode_t * | | 4026 | static tnode_t * |
4082 | cast_to_union(const tnode_t *otn, type_t *ntp) | | 4027 | cast_to_union(const tnode_t *otn, type_t *ntp) |
4083 | { | | 4028 | { |
4084 | | | 4029 | |
4085 | if (!allow_gcc) { | | 4030 | if (!allow_gcc) { |
4086 | /* union cast is a GCC extension */ | | 4031 | /* union cast is a GCC extension */ |
4087 | error(328); | | 4032 | error(328); |
4088 | return NULL; | | 4033 | return NULL; |
4089 | } | | 4034 | } |
4090 | | | 4035 | |
4091 | for (const sym_t *m = ntp->t_str->sou_first_member; | | 4036 | for (const sym_t *m = ntp->t_str->sou_first_member; |
4092 | m != NULL; m = m->s_next) { | | 4037 | m != NULL; m = m->s_next) { |
4093 | if (types_compatible(m->s_type, otn->tn_type, | | 4038 | if (types_compatible(m->s_type, otn->tn_type, |
4094 | false, false, NULL)) { | | 4039 | false, false, NULL)) { |
4095 | tnode_t *ntn = expr_alloc_tnode(); | | 4040 | tnode_t *ntn = expr_alloc_tnode(); |
4096 | ntn->tn_op = CVT; | | 4041 | ntn->tn_op = CVT; |
4097 | ntn->tn_type = ntp; | | 4042 | ntn->tn_type = ntp; |
4098 | ntn->tn_cast = true; | | 4043 | ntn->tn_cast = true; |
4099 | ntn->tn_right = NULL; | | 4044 | ntn->tn_right = NULL; |
4100 | return ntn; | | 4045 | return ntn; |
4101 | } | | 4046 | } |
4102 | } | | 4047 | } |
4103 | | | 4048 | |
4104 | /* type '%s' is not a member of '%s' */ | | 4049 | /* type '%s' is not a member of '%s' */ |
4105 | error(329, type_name(otn->tn_type), type_name(ntp)); | | 4050 | error(329, type_name(otn->tn_type), type_name(ntp)); |
4106 | return NULL; | | 4051 | return NULL; |
4107 | } | | 4052 | } |
4108 | | | 4053 | |
4109 | /* | | 4054 | /* |
4110 | * Type casts. | | 4055 | * Type casts. |
4111 | */ | | 4056 | */ |
4112 | tnode_t * | | 4057 | tnode_t * |
4113 | cast(tnode_t *tn, type_t *tp) | | 4058 | cast(tnode_t *tn, type_t *tp) |
4114 | { | | 4059 | { |
4115 | tspec_t nt, ot; | | 4060 | tspec_t nt, ot; |
4116 | | | 4061 | |
4117 | if (tn == NULL) | | 4062 | if (tn == NULL) |
4118 | return NULL; | | 4063 | return NULL; |
4119 | | | 4064 | |
4120 | tn = cconv(tn); | | 4065 | tn = cconv(tn); |
4121 | | | 4066 | |
4122 | lint_assert(tp != NULL); | | 4067 | lint_assert(tp != NULL); |
4123 | nt = tp->t_tspec; | | 4068 | nt = tp->t_tspec; |
4124 | ot = tn->tn_type->t_tspec; | | 4069 | ot = tn->tn_type->t_tspec; |
4125 | | | 4070 | |
4126 | if (nt == VOID) { | | 4071 | if (nt == VOID) { |
4127 | /* | | 4072 | /* |
4128 | * C90 6.3.4, C99 6.5.4p2 and C11 6.5.4p2 allow any type to | | 4073 | * C90 6.3.4, C99 6.5.4p2 and C11 6.5.4p2 allow any type to |
4129 | * be cast to void. The only other allowed casts are from a | | 4074 | * be cast to void. The only other allowed casts are from a |
4130 | * scalar type to a scalar type. | | 4075 | * scalar type to a scalar type. |
4131 | */ | | 4076 | */ |
4132 | } else if (nt == UNION) { | | 4077 | } else if (nt == UNION) { |
4133 | return cast_to_union(tn, tp); | | 4078 | return cast_to_union(tn, tp); |
4134 | } else if (nt == STRUCT || nt == ARRAY || nt == FUNC) { | | 4079 | } else if (nt == STRUCT || nt == ARRAY || nt == FUNC) { |
4135 | /* Casting to a struct is an undocumented GCC extension. */ | | 4080 | /* Casting to a struct is an undocumented GCC extension. */ |
4136 | if (!(allow_gcc && nt == STRUCT)) | | 4081 | if (!(allow_gcc && nt == STRUCT)) |
4137 | goto invalid_cast; | | 4082 | goto invalid_cast; |
4138 | } else if (is_struct_or_union(ot)) { | | 4083 | } else if (is_struct_or_union(ot)) { |
4139 | goto invalid_cast; | | 4084 | goto invalid_cast; |
4140 | } else if (ot == VOID) { | | 4085 | } else if (ot == VOID) { |
4141 | /* improper cast of void expression */ | | 4086 | /* improper cast of void expression */ |
4142 | error(148); | | 4087 | error(148); |
4143 | return NULL; | | 4088 | return NULL; |
4144 | } else if (is_integer(nt) && is_scalar(ot)) { | | 4089 | } else if (is_integer(nt) && is_scalar(ot)) { |
4145 | /* ok */ | | 4090 | /* ok */ |
4146 | } else if (is_floating(nt) && is_arithmetic(ot)) { | | 4091 | } else if (is_floating(nt) && is_arithmetic(ot)) { |
4147 | /* ok */ | | 4092 | /* ok */ |
4148 | } else if (nt == PTR && is_integer(ot)) { | | 4093 | } else if (nt == PTR && is_integer(ot)) { |
4149 | /* ok */ | | 4094 | /* ok */ |
4150 | } else if (nt == PTR && ot == PTR) { | | 4095 | } else if (nt == PTR && ot == PTR) { |
4151 | if (!tp->t_subt->t_const && tn->tn_type->t_subt->t_const) { | | 4096 | if (!tp->t_subt->t_const && tn->tn_type->t_subt->t_const) { |
4152 | if (hflag) | | 4097 | if (hflag) |
4153 | /* cast discards 'const' from type '%s' */ | | 4098 | /* cast discards 'const' from type '%s' */ |
4154 | warning(275, type_name(tn->tn_type)); | | 4099 | warning(275, type_name(tn->tn_type)); |
4155 | } | | 4100 | } |
4156 | } else | | 4101 | } else |
4157 | goto invalid_cast; | | 4102 | goto invalid_cast; |
4158 | | | 4103 | |
4159 | if (any_query_enabled && types_compatible(tp, tn->tn_type, | | 4104 | if (any_query_enabled && types_compatible(tp, tn->tn_type, |
4160 | false, false, NULL)) { | | 4105 | false, false, NULL)) { |
4161 | /* no-op cast from '%s' to '%s' */ | | 4106 | /* no-op cast from '%s' to '%s' */ |
4162 | query_message(6, type_name(tn->tn_type), type_name(tp)); | | 4107 | query_message(6, type_name(tn->tn_type), type_name(tp)); |
4163 | } | | 4108 | } |
4164 | | | 4109 | |
4165 | tn = convert(CVT, 0, tp, tn); | | 4110 | tn = convert(CVT, 0, tp, tn); |
4166 | tn->tn_cast = true; | | 4111 | tn->tn_cast = true; |
4167 | | | 4112 | |
4168 | return tn; | | 4113 | return tn; |
4169 | | | 4114 | |
4170 | invalid_cast: | | 4115 | invalid_cast: |
4171 | /* invalid cast from '%s' to '%s' */ | | 4116 | /* invalid cast from '%s' to '%s' */ |
4172 | error(147, type_name(tn->tn_type), type_name(tp)); | | 4117 | error(147, type_name(tn->tn_type), type_name(tp)); |
4173 | return NULL; | | 4118 | return NULL; |
4174 | } | | 4119 | } |
4175 | | | 4120 | |
4176 | /* | | 4121 | /* |
4177 | * Create the node for a function argument. | | 4122 | * Create the node for a function argument. |
4178 | * All necessary conversions and type checks are done in | | 4123 | * All necessary conversions and type checks are done in |
4179 | * build_function_call because build_function_argument has no | | 4124 | * build_function_call because build_function_argument has no |
4180 | * information about expected argument types. | | 4125 | * information about expected argument types. |
4181 | */ | | 4126 | */ |
4182 | tnode_t * | | 4127 | tnode_t * |
4183 | build_function_argument(tnode_t *args, tnode_t *arg) | | 4128 | build_function_argument(tnode_t *args, tnode_t *arg) |
4184 | { | | 4129 | { |
4185 | /* | | 4130 | /* |
4186 | * If there was a serious error in the expression for the argument, | | 4131 | * If there was a serious error in the expression for the argument, |
4187 | * create a dummy argument so the positions of the remaining arguments | | 4132 | * create a dummy argument so the positions of the remaining arguments |
4188 | * will not change. | | 4133 | * will not change. |
4189 | */ | | 4134 | */ |
4190 | if (arg == NULL) | | 4135 | if (arg == NULL) |
4191 | arg = build_integer_constant(INT, 0); | | 4136 | arg = build_integer_constant(INT, 0); |
4192 | | | 4137 | |
4193 | return new_tnode(PUSH, arg->tn_sys, arg->tn_type, arg, args); | | 4138 | return new_tnode(PUSH, arg->tn_sys, arg->tn_type, arg, args); |
4194 | } | | 4139 | } |
4195 | | | 4140 | |
4196 | /* | | 4141 | /* |
4197 | * Compare the type of an argument with the corresponding type of a | | 4142 | * Compare the type of an argument with the corresponding type of a |
4198 | * prototype parameter. If it is a valid combination, but both types | | 4143 | * prototype parameter. If it is a valid combination, but both types |
4199 | * are not the same, insert a conversion to convert the argument into | | 4144 | * are not the same, insert a conversion to convert the argument into |
4200 | * the type of the parameter. | | 4145 | * the type of the parameter. |
4201 | */ | | 4146 | */ |
4202 | static tnode_t * | | 4147 | static tnode_t * |
4203 | check_prototype_argument( | | 4148 | check_prototype_argument( |
4204 | int n, /* pos of arg */ | | 4149 | int n, /* pos of arg */ |
4205 | type_t *tp, /* expected type (from prototype) */ | | 4150 | type_t *tp, /* expected type (from prototype) */ |
4206 | tnode_t *tn) /* argument */ | | 4151 | tnode_t *tn) /* argument */ |
4207 | { | | 4152 | { |
4208 | tnode_t *ln; | | 4153 | tnode_t *ln = xcalloc(1, sizeof(*ln)); |
4209 | bool dowarn; | | | |
4210 | | | | |
4211 | ln = xcalloc(1, sizeof(*ln)); | | | |
4212 | ln->tn_type = expr_unqualified_type(tp); | | 4154 | ln->tn_type = expr_unqualified_type(tp); |
4213 | ln->tn_lvalue = true; | | 4155 | ln->tn_lvalue = true; |
4214 | if (typeok(FARG, n, ln, tn)) { | | 4156 | if (typeok(FARG, n, ln, tn)) { |
| | | 4157 | bool dowarn; |
4215 | if (!types_compatible(tp, tn->tn_type, | | 4158 | if (!types_compatible(tp, tn->tn_type, |
4216 | true, false, (dowarn = false, &dowarn)) || dowarn) | | 4159 | true, false, (dowarn = false, &dowarn)) || dowarn) |
4217 | tn = convert(FARG, n, tp, tn); | | 4160 | tn = convert(FARG, n, tp, tn); |
4218 | } | | 4161 | } |
4219 | free(ln); | | 4162 | free(ln); |
4220 | return tn; | | 4163 | return tn; |
4221 | } | | 4164 | } |
4222 | | | 4165 | |
4223 | /* | | 4166 | /* |
4224 | * Check types of all function arguments and insert conversions, | | 4167 | * Check types of all function arguments and insert conversions, |
4225 | * if necessary. | | 4168 | * if necessary. |
4226 | */ | | 4169 | */ |
4227 | static tnode_t * | | 4170 | static tnode_t * |
4228 | check_function_arguments(type_t *ftp, tnode_t *args) | | 4171 | check_function_arguments(type_t *ftp, tnode_t *args) |
4229 | { | | 4172 | { |
4230 | tnode_t *arg; | | 4173 | tnode_t *arg; |
4231 | sym_t *asym; | | 4174 | sym_t *asym; |
4232 | tspec_t at; | | 4175 | tspec_t at; |
4233 | int narg, npar, n, i; | | 4176 | int narg, npar, n, i; |
4234 | | | 4177 | |
4235 | /* get # of args in the prototype */ | | 4178 | /* get # of args in the prototype */ |
4236 | npar = 0; | | 4179 | npar = 0; |
4237 | for (asym = ftp->t_args; asym != NULL; asym = asym->s_next) | | 4180 | for (asym = ftp->t_args; asym != NULL; asym = asym->s_next) |
4238 | npar++; | | 4181 | npar++; |
4239 | | | 4182 | |
4240 | /* get # of args in function call */ | | 4183 | /* get # of args in function call */ |
4241 | narg = 0; | | 4184 | narg = 0; |
4242 | for (arg = args; arg != NULL; arg = arg->tn_right) | | 4185 | for (arg = args; arg != NULL; arg = arg->tn_right) |
4243 | narg++; | | 4186 | narg++; |
4244 | | | 4187 | |
4245 | asym = ftp->t_args; | | 4188 | asym = ftp->t_args; |
4246 | if (ftp->t_proto && npar != narg && !(ftp->t_vararg && npar < narg)) { | | 4189 | if (ftp->t_proto && npar != narg && !(ftp->t_vararg && npar < narg)) { |
4247 | /* argument mismatch: %d %s passed, %d expected */ | | 4190 | /* argument mismatch: %d %s passed, %d expected */ |
4248 | error(150, narg, narg > 1 ? "arguments" : "argument", npar); | | 4191 | error(150, narg, narg > 1 ? "arguments" : "argument", npar); |
4249 | asym = NULL; | | 4192 | asym = NULL; |
4250 | } | | 4193 | } |
4251 | | | 4194 | |
4252 | for (n = 1; n <= narg; n++) { | | 4195 | for (n = 1; n <= narg; n++) { |
4253 | | | 4196 | |
4254 | /* | | 4197 | /* |
4255 | * The rightmost argument is at the top of the argument | | 4198 | * The rightmost argument is at the top of the argument |
4256 | * subtree. | | 4199 | * subtree. |
4257 | */ | | 4200 | */ |
4258 | for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) | | 4201 | for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) |
4259 | continue; | | 4202 | continue; |
4260 | | | 4203 | |
4261 | /* some things which are always not allowed */ | | 4204 | /* some things which are always not allowed */ |
4262 | if ((at = arg->tn_left->tn_type->t_tspec) == VOID) { | | 4205 | if ((at = arg->tn_left->tn_type->t_tspec) == VOID) { |
4263 | /* void expressions may not be arguments, arg #%d */ | | 4206 | /* void expressions may not be arguments, arg #%d */ |
4264 | error(151, n); | | 4207 | error(151, n); |
4265 | return NULL; | | 4208 | return NULL; |
4266 | } else if (is_struct_or_union(at) && | | 4209 | } else if (is_struct_or_union(at) && |
4267 | is_incomplete(arg->tn_left->tn_type)) { | | 4210 | is_incomplete(arg->tn_left->tn_type)) { |
4268 | /* argument cannot have unknown size, arg #%d */ | | 4211 | /* argument cannot have unknown size, arg #%d */ |
4269 | error(152, n); | | 4212 | error(152, n); |
4270 | return NULL; | | 4213 | return NULL; |
4271 | } else if (is_integer(at) && | | 4214 | } else if (is_integer(at) && |
4272 | arg->tn_left->tn_type->t_is_enum && | | 4215 | arg->tn_left->tn_type->t_is_enum && |
4273 | is_incomplete(arg->tn_left->tn_type)) { | | 4216 | is_incomplete(arg->tn_left->tn_type)) { |
4274 | /* argument cannot have unknown size, arg #%d */ | | 4217 | /* argument cannot have unknown size, arg #%d */ |
4275 | warning(152, n); | | 4218 | warning(152, n); |
4276 | } | | 4219 | } |
4277 | | | 4220 | |
4278 | /* class conversions (arg in value context) */ | | 4221 | /* class conversions (arg in value context) */ |
4279 | arg->tn_left = cconv(arg->tn_left); | | 4222 | arg->tn_left = cconv(arg->tn_left); |
4280 | | | 4223 | |
4281 | if (asym != NULL) { | | 4224 | if (asym != NULL) { |
4282 | arg->tn_left = check_prototype_argument( | | 4225 | arg->tn_left = check_prototype_argument( |
4283 | n, asym->s_type, arg->tn_left); | | 4226 | n, asym->s_type, arg->tn_left); |
4284 | } else { | | 4227 | } else { |
4285 | arg->tn_left = promote(NOOP, true, arg->tn_left); | | 4228 | arg->tn_left = promote(NOOP, true, arg->tn_left); |
4286 | } | | 4229 | } |
4287 | arg->tn_type = arg->tn_left->tn_type; | | 4230 | arg->tn_type = arg->tn_left->tn_type; |
4288 | | | 4231 | |
4289 | if (asym != NULL) | | 4232 | if (asym != NULL) |
4290 | asym = asym->s_next; | | 4233 | asym = asym->s_next; |
4291 | } | | 4234 | } |
4292 | | | 4235 | |
4293 | return args; | | 4236 | return args; |
4294 | } | | 4237 | } |
4295 | | | 4238 | |
4296 | /* | | 4239 | /* |
4297 | * Create the node for a function call. Also check types of | | 4240 | * Create the node for a function call. Also check types of |
4298 | * function arguments and insert conversions, if necessary. | | 4241 | * function arguments and insert conversions, if necessary. |
4299 | */ | | 4242 | */ |
4300 | tnode_t * | | 4243 | tnode_t * |
4301 | build_function_call(tnode_t *func, bool sys, tnode_t *args) | | 4244 | build_function_call(tnode_t *func, bool sys, tnode_t *args) |
4302 | { | | 4245 | { |
4303 | tnode_t *ntn; | | 4246 | tnode_t *ntn; |
4304 | op_t fcop; | | 4247 | op_t fcop; |
4305 | | | 4248 | |
4306 | if (func == NULL) | | 4249 | if (func == NULL) |
4307 | return NULL; | | 4250 | return NULL; |
4308 | | | 4251 | |
4309 | if (func->tn_op == NAME && func->tn_type->t_tspec == FUNC) { | | 4252 | if (func->tn_op == NAME && func->tn_type->t_tspec == FUNC) { |
4310 | fcop = CALL; | | 4253 | fcop = CALL; |
4311 | } else { | | 4254 | } else { |
4312 | fcop = ICALL; | | 4255 | fcop = ICALL; |
4313 | } | | 4256 | } |
4314 | | | 4257 | |
4315 | check_ctype_function_call(func, args); | | 4258 | check_ctype_function_call(func, args); |
4316 | | | 4259 | |
4317 | /* | | 4260 | /* |
4318 | * after cconv() func will always be a pointer to a function | | 4261 | * after cconv() func will always be a pointer to a function |
4319 | * if it is a valid function designator. | | 4262 | * if it is a valid function designator. |
4320 | */ | | 4263 | */ |
4321 | func = cconv(func); | | 4264 | func = cconv(func); |
4322 | | | 4265 | |
4323 | if (func->tn_type->t_tspec != PTR || | | 4266 | if (func->tn_type->t_tspec != PTR || |
4324 | func->tn_type->t_subt->t_tspec != FUNC) { | | 4267 | func->tn_type->t_subt->t_tspec != FUNC) { |
4325 | /* cannot call '%s', must be a function */ | | 4268 | /* cannot call '%s', must be a function */ |
4326 | error(149, type_name(func->tn_type)); | | 4269 | error(149, type_name(func->tn_type)); |
4327 | return NULL; | | 4270 | return NULL; |
4328 | } | | 4271 | } |
4329 | | | 4272 | |
4330 | args = check_function_arguments(func->tn_type->t_subt, args); | | 4273 | args = check_function_arguments(func->tn_type->t_subt, args); |
4331 | | | 4274 | |
4332 | ntn = new_tnode(fcop, sys, func->tn_type->t_subt->t_subt, func, args); | | 4275 | ntn = new_tnode(fcop, sys, func->tn_type->t_subt->t_subt, func, args); |
4333 | | | 4276 | |
4334 | return ntn; | | 4277 | return ntn; |
4335 | } | | 4278 | } |
4336 | | | 4279 | |
4337 | /* | | 4280 | /* |
4338 | * Return the value of an integral constant expression. | | 4281 | * Return the value of an integral constant expression. |
4339 | * If the expression is not constant or its type is not an integer | | 4282 | * If the expression is not constant or its type is not an integer |
4340 | * type, an error message is printed. | | 4283 | * type, an error message is printed. |
4341 | */ | | 4284 | */ |
4342 | val_t * | | 4285 | val_t * |
4343 | constant(tnode_t *tn, bool required) | | 4286 | constant(tnode_t *tn, bool required) |
4344 | { | | 4287 | { |
4345 | val_t *v; | | | |
4346 | | | 4288 | |
4347 | if (tn != NULL) | | 4289 | if (tn != NULL) |
4348 | tn = cconv(tn); | | 4290 | tn = cconv(tn); |
4349 | if (tn != NULL) | | 4291 | if (tn != NULL) |
4350 | tn = promote(NOOP, false, tn); | | 4292 | tn = promote(NOOP, false, tn); |
4351 | | | 4293 | |
4352 | v = xcalloc(1, sizeof(*v)); | | 4294 | val_t *v = xcalloc(1, sizeof(*v)); |
4353 | | | 4295 | |
4354 | if (tn == NULL) { | | 4296 | if (tn == NULL) { |
4355 | lint_assert(nerr != 0); | | 4297 | lint_assert(nerr != 0); |
4356 | debug_step("constant node is null; returning 1 instead"); | | 4298 | debug_step("constant node is null; returning 1 instead"); |
4357 | v->v_tspec = INT; | | 4299 | v->v_tspec = INT; |
4358 | v->v_quad = 1; | | 4300 | v->v_quad = 1; |
4359 | return v; | | 4301 | return v; |
4360 | } | | 4302 | } |
4361 | | | 4303 | |
4362 | v->v_tspec = tn->tn_type->t_tspec; | | 4304 | v->v_tspec = tn->tn_type->t_tspec; |
4363 | | | 4305 | |
4364 | if (tn->tn_op == CON) { | | 4306 | if (tn->tn_op == CON) { |
4365 | lint_assert(tn->tn_type->t_tspec == tn->tn_val->v_tspec); | | 4307 | lint_assert(tn->tn_type->t_tspec == tn->tn_val->v_tspec); |
4366 | if (is_integer(tn->tn_val->v_tspec)) { | | 4308 | if (is_integer(tn->tn_val->v_tspec)) { |
4367 | v->v_unsigned_since_c90 = | | 4309 | v->v_unsigned_since_c90 = |
4368 | tn->tn_val->v_unsigned_since_c90; | | 4310 | tn->tn_val->v_unsigned_since_c90; |
4369 | v->v_quad = tn->tn_val->v_quad; | | 4311 | v->v_quad = tn->tn_val->v_quad; |
4370 | return v; | | 4312 | return v; |
4371 | } | | 4313 | } |
4372 | v->v_quad = tn->tn_val->v_ldbl; | | 4314 | v->v_quad = tn->tn_val->v_ldbl; |
4373 | } else { | | 4315 | } else { |
4374 | v->v_quad = 1; | | 4316 | v->v_quad = 1; |
4375 | } | | 4317 | } |
4376 | | | 4318 | |
4377 | if (required) | | 4319 | if (required) |
4378 | /* integral constant expression expected */ | | 4320 | /* integral constant expression expected */ |
4379 | error(55); | | 4321 | error(55); |
4380 | else | | 4322 | else |
4381 | /* variable array dimension is a C99/GCC extension */ | | 4323 | /* variable array dimension is a C99/GCC extension */ |
4382 | c99ism(318); | | 4324 | c99ism(318); |
4383 | | | 4325 | |
4384 | if (!is_integer(v->v_tspec)) | | 4326 | if (!is_integer(v->v_tspec)) |
4385 | v->v_tspec = INT; | | 4327 | v->v_tspec = INT; |
4386 | | | 4328 | |
4387 | return v; | | 4329 | return v; |
4388 | } | | 4330 | } |
4389 | | | 4331 | |
4390 | static bool | | 4332 | static bool |
4391 | is_constcond_false(const tnode_t *tn, tspec_t t) | | 4333 | is_constcond_false(const tnode_t *tn, tspec_t t) |
4392 | { | | 4334 | { |
4393 | return (t == BOOL || t == INT) && | | 4335 | return (t == BOOL || t == INT) && |
4394 | tn->tn_op == CON && tn->tn_val->v_quad == 0; | | 4336 | tn->tn_op == CON && tn->tn_val->v_quad == 0; |
4395 | } | | 4337 | } |
4396 | | | 4338 | |
4397 | /* | | 4339 | /* |
4398 | * Perform some tests on expressions which can't be done in build_binary() | | 4340 | * Perform some tests on expressions which can't be done in build_binary() |
4399 | * and functions called by build_binary(). These tests must be done here | | 4341 | * and functions called by build_binary(). These tests must be done here |
4400 | * because we need some information about the context in which the operations | | 4342 | * because we need some information about the context in which the operations |
4401 | * are performed. | | 4343 | * are performed. |
4402 | * After all tests are performed and dofreeblk is true, expr() frees the | | 4344 | * After all tests are performed and dofreeblk is true, expr() frees the |
4403 | * memory which is used for the expression. | | 4345 | * memory which is used for the expression. |
4404 | */ | | 4346 | */ |
4405 | void | | 4347 | void |
4406 | expr(tnode_t *tn, bool vctx, bool cond, bool dofreeblk, bool is_do_while) | | 4348 | expr(tnode_t *tn, bool vctx, bool cond, bool dofreeblk, bool is_do_while) |
4407 | { | | 4349 | { |
4408 | | | 4350 | |
4409 | if (tn == NULL) { /* in case of errors */ | | 4351 | if (tn == NULL) { /* in case of errors */ |
4410 | expr_free_all(); | | 4352 | expr_free_all(); |
4411 | return; | | 4353 | return; |
4412 | } | | 4354 | } |
4413 | | | 4355 | |
4414 | /* expr() is also called in global initializations */ | | 4356 | /* expr() is also called in global initializations */ |
4415 | if (dcs->d_kind != DK_EXTERN && !is_do_while) | | 4357 | if (dcs->d_kind != DK_EXTERN && !is_do_while) |
4416 | check_statement_reachable(); | | 4358 | check_statement_reachable(); |
4417 | | | 4359 | |
4418 | check_expr_misc(tn, vctx, cond, !cond, false, false, false); | | 4360 | check_expr_misc(tn, vctx, cond, !cond, false, false, false); |
4419 | if (tn->tn_op == ASSIGN) { | | 4361 | if (tn->tn_op == ASSIGN) { |
4420 | if (hflag && cond) | | 4362 | if (hflag && cond) |
4421 | /* assignment in conditional context */ | | 4363 | /* assignment in conditional context */ |
4422 | warning(159); | | 4364 | warning(159); |
4423 | } else if (tn->tn_op == CON) { | | 4365 | } else if (tn->tn_op == CON) { |
4424 | if (hflag && cond && !constcond_flag && | | 4366 | if (hflag && cond && !constcond_flag && |
4425 | !tn->tn_system_dependent && | | 4367 | !tn->tn_system_dependent && |
4426 | !(is_do_while && | | 4368 | !(is_do_while && |
4427 | is_constcond_false(tn, tn->tn_type->t_tspec))) | | 4369 | is_constcond_false(tn, tn->tn_type->t_tspec))) |
4428 | /* constant in conditional context */ | | 4370 | /* constant in conditional context */ |
4429 | warning(161); | | 4371 | warning(161); |
4430 | } | | 4372 | } |
4431 | if (!modtab[tn->tn_op].m_has_side_effect) { | | 4373 | if (!modtab[tn->tn_op].m_has_side_effect) { |
4432 | /* | | 4374 | /* |
4433 | * for left operands of COMMA this warning is already | | 4375 | * for left operands of COMMA this warning is already |
4434 | * printed | | 4376 | * printed |
4435 | */ | | 4377 | */ |
4436 | if (tn->tn_op != COMMA && !vctx && !cond) | | 4378 | if (tn->tn_op != COMMA && !vctx && !cond) |
4437 | check_null_effect(tn); | | 4379 | check_null_effect(tn); |
4438 | } | | 4380 | } |
4439 | debug_node(tn); | | 4381 | debug_node(tn); |
4440 | | | 4382 | |
4441 | /* free the tree memory */ | | 4383 | /* free the tree memory */ |
4442 | if (dofreeblk) | | 4384 | if (dofreeblk) |
4443 | expr_free_all(); | | 4385 | expr_free_all(); |
4444 | } | | 4386 | } |
4445 | | | 4387 | |
4446 | /* | | 4388 | /* |
4447 | * Checks the range of array indices, if possible. | | 4389 | * Checks the range of array indices, if possible. |
4448 | * amper is set if only the address of the element is used. This | | 4390 | * amper is set if only the address of the element is used. This |
4449 | * means that the index is allowed to refer to the first element | | 4391 | * means that the index is allowed to refer to the first element |
4450 | * after the array. | | 4392 | * after the array. |
4451 | */ | | 4393 | */ |
4452 | static void | | 4394 | static void |
4453 | check_array_index(tnode_t *tn, bool amper) | | 4395 | check_array_index(tnode_t *tn, bool amper) |
4454 | { | | 4396 | { |
4455 | int dim; | | 4397 | const tnode_t *ln = tn->tn_left; |
4456 | tnode_t *ln, *rn; | | 4398 | const tnode_t *rn = tn->tn_right; |
4457 | int elsz; | | | |
4458 | int64_t con; | | | |
4459 | | | | |
4460 | ln = tn->tn_left; | | | |
4461 | rn = tn->tn_right; | | | |
4462 | | | 4399 | |
4463 | /* We can only check constant indices. */ | | 4400 | /* We can only check constant indices. */ |
4464 | if (rn->tn_op != CON) | | 4401 | if (rn->tn_op != CON) |
4465 | return; | | 4402 | return; |
4466 | | | 4403 | |
4467 | /* Return if the left node does not stem from an array. */ | | 4404 | /* Return if the left node does not stem from an array. */ |
4468 | if (ln->tn_op != ADDR) | | 4405 | if (ln->tn_op != ADDR) |
4469 | return; | | 4406 | return; |
4470 | if (ln->tn_left->tn_op != STRING && ln->tn_left->tn_op != NAME) | | 4407 | if (ln->tn_left->tn_op != STRING && ln->tn_left->tn_op != NAME) |
4471 | return; | | 4408 | return; |
4472 | if (ln->tn_left->tn_type->t_tspec != ARRAY) | | 4409 | if (ln->tn_left->tn_type->t_tspec != ARRAY) |
4473 | return; | | 4410 | return; |
4474 | | | 4411 | |
4475 | /* | | 4412 | /* |
4476 | * For incomplete array types, we can print a warning only if | | 4413 | * For incomplete array types, we can print a warning only if |
4477 | * the index is negative. | | 4414 | * the index is negative. |
4478 | */ | | 4415 | */ |
4479 | if (is_incomplete(ln->tn_left->tn_type) && rn->tn_val->v_quad >= 0) | | 4416 | if (is_incomplete(ln->tn_left->tn_type) && rn->tn_val->v_quad >= 0) |
4480 | return; | | 4417 | return; |
4481 | | | 4418 | |
4482 | /* Get the size of one array element */ | | 4419 | /* Get the size of one array element */ |
4483 | if ((elsz = length_in_bits(ln->tn_type->t_subt, NULL)) == 0) | | 4420 | int elsz = length_in_bits(ln->tn_type->t_subt, NULL); |
| | | 4421 | if (elsz == 0) |
4484 | return; | | 4422 | return; |
4485 | elsz /= CHAR_SIZE; | | 4423 | elsz /= CHAR_SIZE; |
4486 | | | 4424 | |
4487 | /* Change the unit of the index from bytes to element size. */ | | 4425 | /* Change the unit of the index from bytes to element size. */ |
4488 | if (is_uinteger(rn->tn_type->t_tspec)) { | | 4426 | int64_t con; |
| | | 4427 | if (is_uinteger(rn->tn_type->t_tspec)) |
4489 | con = (uint64_t)rn->tn_val->v_quad / elsz; | | 4428 | con = (uint64_t)rn->tn_val->v_quad / elsz; |
4490 | } else { | | 4429 | else |
4491 | con = rn->tn_val->v_quad / elsz; | | 4430 | con = rn->tn_val->v_quad / elsz; |
4492 | } | | | |
4493 | | | 4431 | |
4494 | dim = ln->tn_left->tn_type->t_dim + (amper ? 1 : 0); | | 4432 | int dim = ln->tn_left->tn_type->t_dim + (amper ? 1 : 0); |
4495 | | | 4433 | |
4496 | if (!is_uinteger(rn->tn_type->t_tspec) && con < 0) { | | 4434 | if (!is_uinteger(rn->tn_type->t_tspec) && con < 0) { |
4497 | /* array subscript cannot be negative: %ld */ | | 4435 | /* array subscript cannot be negative: %ld */ |
4498 | warning(167, (long)con); | | 4436 | warning(167, (long)con); |
4499 | } else if (dim > 0 && (uint64_t)con >= (uint64_t)dim) { | | 4437 | } else if (dim > 0 && (uint64_t)con >= (uint64_t)dim) { |
4500 | /* array subscript cannot be > %d: %ld */ | | 4438 | /* array subscript cannot be > %d: %ld */ |
4501 | warning(168, dim - 1, (long)con); | | 4439 | warning(168, dim - 1, (long)con); |
4502 | } | | 4440 | } |
4503 | } | | 4441 | } |
4504 | | | 4442 | |
4505 | static void | | 4443 | static void |
4506 | check_expr_addr(const tnode_t *ln, bool szof, bool fcall) | | 4444 | check_expr_addr(const tnode_t *ln, bool szof, bool fcall) |
4507 | { | | 4445 | { |
4508 | /* XXX: Taking warn_about_unreachable into account here feels wrong. */ | | 4446 | /* XXX: Taking warn_about_unreachable into account here feels wrong. */ |
4509 | if (ln->tn_op == NAME && (reached || !warn_about_unreachable)) { | | 4447 | if (ln->tn_op == NAME && (reached || !warn_about_unreachable)) { |
4510 | if (!szof) | | 4448 | if (!szof) |
4511 | mark_as_set(ln->tn_sym); | | 4449 | mark_as_set(ln->tn_sym); |
4512 | mark_as_used(ln->tn_sym, fcall, szof); | | 4450 | mark_as_used(ln->tn_sym, fcall, szof); |
4513 | } | | 4451 | } |
4514 | if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) | | 4452 | if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) |
4515 | /* check the range of array indices */ | | 4453 | /* check the range of array indices */ |
4516 | check_array_index(ln->tn_left, true); | | 4454 | check_array_index(ln->tn_left, true); |
4517 | } | | 4455 | } |
4518 | | | 4456 | |
4519 | static void | | 4457 | static void |
4520 | check_expr_load(const tnode_t *ln) | | 4458 | check_expr_load(const tnode_t *ln) |
4521 | { | | 4459 | { |
4522 | if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) | | 4460 | if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) |
4523 | /* check the range of array indices */ | | 4461 | /* check the range of array indices */ |
4524 | check_array_index(ln->tn_left, false); | | 4462 | check_array_index(ln->tn_left, false); |
4525 | } | | 4463 | } |
4526 | | | 4464 | |
4527 | static void | | 4465 | static void |
4528 | check_expr_side_effect(const tnode_t *ln, bool szof) | | 4466 | check_expr_side_effect(const tnode_t *ln, bool szof) |
4529 | { | | 4467 | { |
4530 | scl_t sc; | | | |
4531 | dinfo_t *di; | | 4468 | dinfo_t *di; |
4532 | | | 4469 | |
4533 | /* XXX: Taking warn_about_unreachable into account here feels wrong. */ | | 4470 | /* XXX: Taking warn_about_unreachable into account here feels wrong. */ |
4534 | if (ln->tn_op == NAME && (reached || !warn_about_unreachable)) { | | 4471 | if (ln->tn_op == NAME && (reached || !warn_about_unreachable)) { |
4535 | sc = ln->tn_sym->s_scl; | | 4472 | scl_t sc = ln->tn_sym->s_scl; |
4536 | /* | | 4473 | /* |
4537 | * Look if there was a asm statement in one of the | | 4474 | * Look if there was a asm statement in one of the |
4538 | * compound statements we are in. If not, we don't | | 4475 | * compound statements we are in. If not, we don't |
4539 | * print a warning. | | 4476 | * print a warning. |
4540 | */ | | 4477 | */ |
4541 | for (di = dcs; di != NULL; di = di->d_enclosing) { | | 4478 | for (di = dcs; di != NULL; di = di->d_enclosing) { |
4542 | if (di->d_asm) | | 4479 | if (di->d_asm) |
4543 | break; | | 4480 | break; |
4544 | } | | 4481 | } |
4545 | if (sc != EXTERN && sc != STATIC && | | 4482 | if (sc != EXTERN && sc != STATIC && |
4546 | !ln->tn_sym->s_set && !szof && di == NULL) { | | 4483 | !ln->tn_sym->s_set && !szof && di == NULL) { |
4547 | /* '%s' may be used before set */ | | 4484 | /* '%s' may be used before set */ |
4548 | warning(158, ln->tn_sym->s_name); | | 4485 | warning(158, ln->tn_sym->s_name); |
4549 | mark_as_set(ln->tn_sym); | | 4486 | mark_as_set(ln->tn_sym); |
4550 | } | | 4487 | } |
4551 | mark_as_used(ln->tn_sym, false, false); | | 4488 | mark_as_used(ln->tn_sym, false, false); |
4552 | } | | 4489 | } |
4553 | } | | 4490 | } |
4554 | | | 4491 | |
4555 | static void | | 4492 | static void |
4556 | check_expr_assign(const tnode_t *ln, bool szof) | | 4493 | check_expr_assign(const tnode_t *ln, bool szof) |
4557 | { | | 4494 | { |
4558 | /* XXX: Taking warn_about_unreachable into account here feels wrong. */ | | 4495 | /* XXX: Taking warn_about_unreachable into account here feels wrong. */ |
4559 | if (ln->tn_op == NAME && !szof && (reached || !warn_about_unreachable)) { | | 4496 | if (ln->tn_op == NAME && !szof && (reached || !warn_about_unreachable)) { |
4560 | mark_as_set(ln->tn_sym); | | 4497 | mark_as_set(ln->tn_sym); |
4561 | if (ln->tn_sym->s_scl == EXTERN) | | 4498 | if (ln->tn_sym->s_scl == EXTERN) |
4562 | outusg(ln->tn_sym); | | 4499 | outusg(ln->tn_sym); |
4563 | } | | 4500 | } |
4564 | if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) | | 4501 | if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) |
4565 | /* check the range of array indices */ | | 4502 | /* check the range of array indices */ |
4566 | check_array_index(ln->tn_left, false); | | 4503 | check_array_index(ln->tn_left, false); |
4567 | } | | 4504 | } |
4568 | | | 4505 | |
4569 | static void | | 4506 | static void |
4570 | check_expr_call(const tnode_t *tn, const tnode_t *ln, | | 4507 | check_expr_call(const tnode_t *tn, const tnode_t *ln, |
4571 | bool szof, bool vctx, bool cond, bool retval_discarded) | | 4508 | bool szof, bool vctx, bool cond, bool retval_discarded) |
4572 | { | | 4509 | { |
4573 | lint_assert(ln->tn_op == ADDR); | | 4510 | lint_assert(ln->tn_op == ADDR); |
4574 | lint_assert(ln->tn_left->tn_op == NAME); | | 4511 | lint_assert(ln->tn_left->tn_op == NAME); |
4575 | if (!szof && | | 4512 | if (!szof && |
4576 | !is_compiler_builtin(ln->tn_left->tn_sym->s_name)) | | 4513 | !is_compiler_builtin(ln->tn_left->tn_sym->s_name)) |
4577 | outcall(tn, vctx || cond, retval_discarded); | | 4514 | outcall(tn, vctx || cond, retval_discarded); |
4578 | } | | 4515 | } |
4579 | | | 4516 | |
4580 | static bool | | 4517 | static bool |
4581 | check_expr_op(const tnode_t *tn, op_t op, const tnode_t *ln, | | 4518 | check_expr_op(const tnode_t *tn, op_t op, const tnode_t *ln, |
4582 | bool szof, bool fcall, bool vctx, bool cond, | | 4519 | bool szof, bool fcall, bool vctx, bool cond, |
4583 | bool retval_discarded, bool eqwarn) | | 4520 | bool retval_discarded, bool eqwarn) |
4584 | { | | 4521 | { |
4585 | switch (op) { | | 4522 | switch (op) { |
4586 | case ADDR: | | 4523 | case ADDR: |
4587 | check_expr_addr(ln, szof, fcall); | | 4524 | check_expr_addr(ln, szof, fcall); |
4588 | break; | | 4525 | break; |
4589 | case LOAD: | | 4526 | case LOAD: |
4590 | check_expr_load(ln); | | 4527 | check_expr_load(ln); |
4591 | /* FALLTHROUGH */ | | 4528 | /* FALLTHROUGH */ |
4592 | case PUSH: | | 4529 | case PUSH: |
4593 | case INCBEF: | | 4530 | case INCBEF: |
4594 | case DECBEF: | | 4531 | case DECBEF: |
4595 | case INCAFT: | | 4532 | case INCAFT: |
4596 | case DECAFT: | | 4533 | case DECAFT: |
4597 | case ADDASS: | | 4534 | case ADDASS: |
4598 | case SUBASS: | | 4535 | case SUBASS: |
4599 | case MULASS: | | 4536 | case MULASS: |
4600 | case DIVASS: | | 4537 | case DIVASS: |
4601 | case MODASS: | | 4538 | case MODASS: |
4602 | case ANDASS: | | 4539 | case ANDASS: |
4603 | case ORASS: | | 4540 | case ORASS: |
4604 | case XORASS: | | 4541 | case XORASS: |
4605 | case SHLASS: | | 4542 | case SHLASS: |
4606 | case SHRASS: | | 4543 | case SHRASS: |
4607 | case REAL: | | 4544 | case REAL: |
4608 | case IMAG: | | 4545 | case IMAG: |
4609 | check_expr_side_effect(ln, szof); | | 4546 | check_expr_side_effect(ln, szof); |
4610 | break; | | 4547 | break; |
4611 | case ASSIGN: | | 4548 | case ASSIGN: |
4612 | check_expr_assign(ln, szof); | | 4549 | check_expr_assign(ln, szof); |
4613 | break; | | 4550 | break; |
4614 | case CALL: | | 4551 | case CALL: |
4615 | check_expr_call(tn, ln, szof, vctx, cond, retval_discarded); | | 4552 | check_expr_call(tn, ln, szof, vctx, cond, retval_discarded); |
4616 | break; | | 4553 | break; |
4617 | case EQ: | | 4554 | case EQ: |
4618 | if (hflag && eqwarn) | | 4555 | if (hflag && eqwarn) |
4619 | /* operator '==' found where '=' was expected */ | | 4556 | /* operator '==' found where '=' was expected */ |
4620 | warning(160); | | 4557 | warning(160); |
4621 | break; | | 4558 | break; |
4622 | case CON: | | 4559 | case CON: |
4623 | case NAME: | | 4560 | case NAME: |
4624 | case STRING: | | 4561 | case STRING: |
4625 | return false; | | 4562 | return false; |
4626 | default: | | 4563 | default: |
4627 | break; | | 4564 | break; |
4628 | } | | 4565 | } |
4629 | return true; | | 4566 | return true; |
4630 | } | | 4567 | } |
4631 | | | 4568 | |
4632 | /* | | 4569 | /* |
4633 | * vctx ??? | | 4570 | * vctx ??? |
4634 | * cond whether the expression is a condition that | | 4571 | * cond whether the expression is a condition that |
4635 | * will be compared with 0 | | 4572 | * will be compared with 0 |
4636 | * eqwarn whether the operator '==' might be a | | 4573 | * eqwarn whether the operator '==' might be a |
4637 | * misspelled '=' | | 4574 | * misspelled '=' |
4638 | * fcall whether the expression is a function call | | 4575 | * fcall whether the expression is a function call |
4639 | * retval_discarded whether the return value of a function call | | 4576 | * retval_discarded whether the return value of a function call |
4640 | * is discarded; such calls will be analyzed by | | 4577 | * is discarded; such calls will be analyzed by |
4641 | * lint2 in messages 4, 8 and 9 | | 4578 | * lint2 in messages 4, 8 and 9 |
4642 | * szof whether the expression is part of a sizeof | | 4579 | * szof whether the expression is part of a sizeof |
4643 | * expression, which means that its value is | | 4580 | * expression, which means that its value is |
4644 | * discarded since only the type is relevant | | 4581 | * discarded since only the type is relevant |
4645 | */ | | 4582 | */ |
4646 | void | | 4583 | void |
4647 | check_expr_misc(const tnode_t *tn, bool vctx, bool cond, | | 4584 | check_expr_misc(const tnode_t *tn, bool vctx, bool cond, |
4648 | bool eqwarn, bool fcall, bool retval_discarded, bool szof) | | 4585 | bool eqwarn, bool fcall, bool retval_discarded, bool szof) |
4649 | { | | 4586 | { |
4650 | tnode_t *ln, *rn; | | 4587 | tnode_t *ln, *rn; |
4651 | const mod_t *mp; | | 4588 | const mod_t *mp; |
4652 | op_t op; | | 4589 | op_t op; |
4653 | bool cvctx, ccond, eq, discard; | | 4590 | bool cvctx, ccond, eq, discard; |
4654 | | | 4591 | |
4655 | if (tn == NULL) | | 4592 | if (tn == NULL) |
4656 | return; | | 4593 | return; |
4657 | | | 4594 | |
4658 | ln = tn->tn_left; | | 4595 | ln = tn->tn_left; |
4659 | rn = tn->tn_right; | | 4596 | rn = tn->tn_right; |
4660 | mp = &modtab[op = tn->tn_op]; | | 4597 | mp = &modtab[op = tn->tn_op]; |
4661 | | | 4598 | |
4662 | if (!check_expr_op(tn, op, ln, | | 4599 | if (!check_expr_op(tn, op, ln, |
4663 | szof, fcall, vctx, cond, retval_discarded, eqwarn)) | | 4600 | szof, fcall, vctx, cond, retval_discarded, eqwarn)) |
4664 | return; | | 4601 | return; |
4665 | | | 4602 | |
4666 | cvctx = mp->m_value_context; | | 4603 | cvctx = mp->m_value_context; |
4667 | ccond = mp->m_compares_with_zero; | | 4604 | ccond = mp->m_compares_with_zero; |
4668 | eq = mp->m_warn_if_operand_eq && | | 4605 | eq = mp->m_warn_if_operand_eq && |
4669 | !ln->tn_parenthesized && | | 4606 | !ln->tn_parenthesized && |
4670 | rn != NULL && !rn->tn_parenthesized; | | 4607 | rn != NULL && !rn->tn_parenthesized; |
4671 | | | 4608 | |
4672 | /* | | 4609 | /* |
4673 | * values of operands of ':' are not used if the type of at least | | 4610 | * values of operands of ':' are not used if the type of at least |
4674 | * one of the operands (for gcc compatibility) is void | | 4611 | * one of the operands (for gcc compatibility) is void |
4675 | * XXX test/value context of QUEST should probably be used as | | 4612 | * XXX test/value context of QUEST should probably be used as |
4676 | * context for both operands of COLON | | 4613 | * context for both operands of COLON |
4677 | */ | | 4614 | */ |
4678 | if (op == COLON && tn->tn_type->t_tspec == VOID) | | 4615 | if (op == COLON && tn->tn_type->t_tspec == VOID) |
4679 | cvctx = ccond = false; | | 4616 | cvctx = ccond = false; |
4680 | discard = op == CVT && tn->tn_type->t_tspec == VOID; | | 4617 | discard = op == CVT && tn->tn_type->t_tspec == VOID; |
4681 | check_expr_misc(ln, cvctx, ccond, eq, op == CALL, discard, szof); | | 4618 | check_expr_misc(ln, cvctx, ccond, eq, op == CALL, discard, szof); |
4682 | | | 4619 | |
4683 | switch (op) { | | 4620 | switch (op) { |
4684 | case PUSH: | | 4621 | case PUSH: |
4685 | if (rn != NULL) | | 4622 | if (rn != NULL) |
4686 | check_expr_misc(rn, false, false, eq, false, false, | | 4623 | check_expr_misc(rn, false, false, eq, false, false, |
4687 | szof); | | 4624 | szof); |
4688 | break; | | 4625 | break; |
4689 | case LOGAND: | | 4626 | case LOGAND: |
4690 | case LOGOR: | | 4627 | case LOGOR: |
4691 | check_expr_misc(rn, false, true, eq, false, false, szof); | | 4628 | check_expr_misc(rn, false, true, eq, false, false, szof); |
4692 | break; | | 4629 | break; |
4693 | case COLON: | | 4630 | case COLON: |
4694 | check_expr_misc(rn, cvctx, ccond, eq, false, false, szof); | | 4631 | check_expr_misc(rn, cvctx, ccond, eq, false, false, szof); |
4695 | break; | | 4632 | break; |
4696 | case COMMA: | | 4633 | case COMMA: |
4697 | check_expr_misc(rn, vctx, cond, false, false, false, szof); | | 4634 | check_expr_misc(rn, vctx, cond, false, false, false, szof); |
4698 | break; | | 4635 | break; |
4699 | default: | | 4636 | default: |
4700 | if (mp->m_binary) | | 4637 | if (mp->m_binary) |
4701 | check_expr_misc(rn, true, false, eq, false, false, | | 4638 | check_expr_misc(rn, true, false, eq, false, false, |
4702 | szof); | | 4639 | szof); |
4703 | break; | | 4640 | break; |
4704 | } | | 4641 | } |
4705 | } | | 4642 | } |
4706 | | | 4643 | |
4707 | /* | | 4644 | /* |
4708 | * Return whether the expression can be used for static initialization. | | 4645 | * Return whether the expression can be used for static initialization. |
4709 | * | | 4646 | * |
4710 | * Constant initialization expressions must be constant or an address | | 4647 | * Constant initialization expressions must be constant or an address |
4711 | * of a static object with an optional offset. In the first case, | | 4648 | * of a static object with an optional offset. In the first case, |
4712 | * the result is returned in *offsp. In the second case, the static | | 4649 | * the result is returned in *offsp. In the second case, the static |
4713 | * object is returned in *symp and the offset in *offsp. | | 4650 | * object is returned in *symp and the offset in *offsp. |
4714 | * | | 4651 | * |
4715 | * The expression can consist of PLUS, MINUS, ADDR, NAME, STRING and | | 4652 | * The expression can consist of PLUS, MINUS, ADDR, NAME, STRING and |
4716 | * CON. Type conversions are allowed if they do not change binary | | 4653 | * CON. Type conversions are allowed if they do not change binary |
4717 | * representation (including width). | | 4654 | * representation (including width). |
4718 | * | | 4655 | * |
4719 | * C99 6.6 "Constant expressions" | | 4656 | * C99 6.6 "Constant expressions" |
4720 | * C99 6.7.8p4 restricts initializers for static storage duration | | 4657 | * C99 6.7.8p4 restricts initializers for static storage duration |
4721 | */ | | 4658 | */ |
4722 | bool | | 4659 | bool |
4723 | constant_addr(const tnode_t *tn, const sym_t **symp, ptrdiff_t *offsp) | | 4660 | constant_addr(const tnode_t *tn, const sym_t **symp, ptrdiff_t *offsp) |
4724 | { | | 4661 | { |
4725 | const sym_t *sym; | | 4662 | const sym_t *sym; |
4726 | ptrdiff_t offs1, offs2; | | 4663 | ptrdiff_t offs1, offs2; |
4727 | tspec_t t, ot; | | 4664 | tspec_t t, ot; |
4728 | | | 4665 | |
4729 | switch (tn->tn_op) { | | 4666 | switch (tn->tn_op) { |
4730 | case MINUS: | | 4667 | case MINUS: |
4731 | if (tn->tn_right->tn_op == CVT) | | 4668 | if (tn->tn_right->tn_op == CVT) |
4732 | return constant_addr(tn->tn_right, symp, offsp); | | 4669 | return constant_addr(tn->tn_right, symp, offsp); |
4733 | else if (tn->tn_right->tn_op != CON) | | 4670 | else if (tn->tn_right->tn_op != CON) |
4734 | return false; | | 4671 | return false; |
4735 | /* FALLTHROUGH */ | | 4672 | /* FALLTHROUGH */ |
4736 | case PLUS: | | 4673 | case PLUS: |
4737 | offs1 = offs2 = 0; | | 4674 | offs1 = offs2 = 0; |
4738 | if (tn->tn_left->tn_op == CON) { | | 4675 | if (tn->tn_left->tn_op == CON) { |
4739 | offs1 = (ptrdiff_t)tn->tn_left->tn_val->v_quad; | | 4676 | offs1 = (ptrdiff_t)tn->tn_left->tn_val->v_quad; |
4740 | if (!constant_addr(tn->tn_right, &sym, &offs2)) | | 4677 | if (!constant_addr(tn->tn_right, &sym, &offs2)) |
4741 | return false; | | 4678 | return false; |
4742 | } else if (tn->tn_right->tn_op == CON) { | | 4679 | } else if (tn->tn_right->tn_op == CON) { |
4743 | offs2 = (ptrdiff_t)tn->tn_right->tn_val->v_quad; | | 4680 | offs2 = (ptrdiff_t)tn->tn_right->tn_val->v_quad; |
4744 | if (tn->tn_op == MINUS) | | 4681 | if (tn->tn_op == MINUS) |
4745 | offs2 = -offs2; | | 4682 | offs2 = -offs2; |
4746 | if (!constant_addr(tn->tn_left, &sym, &offs1)) | | 4683 | if (!constant_addr(tn->tn_left, &sym, &offs1)) |
4747 | return false; | | 4684 | return false; |
4748 | } else { | | 4685 | } else { |
4749 | return false; | | 4686 | return false; |
4750 | } | | 4687 | } |
4751 | *symp = sym; | | 4688 | *symp = sym; |
4752 | *offsp = offs1 + offs2; | | 4689 | *offsp = offs1 + offs2; |
4753 | return true; | | 4690 | return true; |
4754 | case ADDR: | | 4691 | case ADDR: |
4755 | if (tn->tn_left->tn_op == NAME) { | | 4692 | if (tn->tn_left->tn_op == NAME) { |
4756 | *symp = tn->tn_left->tn_sym; | | 4693 | *symp = tn->tn_left->tn_sym; |
4757 | *offsp = 0; | | 4694 | *offsp = 0; |
4758 | return true; | | 4695 | return true; |
4759 | } else { | | 4696 | } else { |
4760 | /* | | 4697 | /* |
4761 | * If this would be the front end of a compiler we | | 4698 | * If this would be the front end of a compiler we |
4762 | * would return a label instead of 0, at least if | | 4699 | * would return a label instead of 0, at least if |
4763 | * 'tn->tn_left->tn_op == STRING'. | | 4700 | * 'tn->tn_left->tn_op == STRING'. |
4764 | */ | | 4701 | */ |
4765 | *symp = NULL; | | 4702 | *symp = NULL; |
4766 | *offsp = 0; | | 4703 | *offsp = 0; |
4767 | return true; | | 4704 | return true; |
4768 | } | | 4705 | } |
4769 | case CVT: | | 4706 | case CVT: |
4770 | t = tn->tn_type->t_tspec; | | 4707 | t = tn->tn_type->t_tspec; |
4771 | ot = tn->tn_left->tn_type->t_tspec; | | 4708 | ot = tn->tn_left->tn_type->t_tspec; |
4772 | if ((!is_integer(t) && t != PTR) || | | 4709 | if ((!is_integer(t) && t != PTR) || |
4773 | (!is_integer(ot) && ot != PTR)) { | | 4710 | (!is_integer(ot) && ot != PTR)) { |
4774 | return false; | | 4711 | return false; |
4775 | } | | 4712 | } |
4776 | #if 0 | | 4713 | #if 0 |
4777 | /* | | 4714 | /* |
4778 | * consider: | | 4715 | * consider: |
4779 | * struct foo { | | 4716 | * struct foo { |
4780 | * unsigned char a; | | 4717 | * unsigned char a; |
4781 | * } f = { | | 4718 | * } f = { |
4782 | * (unsigned char)(unsigned long) | | 4719 | * (unsigned char)(unsigned long) |
4783 | * (&(((struct foo *)0)->a)) | | 4720 | * (&(((struct foo *)0)->a)) |
4784 | * }; | | 4721 | * }; |
4785 | * since psize(unsigned long) != psize(unsigned char), | | 4722 | * since psize(unsigned long) != psize(unsigned char), |
4786 | * this fails. | | 4723 | * this fails. |
4787 | */ | | 4724 | */ |
4788 | else if (psize(t) != psize(ot)) | | 4725 | else if (psize(t) != psize(ot)) |
4789 | return -1; | | 4726 | return -1; |
4790 | #endif | | 4727 | #endif |
4791 | return constant_addr(tn->tn_left, symp, offsp); | | 4728 | return constant_addr(tn->tn_left, symp, offsp); |
4792 | default: | | 4729 | default: |
4793 | return false; | | 4730 | return false; |
4794 | } | | 4731 | } |
4795 | } | | 4732 | } |
4796 | | | 4733 | |
4797 | /* Append s2 to s1, then free s2. */ | | 4734 | /* Append s2 to s1, then free s2. */ |
4798 | strg_t * | | 4735 | strg_t * |
4799 | cat_strings(strg_t *s1, strg_t *s2) | | 4736 | cat_strings(strg_t *s1, strg_t *s2) |
4800 | { | | 4737 | { |
4801 | | | 4738 | |
4802 | if (s1->st_char != s2->st_char) { | | 4739 | if (s1->st_char != s2->st_char) { |
4803 | /* cannot concatenate wide and regular string literals */ | | 4740 | /* cannot concatenate wide and regular string literals */ |
4804 | error(292); | | 4741 | error(292); |
4805 | return s1; | | 4742 | return s1; |
4806 | } | | 4743 | } |
4807 | | | 4744 | |
4808 | size_t len1 = s1->st_len; | | 4745 | size_t len1 = s1->st_len; |
4809 | size_t len2 = s2->st_len; | | 4746 | size_t len2 = s2->st_len; |
4810 | size_t chsize = s1->st_char ? sizeof(char) : sizeof(wchar_t); | | 4747 | size_t chsize = s1->st_char ? sizeof(char) : sizeof(wchar_t); |
4811 | size_t size1 = len1 * chsize; | | 4748 | size_t size1 = len1 * chsize; |
4812 | size_t size2 = (len2 + 1) * chsize; | | 4749 | size_t size2 = (len2 + 1) * chsize; |
4813 | s1->st_mem = xrealloc(s1->st_mem, size1 + size2); | | 4750 | s1->st_mem = xrealloc(s1->st_mem, size1 + size2); |
4814 | memcpy((char *)s1->st_mem + size1, s2->st_mem, size2); | | 4751 | memcpy((char *)s1->st_mem + size1, s2->st_mem, size2); |
4815 | free(s2->st_mem); | | 4752 | free(s2->st_mem); |
4816 | | | 4753 | |
4817 | s1->st_len = len1 + len2; | | 4754 | s1->st_len = len1 + len2; |
4818 | free(s2); | | 4755 | free(s2); |
4819 | | | 4756 | |
4820 | return s1; | | 4757 | return s1; |
4821 | } | | 4758 | } |
4822 | | | 4759 | |
4823 | | | 4760 | |
4824 | typedef struct stmt_expr { | | 4761 | typedef struct stmt_expr { |
4825 | memory_pool se_mem; | | 4762 | memory_pool se_mem; |
4826 | sym_t *se_sym; | | 4763 | sym_t *se_sym; |
4827 | struct stmt_expr *se_enclosing; | | 4764 | struct stmt_expr *se_enclosing; |
4828 | } stmt_expr; | | 4765 | } stmt_expr; |
4829 | | | 4766 | |
4830 | static stmt_expr *stmt_exprs; | | 4767 | static stmt_expr *stmt_exprs; |
4831 | | | 4768 | |
4832 | void | | 4769 | void |
4833 | begin_statement_expr(void) | | 4770 | begin_statement_expr(void) |
4834 | { | | 4771 | { |
4835 | stmt_expr *se = xmalloc(sizeof(*se)); | | 4772 | stmt_expr *se = xmalloc(sizeof(*se)); |
4836 | se->se_mem = expr_save_memory(); | | 4773 | se->se_mem = expr_save_memory(); |
4837 | se->se_sym = NULL; | | 4774 | se->se_sym = NULL; |
4838 | se->se_enclosing = stmt_exprs; | | 4775 | se->se_enclosing = stmt_exprs; |
4839 | stmt_exprs = se; | | 4776 | stmt_exprs = se; |
4840 | } | | 4777 | } |
4841 | | | 4778 | |
4842 | void | | 4779 | void |
4843 | do_statement_expr(tnode_t *tn) | | 4780 | do_statement_expr(tnode_t *tn) |
4844 | { | | 4781 | { |
4845 | block_level--; | | 4782 | block_level--; |
4846 | mem_block_level--; | | 4783 | mem_block_level--; |
4847 | stmt_exprs->se_sym = tn != NULL | | 4784 | stmt_exprs->se_sym = tn != NULL |
4848 | ? mktempsym(block_dup_type(tn->tn_type)) | | 4785 | ? mktempsym(block_dup_type(tn->tn_type)) |
4849 | : NULL; /* after a syntax error */ | | 4786 | : NULL; /* after a syntax error */ |
4850 | mem_block_level++; | | 4787 | mem_block_level++; |
4851 | block_level++; | | 4788 | block_level++; |
4852 | /* ({ }) is a GCC extension */ | | 4789 | /* ({ }) is a GCC extension */ |
4853 | gnuism(320); | | 4790 | gnuism(320); |
4854 | } | | 4791 | } |
4855 | | | 4792 | |
4856 | tnode_t * | | 4793 | tnode_t * |
4857 | end_statement_expr(void) | | 4794 | end_statement_expr(void) |
4858 | { | | 4795 | { |
4859 | stmt_expr *se = stmt_exprs; | | 4796 | stmt_expr *se = stmt_exprs; |
4860 | if (se->se_sym == NULL) | | 4797 | if (se->se_sym == NULL) |
4861 | return NULL; /* after a syntax error */ | | 4798 | return NULL; /* after a syntax error */ |
4862 | tnode_t *tn = build_name(se->se_sym, false); | | 4799 | tnode_t *tn = build_name(se->se_sym, false); |
4863 | (void)expr_save_memory(); /* leak */ | | 4800 | (void)expr_save_memory(); /* leak */ |
4864 | expr_restore_memory(se->se_mem); | | 4801 | expr_restore_memory(se->se_mem); |
4865 | stmt_exprs = se->se_enclosing; | | 4802 | stmt_exprs = se->se_enclosing; |
4866 | free(se); | | 4803 | free(se); |
4867 | return tn; | | 4804 | return tn; |
4868 | } | | 4805 | } |