| @@ -1,2521 +1,2524 @@ | | | @@ -1,2521 +1,2524 @@ |
1 | /* $NetBSD: tree.c,v 1.512 2023/04/12 19:09:48 rillig Exp $ */ | | 1 | /* $NetBSD: tree.c,v 1.513 2023/04/14 18:42:31 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.512 2023/04/12 19:09:48 rillig Exp $"); | | 40 | __RCSID("$NetBSD: tree.c,v 1.513 2023/04/14 18:42:31 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 | if (t == DOUBLE) | | 1508 | if (t == DOUBLE) |
1509 | return lv < 0 ? -DBL_MAX : DBL_MAX; | | 1509 | return lv < 0 ? -DBL_MAX : DBL_MAX; |
1510 | /* | | 1510 | /* |
1511 | * When lint is compiled on x86_64 to check for sparc64, it uses the | | 1511 | * When NetBSD is cross-built in MKLINT=yes mode on x86_64 for |
1512 | * type 'long double' from x86_64, which is the Intel 80-bit format. | | 1512 | * sparc64, tools/lint checks this code while building usr.bin/xlint. |
1513 | * The constant LDBL_MAX comes from the sparc64 preprocessor though | | 1513 | * In that situation, lint uses the preprocessor for sparc64, in which |
1514 | * and uses the IEEE-754-binary128 format, with the same exponent | | 1514 | * the type 'long double' is IEEE-754-binary128, affecting the macro |
1515 | * range but a wider mantissa. | | 1515 | * LDBL_MAX below. The type 'long double', as well as the strtold |
| | | 1516 | * implementation, comes from the host platform x86_64 though, where |
| | | 1517 | * 'long double' consumes 128 bits as well but only uses 80 of them. |
| | | 1518 | * The exponent range of the two 'long double' types is the same, but |
| | | 1519 | * the maximum finite value differs due to the extended precision on |
| | | 1520 | * sparc64. |
1516 | * | | 1521 | * |
1517 | * To properly handle this situation, lint would have to implement the | | 1522 | * To properly handle the data types of the target platform, lint |
1518 | * floating-point types in a platform-independent way, which is not | | 1523 | * would have to implement the floating-point types in a |
1519 | * worth the effort, given how few programs practically use 'long | | 1524 | * platform-independent way, which is not worth the effort, given how |
1520 | * double'. | | 1525 | * few programs practically use 'long double'. |
1521 | * | | | |
1522 | * This caveat only affects cross builds. | | | |
1523 | */ | | 1526 | */ |
1524 | /* LINTED 248: floating-point constant out of range */ | | 1527 | /* LINTED 248: floating-point constant out of range */ |
1525 | ldbl_t max = LDBL_MAX; | | 1528 | ldbl_t max = LDBL_MAX; |
1526 | return lv < 0 ? -max : max; | | 1529 | return lv < 0 ? -max : max; |
1527 | } | | 1530 | } |
1528 | | | 1531 | |
1529 | /* | | 1532 | /* |
1530 | * Fold constant nodes having operands with floating point type. | | 1533 | * Fold constant nodes having operands with floating point type. |
1531 | */ | | 1534 | */ |
1532 | static tnode_t * | | 1535 | static tnode_t * |
1533 | fold_float(tnode_t *tn) | | 1536 | fold_float(tnode_t *tn) |
1534 | { | | 1537 | { |
1535 | val_t *v; | | 1538 | val_t *v; |
1536 | tspec_t t; | | 1539 | tspec_t t; |
1537 | ldbl_t lv, rv = 0; | | 1540 | ldbl_t lv, rv = 0; |
1538 | | | 1541 | |
1539 | fpe = 0; | | 1542 | fpe = 0; |
1540 | v = xcalloc(1, sizeof(*v)); | | 1543 | v = xcalloc(1, sizeof(*v)); |
1541 | v->v_tspec = t = tn->tn_type->t_tspec; | | 1544 | v->v_tspec = t = tn->tn_type->t_tspec; |
1542 | | | 1545 | |
1543 | lint_assert(is_floating(t)); | | 1546 | lint_assert(is_floating(t)); |
1544 | lint_assert(t == tn->tn_left->tn_type->t_tspec); | | 1547 | lint_assert(t == tn->tn_left->tn_type->t_tspec); |
1545 | lint_assert(!is_binary(tn) || t == tn->tn_right->tn_type->t_tspec); | | 1548 | lint_assert(!is_binary(tn) || t == tn->tn_right->tn_type->t_tspec); |
1546 | | | 1549 | |
1547 | lv = tn->tn_left->tn_val->v_ldbl; | | 1550 | lv = tn->tn_left->tn_val->v_ldbl; |
1548 | if (is_binary(tn)) | | 1551 | if (is_binary(tn)) |
1549 | rv = tn->tn_right->tn_val->v_ldbl; | | 1552 | rv = tn->tn_right->tn_val->v_ldbl; |
1550 | | | 1553 | |
1551 | switch (tn->tn_op) { | | 1554 | switch (tn->tn_op) { |
1552 | case UPLUS: | | 1555 | case UPLUS: |
1553 | v->v_ldbl = lv; | | 1556 | v->v_ldbl = lv; |
1554 | break; | | 1557 | break; |
1555 | case UMINUS: | | 1558 | case UMINUS: |
1556 | v->v_ldbl = -lv; | | 1559 | v->v_ldbl = -lv; |
1557 | break; | | 1560 | break; |
1558 | case MULT: | | 1561 | case MULT: |
1559 | v->v_ldbl = lv * rv; | | 1562 | v->v_ldbl = lv * rv; |
1560 | break; | | 1563 | break; |
1561 | case DIV: | | 1564 | case DIV: |
1562 | if (rv == 0.0) { | | 1565 | if (rv == 0.0) { |
1563 | /* division by 0 */ | | 1566 | /* division by 0 */ |
1564 | error(139); | | 1567 | error(139); |
1565 | v->v_ldbl = floating_error_value(t, lv); | | 1568 | v->v_ldbl = floating_error_value(t, lv); |
1566 | } else { | | 1569 | } else { |
1567 | v->v_ldbl = lv / rv; | | 1570 | v->v_ldbl = lv / rv; |
1568 | } | | 1571 | } |
1569 | break; | | 1572 | break; |
1570 | case PLUS: | | 1573 | case PLUS: |
1571 | v->v_ldbl = lv + rv; | | 1574 | v->v_ldbl = lv + rv; |
1572 | break; | | 1575 | break; |
1573 | case MINUS: | | 1576 | case MINUS: |
1574 | v->v_ldbl = lv - rv; | | 1577 | v->v_ldbl = lv - rv; |
1575 | break; | | 1578 | break; |
1576 | case LT: | | 1579 | case LT: |
1577 | v->v_quad = lv < rv ? 1 : 0; | | 1580 | v->v_quad = lv < rv ? 1 : 0; |
1578 | break; | | 1581 | break; |
1579 | case LE: | | 1582 | case LE: |
1580 | v->v_quad = lv <= rv ? 1 : 0; | | 1583 | v->v_quad = lv <= rv ? 1 : 0; |
1581 | break; | | 1584 | break; |
1582 | case GE: | | 1585 | case GE: |
1583 | v->v_quad = lv >= rv ? 1 : 0; | | 1586 | v->v_quad = lv >= rv ? 1 : 0; |
1584 | break; | | 1587 | break; |
1585 | case GT: | | 1588 | case GT: |
1586 | v->v_quad = lv > rv ? 1 : 0; | | 1589 | v->v_quad = lv > rv ? 1 : 0; |
1587 | break; | | 1590 | break; |
1588 | case EQ: | | 1591 | case EQ: |
1589 | v->v_quad = lv == rv ? 1 : 0; | | 1592 | v->v_quad = lv == rv ? 1 : 0; |
1590 | break; | | 1593 | break; |
1591 | case NE: | | 1594 | case NE: |
1592 | v->v_quad = lv != rv ? 1 : 0; | | 1595 | v->v_quad = lv != rv ? 1 : 0; |
1593 | break; | | 1596 | break; |
1594 | default: | | 1597 | default: |
1595 | lint_assert(/*CONSTCOND*/false); | | 1598 | lint_assert(/*CONSTCOND*/false); |
1596 | } | | 1599 | } |
1597 | | | 1600 | |
1598 | lint_assert(fpe != 0 || isnan(v->v_ldbl) == 0); | | 1601 | lint_assert(fpe != 0 || isnan(v->v_ldbl) == 0); |
1599 | if (is_complex(v->v_tspec)) { | | 1602 | if (is_complex(v->v_tspec)) { |
1600 | /* | | 1603 | /* |
1601 | * Don't warn, as lint doesn't model the imaginary part of | | 1604 | * Don't warn, as lint doesn't model the imaginary part of |
1602 | * complex numbers. | | 1605 | * complex numbers. |
1603 | */ | | 1606 | */ |
1604 | fpe = 0; | | 1607 | fpe = 0; |
1605 | } else if (fpe != 0 || isfinite(v->v_ldbl) == 0 || | | 1608 | } else if (fpe != 0 || isfinite(v->v_ldbl) == 0 || |
1606 | (t == FLOAT && | | 1609 | (t == FLOAT && |
1607 | (v->v_ldbl > FLT_MAX || v->v_ldbl < -FLT_MAX)) || | | 1610 | (v->v_ldbl > FLT_MAX || v->v_ldbl < -FLT_MAX)) || |
1608 | (t == DOUBLE && | | 1611 | (t == DOUBLE && |
1609 | (v->v_ldbl > DBL_MAX || v->v_ldbl < -DBL_MAX))) { | | 1612 | (v->v_ldbl > DBL_MAX || v->v_ldbl < -DBL_MAX))) { |
1610 | /* floating point overflow on operator '%s' */ | | 1613 | /* floating point overflow on operator '%s' */ |
1611 | warning(142, op_name(tn->tn_op)); | | 1614 | warning(142, op_name(tn->tn_op)); |
1612 | v->v_ldbl = floating_error_value(t, v->v_ldbl); | | 1615 | v->v_ldbl = floating_error_value(t, v->v_ldbl); |
1613 | fpe = 0; | | 1616 | fpe = 0; |
1614 | } | | 1617 | } |
1615 | | | 1618 | |
1616 | return build_constant(tn->tn_type, v); | | 1619 | return build_constant(tn->tn_type, v); |
1617 | } | | 1620 | } |
1618 | | | 1621 | |
1619 | /* | | 1622 | /* |
1620 | * Create a tree node for a binary operator and its two operands. Also called | | 1623 | * Create a tree node for a binary operator and its two operands. Also called |
1621 | * for unary operators; in that case rn is NULL. | | 1624 | * for unary operators; in that case rn is NULL. |
1622 | * | | 1625 | * |
1623 | * Function calls, sizeof and casts are handled elsewhere. | | 1626 | * Function calls, sizeof and casts are handled elsewhere. |
1624 | */ | | 1627 | */ |
1625 | tnode_t * | | 1628 | tnode_t * |
1626 | build_binary(tnode_t *ln, op_t op, bool sys, tnode_t *rn) | | 1629 | build_binary(tnode_t *ln, op_t op, bool sys, tnode_t *rn) |
1627 | { | | 1630 | { |
1628 | const mod_t *mp; | | 1631 | const mod_t *mp; |
1629 | tnode_t *ntn; | | 1632 | tnode_t *ntn; |
1630 | type_t *rettp; | | 1633 | type_t *rettp; |
1631 | | | 1634 | |
1632 | mp = &modtab[op]; | | 1635 | mp = &modtab[op]; |
1633 | | | 1636 | |
1634 | /* If there was an error in one of the operands, return. */ | | 1637 | /* If there was an error in one of the operands, return. */ |
1635 | if (ln == NULL || (mp->m_binary && rn == NULL)) | | 1638 | if (ln == NULL || (mp->m_binary && rn == NULL)) |
1636 | return NULL; | | 1639 | return NULL; |
1637 | | | 1640 | |
1638 | /* | | 1641 | /* |
1639 | * Apply class conversions to the left operand, but only if its | | 1642 | * Apply class conversions to the left operand, but only if its |
1640 | * value is needed or it is compared with zero. | | 1643 | * value is needed or it is compared with zero. |
1641 | */ | | 1644 | */ |
1642 | if (mp->m_value_context || mp->m_compares_with_zero) | | 1645 | if (mp->m_value_context || mp->m_compares_with_zero) |
1643 | ln = cconv(ln); | | 1646 | ln = cconv(ln); |
1644 | /* | | 1647 | /* |
1645 | * The right operand is almost always in a test or value context, | | 1648 | * The right operand is almost always in a test or value context, |
1646 | * except if it is a struct or union member. | | 1649 | * except if it is a struct or union member. |
1647 | */ | | 1650 | */ |
1648 | if (mp->m_binary && op != ARROW && op != POINT) | | 1651 | if (mp->m_binary && op != ARROW && op != POINT) |
1649 | rn = cconv(rn); | | 1652 | rn = cconv(rn); |
1650 | | | 1653 | |
1651 | /* | | 1654 | /* |
1652 | * Print some warnings for comparisons of unsigned values with | | 1655 | * Print some warnings for comparisons of unsigned values with |
1653 | * constants lower than or equal to null. This must be done | | 1656 | * constants lower than or equal to null. This must be done |
1654 | * before promote() because otherwise unsigned char and unsigned | | 1657 | * before promote() because otherwise unsigned char and unsigned |
1655 | * short would be promoted to int. Types are also tested to be | | 1658 | * short would be promoted to int. Types are also tested to be |
1656 | * CHAR, which would also become int. | | 1659 | * CHAR, which would also become int. |
1657 | */ | | 1660 | */ |
1658 | if (mp->m_comparison) | | 1661 | if (mp->m_comparison) |
1659 | check_integer_comparison(op, ln, rn); | | 1662 | check_integer_comparison(op, ln, rn); |
1660 | | | 1663 | |
1661 | if (mp->m_value_context || mp->m_compares_with_zero) | | 1664 | if (mp->m_value_context || mp->m_compares_with_zero) |
1662 | ln = promote(op, false, ln); | | 1665 | ln = promote(op, false, ln); |
1663 | if (mp->m_binary && op != ARROW && op != POINT && | | 1666 | if (mp->m_binary && op != ARROW && op != POINT && |
1664 | op != ASSIGN && op != RETURN && op != INIT) { | | 1667 | op != ASSIGN && op != RETURN && op != INIT) { |
1665 | rn = promote(op, false, rn); | | 1668 | rn = promote(op, false, rn); |
1666 | } | | 1669 | } |
1667 | | | 1670 | |
1668 | /* | | 1671 | /* |
1669 | * If the result of the operation is different for signed or | | 1672 | * If the result of the operation is different for signed or |
1670 | * unsigned operands and one of the operands is signed only in | | 1673 | * unsigned operands and one of the operands is signed only in |
1671 | * ANSI C, print a warning. | | 1674 | * ANSI C, print a warning. |
1672 | */ | | 1675 | */ |
1673 | if (mp->m_warn_if_left_unsigned_in_c90 && | | 1676 | if (mp->m_warn_if_left_unsigned_in_c90 && |
1674 | ln->tn_op == CON && ln->tn_val->v_unsigned_since_c90) { | | 1677 | ln->tn_op == CON && ln->tn_val->v_unsigned_since_c90) { |
1675 | /* ANSI C treats constant as unsigned, op '%s' */ | | 1678 | /* ANSI C treats constant as unsigned, op '%s' */ |
1676 | warning(218, mp->m_name); | | 1679 | warning(218, mp->m_name); |
1677 | ln->tn_val->v_unsigned_since_c90 = false; | | 1680 | ln->tn_val->v_unsigned_since_c90 = false; |
1678 | } | | 1681 | } |
1679 | if (mp->m_warn_if_right_unsigned_in_c90 && | | 1682 | if (mp->m_warn_if_right_unsigned_in_c90 && |
1680 | rn->tn_op == CON && rn->tn_val->v_unsigned_since_c90) { | | 1683 | rn->tn_op == CON && rn->tn_val->v_unsigned_since_c90) { |
1681 | /* ANSI C treats constant as unsigned, op '%s' */ | | 1684 | /* ANSI C treats constant as unsigned, op '%s' */ |
1682 | warning(218, mp->m_name); | | 1685 | warning(218, mp->m_name); |
1683 | rn->tn_val->v_unsigned_since_c90 = false; | | 1686 | rn->tn_val->v_unsigned_since_c90 = false; |
1684 | } | | 1687 | } |
1685 | | | 1688 | |
1686 | /* Make sure both operands are of the same type */ | | 1689 | /* Make sure both operands are of the same type */ |
1687 | if (mp->m_balance_operands || (!allow_c90 && (op == SHL || op == SHR))) | | 1690 | if (mp->m_balance_operands || (!allow_c90 && (op == SHL || op == SHR))) |
1688 | balance(op, &ln, &rn); | | 1691 | balance(op, &ln, &rn); |
1689 | | | 1692 | |
1690 | /* | | 1693 | /* |
1691 | * Check types for compatibility with the operation and mutual | | 1694 | * Check types for compatibility with the operation and mutual |
1692 | * compatibility. Return if there are serious problems. | | 1695 | * compatibility. Return if there are serious problems. |
1693 | */ | | 1696 | */ |
1694 | if (!typeok(op, 0, ln, rn)) | | 1697 | if (!typeok(op, 0, ln, rn)) |
1695 | return NULL; | | 1698 | return NULL; |
1696 | | | 1699 | |
1697 | /* And now create the node. */ | | 1700 | /* And now create the node. */ |
1698 | switch (op) { | | 1701 | switch (op) { |
1699 | case POINT: | | 1702 | case POINT: |
1700 | case ARROW: | | 1703 | case ARROW: |
1701 | ntn = build_struct_access(op, sys, ln, rn); | | 1704 | ntn = build_struct_access(op, sys, ln, rn); |
1702 | break; | | 1705 | break; |
1703 | case INCAFT: | | 1706 | case INCAFT: |
1704 | case DECAFT: | | 1707 | case DECAFT: |
1705 | case INCBEF: | | 1708 | case INCBEF: |
1706 | case DECBEF: | | 1709 | case DECBEF: |
1707 | ntn = build_prepost_incdec(op, sys, ln); | | 1710 | ntn = build_prepost_incdec(op, sys, ln); |
1708 | break; | | 1711 | break; |
1709 | case ADDR: | | 1712 | case ADDR: |
1710 | ntn = build_address(sys, ln, false); | | 1713 | ntn = build_address(sys, ln, false); |
1711 | break; | | 1714 | break; |
1712 | case INDIR: | | 1715 | case INDIR: |
1713 | ntn = new_tnode(INDIR, sys, ln->tn_type->t_subt, ln, NULL); | | 1716 | ntn = new_tnode(INDIR, sys, ln->tn_type->t_subt, ln, NULL); |
1714 | break; | | 1717 | break; |
1715 | case PLUS: | | 1718 | case PLUS: |
1716 | case MINUS: | | 1719 | case MINUS: |
1717 | ntn = build_plus_minus(op, sys, ln, rn); | | 1720 | ntn = build_plus_minus(op, sys, ln, rn); |
1718 | break; | | 1721 | break; |
1719 | case SHL: | | 1722 | case SHL: |
1720 | case SHR: | | 1723 | case SHR: |
1721 | ntn = build_bit_shift(op, sys, ln, rn); | | 1724 | ntn = build_bit_shift(op, sys, ln, rn); |
1722 | break; | | 1725 | break; |
1723 | case COLON: | | 1726 | case COLON: |
1724 | ntn = build_colon(sys, ln, rn); | | 1727 | ntn = build_colon(sys, ln, rn); |
1725 | break; | | 1728 | break; |
1726 | case ASSIGN: | | 1729 | case ASSIGN: |
1727 | case MULASS: | | 1730 | case MULASS: |
1728 | case DIVASS: | | 1731 | case DIVASS: |
1729 | case MODASS: | | 1732 | case MODASS: |
1730 | case ADDASS: | | 1733 | case ADDASS: |
1731 | case SUBASS: | | 1734 | case SUBASS: |
1732 | case SHLASS: | | 1735 | case SHLASS: |
1733 | case SHRASS: | | 1736 | case SHRASS: |
1734 | case ANDASS: | | 1737 | case ANDASS: |
1735 | case XORASS: | | 1738 | case XORASS: |
1736 | case ORASS: | | 1739 | case ORASS: |
1737 | case RETURN: | | 1740 | case RETURN: |
1738 | case INIT: | | 1741 | case INIT: |
1739 | ntn = build_assignment(op, sys, ln, rn); | | 1742 | ntn = build_assignment(op, sys, ln, rn); |
1740 | break; | | 1743 | break; |
1741 | case COMMA: | | 1744 | case COMMA: |
1742 | case QUEST: | | 1745 | case QUEST: |
1743 | ntn = new_tnode(op, sys, rn->tn_type, ln, rn); | | 1746 | ntn = new_tnode(op, sys, rn->tn_type, ln, rn); |
1744 | break; | | 1747 | break; |
1745 | case REAL: | | 1748 | case REAL: |
1746 | case IMAG: | | 1749 | case IMAG: |
1747 | ntn = build_real_imag(op, sys, ln); | | 1750 | ntn = build_real_imag(op, sys, ln); |
1748 | break; | | 1751 | break; |
1749 | default: | | 1752 | default: |
1750 | rettp = mp->m_returns_bool | | 1753 | rettp = mp->m_returns_bool |
1751 | ? gettyp(Tflag ? BOOL : INT) : ln->tn_type; | | 1754 | ? gettyp(Tflag ? BOOL : INT) : ln->tn_type; |
1752 | lint_assert(mp->m_binary == (rn != NULL)); | | 1755 | lint_assert(mp->m_binary == (rn != NULL)); |
1753 | ntn = new_tnode(op, sys, rettp, ln, rn); | | 1756 | ntn = new_tnode(op, sys, rettp, ln, rn); |
1754 | break; | | 1757 | break; |
1755 | } | | 1758 | } |
1756 | | | 1759 | |
1757 | /* Return if an error occurred. */ | | 1760 | /* Return if an error occurred. */ |
1758 | if (ntn == NULL) | | 1761 | if (ntn == NULL) |
1759 | return NULL; | | 1762 | return NULL; |
1760 | | | 1763 | |
1761 | /* Print a warning if precedence confusion is possible */ | | 1764 | /* Print a warning if precedence confusion is possible */ |
1762 | if (mp->m_possible_precedence_confusion) | | 1765 | if (mp->m_possible_precedence_confusion) |
1763 | check_precedence_confusion(ntn); | | 1766 | check_precedence_confusion(ntn); |
1764 | | | 1767 | |
1765 | /* | | 1768 | /* |
1766 | * Print a warning if one of the operands is in a context where | | 1769 | * Print a warning if one of the operands is in a context where |
1767 | * it is compared with zero and if this operand is a constant. | | 1770 | * it is compared with zero and if this operand is a constant. |
1768 | */ | | 1771 | */ |
1769 | if (hflag && !constcond_flag && | | 1772 | if (hflag && !constcond_flag && |
1770 | mp->m_compares_with_zero && | | 1773 | mp->m_compares_with_zero && |
1771 | (ln->tn_op == CON || | | 1774 | (ln->tn_op == CON || |
1772 | ((mp->m_binary && op != QUEST) && rn->tn_op == CON)) && | | 1775 | ((mp->m_binary && op != QUEST) && rn->tn_op == CON)) && |
1773 | /* XXX: rn->tn_system_dependent should be checked as well */ | | 1776 | /* XXX: rn->tn_system_dependent should be checked as well */ |
1774 | !ln->tn_system_dependent) { | | 1777 | !ln->tn_system_dependent) { |
1775 | /* constant in conditional context */ | | 1778 | /* constant in conditional context */ |
1776 | warning(161); | | 1779 | warning(161); |
1777 | } | | 1780 | } |
1778 | | | 1781 | |
1779 | /* Fold if the operator requires it */ | | 1782 | /* Fold if the operator requires it */ |
1780 | if (mp->m_fold_constant_operands) { | | 1783 | if (mp->m_fold_constant_operands) { |
1781 | if (ln->tn_op == CON && (!mp->m_binary || rn->tn_op == CON)) { | | 1784 | if (ln->tn_op == CON && (!mp->m_binary || rn->tn_op == CON)) { |
1782 | if (mp->m_compares_with_zero) { | | 1785 | if (mp->m_compares_with_zero) { |
1783 | ntn = fold_bool(ntn); | | 1786 | ntn = fold_bool(ntn); |
1784 | } else if (is_floating(ntn->tn_type->t_tspec)) { | | 1787 | } else if (is_floating(ntn->tn_type->t_tspec)) { |
1785 | ntn = fold_float(ntn); | | 1788 | ntn = fold_float(ntn); |
1786 | } else { | | 1789 | } else { |
1787 | ntn = fold(ntn); | | 1790 | ntn = fold(ntn); |
1788 | } | | 1791 | } |
1789 | } else if (op == QUEST && ln->tn_op == CON) { | | 1792 | } else if (op == QUEST && ln->tn_op == CON) { |
1790 | ntn = ln->tn_val->v_quad != 0 | | 1793 | ntn = ln->tn_val->v_quad != 0 |
1791 | ? rn->tn_left : rn->tn_right; | | 1794 | ? rn->tn_left : rn->tn_right; |
1792 | } | | 1795 | } |
1793 | } | | 1796 | } |
1794 | | | 1797 | |
1795 | return ntn; | | 1798 | return ntn; |
1796 | } | | 1799 | } |
1797 | | | 1800 | |
1798 | tnode_t * | | 1801 | tnode_t * |
1799 | build_unary(op_t op, bool sys, tnode_t *tn) | | 1802 | build_unary(op_t op, bool sys, tnode_t *tn) |
1800 | { | | 1803 | { |
1801 | return build_binary(tn, op, sys, NULL); | | 1804 | return build_binary(tn, op, sys, NULL); |
1802 | } | | 1805 | } |
1803 | | | 1806 | |
1804 | /* | | 1807 | /* |
1805 | * Return whether all struct/union members with the same name have the same | | 1808 | * Return whether all struct/union members with the same name have the same |
1806 | * type and offset. | | 1809 | * type and offset. |
1807 | */ | | 1810 | */ |
1808 | static bool | | 1811 | static bool |
1809 | all_members_compatible(const sym_t *msym) | | 1812 | all_members_compatible(const sym_t *msym) |
1810 | { | | 1813 | { |
1811 | for (const sym_t *csym = msym; | | 1814 | for (const sym_t *csym = msym; |
1812 | csym != NULL; csym = csym->s_symtab_next) { | | 1815 | csym != NULL; csym = csym->s_symtab_next) { |
1813 | if (!is_member(csym)) | | 1816 | if (!is_member(csym)) |
1814 | continue; | | 1817 | continue; |
1815 | if (strcmp(msym->s_name, csym->s_name) != 0) | | 1818 | if (strcmp(msym->s_name, csym->s_name) != 0) |
1816 | continue; | | 1819 | continue; |
1817 | | | 1820 | |
1818 | for (const sym_t *sym = csym->s_symtab_next; | | 1821 | for (const sym_t *sym = csym->s_symtab_next; |
1819 | sym != NULL; sym = sym->s_symtab_next) { | | 1822 | sym != NULL; sym = sym->s_symtab_next) { |
1820 | | | 1823 | |
1821 | if (!is_member(sym)) | | 1824 | if (!is_member(sym)) |
1822 | continue; | | 1825 | continue; |
1823 | if (strcmp(csym->s_name, sym->s_name) != 0) | | 1826 | if (strcmp(csym->s_name, sym->s_name) != 0) |
1824 | continue; | | 1827 | continue; |
1825 | if (csym->u.s_member.sm_offset_in_bits != | | 1828 | if (csym->u.s_member.sm_offset_in_bits != |
1826 | sym->u.s_member.sm_offset_in_bits) | | 1829 | sym->u.s_member.sm_offset_in_bits) |
1827 | return false; | | 1830 | return false; |
1828 | | | 1831 | |
1829 | bool w = false; | | 1832 | bool w = false; |
1830 | if (!types_compatible(csym->s_type, sym->s_type, | | 1833 | if (!types_compatible(csym->s_type, sym->s_type, |
1831 | false, false, &w) && !w) | | 1834 | false, false, &w) && !w) |
1832 | return false; | | 1835 | return false; |
1833 | if (csym->s_bitfield != sym->s_bitfield) | | 1836 | if (csym->s_bitfield != sym->s_bitfield) |
1834 | return false; | | 1837 | return false; |
1835 | if (csym->s_bitfield) { | | 1838 | if (csym->s_bitfield) { |
1836 | type_t *tp1 = csym->s_type; | | 1839 | type_t *tp1 = csym->s_type; |
1837 | type_t *tp2 = sym->s_type; | | 1840 | type_t *tp2 = sym->s_type; |
1838 | if (tp1->t_flen != tp2->t_flen) | | 1841 | if (tp1->t_flen != tp2->t_flen) |
1839 | return false; | | 1842 | return false; |
1840 | if (tp1->t_foffs != tp2->t_foffs) | | 1843 | if (tp1->t_foffs != tp2->t_foffs) |
1841 | return false; | | 1844 | return false; |
1842 | } | | 1845 | } |
1843 | } | | 1846 | } |
1844 | } | | 1847 | } |
1845 | return true; | | 1848 | return true; |
1846 | } | | 1849 | } |
1847 | | | 1850 | |
1848 | /* | | 1851 | /* |
1849 | * Returns a symbol which has the same name as the msym argument and is a | | 1852 | * Returns a symbol which has the same name as the msym argument and is a |
1850 | * member of the struct or union specified by the tn argument. | | 1853 | * member of the struct or union specified by the tn argument. |
1851 | */ | | 1854 | */ |
1852 | static sym_t * | | 1855 | static sym_t * |
1853 | struct_or_union_member(tnode_t *tn, op_t op, sym_t *msym) | | 1856 | struct_or_union_member(tnode_t *tn, op_t op, sym_t *msym) |
1854 | { | | 1857 | { |
1855 | struct_or_union *str; | | 1858 | struct_or_union *str; |
1856 | type_t *tp; | | 1859 | type_t *tp; |
1857 | tspec_t t; | | 1860 | tspec_t t; |
1858 | | | 1861 | |
1859 | /* | | 1862 | /* |
1860 | * Remove the member if it was unknown until now, which means | | 1863 | * Remove the member if it was unknown until now, which means |
1861 | * that no defined struct or union has a member with the same name. | | 1864 | * that no defined struct or union has a member with the same name. |
1862 | */ | | 1865 | */ |
1863 | if (msym->s_scl == NOSCL) { | | 1866 | if (msym->s_scl == NOSCL) { |
1864 | /* type '%s' does not have member '%s' */ | | 1867 | /* type '%s' does not have member '%s' */ |
1865 | error(101, type_name(tn->tn_type), msym->s_name); | | 1868 | error(101, type_name(tn->tn_type), msym->s_name); |
1866 | rmsym(msym); | | 1869 | rmsym(msym); |
1867 | msym->s_kind = FMEMBER; | | 1870 | msym->s_kind = FMEMBER; |
1868 | msym->s_scl = STRUCT_MEMBER; | | 1871 | msym->s_scl = STRUCT_MEMBER; |
1869 | | | 1872 | |
1870 | struct_or_union *sou = expr_zero_alloc(sizeof(*sou)); | | 1873 | struct_or_union *sou = expr_zero_alloc(sizeof(*sou)); |
1871 | sou->sou_tag = expr_zero_alloc(sizeof(*sou->sou_tag)); | | 1874 | sou->sou_tag = expr_zero_alloc(sizeof(*sou->sou_tag)); |
1872 | sou->sou_tag->s_name = unnamed; | | 1875 | sou->sou_tag->s_name = unnamed; |
1873 | | | 1876 | |
1874 | msym->u.s_member.sm_sou_type = sou; | | 1877 | msym->u.s_member.sm_sou_type = sou; |
1875 | /* | | 1878 | /* |
1876 | * The member sm_offset_in_bits is not needed here since this | | 1879 | * The member sm_offset_in_bits is not needed here since this |
1877 | * symbol can only be used for error reporting. | | 1880 | * symbol can only be used for error reporting. |
1878 | */ | | 1881 | */ |
1879 | return msym; | | 1882 | return msym; |
1880 | } | | 1883 | } |
1881 | | | 1884 | |
1882 | /* Set str to the tag of which msym is expected to be a member. */ | | 1885 | /* Set str to the tag of which msym is expected to be a member. */ |
1883 | str = NULL; | | 1886 | str = NULL; |
1884 | t = (tp = tn->tn_type)->t_tspec; | | 1887 | t = (tp = tn->tn_type)->t_tspec; |
1885 | if (op == POINT) { | | 1888 | if (op == POINT) { |
1886 | if (is_struct_or_union(t)) | | 1889 | if (is_struct_or_union(t)) |
1887 | str = tp->t_str; | | 1890 | str = tp->t_str; |
1888 | } else if (op == ARROW && t == PTR) { | | 1891 | } else if (op == ARROW && t == PTR) { |
1889 | t = (tp = tp->t_subt)->t_tspec; | | 1892 | t = (tp = tp->t_subt)->t_tspec; |
1890 | if (is_struct_or_union(t)) | | 1893 | if (is_struct_or_union(t)) |
1891 | str = tp->t_str; | | 1894 | str = tp->t_str; |
1892 | } | | 1895 | } |
1893 | | | 1896 | |
1894 | /* | | 1897 | /* |
1895 | * If this struct/union has a member with the name of msym, return it. | | 1898 | * If this struct/union has a member with the name of msym, return it. |
1896 | */ | | 1899 | */ |
1897 | if (str != NULL) { | | 1900 | if (str != NULL) { |
1898 | for (sym_t *sym = msym; | | 1901 | for (sym_t *sym = msym; |
1899 | sym != NULL; sym = sym->s_symtab_next) { | | 1902 | sym != NULL; sym = sym->s_symtab_next) { |
1900 | if (is_member(sym) && | | 1903 | if (is_member(sym) && |
1901 | sym->u.s_member.sm_sou_type == str && | | 1904 | sym->u.s_member.sm_sou_type == str && |
1902 | strcmp(sym->s_name, msym->s_name) == 0) | | 1905 | strcmp(sym->s_name, msym->s_name) == 0) |
1903 | return sym; | | 1906 | return sym; |
1904 | } | | 1907 | } |
1905 | } | | 1908 | } |
1906 | | | 1909 | |
1907 | bool eq = all_members_compatible(msym); | | 1910 | bool eq = all_members_compatible(msym); |
1908 | | | 1911 | |
1909 | /* | | 1912 | /* |
1910 | * Now handle the case in which the left operand refers really | | 1913 | * Now handle the case in which the left operand refers really |
1911 | * to a struct/union, but the right operand is not member of it. | | 1914 | * to a struct/union, but the right operand is not member of it. |
1912 | */ | | 1915 | */ |
1913 | if (str != NULL) { | | 1916 | if (str != NULL) { |
1914 | if (eq && !allow_c90) { | | 1917 | if (eq && !allow_c90) { |
1915 | /* illegal use of member '%s' */ | | 1918 | /* illegal use of member '%s' */ |
1916 | warning(102, msym->s_name); | | 1919 | warning(102, msym->s_name); |
1917 | } else { | | 1920 | } else { |
1918 | /* illegal use of member '%s' */ | | 1921 | /* illegal use of member '%s' */ |
1919 | error(102, msym->s_name); | | 1922 | error(102, msym->s_name); |
1920 | } | | 1923 | } |
1921 | return msym; | | 1924 | return msym; |
1922 | } | | 1925 | } |
1923 | | | 1926 | |
1924 | /* | | 1927 | /* |
1925 | * Now the left operand of ARROW does not point to a struct/union | | 1928 | * Now the left operand of ARROW does not point to a struct/union |
1926 | * or the left operand of POINT is no struct/union. | | 1929 | * or the left operand of POINT is no struct/union. |
1927 | */ | | 1930 | */ |
1928 | if (eq) { | | 1931 | if (eq) { |
1929 | if (op == POINT) { | | 1932 | if (op == POINT) { |
1930 | if (!allow_c90) { | | 1933 | if (!allow_c90) { |
1931 | /* left operand of '.' must be struct ... */ | | 1934 | /* left operand of '.' must be struct ... */ |
1932 | warning(103, type_name(tn->tn_type)); | | 1935 | warning(103, type_name(tn->tn_type)); |
1933 | } else { | | 1936 | } else { |
1934 | /* left operand of '.' must be struct ... */ | | 1937 | /* left operand of '.' must be struct ... */ |
1935 | error(103, type_name(tn->tn_type)); | | 1938 | error(103, type_name(tn->tn_type)); |
1936 | } | | 1939 | } |
1937 | } else { | | 1940 | } else { |
1938 | if (!allow_c90 && tn->tn_type->t_tspec == PTR) { | | 1941 | if (!allow_c90 && tn->tn_type->t_tspec == PTR) { |
1939 | /* left operand of '->' must be pointer ... */ | | 1942 | /* left operand of '->' must be pointer ... */ |
1940 | warning(104, type_name(tn->tn_type)); | | 1943 | warning(104, type_name(tn->tn_type)); |
1941 | } else { | | 1944 | } else { |
1942 | /* left operand of '->' must be pointer ... */ | | 1945 | /* left operand of '->' must be pointer ... */ |
1943 | error(104, type_name(tn->tn_type)); | | 1946 | error(104, type_name(tn->tn_type)); |
1944 | } | | 1947 | } |
1945 | } | | 1948 | } |
1946 | } else { | | 1949 | } else { |
1947 | if (!allow_c90) { | | 1950 | if (!allow_c90) { |
1948 | /* non-unique member requires struct/union %s */ | | 1951 | /* non-unique member requires struct/union %s */ |
1949 | error(105, op == POINT ? "object" : "pointer"); | | 1952 | error(105, op == POINT ? "object" : "pointer"); |
1950 | } else { | | 1953 | } else { |
1951 | /* unacceptable operand of '%s' */ | | 1954 | /* unacceptable operand of '%s' */ |
1952 | error(111, op_name(op)); | | 1955 | error(111, op_name(op)); |
1953 | } | | 1956 | } |
1954 | } | | 1957 | } |
1955 | | | 1958 | |
1956 | return msym; | | 1959 | return msym; |
1957 | } | | 1960 | } |
1958 | | | 1961 | |
1959 | tnode_t * | | 1962 | tnode_t * |
1960 | build_member_access(tnode_t *ln, op_t op, bool sys, sbuf_t *member) | | 1963 | build_member_access(tnode_t *ln, op_t op, bool sys, sbuf_t *member) |
1961 | { | | 1964 | { |
1962 | sym_t *msym; | | 1965 | sym_t *msym; |
1963 | | | 1966 | |
1964 | if (ln == NULL) | | 1967 | if (ln == NULL) |
1965 | return NULL; | | 1968 | return NULL; |
1966 | | | 1969 | |
1967 | if (op == ARROW) { | | 1970 | if (op == ARROW) { |
1968 | /* must do this before struct_or_union_member is called */ | | 1971 | /* must do this before struct_or_union_member is called */ |
1969 | ln = cconv(ln); | | 1972 | ln = cconv(ln); |
1970 | } | | 1973 | } |
1971 | msym = struct_or_union_member(ln, op, getsym(member)); | | 1974 | msym = struct_or_union_member(ln, op, getsym(member)); |
1972 | return build_binary(ln, op, sys, build_name(msym, false)); | | 1975 | return build_binary(ln, op, sys, build_name(msym, false)); |
1973 | } | | 1976 | } |
1974 | | | 1977 | |
1975 | /* | | 1978 | /* |
1976 | * Perform class conversions. | | 1979 | * Perform class conversions. |
1977 | * | | 1980 | * |
1978 | * Arrays of type T are converted into pointers to type T. | | 1981 | * Arrays of type T are converted into pointers to type T. |
1979 | * Functions are converted to pointers to functions. | | 1982 | * Functions are converted to pointers to functions. |
1980 | * Lvalues are converted to rvalues. | | 1983 | * Lvalues are converted to rvalues. |
1981 | * | | 1984 | * |
1982 | * C99 6.3 "Conversions" | | 1985 | * C99 6.3 "Conversions" |
1983 | * C99 6.3.2 "Other operands" | | 1986 | * C99 6.3.2 "Other operands" |
1984 | * C99 6.3.2.1 "Lvalues, arrays, and function designators" | | 1987 | * C99 6.3.2.1 "Lvalues, arrays, and function designators" |
1985 | */ | | 1988 | */ |
1986 | tnode_t * | | 1989 | tnode_t * |
1987 | cconv(tnode_t *tn) | | 1990 | cconv(tnode_t *tn) |
1988 | { | | 1991 | { |
1989 | /* | | 1992 | /* |
1990 | * Array-lvalue (array of type T) is converted into rvalue | | 1993 | * Array-lvalue (array of type T) is converted into rvalue |
1991 | * (pointer to type T) | | 1994 | * (pointer to type T) |
1992 | */ | | 1995 | */ |
1993 | if (tn->tn_type->t_tspec == ARRAY) { | | 1996 | if (tn->tn_type->t_tspec == ARRAY) { |
1994 | if (!tn->tn_lvalue) { | | 1997 | if (!tn->tn_lvalue) { |
1995 | /* XXX print correct operator */ | | 1998 | /* XXX print correct operator */ |
1996 | /* %soperand of '%s' must be lvalue */ | | 1999 | /* %soperand of '%s' must be lvalue */ |
1997 | gnuism(114, "", op_name(ADDR)); | | 2000 | gnuism(114, "", op_name(ADDR)); |
1998 | } | | 2001 | } |
1999 | tn = new_tnode(ADDR, tn->tn_sys, | | 2002 | tn = new_tnode(ADDR, tn->tn_sys, |
2000 | expr_derive_type(tn->tn_type->t_subt, PTR), tn, NULL); | | 2003 | expr_derive_type(tn->tn_type->t_subt, PTR), tn, NULL); |
2001 | } | | 2004 | } |
2002 | | | 2005 | |
2003 | /* | | 2006 | /* |
2004 | * Expression of type function (function with return value of type T) | | 2007 | * Expression of type function (function with return value of type T) |
2005 | * in rvalue-expression (pointer to function with return value | | 2008 | * in rvalue-expression (pointer to function with return value |
2006 | * of type T) | | 2009 | * of type T) |
2007 | */ | | 2010 | */ |
2008 | if (tn->tn_type->t_tspec == FUNC) | | 2011 | if (tn->tn_type->t_tspec == FUNC) |
2009 | tn = build_address(tn->tn_sys, tn, true); | | 2012 | tn = build_address(tn->tn_sys, tn, true); |
2010 | | | 2013 | |
2011 | /* lvalue to rvalue */ | | 2014 | /* lvalue to rvalue */ |
2012 | if (tn->tn_lvalue) { | | 2015 | if (tn->tn_lvalue) { |
2013 | type_t *tp = expr_dup_type(tn->tn_type); | | 2016 | type_t *tp = expr_dup_type(tn->tn_type); |
2014 | /* C99 6.3.2.1p2 sentence 2 says to remove the qualifiers. */ | | 2017 | /* C99 6.3.2.1p2 sentence 2 says to remove the qualifiers. */ |
2015 | tp->t_const = tp->t_volatile = false; | | 2018 | tp->t_const = tp->t_volatile = false; |
2016 | tn = new_tnode(LOAD, tn->tn_sys, tp, tn, NULL); | | 2019 | tn = new_tnode(LOAD, tn->tn_sys, tp, tn, NULL); |
2017 | } | | 2020 | } |
2018 | | | 2021 | |
2019 | return tn; | | 2022 | return tn; |
2020 | } | | 2023 | } |
2021 | | | 2024 | |
2022 | const tnode_t * | | 2025 | const tnode_t * |
2023 | before_conversion(const tnode_t *tn) | | 2026 | before_conversion(const tnode_t *tn) |
2024 | { | | 2027 | { |
2025 | while (tn->tn_op == CVT && !tn->tn_cast) | | 2028 | while (tn->tn_op == CVT && !tn->tn_cast) |
2026 | tn = tn->tn_left; | | 2029 | tn = tn->tn_left; |
2027 | return tn; | | 2030 | return tn; |
2028 | } | | 2031 | } |
2029 | | | 2032 | |
2030 | /* | | 2033 | /* |
2031 | * Most errors required by ANSI C are reported in struct_or_union_member(). | | 2034 | * Most errors required by ANSI C are reported in struct_or_union_member(). |
2032 | * Here we only check for totally wrong things. | | 2035 | * Here we only check for totally wrong things. |
2033 | */ | | 2036 | */ |
2034 | static bool | | 2037 | static bool |
2035 | typeok_point(const tnode_t *ln, const type_t *ltp, tspec_t lt) | | 2038 | typeok_point(const tnode_t *ln, const type_t *ltp, tspec_t lt) |
2036 | { | | 2039 | { |
2037 | if (is_struct_or_union(lt)) | | 2040 | if (is_struct_or_union(lt)) |
2038 | return true; | | 2041 | return true; |
2039 | | | 2042 | |
2040 | if (lt == FUNC || lt == VOID || ltp->t_bitfield) | | 2043 | if (lt == FUNC || lt == VOID || ltp->t_bitfield) |
2041 | goto wrong; | | 2044 | goto wrong; |
2042 | | | 2045 | |
2043 | /* | | 2046 | /* |
2044 | * Some C dialects from before C90 tolerated any lvalue on the | | 2047 | * Some C dialects from before C90 tolerated any lvalue on the |
2045 | * left-hand side of the '.' operator, allowing things like | | 2048 | * left-hand side of the '.' operator, allowing things like |
2046 | * char st[100]; st.st_mtime, assuming that the member 'st_mtime' | | 2049 | * char st[100]; st.st_mtime, assuming that the member 'st_mtime' |
2047 | * only occurred in a single struct; see typeok_arrow. | | 2050 | * only occurred in a single struct; see typeok_arrow. |
2048 | */ | | 2051 | */ |
2049 | if (ln->tn_lvalue) | | 2052 | if (ln->tn_lvalue) |
2050 | return true; | | 2053 | return true; |
2051 | | | 2054 | |
2052 | wrong: | | 2055 | wrong: |
2053 | /* With allow_c90 we already got an error */ | | 2056 | /* With allow_c90 we already got an error */ |
2054 | if (!allow_c90) | | 2057 | if (!allow_c90) |
2055 | /* unacceptable operand of '%s' */ | | 2058 | /* unacceptable operand of '%s' */ |
2056 | error(111, op_name(POINT)); | | 2059 | error(111, op_name(POINT)); |
2057 | | | 2060 | |
2058 | return false; | | 2061 | return false; |
2059 | } | | 2062 | } |
2060 | | | 2063 | |
2061 | static bool | | 2064 | static bool |
2062 | typeok_arrow(tspec_t lt) | | 2065 | typeok_arrow(tspec_t lt) |
2063 | { | | 2066 | { |
2064 | /* | | 2067 | /* |
2065 | * C1978 Appendix A 14.1 says: <quote>In fact, any lvalue is allowed | | 2068 | * C1978 Appendix A 14.1 says: <quote>In fact, any lvalue is allowed |
2066 | * before '.', and that lvalue is then assumed to have the form of | | 2069 | * before '.', and that lvalue is then assumed to have the form of |
2067 | * the structure of which the name of the right is a member. [...] | | 2070 | * the structure of which the name of the right is a member. [...] |
2068 | * Such constructions are non-portable.</quote> | | 2071 | * Such constructions are non-portable.</quote> |
2069 | */ | | 2072 | */ |
2070 | if (lt == PTR || (!allow_c90 && is_integer(lt))) | | 2073 | if (lt == PTR || (!allow_c90 && is_integer(lt))) |
2071 | return true; | | 2074 | return true; |
2072 | | | 2075 | |
2073 | /* With allow_c90 we already got an error */ | | 2076 | /* With allow_c90 we already got an error */ |
2074 | if (!allow_c90) | | 2077 | if (!allow_c90) |
2075 | /* unacceptable operand of '%s' */ | | 2078 | /* unacceptable operand of '%s' */ |
2076 | error(111, op_name(ARROW)); | | 2079 | error(111, op_name(ARROW)); |
2077 | return false; | | 2080 | return false; |
2078 | } | | 2081 | } |
2079 | | | 2082 | |
2080 | static bool | | 2083 | static bool |
2081 | typeok_incdec(op_t op, const tnode_t *tn, const type_t *tp) | | 2084 | typeok_incdec(op_t op, const tnode_t *tn, const type_t *tp) |
2082 | { | | 2085 | { |
2083 | /* operand has scalar type (checked in typeok) */ | | 2086 | /* operand has scalar type (checked in typeok) */ |
2084 | if (!tn->tn_lvalue) { | | 2087 | if (!tn->tn_lvalue) { |
2085 | if (tn->tn_op == CVT && tn->tn_cast && | | 2088 | if (tn->tn_op == CVT && tn->tn_cast && |
2086 | tn->tn_left->tn_op == LOAD) { | | 2089 | tn->tn_left->tn_op == LOAD) { |
2087 | /* a cast does not yield an lvalue */ | | 2090 | /* a cast does not yield an lvalue */ |
2088 | error(163); | | 2091 | error(163); |
2089 | } | | 2092 | } |
2090 | /* %soperand of '%s' must be lvalue */ | | 2093 | /* %soperand of '%s' must be lvalue */ |
2091 | error(114, "", op_name(op)); | | 2094 | error(114, "", op_name(op)); |
2092 | return false; | | 2095 | return false; |
2093 | } | | 2096 | } |
2094 | if (tp->t_const && allow_c90) { | | 2097 | if (tp->t_const && allow_c90) { |
2095 | /* %soperand of '%s' must be modifiable lvalue */ | | 2098 | /* %soperand of '%s' must be modifiable lvalue */ |
2096 | warning(115, "", op_name(op)); | | 2099 | warning(115, "", op_name(op)); |
2097 | } | | 2100 | } |
2098 | return true; | | 2101 | return true; |
2099 | } | | 2102 | } |
2100 | | | 2103 | |
2101 | static bool | | 2104 | static bool |
2102 | typeok_address(const mod_t *mp, | | 2105 | typeok_address(const mod_t *mp, |
2103 | const tnode_t *tn, const type_t *tp, tspec_t t) | | 2106 | const tnode_t *tn, const type_t *tp, tspec_t t) |
2104 | { | | 2107 | { |
2105 | if (t == ARRAY || t == FUNC) { | | 2108 | if (t == ARRAY || t == FUNC) { |
2106 | /* ok, a warning comes later (in build_address()) */ | | 2109 | /* ok, a warning comes later (in build_address()) */ |
2107 | } else if (!tn->tn_lvalue) { | | 2110 | } else if (!tn->tn_lvalue) { |
2108 | if (tn->tn_op == CVT && tn->tn_cast && | | 2111 | if (tn->tn_op == CVT && tn->tn_cast && |
2109 | tn->tn_left->tn_op == LOAD) { | | 2112 | tn->tn_left->tn_op == LOAD) { |
2110 | /* a cast does not yield an lvalue */ | | 2113 | /* a cast does not yield an lvalue */ |
2111 | error(163); | | 2114 | error(163); |
2112 | } | | 2115 | } |
2113 | /* %soperand of '%s' must be lvalue */ | | 2116 | /* %soperand of '%s' must be lvalue */ |
2114 | error(114, "", mp->m_name); | | 2117 | error(114, "", mp->m_name); |
2115 | return false; | | 2118 | return false; |
2116 | } else if (is_scalar(t)) { | | 2119 | } else if (is_scalar(t)) { |
2117 | if (tp->t_bitfield) { | | 2120 | if (tp->t_bitfield) { |
2118 | /* cannot take address of bit-field */ | | 2121 | /* cannot take address of bit-field */ |
2119 | error(112); | | 2122 | error(112); |
2120 | return false; | | 2123 | return false; |
2121 | } | | 2124 | } |
2122 | } else if (t != STRUCT && t != UNION) { | | 2125 | } else if (t != STRUCT && t != UNION) { |
2123 | /* unacceptable operand of '%s' */ | | 2126 | /* unacceptable operand of '%s' */ |
2124 | error(111, mp->m_name); | | 2127 | error(111, mp->m_name); |
2125 | return false; | | 2128 | return false; |
2126 | } | | 2129 | } |
2127 | if (tn->tn_op == NAME && tn->tn_sym->s_register) { | | 2130 | if (tn->tn_op == NAME && tn->tn_sym->s_register) { |
2128 | /* cannot take address of register '%s' */ | | 2131 | /* cannot take address of register '%s' */ |
2129 | error(113, tn->tn_sym->s_name); | | 2132 | error(113, tn->tn_sym->s_name); |
2130 | return false; | | 2133 | return false; |
2131 | } | | 2134 | } |
2132 | return true; | | 2135 | return true; |
2133 | } | | 2136 | } |
2134 | | | 2137 | |
2135 | static bool | | 2138 | static bool |
2136 | typeok_indir(const type_t *tp, tspec_t t) | | 2139 | typeok_indir(const type_t *tp, tspec_t t) |
2137 | { | | 2140 | { |
2138 | | | 2141 | |
2139 | if (t != PTR) { | | 2142 | if (t != PTR) { |
2140 | /* cannot dereference non-pointer type '%s' */ | | 2143 | /* cannot dereference non-pointer type '%s' */ |
2141 | error(96, type_name(tp)); | | 2144 | error(96, type_name(tp)); |
2142 | return false; | | 2145 | return false; |
2143 | } | | 2146 | } |
2144 | return true; | | 2147 | return true; |
2145 | } | | 2148 | } |
2146 | | | 2149 | |
2147 | static void | | 2150 | static void |
2148 | warn_incompatible_types(op_t op, | | 2151 | warn_incompatible_types(op_t op, |
2149 | const type_t *ltp, tspec_t lt, | | 2152 | const type_t *ltp, tspec_t lt, |
2150 | const type_t *rtp, tspec_t rt) | | 2153 | const type_t *rtp, tspec_t rt) |
2151 | { | | 2154 | { |
2152 | const mod_t *mp = &modtab[op]; | | 2155 | const mod_t *mp = &modtab[op]; |
2153 | | | 2156 | |
2154 | if (lt == VOID || (mp->m_binary && rt == VOID)) { | | 2157 | if (lt == VOID || (mp->m_binary && rt == VOID)) { |
2155 | /* void type illegal in expression */ | | 2158 | /* void type illegal in expression */ |
2156 | error(109); | | 2159 | error(109); |
2157 | } else if (op == ASSIGN) { | | 2160 | } else if (op == ASSIGN) { |
2158 | /* cannot assign to '%s' from '%s' */ | | 2161 | /* cannot assign to '%s' from '%s' */ |
2159 | error(171, type_name(ltp), type_name(rtp)); | | 2162 | error(171, type_name(ltp), type_name(rtp)); |
2160 | } else if (mp->m_binary) { | | 2163 | } else if (mp->m_binary) { |
2161 | /* operands of '%s' have incompatible types '%s' and '%s' */ | | 2164 | /* operands of '%s' have incompatible types '%s' and '%s' */ |
2162 | error(107, mp->m_name, tspec_name(lt), tspec_name(rt)); | | 2165 | error(107, mp->m_name, tspec_name(lt), tspec_name(rt)); |
2163 | } else { | | 2166 | } else { |
2164 | lint_assert(rt == NOTSPEC); | | 2167 | lint_assert(rt == NOTSPEC); |
2165 | /* operand of '%s' has invalid type '%s' */ | | 2168 | /* operand of '%s' has invalid type '%s' */ |
2166 | error(108, mp->m_name, type_name(ltp)); | | 2169 | error(108, mp->m_name, type_name(ltp)); |
2167 | } | | 2170 | } |
2168 | } | | 2171 | } |
2169 | | | 2172 | |
2170 | static bool | | 2173 | static bool |
2171 | typeok_plus(op_t op, | | 2174 | typeok_plus(op_t op, |
2172 | const type_t *ltp, tspec_t lt, | | 2175 | const type_t *ltp, tspec_t lt, |
2173 | const type_t *rtp, tspec_t rt) | | 2176 | const type_t *rtp, tspec_t rt) |
2174 | { | | 2177 | { |
2175 | /* operands have scalar types (checked in typeok) */ | | 2178 | /* operands have scalar types (checked in typeok) */ |
2176 | if ((lt == PTR && !is_integer(rt)) || (rt == PTR && !is_integer(lt))) { | | 2179 | if ((lt == PTR && !is_integer(rt)) || (rt == PTR && !is_integer(lt))) { |
2177 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 2180 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
2178 | return false; | | 2181 | return false; |
2179 | } | | 2182 | } |
2180 | return true; | | 2183 | return true; |
2181 | } | | 2184 | } |
2182 | | | 2185 | |
2183 | static bool | | 2186 | static bool |
2184 | typeok_minus(op_t op, | | 2187 | typeok_minus(op_t op, |
2185 | const type_t *ltp, tspec_t lt, | | 2188 | const type_t *ltp, tspec_t lt, |
2186 | const type_t *rtp, tspec_t rt) | | 2189 | const type_t *rtp, tspec_t rt) |
2187 | { | | 2190 | { |
2188 | /* operands have scalar types (checked in typeok) */ | | 2191 | /* operands have scalar types (checked in typeok) */ |
2189 | if ((lt == PTR && rt != PTR && !is_integer(rt)) || | | 2192 | if ((lt == PTR && rt != PTR && !is_integer(rt)) || |
2190 | (lt != PTR && rt == PTR)) { | | 2193 | (lt != PTR && rt == PTR)) { |
2191 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 2194 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
2192 | return false; | | 2195 | return false; |
2193 | } | | 2196 | } |
2194 | if (lt == PTR && rt == PTR && | | 2197 | if (lt == PTR && rt == PTR && |
2195 | !types_compatible(ltp->t_subt, rtp->t_subt, true, false, NULL)) { | | 2198 | !types_compatible(ltp->t_subt, rtp->t_subt, true, false, NULL)) { |
2196 | /* illegal pointer subtraction */ | | 2199 | /* illegal pointer subtraction */ |
2197 | error(116); | | 2200 | error(116); |
2198 | } | | 2201 | } |
2199 | return true; | | 2202 | return true; |
2200 | } | | 2203 | } |
2201 | | | 2204 | |
2202 | static void | | 2205 | static void |
2203 | typeok_shr(const mod_t *mp, | | 2206 | typeok_shr(const mod_t *mp, |
2204 | const tnode_t *ln, tspec_t lt, | | 2207 | const tnode_t *ln, tspec_t lt, |
2205 | const tnode_t *rn, tspec_t rt) | | 2208 | const tnode_t *rn, tspec_t rt) |
2206 | { | | 2209 | { |
2207 | tspec_t olt, ort; | | 2210 | tspec_t olt, ort; |
2208 | | | 2211 | |
2209 | olt = before_conversion(ln)->tn_type->t_tspec; | | 2212 | olt = before_conversion(ln)->tn_type->t_tspec; |
2210 | ort = before_conversion(rn)->tn_type->t_tspec; | | 2213 | ort = before_conversion(rn)->tn_type->t_tspec; |
2211 | | | 2214 | |
2212 | /* operands have integer types (checked in typeok) */ | | 2215 | /* operands have integer types (checked in typeok) */ |
2213 | if (pflag && !is_uinteger(olt)) { | | 2216 | if (pflag && !is_uinteger(olt)) { |
2214 | integer_constraints lc = ic_expr(ln); | | 2217 | integer_constraints lc = ic_expr(ln); |
2215 | if (!ic_maybe_signed(ln->tn_type, &lc)) | | 2218 | if (!ic_maybe_signed(ln->tn_type, &lc)) |
2216 | return; | | 2219 | return; |
2217 | | | 2220 | |
2218 | /* | | 2221 | /* |
2219 | * The left operand is signed. This means that | | 2222 | * The left operand is signed. This means that |
2220 | * the operation is (possibly) nonportable. | | 2223 | * the operation is (possibly) nonportable. |
2221 | */ | | 2224 | */ |
2222 | if (ln->tn_op != CON) { | | 2225 | if (ln->tn_op != CON) { |
2223 | /* bitwise '%s' on signed value possibly nonportable */ | | 2226 | /* bitwise '%s' on signed value possibly nonportable */ |
2224 | warning(117, mp->m_name); | | 2227 | warning(117, mp->m_name); |
2225 | } else if (ln->tn_val->v_quad < 0) { | | 2228 | } else if (ln->tn_val->v_quad < 0) { |
2226 | /* bitwise '%s' on signed value nonportable */ | | 2229 | /* bitwise '%s' on signed value nonportable */ |
2227 | warning(120, mp->m_name); | | 2230 | warning(120, mp->m_name); |
2228 | } | | 2231 | } |
2229 | } else if (allow_trad && allow_c90 && | | 2232 | } else if (allow_trad && allow_c90 && |
2230 | !is_uinteger(olt) && is_uinteger(ort)) { | | 2233 | !is_uinteger(olt) && is_uinteger(ort)) { |
2231 | /* The left operand would become unsigned in traditional C. */ | | 2234 | /* The left operand would become unsigned in traditional C. */ |
2232 | if (hflag && (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { | | 2235 | if (hflag && (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { |
2233 | /* semantics of '%s' change in ANSI C; use ... */ | | 2236 | /* semantics of '%s' change in ANSI C; use ... */ |
2234 | warning(118, mp->m_name); | | 2237 | warning(118, mp->m_name); |
2235 | } | | 2238 | } |
2236 | } else if (allow_trad && allow_c90 && | | 2239 | } else if (allow_trad && allow_c90 && |
2237 | !is_uinteger(olt) && !is_uinteger(ort) && | | 2240 | !is_uinteger(olt) && !is_uinteger(ort) && |
2238 | portable_size_in_bits(lt) < portable_size_in_bits(rt)) { | | 2241 | portable_size_in_bits(lt) < portable_size_in_bits(rt)) { |
2239 | /* | | 2242 | /* |
2240 | * In traditional C the left operand would be extended | | 2243 | * In traditional C the left operand would be extended |
2241 | * (possibly sign-extended) and then shifted. | | 2244 | * (possibly sign-extended) and then shifted. |
2242 | */ | | 2245 | */ |
2243 | if (hflag && (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { | | 2246 | if (hflag && (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { |
2244 | /* semantics of '%s' change in ANSI C; use ... */ | | 2247 | /* semantics of '%s' change in ANSI C; use ... */ |
2245 | warning(118, mp->m_name); | | 2248 | warning(118, mp->m_name); |
2246 | } | | 2249 | } |
2247 | } | | 2250 | } |
2248 | } | | 2251 | } |
2249 | | | 2252 | |
2250 | static void | | 2253 | static void |
2251 | typeok_shl(const mod_t *mp, tspec_t lt, tspec_t rt) | | 2254 | typeok_shl(const mod_t *mp, tspec_t lt, tspec_t rt) |
2252 | { | | 2255 | { |
2253 | /* | | 2256 | /* |
2254 | * C90 does not perform balancing for shift operations, | | 2257 | * C90 does not perform balancing for shift operations, |
2255 | * but traditional C does. If the width of the right operand | | 2258 | * but traditional C does. If the width of the right operand |
2256 | * is greater than the width of the left operand, then in | | 2259 | * is greater than the width of the left operand, then in |
2257 | * traditional C the left operand would be extended to the | | 2260 | * traditional C the left operand would be extended to the |
2258 | * width of the right operand. For SHL this may result in | | 2261 | * width of the right operand. For SHL this may result in |
2259 | * different results. | | 2262 | * different results. |
2260 | */ | | 2263 | */ |
2261 | if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { | | 2264 | if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { |
2262 | /* | | 2265 | /* |
2263 | * XXX If both operands are constant, make sure | | 2266 | * XXX If both operands are constant, make sure |
2264 | * that there is really a difference between | | 2267 | * that there is really a difference between |
2265 | * ANSI C and traditional C. | | 2268 | * ANSI C and traditional C. |
2266 | */ | | 2269 | */ |
2267 | if (hflag && !allow_c99) | | 2270 | if (hflag && !allow_c99) |
2268 | /* semantics of '%s' change in ANSI C; use ... */ | | 2271 | /* semantics of '%s' change in ANSI C; use ... */ |
2269 | warning(118, mp->m_name); | | 2272 | warning(118, mp->m_name); |
2270 | } | | 2273 | } |
2271 | } | | 2274 | } |
2272 | | | 2275 | |
2273 | static void | | 2276 | static void |
2274 | typeok_shift(const type_t *ltp, tspec_t lt, const tnode_t *rn, tspec_t rt) | | 2277 | typeok_shift(const type_t *ltp, tspec_t lt, const tnode_t *rn, tspec_t rt) |
2275 | { | | 2278 | { |
2276 | if (rn->tn_op != CON) | | 2279 | if (rn->tn_op != CON) |
2277 | return; | | 2280 | return; |
2278 | | | 2281 | |
2279 | if (!is_uinteger(rt) && rn->tn_val->v_quad < 0) { | | 2282 | if (!is_uinteger(rt) && rn->tn_val->v_quad < 0) { |
2280 | /* negative shift */ | | 2283 | /* negative shift */ |
2281 | warning(121); | | 2284 | warning(121); |
2282 | } else if ((uint64_t)rn->tn_val->v_quad == | | 2285 | } else if ((uint64_t)rn->tn_val->v_quad == |
2283 | (uint64_t)size_in_bits(lt)) { | | 2286 | (uint64_t)size_in_bits(lt)) { |
2284 | /* shift amount %u equals bit-size of '%s' */ | | 2287 | /* shift amount %u equals bit-size of '%s' */ |
2285 | warning(267, (unsigned)rn->tn_val->v_quad, type_name(ltp)); | | 2288 | warning(267, (unsigned)rn->tn_val->v_quad, type_name(ltp)); |
2286 | } else if ((uint64_t)rn->tn_val->v_quad > (uint64_t)size_in_bits(lt)) { | | 2289 | } else if ((uint64_t)rn->tn_val->v_quad > (uint64_t)size_in_bits(lt)) { |
2287 | /* shift amount %llu is greater than bit-size %llu of '%s' */ | | 2290 | /* shift amount %llu is greater than bit-size %llu of '%s' */ |
2288 | warning(122, (unsigned long long)rn->tn_val->v_quad, | | 2291 | warning(122, (unsigned long long)rn->tn_val->v_quad, |
2289 | (unsigned long long)size_in_bits(lt), | | 2292 | (unsigned long long)size_in_bits(lt), |
2290 | tspec_name(lt)); | | 2293 | tspec_name(lt)); |
2291 | } | | 2294 | } |
2292 | } | | 2295 | } |
2293 | | | 2296 | |
2294 | static bool | | 2297 | static bool |
2295 | is_typeok_eq(const tnode_t *ln, tspec_t lt, const tnode_t *rn, tspec_t rt) | | 2298 | is_typeok_eq(const tnode_t *ln, tspec_t lt, const tnode_t *rn, tspec_t rt) |
2296 | { | | 2299 | { |
2297 | if (lt == PTR && is_null_pointer(rn)) | | 2300 | if (lt == PTR && is_null_pointer(rn)) |
2298 | return true; | | 2301 | return true; |
2299 | if (rt == PTR && is_null_pointer(ln)) | | 2302 | if (rt == PTR && is_null_pointer(ln)) |
2300 | return true; | | 2303 | return true; |
2301 | return false; | | 2304 | return false; |
2302 | } | | 2305 | } |
2303 | | | 2306 | |
2304 | /* | | 2307 | /* |
2305 | * Called if incompatible pointer types are detected. | | 2308 | * Called if incompatible pointer types are detected. |
2306 | * Print an appropriate warning. | | 2309 | * Print an appropriate warning. |
2307 | */ | | 2310 | */ |
2308 | static void | | 2311 | static void |
2309 | warn_incompatible_pointers(const mod_t *mp, | | 2312 | warn_incompatible_pointers(const mod_t *mp, |
2310 | const type_t *ltp, const type_t *rtp) | | 2313 | const type_t *ltp, const type_t *rtp) |
2311 | { | | 2314 | { |
2312 | lint_assert(ltp->t_tspec == PTR); | | 2315 | lint_assert(ltp->t_tspec == PTR); |
2313 | lint_assert(rtp->t_tspec == PTR); | | 2316 | lint_assert(rtp->t_tspec == PTR); |
2314 | | | 2317 | |
2315 | tspec_t lt = ltp->t_subt->t_tspec; | | 2318 | tspec_t lt = ltp->t_subt->t_tspec; |
2316 | tspec_t rt = rtp->t_subt->t_tspec; | | 2319 | tspec_t rt = rtp->t_subt->t_tspec; |
2317 | | | 2320 | |
2318 | if (is_struct_or_union(lt) && is_struct_or_union(rt)) { | | 2321 | if (is_struct_or_union(lt) && is_struct_or_union(rt)) { |
2319 | if (mp == NULL) { | | 2322 | if (mp == NULL) { |
2320 | /* illegal structure pointer combination */ | | 2323 | /* illegal structure pointer combination */ |
2321 | warning(244); | | 2324 | warning(244); |
2322 | } else { | | 2325 | } else { |
2323 | /* incompatible structure pointers: '%s' '%s' '%s' */ | | 2326 | /* incompatible structure pointers: '%s' '%s' '%s' */ |
2324 | warning(245, type_name(ltp), mp->m_name, type_name(rtp)); | | 2327 | warning(245, type_name(ltp), mp->m_name, type_name(rtp)); |
2325 | } | | 2328 | } |
2326 | } else { | | 2329 | } else { |
2327 | if (mp == NULL) { | | 2330 | if (mp == NULL) { |
2328 | /* illegal combination of '%s' and '%s' */ | | 2331 | /* illegal combination of '%s' and '%s' */ |
2329 | warning(184, type_name(ltp), type_name(rtp)); | | 2332 | warning(184, type_name(ltp), type_name(rtp)); |
2330 | } else { | | 2333 | } else { |
2331 | /* illegal combination of '%s' and '%s', op '%s' */ | | 2334 | /* illegal combination of '%s' and '%s', op '%s' */ |
2332 | warning(124, | | 2335 | warning(124, |
2333 | type_name(ltp), type_name(rtp), mp->m_name); | | 2336 | type_name(ltp), type_name(rtp), mp->m_name); |
2334 | } | | 2337 | } |
2335 | } | | 2338 | } |
2336 | } | | 2339 | } |
2337 | | | 2340 | |
2338 | static void | | 2341 | static void |
2339 | check_pointer_comparison(op_t op, const tnode_t *ln, const tnode_t *rn) | | 2342 | check_pointer_comparison(op_t op, const tnode_t *ln, const tnode_t *rn) |
2340 | { | | 2343 | { |
2341 | type_t *ltp = ln->tn_type, *rtp = rn->tn_type; | | 2344 | type_t *ltp = ln->tn_type, *rtp = rn->tn_type; |
2342 | tspec_t lst = ltp->t_subt->t_tspec, rst = rtp->t_subt->t_tspec; | | 2345 | tspec_t lst = ltp->t_subt->t_tspec, rst = rtp->t_subt->t_tspec; |
2343 | | | 2346 | |
2344 | if (lst == VOID || rst == VOID) { | | 2347 | if (lst == VOID || rst == VOID) { |
2345 | /* TODO: C99 behaves like C90 here. */ | | 2348 | /* TODO: C99 behaves like C90 here. */ |
2346 | if ((!allow_trad && !allow_c99) && | | 2349 | if ((!allow_trad && !allow_c99) && |
2347 | (lst == FUNC || rst == FUNC)) { | | 2350 | (lst == FUNC || rst == FUNC)) { |
2348 | /* (void *)0 is already handled in typeok() */ | | 2351 | /* (void *)0 is already handled in typeok() */ |
2349 | const char *lsts, *rsts; | | 2352 | const char *lsts, *rsts; |
2350 | *(lst == FUNC ? &lsts : &rsts) = "function pointer"; | | 2353 | *(lst == FUNC ? &lsts : &rsts) = "function pointer"; |
2351 | *(lst == VOID ? &lsts : &rsts) = "'void *'"; | | 2354 | *(lst == VOID ? &lsts : &rsts) = "'void *'"; |
2352 | /* ANSI C forbids comparison of %s with %s */ | | 2355 | /* ANSI C forbids comparison of %s with %s */ |
2353 | warning(274, lsts, rsts); | | 2356 | warning(274, lsts, rsts); |
2354 | } | | 2357 | } |
2355 | return; | | 2358 | return; |
2356 | } | | 2359 | } |
2357 | | | 2360 | |
2358 | if (!types_compatible(ltp->t_subt, rtp->t_subt, true, false, NULL)) { | | 2361 | if (!types_compatible(ltp->t_subt, rtp->t_subt, true, false, NULL)) { |
2359 | warn_incompatible_pointers(&modtab[op], ltp, rtp); | | 2362 | warn_incompatible_pointers(&modtab[op], ltp, rtp); |
2360 | return; | | 2363 | return; |
2361 | } | | 2364 | } |
2362 | | | 2365 | |
2363 | if (lst == FUNC && rst == FUNC) { | | 2366 | if (lst == FUNC && rst == FUNC) { |
2364 | /* TODO: C99 behaves like C90 here, see C99 6.5.8p2. */ | | 2367 | /* TODO: C99 behaves like C90 here, see C99 6.5.8p2. */ |
2365 | if ((!allow_trad && !allow_c99) && op != EQ && op != NE) | | 2368 | if ((!allow_trad && !allow_c99) && op != EQ && op != NE) |
2366 | /* ANSI C forbids ordered comparisons of ... */ | | 2369 | /* ANSI C forbids ordered comparisons of ... */ |
2367 | warning(125); | | 2370 | warning(125); |
2368 | } | | 2371 | } |
2369 | } | | 2372 | } |
2370 | | | 2373 | |
2371 | static bool | | 2374 | static bool |
2372 | typeok_compare(op_t op, | | 2375 | typeok_compare(op_t op, |
2373 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | | 2376 | const tnode_t *ln, const type_t *ltp, tspec_t lt, |
2374 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | | 2377 | const tnode_t *rn, const type_t *rtp, tspec_t rt) |
2375 | { | | 2378 | { |
2376 | if (lt == PTR && rt == PTR) { | | 2379 | if (lt == PTR && rt == PTR) { |
2377 | check_pointer_comparison(op, ln, rn); | | 2380 | check_pointer_comparison(op, ln, rn); |
2378 | return true; | | 2381 | return true; |
2379 | } | | 2382 | } |
2380 | | | 2383 | |
2381 | if (lt != PTR && rt != PTR) | | 2384 | if (lt != PTR && rt != PTR) |
2382 | return true; | | 2385 | return true; |
2383 | | | 2386 | |
2384 | if (!is_integer(lt) && !is_integer(rt)) { | | 2387 | if (!is_integer(lt) && !is_integer(rt)) { |
2385 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 2388 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
2386 | return false; | | 2389 | return false; |
2387 | } | | 2390 | } |
2388 | | | 2391 | |
2389 | const char *lx = lt == PTR ? "pointer" : "integer"; | | 2392 | const char *lx = lt == PTR ? "pointer" : "integer"; |
2390 | const char *rx = rt == PTR ? "pointer" : "integer"; | | 2393 | const char *rx = rt == PTR ? "pointer" : "integer"; |
2391 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ | | 2394 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ |
2392 | warning(123, lx, type_name(ltp), rx, type_name(rtp), op_name(op)); | | 2395 | warning(123, lx, type_name(ltp), rx, type_name(rtp), op_name(op)); |
2393 | return true; | | 2396 | return true; |
2394 | } | | 2397 | } |
2395 | | | 2398 | |
2396 | static bool | | 2399 | static bool |
2397 | typeok_quest(tspec_t lt, const tnode_t *rn) | | 2400 | typeok_quest(tspec_t lt, const tnode_t *rn) |
2398 | { | | 2401 | { |
2399 | if (!is_scalar(lt)) { | | 2402 | if (!is_scalar(lt)) { |
2400 | /* first operand must have scalar type, op ? : */ | | 2403 | /* first operand must have scalar type, op ? : */ |
2401 | error(170); | | 2404 | error(170); |
2402 | return false; | | 2405 | return false; |
2403 | } | | 2406 | } |
2404 | lint_assert(before_conversion(rn)->tn_op == COLON); | | 2407 | lint_assert(before_conversion(rn)->tn_op == COLON); |
2405 | return true; | | 2408 | return true; |
2406 | } | | 2409 | } |
2407 | | | 2410 | |
2408 | static void | | 2411 | static void |
2409 | typeok_colon_pointer(const mod_t *mp, const type_t *ltp, const type_t *rtp) | | 2412 | typeok_colon_pointer(const mod_t *mp, const type_t *ltp, const type_t *rtp) |
2410 | { | | 2413 | { |
2411 | type_t *lstp = ltp->t_subt; | | 2414 | type_t *lstp = ltp->t_subt; |
2412 | type_t *rstp = rtp->t_subt; | | 2415 | type_t *rstp = rtp->t_subt; |
2413 | tspec_t lst = lstp->t_tspec; | | 2416 | tspec_t lst = lstp->t_tspec; |
2414 | tspec_t rst = rstp->t_tspec; | | 2417 | tspec_t rst = rstp->t_tspec; |
2415 | | | 2418 | |
2416 | if ((lst == VOID && rst == FUNC) || (lst == FUNC && rst == VOID)) { | | 2419 | if ((lst == VOID && rst == FUNC) || (lst == FUNC && rst == VOID)) { |
2417 | /* (void *)0 is handled in typeok_colon */ | | 2420 | /* (void *)0 is handled in typeok_colon */ |
2418 | /* TODO: C99 behaves like C90 here. */ | | 2421 | /* TODO: C99 behaves like C90 here. */ |
2419 | if (!allow_trad && !allow_c99) | | 2422 | if (!allow_trad && !allow_c99) |
2420 | /* ANSI C forbids conversion of %s to %s, op %s */ | | 2423 | /* ANSI C forbids conversion of %s to %s, op %s */ |
2421 | warning(305, "function pointer", "'void *'", | | 2424 | warning(305, "function pointer", "'void *'", |
2422 | mp->m_name); | | 2425 | mp->m_name); |
2423 | return; | | 2426 | return; |
2424 | } | | 2427 | } |
2425 | | | 2428 | |
2426 | if (pointer_types_are_compatible(lstp, rstp, true)) | | 2429 | if (pointer_types_are_compatible(lstp, rstp, true)) |
2427 | return; | | 2430 | return; |
2428 | if (!types_compatible(lstp, rstp, true, false, NULL)) | | 2431 | if (!types_compatible(lstp, rstp, true, false, NULL)) |
2429 | warn_incompatible_pointers(mp, ltp, rtp); | | 2432 | warn_incompatible_pointers(mp, ltp, rtp); |
2430 | } | | 2433 | } |
2431 | | | 2434 | |
2432 | static bool | | 2435 | static bool |
2433 | typeok_colon(const mod_t *mp, | | 2436 | typeok_colon(const mod_t *mp, |
2434 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | | 2437 | const tnode_t *ln, const type_t *ltp, tspec_t lt, |
2435 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | | 2438 | const tnode_t *rn, const type_t *rtp, tspec_t rt) |
2436 | { | | 2439 | { |
2437 | | | 2440 | |
2438 | if (is_arithmetic(lt) && is_arithmetic(rt)) | | 2441 | if (is_arithmetic(lt) && is_arithmetic(rt)) |
2439 | return true; | | 2442 | return true; |
2440 | if (lt == BOOL && rt == BOOL) | | 2443 | if (lt == BOOL && rt == BOOL) |
2441 | return true; | | 2444 | return true; |
2442 | | | 2445 | |
2443 | if (lt == STRUCT && rt == STRUCT && ltp->t_str == rtp->t_str) | | 2446 | if (lt == STRUCT && rt == STRUCT && ltp->t_str == rtp->t_str) |
2444 | return true; | | 2447 | return true; |
2445 | if (lt == UNION && rt == UNION && ltp->t_str == rtp->t_str) | | 2448 | if (lt == UNION && rt == UNION && ltp->t_str == rtp->t_str) |
2446 | return true; | | 2449 | return true; |
2447 | | | 2450 | |
2448 | if (lt == PTR && is_null_pointer(rn)) | | 2451 | if (lt == PTR && is_null_pointer(rn)) |
2449 | return true; | | 2452 | return true; |
2450 | if (rt == PTR && is_null_pointer(ln)) | | 2453 | if (rt == PTR && is_null_pointer(ln)) |
2451 | return true; | | 2454 | return true; |
2452 | | | 2455 | |
2453 | if ((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)) { | | 2456 | if ((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)) { |
2454 | const char *lx = lt == PTR ? "pointer" : "integer"; | | 2457 | const char *lx = lt == PTR ? "pointer" : "integer"; |
2455 | const char *rx = rt == PTR ? "pointer" : "integer"; | | 2458 | const char *rx = rt == PTR ? "pointer" : "integer"; |
2456 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ | | 2459 | /* illegal combination of %s '%s' and %s '%s', op '%s' */ |
2457 | warning(123, lx, type_name(ltp), | | 2460 | warning(123, lx, type_name(ltp), |
2458 | rx, type_name(rtp), mp->m_name); | | 2461 | rx, type_name(rtp), mp->m_name); |
2459 | return true; | | 2462 | return true; |
2460 | } | | 2463 | } |
2461 | | | 2464 | |
2462 | if (lt == VOID || rt == VOID) { | | 2465 | if (lt == VOID || rt == VOID) { |
2463 | if (lt != VOID || rt != VOID) | | 2466 | if (lt != VOID || rt != VOID) |
2464 | /* incompatible types '%s' and '%s' in conditional */ | | 2467 | /* incompatible types '%s' and '%s' in conditional */ |
2465 | warning(126, type_name(ltp), type_name(rtp)); | | 2468 | warning(126, type_name(ltp), type_name(rtp)); |
2466 | return true; | | 2469 | return true; |
2467 | } | | 2470 | } |
2468 | | | 2471 | |
2469 | if (lt == PTR && rt == PTR) { | | 2472 | if (lt == PTR && rt == PTR) { |
2470 | typeok_colon_pointer(mp, ltp, rtp); | | 2473 | typeok_colon_pointer(mp, ltp, rtp); |
2471 | return true; | | 2474 | return true; |
2472 | } | | 2475 | } |
2473 | | | 2476 | |
2474 | /* incompatible types '%s' and '%s' in conditional */ | | 2477 | /* incompatible types '%s' and '%s' in conditional */ |
2475 | error(126, type_name(ltp), type_name(rtp)); | | 2478 | error(126, type_name(ltp), type_name(rtp)); |
2476 | return false; | | 2479 | return false; |
2477 | } | | 2480 | } |
2478 | | | 2481 | |
2479 | /* | | 2482 | /* |
2480 | * Returns true if the given structure or union has a constant member | | 2483 | * Returns true if the given structure or union has a constant member |
2481 | * (maybe recursively). | | 2484 | * (maybe recursively). |
2482 | */ | | 2485 | */ |
2483 | static bool | | 2486 | static bool |
2484 | has_constant_member(const type_t *tp) | | 2487 | has_constant_member(const type_t *tp) |
2485 | { | | 2488 | { |
2486 | lint_assert(is_struct_or_union(tp->t_tspec)); | | 2489 | lint_assert(is_struct_or_union(tp->t_tspec)); |
2487 | | | 2490 | |
2488 | for (sym_t *m = tp->t_str->sou_first_member; | | 2491 | for (sym_t *m = tp->t_str->sou_first_member; |
2489 | m != NULL; m = m->s_next) { | | 2492 | m != NULL; m = m->s_next) { |
2490 | const type_t *mtp = m->s_type; | | 2493 | const type_t *mtp = m->s_type; |
2491 | if (mtp->t_const) | | 2494 | if (mtp->t_const) |
2492 | return true; | | 2495 | return true; |
2493 | if (is_struct_or_union(mtp->t_tspec) && | | 2496 | if (is_struct_or_union(mtp->t_tspec) && |
2494 | has_constant_member(mtp)) | | 2497 | has_constant_member(mtp)) |
2495 | return true; | | 2498 | return true; |
2496 | } | | 2499 | } |
2497 | return false; | | 2500 | return false; |
2498 | } | | 2501 | } |
2499 | | | 2502 | |
2500 | static bool | | 2503 | static bool |
2501 | typeok_assign(op_t op, const tnode_t *ln, const type_t *ltp, tspec_t lt) | | 2504 | typeok_assign(op_t op, const tnode_t *ln, const type_t *ltp, tspec_t lt) |
2502 | { | | 2505 | { |
2503 | if (op == RETURN || op == INIT || op == FARG) | | 2506 | if (op == RETURN || op == INIT || op == FARG) |
2504 | return true; | | 2507 | return true; |
2505 | | | 2508 | |
2506 | if (!ln->tn_lvalue) { | | 2509 | if (!ln->tn_lvalue) { |
2507 | if (ln->tn_op == CVT && ln->tn_cast && | | 2510 | if (ln->tn_op == CVT && ln->tn_cast && |
2508 | ln->tn_left->tn_op == LOAD) { | | 2511 | ln->tn_left->tn_op == LOAD) { |
2509 | /* a cast does not yield an lvalue */ | | 2512 | /* a cast does not yield an lvalue */ |
2510 | error(163); | | 2513 | error(163); |
2511 | } | | 2514 | } |
2512 | /* %soperand of '%s' must be lvalue */ | | 2515 | /* %soperand of '%s' must be lvalue */ |
2513 | error(114, "left ", op_name(op)); | | 2516 | error(114, "left ", op_name(op)); |
2514 | return false; | | 2517 | return false; |
2515 | } else if (ltp->t_const || (is_struct_or_union(lt) && | | 2518 | } else if (ltp->t_const || (is_struct_or_union(lt) && |
2516 | has_constant_member(ltp))) { | | 2519 | has_constant_member(ltp))) { |
2517 | if (allow_c90) | | 2520 | if (allow_c90) |
2518 | /* %soperand of '%s' must be modifiable lvalue */ | | 2521 | /* %soperand of '%s' must be modifiable lvalue */ |
2519 | warning(115, "left ", op_name(op)); | | 2522 | warning(115, "left ", op_name(op)); |
2520 | } | | 2523 | } |
2521 | return true; | | 2524 | return true; |