| @@ -1,4414 +1,4412 @@ | | | @@ -1,4414 +1,4412 @@ |
1 | /* $NetBSD: tree.c,v 1.260 2021/04/02 15:06:35 rillig Exp $ */ | | 1 | /* $NetBSD: tree.c,v 1.261 2021/04/02 16:17:19 rillig Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1994, 1995 Jochen Pohl | | 4 | * Copyright (c) 1994, 1995 Jochen Pohl |
5 | * All Rights Reserved. | | 5 | * All Rights Reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
15 | * 3. All advertising materials mentioning features or use of this software | | 15 | * 3. All advertising materials mentioning features or use of this software |
16 | * must display the following acknowledgement: | | 16 | * must display the following acknowledgement: |
17 | * This product includes software developed by Jochen Pohl for | | 17 | * This product includes software developed by Jochen Pohl for |
18 | * The NetBSD Project. | | 18 | * The NetBSD Project. |
19 | * 4. The name of the author may not be used to endorse or promote products | | 19 | * 4. The name of the author may not be used to endorse or promote products |
20 | * derived from this software without specific prior written permission. | | 20 | * derived from this software without specific prior written permission. |
21 | * | | 21 | * |
22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 22 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 23 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 24 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 25 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 26 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #if HAVE_NBTOOL_CONFIG_H | | 34 | #if HAVE_NBTOOL_CONFIG_H |
35 | #include "nbtool_config.h" | | 35 | #include "nbtool_config.h" |
36 | #endif | | 36 | #endif |
37 | | | 37 | |
38 | #include <sys/cdefs.h> | | 38 | #include <sys/cdefs.h> |
39 | #if defined(__RCSID) && !defined(lint) | | 39 | #if defined(__RCSID) && !defined(lint) |
40 | __RCSID("$NetBSD: tree.c,v 1.260 2021/04/02 15:06:35 rillig Exp $"); | | 40 | __RCSID("$NetBSD: tree.c,v 1.261 2021/04/02 16:17:19 rillig Exp $"); |
41 | #endif | | 41 | #endif |
42 | | | 42 | |
43 | #include <float.h> | | 43 | #include <float.h> |
44 | #include <limits.h> | | 44 | #include <limits.h> |
45 | #include <math.h> | | 45 | #include <math.h> |
46 | #include <signal.h> | | 46 | #include <signal.h> |
47 | #include <stdlib.h> | | 47 | #include <stdlib.h> |
48 | #include <string.h> | | 48 | #include <string.h> |
49 | | | 49 | |
50 | #include "lint1.h" | | 50 | #include "lint1.h" |
51 | #include "cgram.h" | | 51 | #include "cgram.h" |
52 | | | 52 | |
53 | static tnode_t *expr_new_integer_constant(tspec_t, int64_t); | | 53 | static tnode_t *expr_new_integer_constant(tspec_t, int64_t); |
54 | static void check_pointer_comparison(op_t, | | 54 | static void check_pointer_comparison(op_t, |
55 | const tnode_t *, const tnode_t *); | | 55 | const tnode_t *, const tnode_t *); |
56 | static bool check_assign_types_compatible(op_t, int, | | 56 | static bool check_assign_types_compatible(op_t, int, |
57 | const tnode_t *, const tnode_t *); | | 57 | const tnode_t *, const tnode_t *); |
58 | static void check_bad_enum_operation(op_t, | | 58 | static void check_bad_enum_operation(op_t, |
59 | const tnode_t *, const tnode_t *); | | 59 | const tnode_t *, const tnode_t *); |
60 | static void check_enum_type_mismatch(op_t, int, | | 60 | static void check_enum_type_mismatch(op_t, int, |
61 | const tnode_t *, const tnode_t *); | | 61 | const tnode_t *, const tnode_t *); |
62 | static void check_enum_int_mismatch(op_t, int, | | 62 | static void check_enum_int_mismatch(op_t, int, |
63 | const tnode_t *, const tnode_t *); | | 63 | const tnode_t *, const tnode_t *); |
64 | static tnode_t *new_tnode(op_t, type_t *, tnode_t *, tnode_t *); | | 64 | static tnode_t *new_tnode(op_t, type_t *, tnode_t *, tnode_t *); |
65 | static void balance(op_t, tnode_t **, tnode_t **); | | 65 | static void balance(op_t, tnode_t **, tnode_t **); |
66 | static void warn_incompatible_types(op_t, const type_t *, tspec_t, | | 66 | static void warn_incompatible_types(op_t, const type_t *, tspec_t, |
67 | const type_t *, tspec_t); | | 67 | const type_t *, tspec_t); |
68 | static void warn_incompatible_pointers(const mod_t *, | | 68 | static void warn_incompatible_pointers(const mod_t *, |
69 | const type_t *, const type_t *); | | 69 | const type_t *, const type_t *); |
70 | static void merge_qualifiers(type_t **, type_t *, type_t *); | | 70 | static void merge_qualifiers(type_t **, type_t *, type_t *); |
71 | static bool has_constant_member(const type_t *); | | 71 | static bool has_constant_member(const type_t *); |
72 | static void check_prototype_conversion(int, tspec_t, tspec_t, type_t *, | | 72 | static void check_prototype_conversion(int, tspec_t, tspec_t, type_t *, |
73 | tnode_t *); | | 73 | tnode_t *); |
74 | static void check_integer_conversion(op_t, int, tspec_t, tspec_t, type_t *, | | 74 | static void check_integer_conversion(op_t, int, tspec_t, tspec_t, type_t *, |
75 | tnode_t *); | | 75 | tnode_t *); |
76 | static void check_pointer_integer_conversion(op_t, tspec_t, type_t *, | | 76 | static void check_pointer_integer_conversion(op_t, tspec_t, type_t *, |
77 | tnode_t *); | | 77 | tnode_t *); |
78 | static void check_pointer_conversion(op_t, tnode_t *, type_t *); | | 78 | static void check_pointer_conversion(op_t, tnode_t *, type_t *); |
79 | static tnode_t *build_struct_access(op_t, tnode_t *, tnode_t *); | | 79 | static tnode_t *build_struct_access(op_t, tnode_t *, tnode_t *); |
80 | static tnode_t *build_prepost_incdec(op_t, tnode_t *); | | 80 | static tnode_t *build_prepost_incdec(op_t, tnode_t *); |
81 | static tnode_t *build_real_imag(op_t, tnode_t *); | | 81 | static tnode_t *build_real_imag(op_t, tnode_t *); |
82 | static tnode_t *build_address(tnode_t *, bool); | | 82 | static tnode_t *build_address(tnode_t *, bool); |
83 | static tnode_t *build_plus_minus(op_t, tnode_t *, tnode_t *); | | 83 | static tnode_t *build_plus_minus(op_t, tnode_t *, tnode_t *); |
84 | static tnode_t *build_bit_shift(op_t, tnode_t *, tnode_t *); | | 84 | static tnode_t *build_bit_shift(op_t, tnode_t *, tnode_t *); |
85 | static tnode_t *build_colon(tnode_t *, tnode_t *); | | 85 | static tnode_t *build_colon(tnode_t *, tnode_t *); |
86 | static tnode_t *build_assignment(op_t, tnode_t *, tnode_t *); | | 86 | static tnode_t *build_assignment(op_t, tnode_t *, tnode_t *); |
87 | static tnode_t *plength(type_t *); | | 87 | static tnode_t *plength(type_t *); |
88 | static tnode_t *fold(tnode_t *); | | 88 | static tnode_t *fold(tnode_t *); |
89 | static tnode_t *fold_test(tnode_t *); | | 89 | static tnode_t *fold_test(tnode_t *); |
90 | static tnode_t *fold_float(tnode_t *); | | 90 | static tnode_t *fold_float(tnode_t *); |
91 | static tnode_t *check_function_arguments(type_t *, tnode_t *); | | 91 | static tnode_t *check_function_arguments(type_t *, tnode_t *); |
92 | static tnode_t *check_prototype_argument(int, type_t *, tnode_t *); | | 92 | static tnode_t *check_prototype_argument(int, type_t *, tnode_t *); |
93 | static void check_null_effect(const tnode_t *); | | 93 | static void check_null_effect(const tnode_t *); |
94 | static void display_expression(const tnode_t *, int); | | 94 | static void display_expression(const tnode_t *, int); |
95 | static void check_array_index(tnode_t *, bool); | | 95 | static void check_array_index(tnode_t *, bool); |
96 | static void check_integer_comparison(op_t, tnode_t *, tnode_t *); | | 96 | static void check_integer_comparison(op_t, tnode_t *, tnode_t *); |
97 | static void check_precedence_confusion(tnode_t *); | | 97 | static void check_precedence_confusion(tnode_t *); |
98 | | | 98 | |
99 | extern sig_atomic_t fpe; | | 99 | extern sig_atomic_t fpe; |
100 | | | 100 | |
101 | static const char * | | 101 | static const char * |
102 | op_name(op_t op) | | 102 | op_name(op_t op) |
103 | { | | 103 | { |
104 | return modtab[op].m_name; | | 104 | return modtab[op].m_name; |
105 | } | | 105 | } |
106 | | | 106 | |
107 | #ifdef DEBUG | | 107 | #ifdef DEBUG |
108 | void | | 108 | void |
109 | debug_node(const tnode_t *tn, int indent) | | 109 | debug_node(const tnode_t *tn, int indent) |
110 | { | | 110 | { |
111 | op_t op; | | 111 | op_t op; |
112 | | | 112 | |
113 | if (tn == NULL) { | | 113 | if (tn == NULL) { |
114 | printf("%*s" "null\n", indent, ""); | | 114 | printf("%*s" "null\n", indent, ""); |
115 | return; | | 115 | return; |
116 | } | | 116 | } |
117 | | | 117 | |
118 | op = tn->tn_op; | | 118 | op = tn->tn_op; |
119 | printf("%*s%s with type '%s'%s%s", | | 119 | printf("%*s%s with type '%s'%s%s", |
120 | 2 * indent, "", | | 120 | 2 * indent, "", |
121 | op == CVT && !tn->tn_cast ? "convert" : op_name(op), | | 121 | op == CVT && !tn->tn_cast ? "convert" : op_name(op), |
122 | type_name(tn->tn_type), tn->tn_lvalue ? ", lvalue" : "", | | 122 | type_name(tn->tn_type), tn->tn_lvalue ? ", lvalue" : "", |
123 | tn->tn_parenthesized ? ", parenthesized" : ""); | | 123 | tn->tn_parenthesized ? ", parenthesized" : ""); |
124 | | | 124 | |
125 | if (op == NAME) | | 125 | if (op == NAME) |
126 | printf(" %s\n", tn->tn_sym->s_name); | | 126 | printf(" %s\n", tn->tn_sym->s_name); |
127 | else if (op == CON && is_floating(tn->tn_type->t_tspec)) | | 127 | else if (op == CON && is_floating(tn->tn_type->t_tspec)) |
128 | printf(", value %Lg", tn->tn_val->v_ldbl); | | 128 | printf(", value %Lg", tn->tn_val->v_ldbl); |
129 | else if (op == CON && is_uinteger(tn->tn_type->t_tspec)) | | 129 | else if (op == CON && is_uinteger(tn->tn_type->t_tspec)) |
130 | printf(", value %llu\n", (unsigned long long)tn->tn_val->v_quad); | | 130 | printf(", value %llu\n", (unsigned long long)tn->tn_val->v_quad); |
131 | else if (op == CON && is_integer(tn->tn_type->t_tspec)) | | 131 | else if (op == CON && is_integer(tn->tn_type->t_tspec)) |
132 | printf(", value %lld\n", (long long)tn->tn_val->v_quad); | | 132 | printf(", value %lld\n", (long long)tn->tn_val->v_quad); |
133 | else if (op == CON) | | 133 | else if (op == CON) |
134 | printf(", unknown value\n"); | | 134 | printf(", unknown value\n"); |
135 | else if (op == STRING) | | 135 | else if (op == STRING) |
136 | printf(", length %zu\n", tn->tn_string->st_len); | | 136 | printf(", length %zu\n", tn->tn_string->st_len); |
137 | else { | | 137 | else { |
138 | printf("\n"); | | 138 | printf("\n"); |
139 | | | 139 | |
140 | debug_node(tn->tn_left, indent + 1); | | 140 | debug_node(tn->tn_left, indent + 1); |
141 | if (modtab[op].m_binary || tn->tn_right != NULL) | | 141 | if (modtab[op].m_binary || tn->tn_right != NULL) |
142 | debug_node(tn->tn_right, indent + 1); | | 142 | debug_node(tn->tn_right, indent + 1); |
143 | } | | 143 | } |
144 | } | | 144 | } |
145 | #endif | | 145 | #endif |
146 | | | 146 | |
147 | /* Build 'pointer to tp', 'array of tp' or 'function returning tp'. */ | | 147 | /* Build 'pointer to tp', 'array of tp' or 'function returning tp'. */ |
148 | type_t * | | 148 | type_t * |
149 | derive_type(type_t *tp, tspec_t t) | | 149 | derive_type(type_t *tp, tspec_t t) |
150 | { | | 150 | { |
151 | type_t *tp2; | | 151 | type_t *tp2; |
152 | | | 152 | |
153 | tp2 = getblk(sizeof(*tp2)); | | 153 | tp2 = getblk(sizeof(*tp2)); |
154 | tp2->t_tspec = t; | | 154 | tp2->t_tspec = t; |
155 | tp2->t_subt = tp; | | 155 | tp2->t_subt = tp; |
156 | return tp2; | | 156 | return tp2; |
157 | } | | 157 | } |
158 | | | 158 | |
159 | /* | | 159 | /* |
160 | * Build 'pointer to tp', 'array of tp' or 'function returning tp'. The | | 160 | * Build 'pointer to tp', 'array of tp' or 'function returning tp'. The |
161 | * memory is freed at the end of the current expression. | | 161 | * memory is freed at the end of the current expression. |
162 | */ | | 162 | */ |
163 | type_t * | | 163 | type_t * |
164 | expr_derive_type(type_t *tp, tspec_t t) | | 164 | expr_derive_type(type_t *tp, tspec_t t) |
165 | { | | 165 | { |
166 | type_t *tp2; | | 166 | type_t *tp2; |
167 | | | 167 | |
168 | tp2 = expr_zalloc(sizeof(*tp2)); | | 168 | tp2 = expr_zalloc(sizeof(*tp2)); |
169 | tp2->t_tspec = t; | | 169 | tp2->t_tspec = t; |
170 | tp2->t_subt = tp; | | 170 | tp2->t_subt = tp; |
171 | return tp2; | | 171 | return tp2; |
172 | } | | 172 | } |
173 | | | 173 | |
174 | /* | | 174 | /* |
175 | * Create a node for a constant. | | 175 | * Create a node for a constant. |
176 | */ | | 176 | */ |
177 | tnode_t * | | 177 | tnode_t * |
178 | expr_new_constant(type_t *tp, val_t *v) | | 178 | expr_new_constant(type_t *tp, val_t *v) |
179 | { | | 179 | { |
180 | tnode_t *n; | | 180 | tnode_t *n; |
181 | | | 181 | |
182 | n = expr_zalloc_tnode(); | | 182 | n = expr_zalloc_tnode(); |
183 | n->tn_op = CON; | | 183 | n->tn_op = CON; |
184 | n->tn_type = tp; | | 184 | n->tn_type = tp; |
185 | n->tn_val = expr_zalloc(sizeof(*n->tn_val)); | | 185 | n->tn_val = expr_zalloc(sizeof(*n->tn_val)); |
186 | n->tn_val->v_tspec = tp->t_tspec; | | 186 | n->tn_val->v_tspec = tp->t_tspec; |
187 | n->tn_val->v_ansiu = v->v_ansiu; | | 187 | n->tn_val->v_ansiu = v->v_ansiu; |
188 | n->tn_val->v_u = v->v_u; | | 188 | n->tn_val->v_u = v->v_u; |
189 | free(v); | | 189 | free(v); |
190 | return n; | | 190 | return n; |
191 | } | | 191 | } |
192 | | | 192 | |
193 | static tnode_t * | | 193 | static tnode_t * |
194 | expr_new_integer_constant(tspec_t t, int64_t q) | | 194 | expr_new_integer_constant(tspec_t t, int64_t q) |
195 | { | | 195 | { |
196 | tnode_t *n; | | 196 | tnode_t *n; |
197 | | | 197 | |
198 | n = expr_zalloc_tnode(); | | 198 | n = expr_zalloc_tnode(); |
199 | n->tn_op = CON; | | 199 | n->tn_op = CON; |
200 | n->tn_type = gettyp(t); | | 200 | n->tn_type = gettyp(t); |
201 | n->tn_val = expr_zalloc(sizeof(*n->tn_val)); | | 201 | n->tn_val = expr_zalloc(sizeof(*n->tn_val)); |
202 | n->tn_val->v_tspec = t; | | 202 | n->tn_val->v_tspec = t; |
203 | n->tn_val->v_quad = q; | | 203 | n->tn_val->v_quad = q; |
204 | return n; | | 204 | return n; |
205 | } | | 205 | } |
206 | | | 206 | |
207 | static void | | 207 | static void |
208 | fallback_symbol(sym_t *sym) | | 208 | fallback_symbol(sym_t *sym) |
209 | { | | 209 | { |
210 | | | 210 | |
211 | if (Tflag && strcmp(sym->s_name, "__lint_false") == 0) { | | 211 | if (Tflag && strcmp(sym->s_name, "__lint_false") == 0) { |
212 | sym->s_scl = CTCONST; /* close enough */ | | 212 | sym->s_scl = CTCONST; /* close enough */ |
213 | sym->s_type = gettyp(BOOL); | | 213 | sym->s_type = gettyp(BOOL); |
214 | sym->s_value.v_tspec = BOOL; | | 214 | sym->s_value.v_tspec = BOOL; |
215 | sym->s_value.v_ansiu = false; | | 215 | sym->s_value.v_ansiu = false; |
216 | sym->s_value.v_quad = 0; | | 216 | sym->s_value.v_quad = 0; |
217 | return; | | 217 | return; |
218 | } | | 218 | } |
219 | | | 219 | |
220 | if (Tflag && strcmp(sym->s_name, "__lint_true") == 0) { | | 220 | if (Tflag && strcmp(sym->s_name, "__lint_true") == 0) { |
221 | sym->s_scl = CTCONST; /* close enough */ | | 221 | sym->s_scl = CTCONST; /* close enough */ |
222 | sym->s_type = gettyp(BOOL); | | 222 | sym->s_type = gettyp(BOOL); |
223 | sym->s_value.v_tspec = BOOL; | | 223 | sym->s_value.v_tspec = BOOL; |
224 | sym->s_value.v_ansiu = false; | | 224 | sym->s_value.v_ansiu = false; |
225 | sym->s_value.v_quad = 1; | | 225 | sym->s_value.v_quad = 1; |
226 | return; | | 226 | return; |
227 | } | | 227 | } |
228 | | | 228 | |
229 | if (block_level > 0 && (strcmp(sym->s_name, "__FUNCTION__") == 0 || | | 229 | if (block_level > 0 && (strcmp(sym->s_name, "__FUNCTION__") == 0 || |
230 | strcmp(sym->s_name, "__PRETTY_FUNCTION__") == 0)) { | | 230 | strcmp(sym->s_name, "__PRETTY_FUNCTION__") == 0)) { |
231 | /* __FUNCTION__/__PRETTY_FUNCTION__ is a GCC extension */ | | 231 | /* __FUNCTION__/__PRETTY_FUNCTION__ is a GCC extension */ |
232 | gnuism(316); | | 232 | gnuism(316); |
233 | sym->s_type = derive_type(gettyp(CHAR), PTR); | | 233 | sym->s_type = derive_type(gettyp(CHAR), PTR); |
234 | sym->s_type->t_const = true; | | 234 | sym->s_type->t_const = true; |
235 | return; | | 235 | return; |
236 | } | | 236 | } |
237 | | | 237 | |
238 | if (block_level > 0 && strcmp(sym->s_name, "__func__") == 0) { | | 238 | if (block_level > 0 && strcmp(sym->s_name, "__func__") == 0) { |
239 | if (!Sflag) | | 239 | if (!Sflag) |
240 | /* __func__ is a C9X feature */ | | 240 | /* __func__ is a C9X feature */ |
241 | warning(317); | | 241 | warning(317); |
242 | sym->s_type = derive_type(gettyp(CHAR), PTR); | | 242 | sym->s_type = derive_type(gettyp(CHAR), PTR); |
243 | sym->s_type->t_const = true; | | 243 | sym->s_type->t_const = true; |
244 | return; | | 244 | return; |
245 | } | | 245 | } |
246 | | | 246 | |
247 | /* '%s' undefined */ | | 247 | /* '%s' undefined */ |
248 | error(99, sym->s_name); | | 248 | error(99, sym->s_name); |
249 | } | | 249 | } |
250 | | | 250 | |
251 | /* | | 251 | /* |
252 | * Create a node for a name (symbol table entry). | | 252 | * Create a node for a name (symbol table entry). |
253 | * follow_token is the token which follows the name. | | 253 | * follow_token is the token which follows the name. |
254 | */ | | 254 | */ |
255 | tnode_t * | | 255 | tnode_t * |
256 | new_name_node(sym_t *sym, int follow_token) | | 256 | new_name_node(sym_t *sym, int follow_token) |
257 | { | | 257 | { |
258 | tnode_t *n; | | 258 | tnode_t *n; |
259 | | | 259 | |
260 | if (sym->s_scl == NOSCL) { | | 260 | if (sym->s_scl == NOSCL) { |
261 | sym->s_scl = EXTERN; | | 261 | sym->s_scl = EXTERN; |
262 | sym->s_def = DECL; | | 262 | sym->s_def = DECL; |
263 | if (follow_token == T_LPAREN) { | | 263 | if (follow_token == T_LPAREN) { |
264 | if (sflag) { | | 264 | if (sflag) { |
265 | /* function implicitly declared to ... */ | | 265 | /* function implicitly declared to ... */ |
266 | warning(215); | | 266 | warning(215); |
267 | } | | 267 | } |
268 | /* | | 268 | /* |
269 | * XXX if tflag is set the symbol should be | | 269 | * XXX if tflag is set the symbol should be |
270 | * exported to level 0 | | 270 | * exported to level 0 |
271 | */ | | 271 | */ |
272 | sym->s_type = derive_type(sym->s_type, FUNC); | | 272 | sym->s_type = derive_type(sym->s_type, FUNC); |
273 | } else { | | 273 | } else { |
274 | fallback_symbol(sym); | | 274 | fallback_symbol(sym); |
275 | } | | 275 | } |
276 | } | | 276 | } |
277 | | | 277 | |
278 | lint_assert(sym->s_kind == FVFT || sym->s_kind == FMEMBER); | | 278 | lint_assert(sym->s_kind == FVFT || sym->s_kind == FMEMBER); |
279 | | | 279 | |
280 | n = expr_zalloc_tnode(); | | 280 | n = expr_zalloc_tnode(); |
281 | n->tn_type = sym->s_type; | | 281 | n->tn_type = sym->s_type; |
282 | if (sym->s_scl != CTCONST) { | | 282 | if (sym->s_scl != CTCONST) { |
283 | n->tn_op = NAME; | | 283 | n->tn_op = NAME; |
284 | n->tn_sym = sym; | | 284 | n->tn_sym = sym; |
285 | if (sym->s_kind == FVFT && sym->s_type->t_tspec != FUNC) | | 285 | if (sym->s_kind == FVFT && sym->s_type->t_tspec != FUNC) |
286 | n->tn_lvalue = true; | | 286 | n->tn_lvalue = true; |
287 | } else { | | 287 | } else { |
288 | n->tn_op = CON; | | 288 | n->tn_op = CON; |
289 | n->tn_val = expr_zalloc(sizeof(*n->tn_val)); | | 289 | n->tn_val = expr_zalloc(sizeof(*n->tn_val)); |
290 | *n->tn_val = sym->s_value; | | 290 | *n->tn_val = sym->s_value; |
291 | } | | 291 | } |
292 | | | 292 | |
293 | return n; | | 293 | return n; |
294 | } | | 294 | } |
295 | | | 295 | |
296 | tnode_t * | | 296 | tnode_t * |
297 | new_string_node(strg_t *strg) | | 297 | new_string_node(strg_t *strg) |
298 | { | | 298 | { |
299 | size_t len; | | 299 | size_t len; |
300 | tnode_t *n; | | 300 | tnode_t *n; |
301 | | | 301 | |
302 | len = strg->st_len; | | 302 | len = strg->st_len; |
303 | | | 303 | |
304 | n = expr_zalloc_tnode(); | | 304 | n = expr_zalloc_tnode(); |
305 | | | 305 | |
306 | n->tn_op = STRING; | | 306 | n->tn_op = STRING; |
307 | n->tn_type = expr_derive_type(gettyp(strg->st_tspec), ARRAY); | | 307 | n->tn_type = expr_derive_type(gettyp(strg->st_tspec), ARRAY); |
308 | n->tn_type->t_dim = len + 1; | | 308 | n->tn_type->t_dim = len + 1; |
309 | n->tn_lvalue = true; | | 309 | n->tn_lvalue = true; |
310 | | | 310 | |
311 | n->tn_string = expr_zalloc(sizeof(*n->tn_string)); | | 311 | n->tn_string = expr_zalloc(sizeof(*n->tn_string)); |
312 | n->tn_string->st_tspec = strg->st_tspec; | | 312 | n->tn_string->st_tspec = strg->st_tspec; |
313 | n->tn_string->st_len = len; | | 313 | n->tn_string->st_len = len; |
314 | | | 314 | |
315 | if (strg->st_tspec == CHAR) { | | 315 | if (strg->st_tspec == CHAR) { |
316 | n->tn_string->st_cp = expr_zalloc(len + 1); | | 316 | n->tn_string->st_cp = expr_zalloc(len + 1); |
317 | (void)memcpy(n->tn_string->st_cp, strg->st_cp, len + 1); | | 317 | (void)memcpy(n->tn_string->st_cp, strg->st_cp, len + 1); |
318 | free(strg->st_cp); | | 318 | free(strg->st_cp); |
319 | } else { | | 319 | } else { |
320 | size_t size = (len + 1) * sizeof(*n->tn_string->st_wcp); | | 320 | size_t size = (len + 1) * sizeof(*n->tn_string->st_wcp); |
321 | n->tn_string->st_wcp = expr_zalloc(size); | | 321 | n->tn_string->st_wcp = expr_zalloc(size); |
322 | (void)memcpy(n->tn_string->st_wcp, strg->st_wcp, size); | | 322 | (void)memcpy(n->tn_string->st_wcp, strg->st_wcp, size); |
323 | free(strg->st_wcp); | | 323 | free(strg->st_wcp); |
324 | } | | 324 | } |
325 | free(strg); | | 325 | free(strg); |
326 | | | 326 | |
327 | return n; | | 327 | return n; |
328 | } | | 328 | } |
329 | | | 329 | |
330 | /* | | 330 | /* |
331 | * Returns a symbol which has the same name as the msym argument and is a | | 331 | * Returns a symbol which has the same name as the msym argument and is a |
332 | * member of the struct or union specified by the tn argument. | | 332 | * member of the struct or union specified by the tn argument. |
333 | */ | | 333 | */ |
334 | sym_t * | | 334 | sym_t * |
335 | struct_or_union_member(tnode_t *tn, op_t op, sym_t *msym) | | 335 | struct_or_union_member(tnode_t *tn, op_t op, sym_t *msym) |
336 | { | | 336 | { |
337 | struct_or_union *str; | | 337 | struct_or_union *str; |
338 | type_t *tp; | | 338 | type_t *tp; |
339 | sym_t *sym, *csym; | | 339 | sym_t *sym, *csym; |
340 | bool eq; | | 340 | bool eq; |
341 | tspec_t t; | | 341 | tspec_t t; |
342 | | | 342 | |
343 | /* | | 343 | /* |
344 | * Remove the member if it was unknown until now, which means | | 344 | * Remove the member if it was unknown until now, which means |
345 | * that no defined struct or union has a member with the same name. | | 345 | * that no defined struct or union has a member with the same name. |
346 | */ | | 346 | */ |
347 | if (msym->s_scl == NOSCL) { | | 347 | if (msym->s_scl == NOSCL) { |
348 | /* type '%s' does not have member '%s' */ | | 348 | /* type '%s' does not have member '%s' */ |
349 | error(101, type_name(msym->s_type), msym->s_name); | | 349 | error(101, type_name(msym->s_type), msym->s_name); |
350 | rmsym(msym); | | 350 | rmsym(msym); |
351 | msym->s_kind = FMEMBER; | | 351 | msym->s_kind = FMEMBER; |
352 | msym->s_scl = MOS; | | 352 | msym->s_scl = MOS; |
353 | msym->s_styp = expr_zalloc(sizeof(*msym->s_styp)); | | 353 | msym->s_styp = expr_zalloc(sizeof(*msym->s_styp)); |
354 | msym->s_styp->sou_tag = expr_zalloc( | | 354 | msym->s_styp->sou_tag = expr_zalloc( |
355 | sizeof(*msym->s_styp->sou_tag)); | | 355 | sizeof(*msym->s_styp->sou_tag)); |
356 | msym->s_styp->sou_tag->s_name = unnamed; | | 356 | msym->s_styp->sou_tag->s_name = unnamed; |
357 | msym->s_value.v_tspec = INT; | | 357 | msym->s_value.v_tspec = INT; |
358 | return msym; | | 358 | return msym; |
359 | } | | 359 | } |
360 | | | 360 | |
361 | /* Set str to the tag of which msym is expected to be a member. */ | | 361 | /* Set str to the tag of which msym is expected to be a member. */ |
362 | str = NULL; | | 362 | str = NULL; |
363 | t = (tp = tn->tn_type)->t_tspec; | | 363 | t = (tp = tn->tn_type)->t_tspec; |
364 | if (op == POINT) { | | 364 | if (op == POINT) { |
365 | if (t == STRUCT || t == UNION) | | 365 | if (t == STRUCT || t == UNION) |
366 | str = tp->t_str; | | 366 | str = tp->t_str; |
367 | } else if (op == ARROW && t == PTR) { | | 367 | } else if (op == ARROW && t == PTR) { |
368 | t = (tp = tp->t_subt)->t_tspec; | | 368 | t = (tp = tp->t_subt)->t_tspec; |
369 | if (t == STRUCT || t == UNION) | | 369 | if (t == STRUCT || t == UNION) |
370 | str = tp->t_str; | | 370 | str = tp->t_str; |
371 | } | | 371 | } |
372 | | | 372 | |
373 | /* | | 373 | /* |
374 | * If this struct/union has a member with the name of msym, return it. | | 374 | * If this struct/union has a member with the name of msym, return it. |
375 | */ | | 375 | */ |
376 | if (str != NULL) { | | 376 | if (str != NULL) { |
377 | for (sym = msym; sym != NULL; sym = sym->s_link) { | | 377 | for (sym = msym; sym != NULL; sym = sym->s_link) { |
378 | if (sym->s_scl != MOS && sym->s_scl != MOU) | | 378 | if (sym->s_scl != MOS && sym->s_scl != MOU) |
379 | continue; | | 379 | continue; |
380 | if (sym->s_styp != str) | | 380 | if (sym->s_styp != str) |
381 | continue; | | 381 | continue; |
382 | if (strcmp(sym->s_name, msym->s_name) != 0) | | 382 | if (strcmp(sym->s_name, msym->s_name) != 0) |
383 | continue; | | 383 | continue; |
384 | return sym; | | 384 | return sym; |
385 | } | | 385 | } |
386 | } | | 386 | } |
387 | | | 387 | |
388 | /* | | 388 | /* |
389 | * Set eq to false if there are struct/union members with the same | | 389 | * Set eq to false if there are struct/union members with the same |
390 | * name and different types and/or offsets. | | 390 | * name and different types and/or offsets. |
391 | */ | | 391 | */ |
392 | eq = true; | | 392 | eq = true; |
393 | for (csym = msym; csym != NULL; csym = csym->s_link) { | | 393 | for (csym = msym; csym != NULL; csym = csym->s_link) { |
394 | if (csym->s_scl != MOS && csym->s_scl != MOU) | | 394 | if (csym->s_scl != MOS && csym->s_scl != MOU) |
395 | continue; | | 395 | continue; |
396 | if (strcmp(msym->s_name, csym->s_name) != 0) | | 396 | if (strcmp(msym->s_name, csym->s_name) != 0) |
397 | continue; | | 397 | continue; |
398 | for (sym = csym->s_link ; sym != NULL; sym = sym->s_link) { | | 398 | for (sym = csym->s_link ; sym != NULL; sym = sym->s_link) { |
399 | bool w; | | 399 | bool w; |
400 | | | 400 | |
401 | if (sym->s_scl != MOS && sym->s_scl != MOU) | | 401 | if (sym->s_scl != MOS && sym->s_scl != MOU) |
402 | continue; | | 402 | continue; |
403 | if (strcmp(csym->s_name, sym->s_name) != 0) | | 403 | if (strcmp(csym->s_name, sym->s_name) != 0) |
404 | continue; | | 404 | continue; |
405 | if (csym->s_value.v_quad != sym->s_value.v_quad) { | | 405 | if (csym->s_value.v_quad != sym->s_value.v_quad) { |
406 | eq = false; | | 406 | eq = false; |
407 | break; | | 407 | break; |
408 | } | | 408 | } |
409 | w = false; | | 409 | w = false; |
410 | eq = eqtype(csym->s_type, sym->s_type, | | 410 | eq = eqtype(csym->s_type, sym->s_type, |
411 | false, false, &w) && !w; | | 411 | false, false, &w) && !w; |
412 | if (!eq) | | 412 | if (!eq) |
413 | break; | | 413 | break; |
414 | if (csym->s_bitfield != sym->s_bitfield) { | | 414 | if (csym->s_bitfield != sym->s_bitfield) { |
415 | eq = false; | | 415 | eq = false; |
416 | break; | | 416 | break; |
417 | } | | 417 | } |
418 | if (csym->s_bitfield) { | | 418 | if (csym->s_bitfield) { |
419 | type_t *tp1, *tp2; | | 419 | type_t *tp1, *tp2; |
420 | | | 420 | |
421 | tp1 = csym->s_type; | | 421 | tp1 = csym->s_type; |
422 | tp2 = sym->s_type; | | 422 | tp2 = sym->s_type; |
423 | if (tp1->t_flen != tp2->t_flen) { | | 423 | if (tp1->t_flen != tp2->t_flen) { |
424 | eq = false; | | 424 | eq = false; |
425 | break; | | 425 | break; |
426 | } | | 426 | } |
427 | if (tp1->t_foffs != tp2->t_foffs) { | | 427 | if (tp1->t_foffs != tp2->t_foffs) { |
428 | eq = false; | | 428 | eq = false; |
429 | break; | | 429 | break; |
430 | } | | 430 | } |
431 | } | | 431 | } |
432 | } | | 432 | } |
433 | if (!eq) | | 433 | if (!eq) |
434 | break; | | 434 | break; |
435 | } | | 435 | } |
436 | | | 436 | |
437 | /* | | 437 | /* |
438 | * Now handle the case in which the left operand refers really | | 438 | * Now handle the case in which the left operand refers really |
439 | * to a struct/union, but the right operand is not member of it. | | 439 | * to a struct/union, but the right operand is not member of it. |
440 | */ | | 440 | */ |
441 | if (str != NULL) { | | 441 | if (str != NULL) { |
442 | if (eq && tflag) { | | 442 | if (eq && tflag) { |
443 | /* illegal member use: %s */ | | 443 | /* illegal member use: %s */ |
444 | warning(102, msym->s_name); | | 444 | warning(102, msym->s_name); |
445 | } else { | | 445 | } else { |
446 | /* illegal member use: %s */ | | 446 | /* illegal member use: %s */ |
447 | error(102, msym->s_name); | | 447 | error(102, msym->s_name); |
448 | } | | 448 | } |
449 | return msym; | | 449 | return msym; |
450 | } | | 450 | } |
451 | | | 451 | |
452 | /* | | 452 | /* |
453 | * Now the left operand of ARROW does not point to a struct/union | | 453 | * Now the left operand of ARROW does not point to a struct/union |
454 | * or the left operand of POINT is no struct/union. | | 454 | * or the left operand of POINT is no struct/union. |
455 | */ | | 455 | */ |
456 | if (eq) { | | 456 | if (eq) { |
457 | if (op == POINT) { | | 457 | if (op == POINT) { |
458 | if (tflag) { | | 458 | if (tflag) { |
459 | /* left operand of '.' must be struct/... */ | | 459 | /* left operand of '.' must be struct/... */ |
460 | warning(103); | | 460 | warning(103); |
461 | } else { | | 461 | } else { |
462 | /* left operand of '.' must be struct/... */ | | 462 | /* left operand of '.' must be struct/... */ |
463 | error(103); | | 463 | error(103); |
464 | } | | 464 | } |
465 | } else { | | 465 | } else { |
466 | if (tflag && tn->tn_type->t_tspec == PTR) { | | 466 | if (tflag && tn->tn_type->t_tspec == PTR) { |
467 | /* left operand of '->' must be pointer ... */ | | 467 | /* left operand of '->' must be pointer ... */ |
468 | warning(104, type_name(tn->tn_type)); | | 468 | warning(104, type_name(tn->tn_type)); |
469 | } else { | | 469 | } else { |
470 | /* left operand of '->' must be pointer ... */ | | 470 | /* left operand of '->' must be pointer ... */ |
471 | error(104, type_name(tn->tn_type)); | | 471 | error(104, type_name(tn->tn_type)); |
472 | } | | 472 | } |
473 | } | | 473 | } |
474 | } else { | | 474 | } else { |
475 | if (tflag) { | | 475 | if (tflag) { |
476 | /* non-unique member requires struct/union %s */ | | 476 | /* non-unique member requires struct/union %s */ |
477 | error(105, op == POINT ? "object" : "pointer"); | | 477 | error(105, op == POINT ? "object" : "pointer"); |
478 | } else { | | 478 | } else { |
479 | /* unacceptable operand of '%s' */ | | 479 | /* unacceptable operand of '%s' */ |
480 | error(111, op_name(op)); | | 480 | error(111, op_name(op)); |
481 | } | | 481 | } |
482 | } | | 482 | } |
483 | | | 483 | |
484 | return msym; | | 484 | return msym; |
485 | } | | 485 | } |
486 | | | 486 | |
487 | /* | | 487 | /* |
488 | * Create a tree node. Called for most operands except function calls, | | 488 | * Create a tree node. Called for most operands except function calls, |
489 | * sizeof and casts. | | 489 | * sizeof and casts. |
490 | * | | 490 | * |
491 | * op operator | | 491 | * op operator |
492 | * ln left operand | | 492 | * ln left operand |
493 | * rn if not NULL, right operand | | 493 | * rn if not NULL, right operand |
494 | */ | | 494 | */ |
495 | tnode_t * | | 495 | tnode_t * |
496 | build(op_t op, tnode_t *ln, tnode_t *rn) | | 496 | build(op_t op, tnode_t *ln, tnode_t *rn) |
497 | { | | 497 | { |
498 | const mod_t *mp; | | 498 | const mod_t *mp; |
499 | tnode_t *ntn; | | 499 | tnode_t *ntn; |
500 | type_t *rettp; | | 500 | type_t *rettp; |
501 | | | 501 | |
502 | mp = &modtab[op]; | | 502 | mp = &modtab[op]; |
503 | | | 503 | |
504 | /* If there was an error in one of the operands, return. */ | | 504 | /* If there was an error in one of the operands, return. */ |
505 | if (ln == NULL || (mp->m_binary && rn == NULL)) | | 505 | if (ln == NULL || (mp->m_binary && rn == NULL)) |
506 | return NULL; | | 506 | return NULL; |
507 | | | 507 | |
508 | /* | | 508 | /* |
509 | * Apply class conversions to the left operand, but only if its | | 509 | * Apply class conversions to the left operand, but only if its |
510 | * value is needed or it is compared with null. | | 510 | * value is needed or it is compared with null. |
511 | */ | | 511 | */ |
512 | if (mp->m_left_value_context || mp->m_left_test_context) | | 512 | if (mp->m_left_value_context || mp->m_left_test_context) |
513 | ln = cconv(ln); | | 513 | ln = cconv(ln); |
514 | /* | | 514 | /* |
515 | * The right operand is almost always in a test or value context, | | 515 | * The right operand is almost always in a test or value context, |
516 | * except if it is a struct or union member. | | 516 | * except if it is a struct or union member. |
517 | */ | | 517 | */ |
518 | if (mp->m_binary && op != ARROW && op != POINT) | | 518 | if (mp->m_binary && op != ARROW && op != POINT) |
519 | rn = cconv(rn); | | 519 | rn = cconv(rn); |
520 | | | 520 | |
521 | /* | | 521 | /* |
522 | * Print some warnings for comparisons of unsigned values with | | 522 | * Print some warnings for comparisons of unsigned values with |
523 | * constants lower than or equal to null. This must be done | | 523 | * constants lower than or equal to null. This must be done |
524 | * before promote() because otherwise unsigned char and unsigned | | 524 | * before promote() because otherwise unsigned char and unsigned |
525 | * short would be promoted to int. Also types are tested to be | | 525 | * short would be promoted to int. Also types are tested to be |
526 | * CHAR, which would also become int. | | 526 | * CHAR, which would also become int. |
527 | */ | | 527 | */ |
528 | if (mp->m_comparison) | | 528 | if (mp->m_comparison) |
529 | check_integer_comparison(op, ln, rn); | | 529 | check_integer_comparison(op, ln, rn); |
530 | | | 530 | |
531 | /* | | 531 | /* |
532 | * Promote the left operand if it is in a test or value context | | 532 | * Promote the left operand if it is in a test or value context |
533 | */ | | 533 | */ |
534 | if (mp->m_left_value_context || mp->m_left_test_context) | | 534 | if (mp->m_left_value_context || mp->m_left_test_context) |
535 | ln = promote(op, false, ln); | | 535 | ln = promote(op, false, ln); |
536 | /* | | 536 | /* |
537 | * Promote the right operand, but only if it is no struct or | | 537 | * Promote the right operand, but only if it is no struct or |
538 | * union member, or if it is not to be assigned to the left operand | | 538 | * union member, or if it is not to be assigned to the left operand |
539 | */ | | 539 | */ |
540 | if (mp->m_binary && op != ARROW && op != POINT && | | 540 | if (mp->m_binary && op != ARROW && op != POINT && |
541 | op != ASSIGN && op != RETURN) { | | 541 | op != ASSIGN && op != RETURN) { |
542 | rn = promote(op, false, rn); | | 542 | rn = promote(op, false, rn); |
543 | } | | 543 | } |
544 | | | 544 | |
545 | /* | | 545 | /* |
546 | * If the result of the operation is different for signed or | | 546 | * If the result of the operation is different for signed or |
547 | * unsigned operands and one of the operands is signed only in | | 547 | * unsigned operands and one of the operands is signed only in |
548 | * ANSI C, print a warning. | | 548 | * ANSI C, print a warning. |
549 | */ | | 549 | */ |
550 | if (mp->m_warn_if_left_unsigned_in_c90 && | | 550 | if (mp->m_warn_if_left_unsigned_in_c90 && |
551 | ln->tn_op == CON && ln->tn_val->v_ansiu) { | | 551 | ln->tn_op == CON && ln->tn_val->v_ansiu) { |
552 | /* ANSI C treats constant as unsigned, op %s */ | | 552 | /* ANSI C treats constant as unsigned, op %s */ |
553 | warning(218, mp->m_name); | | 553 | warning(218, mp->m_name); |
554 | ln->tn_val->v_ansiu = false; | | 554 | ln->tn_val->v_ansiu = false; |
555 | } | | 555 | } |
556 | if (mp->m_warn_if_right_unsigned_in_c90 && | | 556 | if (mp->m_warn_if_right_unsigned_in_c90 && |
557 | rn->tn_op == CON && rn->tn_val->v_ansiu) { | | 557 | rn->tn_op == CON && rn->tn_val->v_ansiu) { |
558 | /* ANSI C treats constant as unsigned, op %s */ | | 558 | /* ANSI C treats constant as unsigned, op %s */ |
559 | warning(218, mp->m_name); | | 559 | warning(218, mp->m_name); |
560 | rn->tn_val->v_ansiu = false; | | 560 | rn->tn_val->v_ansiu = false; |
561 | } | | 561 | } |
562 | | | 562 | |
563 | /* Make sure both operands are of the same type */ | | 563 | /* Make sure both operands are of the same type */ |
564 | if (mp->m_balance_operands || (tflag && (op == SHL || op == SHR))) | | 564 | if (mp->m_balance_operands || (tflag && (op == SHL || op == SHR))) |
565 | balance(op, &ln, &rn); | | 565 | balance(op, &ln, &rn); |
566 | | | 566 | |
567 | /* | | 567 | /* |
568 | * Check types for compatibility with the operation and mutual | | 568 | * Check types for compatibility with the operation and mutual |
569 | * compatibility. Return if there are serious problems. | | 569 | * compatibility. Return if there are serious problems. |
570 | */ | | 570 | */ |
571 | if (!typeok(op, 0, ln, rn)) | | 571 | if (!typeok(op, 0, ln, rn)) |
572 | return NULL; | | 572 | return NULL; |
573 | | | 573 | |
574 | /* And now create the node. */ | | 574 | /* And now create the node. */ |
575 | switch (op) { | | 575 | switch (op) { |
576 | case POINT: | | 576 | case POINT: |
577 | case ARROW: | | 577 | case ARROW: |
578 | ntn = build_struct_access(op, ln, rn); | | 578 | ntn = build_struct_access(op, ln, rn); |
579 | break; | | 579 | break; |
580 | case INCAFT: | | 580 | case INCAFT: |
581 | case DECAFT: | | 581 | case DECAFT: |
582 | case INCBEF: | | 582 | case INCBEF: |
583 | case DECBEF: | | 583 | case DECBEF: |
584 | ntn = build_prepost_incdec(op, ln); | | 584 | ntn = build_prepost_incdec(op, ln); |
585 | break; | | 585 | break; |
586 | case ADDR: | | 586 | case ADDR: |
587 | ntn = build_address(ln, false); | | 587 | ntn = build_address(ln, false); |
588 | break; | | 588 | break; |
589 | case INDIR: | | 589 | case INDIR: |
590 | ntn = new_tnode(INDIR, ln->tn_type->t_subt, ln, NULL); | | 590 | ntn = new_tnode(INDIR, ln->tn_type->t_subt, ln, NULL); |
591 | break; | | 591 | break; |
592 | case PLUS: | | 592 | case PLUS: |
593 | case MINUS: | | 593 | case MINUS: |
594 | ntn = build_plus_minus(op, ln, rn); | | 594 | ntn = build_plus_minus(op, ln, rn); |
595 | break; | | 595 | break; |
596 | case SHL: | | 596 | case SHL: |
597 | case SHR: | | 597 | case SHR: |
598 | ntn = build_bit_shift(op, ln, rn); | | 598 | ntn = build_bit_shift(op, ln, rn); |
599 | break; | | 599 | break; |
600 | case COLON: | | 600 | case COLON: |
601 | ntn = build_colon(ln, rn); | | 601 | ntn = build_colon(ln, rn); |
602 | break; | | 602 | break; |
603 | case ASSIGN: | | 603 | case ASSIGN: |
604 | case MULASS: | | 604 | case MULASS: |
605 | case DIVASS: | | 605 | case DIVASS: |
606 | case MODASS: | | 606 | case MODASS: |
607 | case ADDASS: | | 607 | case ADDASS: |
608 | case SUBASS: | | 608 | case SUBASS: |
609 | case SHLASS: | | 609 | case SHLASS: |
610 | case SHRASS: | | 610 | case SHRASS: |
611 | case ANDASS: | | 611 | case ANDASS: |
612 | case XORASS: | | 612 | case XORASS: |
613 | case ORASS: | | 613 | case ORASS: |
614 | case RETURN: | | 614 | case RETURN: |
615 | ntn = build_assignment(op, ln, rn); | | 615 | ntn = build_assignment(op, ln, rn); |
616 | break; | | 616 | break; |
617 | case COMMA: | | 617 | case COMMA: |
618 | case QUEST: | | 618 | case QUEST: |
619 | ntn = new_tnode(op, rn->tn_type, ln, rn); | | 619 | ntn = new_tnode(op, rn->tn_type, ln, rn); |
620 | break; | | 620 | break; |
621 | case REAL: | | 621 | case REAL: |
622 | case IMAG: | | 622 | case IMAG: |
623 | ntn = build_real_imag(op, ln); | | 623 | ntn = build_real_imag(op, ln); |
624 | break; | | 624 | break; |
625 | default: | | 625 | default: |
626 | rettp = mp->m_returns_bool | | 626 | rettp = mp->m_returns_bool |
627 | ? gettyp(Tflag ? BOOL : INT) : ln->tn_type; | | 627 | ? gettyp(Tflag ? BOOL : INT) : ln->tn_type; |
628 | lint_assert(mp->m_binary || rn == NULL); | | 628 | lint_assert(mp->m_binary || rn == NULL); |
629 | ntn = new_tnode(op, rettp, ln, rn); | | 629 | ntn = new_tnode(op, rettp, ln, rn); |
630 | break; | | 630 | break; |
631 | } | | 631 | } |
632 | | | 632 | |
633 | /* Return if an error occurred. */ | | 633 | /* Return if an error occurred. */ |
634 | if (ntn == NULL) | | 634 | if (ntn == NULL) |
635 | return NULL; | | 635 | return NULL; |
636 | | | 636 | |
637 | /* Print a warning if precedence confusion is possible */ | | 637 | /* Print a warning if precedence confusion is possible */ |
638 | if (mp->m_possible_precedence_confusion) | | 638 | if (mp->m_possible_precedence_confusion) |
639 | check_precedence_confusion(ntn); | | 639 | check_precedence_confusion(ntn); |
640 | | | 640 | |
641 | /* | | 641 | /* |
642 | * Print a warning if one of the operands is in a context where | | 642 | * Print a warning if one of the operands is in a context where |
643 | * it is compared with null and if this operand is a constant. | | 643 | * it is compared with null and if this operand is a constant. |
644 | */ | | 644 | */ |
645 | if (mp->m_left_test_context) { | | 645 | if (mp->m_left_test_context) { |
646 | if (ln->tn_op == CON || | | 646 | if (ln->tn_op == CON || |
647 | ((mp->m_binary && op != QUEST) && rn->tn_op == CON)) { | | 647 | ((mp->m_binary && op != QUEST) && rn->tn_op == CON)) { |
648 | if (hflag && !constcond_flag && | | 648 | if (hflag && !constcond_flag && |
649 | !ln->tn_system_dependent) | | 649 | !ln->tn_system_dependent) |
650 | /* constant in conditional context */ | | 650 | /* constant in conditional context */ |
651 | warning(161); | | 651 | warning(161); |
652 | } | | 652 | } |
653 | } | | 653 | } |
654 | | | 654 | |
655 | /* Fold if the operator requires it */ | | 655 | /* Fold if the operator requires it */ |
656 | if (mp->m_fold_constant_operands) { | | 656 | if (mp->m_fold_constant_operands) { |
657 | if (ln->tn_op == CON && (!mp->m_binary || rn->tn_op == CON)) { | | 657 | if (ln->tn_op == CON && (!mp->m_binary || rn->tn_op == CON)) { |
658 | if (mp->m_left_test_context) { | | 658 | if (mp->m_left_test_context) { |
659 | ntn = fold_test(ntn); | | 659 | ntn = fold_test(ntn); |
660 | } else if (is_floating(ntn->tn_type->t_tspec)) { | | 660 | } else if (is_floating(ntn->tn_type->t_tspec)) { |
661 | ntn = fold_float(ntn); | | 661 | ntn = fold_float(ntn); |
662 | } else { | | 662 | } else { |
663 | ntn = fold(ntn); | | 663 | ntn = fold(ntn); |
664 | } | | 664 | } |
665 | } else if (op == QUEST && ln->tn_op == CON) { | | 665 | } else if (op == QUEST && ln->tn_op == CON) { |
666 | ntn = ln->tn_val->v_quad != 0 | | 666 | ntn = ln->tn_val->v_quad != 0 |
667 | ? rn->tn_left : rn->tn_right; | | 667 | ? rn->tn_left : rn->tn_right; |
668 | } | | 668 | } |
669 | } | | 669 | } |
670 | | | 670 | |
671 | return ntn; | | 671 | return ntn; |
672 | } | | 672 | } |
673 | | | 673 | |
674 | /* | | 674 | /* |
675 | * Perform class conversions. | | 675 | * Perform class conversions. |
676 | * | | 676 | * |
677 | * Arrays of type T are converted into pointers to type T. | | 677 | * Arrays of type T are converted into pointers to type T. |
678 | * Functions are converted to pointers to functions. | | 678 | * Functions are converted to pointers to functions. |
679 | * Lvalues are converted to rvalues. | | 679 | * Lvalues are converted to rvalues. |
680 | * | | 680 | * |
681 | * C99 6.3 "Conversions" | | 681 | * C99 6.3 "Conversions" |
682 | * C99 6.3.2 "Other operands" | | 682 | * C99 6.3.2 "Other operands" |
683 | * C99 6.3.2.1 "Lvalues, arrays, and function designators" | | 683 | * C99 6.3.2.1 "Lvalues, arrays, and function designators" |
684 | */ | | 684 | */ |
685 | tnode_t * | | 685 | tnode_t * |
686 | cconv(tnode_t *tn) | | 686 | cconv(tnode_t *tn) |
687 | { | | 687 | { |
688 | type_t *tp; | | 688 | type_t *tp; |
689 | | | 689 | |
690 | /* | | 690 | /* |
691 | * Array-lvalue (array of type T) is converted into rvalue | | 691 | * Array-lvalue (array of type T) is converted into rvalue |
692 | * (pointer to type T) | | 692 | * (pointer to type T) |
693 | */ | | 693 | */ |
694 | if (tn->tn_type->t_tspec == ARRAY) { | | 694 | if (tn->tn_type->t_tspec == ARRAY) { |
695 | if (!tn->tn_lvalue) { | | 695 | if (!tn->tn_lvalue) { |
696 | /* XXX print correct operator */ | | 696 | /* XXX print correct operator */ |
697 | /* %soperand of '%s' must be lvalue */ | | 697 | /* %soperand of '%s' must be lvalue */ |
698 | gnuism(114, "", modtab[ADDR].m_name); | | 698 | gnuism(114, "", op_name(ADDR)); |
699 | } | | 699 | } |
700 | tn = new_tnode(ADDR, | | 700 | tn = new_tnode(ADDR, |
701 | expr_derive_type(tn->tn_type->t_subt, PTR), tn, NULL); | | 701 | expr_derive_type(tn->tn_type->t_subt, PTR), tn, NULL); |
702 | } | | 702 | } |
703 | | | 703 | |
704 | /* | | 704 | /* |
705 | * Expression of type function (function with return value of type T) | | 705 | * Expression of type function (function with return value of type T) |
706 | * in rvalue-expression (pointer to function with return value | | 706 | * in rvalue-expression (pointer to function with return value |
707 | * of type T) | | 707 | * of type T) |
708 | */ | | 708 | */ |
709 | if (tn->tn_type->t_tspec == FUNC) | | 709 | if (tn->tn_type->t_tspec == FUNC) |
710 | tn = build_address(tn, true); | | 710 | tn = build_address(tn, true); |
711 | | | 711 | |
712 | /* lvalue to rvalue */ | | 712 | /* lvalue to rvalue */ |
713 | if (tn->tn_lvalue) { | | 713 | if (tn->tn_lvalue) { |
714 | tp = expr_dup_type(tn->tn_type); | | 714 | tp = expr_dup_type(tn->tn_type); |
715 | tp->t_const = tp->t_volatile = false; | | 715 | tp->t_const = tp->t_volatile = false; |
716 | tn = new_tnode(LOAD, tp, tn, NULL); | | 716 | tn = new_tnode(LOAD, tp, tn, NULL); |
717 | } | | 717 | } |
718 | | | 718 | |
719 | return tn; | | 719 | return tn; |
720 | } | | 720 | } |
721 | | | 721 | |
722 | static const tnode_t * | | 722 | static const tnode_t * |
723 | before_conversion(const tnode_t *tn) | | 723 | before_conversion(const tnode_t *tn) |
724 | { | | 724 | { |
725 | while (tn->tn_op == CVT && !tn->tn_cast) | | 725 | while (tn->tn_op == CVT && !tn->tn_cast) |
726 | tn = tn->tn_left; | | 726 | tn = tn->tn_left; |
727 | return tn; | | 727 | return tn; |
728 | } | | 728 | } |
729 | | | 729 | |
730 | static bool | | 730 | static bool |
731 | is_null_pointer(const tnode_t *tn) | | 731 | is_null_pointer(const tnode_t *tn) |
732 | { | | 732 | { |
733 | tspec_t t = tn->tn_type->t_tspec; | | 733 | tspec_t t = tn->tn_type->t_tspec; |
734 | | | 734 | |
735 | return ((t == PTR && tn->tn_type->t_subt->t_tspec == VOID) || | | 735 | return ((t == PTR && tn->tn_type->t_subt->t_tspec == VOID) || |
736 | is_integer(t)) | | 736 | is_integer(t)) |
737 | && (tn->tn_op == CON && tn->tn_val->v_quad == 0); | | 737 | && (tn->tn_op == CON && tn->tn_val->v_quad == 0); |
738 | } | | 738 | } |
739 | | | 739 | |
740 | /* | | 740 | /* |
741 | * See if the node is valid as operand of an operator that compares its | | 741 | * See if the node is valid as operand of an operator that compares its |
742 | * argument with 0. | | 742 | * argument with 0. |
743 | */ | | 743 | */ |
744 | bool | | 744 | bool |
745 | is_typeok_bool_operand(const tnode_t *tn) | | 745 | is_typeok_bool_operand(const tnode_t *tn) |
746 | { | | 746 | { |
747 | tspec_t t; | | 747 | tspec_t t; |
748 | | | 748 | |
749 | lint_assert(Tflag); | | 749 | lint_assert(Tflag); |
750 | | | 750 | |
751 | tn = before_conversion(tn); | | 751 | tn = before_conversion(tn); |
752 | t = tn->tn_type->t_tspec; | | 752 | t = tn->tn_type->t_tspec; |
753 | | | 753 | |
754 | if (t == BOOL) | | 754 | if (t == BOOL) |
755 | return true; | | 755 | return true; |
756 | | | 756 | |
757 | if (tn->tn_from_system_header && is_scalar(t)) | | 757 | if (tn->tn_from_system_header && is_scalar(t)) |
758 | return true; | | 758 | return true; |
759 | | | 759 | |
760 | /* For enums that are used as bit sets, allow "flags & FLAG". */ | | 760 | /* For enums that are used as bit sets, allow "flags & FLAG". */ |
761 | if (tn->tn_op == BITAND && | | 761 | if (tn->tn_op == BITAND && |
762 | tn->tn_left->tn_op == CVT && | | 762 | tn->tn_left->tn_op == CVT && |
763 | tn->tn_left->tn_type->t_tspec == INT && !tn->tn_left->tn_cast && | | 763 | tn->tn_left->tn_type->t_tspec == INT && !tn->tn_left->tn_cast && |
764 | tn->tn_left->tn_left->tn_type->t_tspec == ENUM && | | 764 | tn->tn_left->tn_left->tn_type->t_tspec == ENUM && |
765 | /* | | 765 | /* |
766 | * XXX: Somehow the type information got lost here. The type | | 766 | * XXX: Somehow the type information got lost here. The type |
767 | * of the enum constant on the right-hand side should still be | | 767 | * of the enum constant on the right-hand side should still be |
768 | * ENUM, but is INT. | | 768 | * ENUM, but is INT. |
769 | */ | | 769 | */ |
770 | tn->tn_right->tn_type->t_tspec == INT) | | 770 | tn->tn_right->tn_type->t_tspec == INT) |
771 | return true; | | 771 | return true; |
772 | | | 772 | |
773 | return false; | | 773 | return false; |
774 | } | | 774 | } |
775 | | | 775 | |
776 | static bool | | 776 | static bool |
777 | typeok_incdec(const mod_t *mp, const tnode_t *tn, const type_t *tp) | | 777 | typeok_incdec(op_t op, const tnode_t *tn, const type_t *tp) |
778 | { | | 778 | { |
779 | /* operand has scalar type (checked in typeok) */ | | 779 | /* operand has scalar type (checked in typeok) */ |
780 | if (!tn->tn_lvalue) { | | 780 | if (!tn->tn_lvalue) { |
781 | if (tn->tn_op == CVT && tn->tn_cast && | | 781 | if (tn->tn_op == CVT && tn->tn_cast && |
782 | tn->tn_left->tn_op == LOAD) { | | 782 | tn->tn_left->tn_op == LOAD) { |
783 | if (tn->tn_type->t_tspec == PTR) | | 783 | if (tn->tn_type->t_tspec == PTR) |
784 | return true; | | 784 | return true; |
785 | /* a cast does not yield an lvalue */ | | 785 | /* a cast does not yield an lvalue */ |
786 | error(163); | | 786 | error(163); |
787 | } | | 787 | } |
788 | /* %soperand of '%s' must be lvalue */ | | 788 | /* %soperand of '%s' must be lvalue */ |
789 | error(114, "", mp->m_name); | | 789 | error(114, "", op_name(op)); |
790 | return false; | | 790 | return false; |
791 | } else if (tp->t_const) { | | 791 | } else if (tp->t_const) { |
792 | if (!tflag) | | 792 | if (!tflag) |
793 | /* %soperand of '%s' must be modifiable lvalue */ | | 793 | /* %soperand of '%s' must be modifiable lvalue */ |
794 | warning(115, "", mp->m_name); | | 794 | warning(115, "", op_name(op)); |
795 | } | | 795 | } |
796 | return true; | | 796 | return true; |
797 | } | | 797 | } |
798 | | | 798 | |
799 | static bool | | 799 | static bool |
800 | typeok_address(const mod_t *mp, | | 800 | typeok_address(const mod_t *mp, |
801 | const tnode_t *tn, const type_t *tp, tspec_t t) | | 801 | const tnode_t *tn, const type_t *tp, tspec_t t) |
802 | { | | 802 | { |
803 | if (t == ARRAY || t == FUNC) { | | 803 | if (t == ARRAY || t == FUNC) { |
804 | /* ok, a warning comes later (in build_address()) */ | | 804 | /* ok, a warning comes later (in build_address()) */ |
805 | } else if (!tn->tn_lvalue) { | | 805 | } else if (!tn->tn_lvalue) { |
806 | if (tn->tn_op == CVT && tn->tn_cast && | | 806 | if (tn->tn_op == CVT && tn->tn_cast && |
807 | tn->tn_left->tn_op == LOAD) { | | 807 | tn->tn_left->tn_op == LOAD) { |
808 | if (tn->tn_type->t_tspec == PTR) | | 808 | if (tn->tn_type->t_tspec == PTR) |
809 | return true; | | 809 | return true; |
810 | /* a cast does not yield an lvalue */ | | 810 | /* a cast does not yield an lvalue */ |
811 | error(163); | | 811 | error(163); |
812 | } | | 812 | } |
813 | /* %soperand of '%s' must be lvalue */ | | 813 | /* %soperand of '%s' must be lvalue */ |
814 | error(114, "", mp->m_name); | | 814 | error(114, "", mp->m_name); |
815 | return false; | | 815 | return false; |
816 | } else if (is_scalar(t)) { | | 816 | } else if (is_scalar(t)) { |
817 | if (tp->t_bitfield) { | | 817 | if (tp->t_bitfield) { |
818 | /* cannot take address of bit-field */ | | 818 | /* cannot take address of bit-field */ |
819 | error(112); | | 819 | error(112); |
820 | return false; | | 820 | return false; |
821 | } | | 821 | } |
822 | } else if (t != STRUCT && t != UNION) { | | 822 | } else if (t != STRUCT && t != UNION) { |
823 | /* unacceptable operand of '%s' */ | | 823 | /* unacceptable operand of '%s' */ |
824 | error(111, mp->m_name); | | 824 | error(111, mp->m_name); |
825 | return false; | | 825 | return false; |
826 | } | | 826 | } |
827 | if (tn->tn_op == NAME && tn->tn_sym->s_reg) { | | 827 | if (tn->tn_op == NAME && tn->tn_sym->s_reg) { |
828 | /* cannot take address of register %s */ | | 828 | /* cannot take address of register %s */ |
829 | error(113, tn->tn_sym->s_name); | | 829 | error(113, tn->tn_sym->s_name); |
830 | return false; | | 830 | return false; |
831 | } | | 831 | } |
832 | return true; | | 832 | return true; |
833 | } | | 833 | } |
834 | | | 834 | |
835 | static bool | | 835 | static bool |
836 | typeok_star(tspec_t t) | | 836 | typeok_star(tspec_t t) |
837 | { | | 837 | { |
838 | /* until now there were no type checks for this operator */ | | 838 | /* until now there were no type checks for this operator */ |
839 | if (t != PTR) { | | 839 | if (t != PTR) { |
840 | /* cannot dereference non-pointer type */ | | 840 | /* cannot dereference non-pointer type */ |
841 | error(96); | | 841 | error(96); |
842 | return false; | | 842 | return false; |
843 | } | | 843 | } |
844 | return true; | | 844 | return true; |
845 | } | | 845 | } |
846 | | | 846 | |
847 | static bool | | 847 | static bool |
848 | typeok_plus(op_t op, | | 848 | typeok_plus(op_t op, |
849 | const type_t *ltp, tspec_t lt, | | 849 | const type_t *ltp, tspec_t lt, |
850 | const type_t *rtp, tspec_t rt) | | 850 | const type_t *rtp, tspec_t rt) |
851 | { | | 851 | { |
852 | /* operands have scalar types (checked above) */ | | 852 | /* operands have scalar types (checked above) */ |
853 | if ((lt == PTR && !is_integer(rt)) || (rt == PTR && !is_integer(lt))) { | | 853 | if ((lt == PTR && !is_integer(rt)) || (rt == PTR && !is_integer(lt))) { |
854 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 854 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
855 | return false; | | 855 | return false; |
856 | } | | 856 | } |
857 | return true; | | 857 | return true; |
858 | } | | 858 | } |
859 | | | 859 | |
860 | static bool | | 860 | static bool |
861 | typeok_minus(op_t op, | | 861 | typeok_minus(op_t op, |
862 | const type_t *ltp, tspec_t lt, | | 862 | const type_t *ltp, tspec_t lt, |
863 | const type_t *rtp, tspec_t rt) | | 863 | const type_t *rtp, tspec_t rt) |
864 | { | | 864 | { |
865 | /* operands have scalar types (checked above) */ | | 865 | /* operands have scalar types (checked above) */ |
866 | if (lt == PTR && (!is_integer(rt) && rt != PTR)) { | | 866 | if (lt == PTR && (!is_integer(rt) && rt != PTR)) { |
867 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 867 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
868 | return false; | | 868 | return false; |
869 | } else if (rt == PTR && lt != PTR) { | | 869 | } else if (rt == PTR && lt != PTR) { |
870 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 870 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
871 | return false; | | 871 | return false; |
872 | } | | 872 | } |
873 | if (lt == PTR && rt == PTR) { | | 873 | if (lt == PTR && rt == PTR) { |
874 | if (!eqtype(ltp->t_subt, rtp->t_subt, true, false, NULL)) { | | 874 | if (!eqtype(ltp->t_subt, rtp->t_subt, true, false, NULL)) { |
875 | /* illegal pointer subtraction */ | | 875 | /* illegal pointer subtraction */ |
876 | error(116); | | 876 | error(116); |
877 | } | | 877 | } |
878 | } | | 878 | } |
879 | return true; | | 879 | return true; |
880 | } | | 880 | } |
881 | | | 881 | |
882 | static void | | 882 | static void |
883 | typeok_shr(const mod_t *mp, | | 883 | typeok_shr(const mod_t *mp, |
884 | const tnode_t *ln, tspec_t lt, | | 884 | const tnode_t *ln, tspec_t lt, |
885 | const tnode_t *rn, tspec_t rt) | | 885 | const tnode_t *rn, tspec_t rt) |
886 | { | | 886 | { |
887 | tspec_t olt, ort; | | 887 | tspec_t olt, ort; |
888 | | | 888 | |
889 | olt = before_conversion(ln)->tn_type->t_tspec; | | 889 | olt = before_conversion(ln)->tn_type->t_tspec; |
890 | ort = before_conversion(rn)->tn_type->t_tspec; | | 890 | ort = before_conversion(rn)->tn_type->t_tspec; |
891 | | | 891 | |
892 | /* operands have integer types (checked above) */ | | 892 | /* operands have integer types (checked above) */ |
893 | if (pflag && !is_uinteger(lt)) { | | 893 | if (pflag && !is_uinteger(lt)) { |
894 | /* | | 894 | /* |
895 | * The left operand is signed. This means that | | 895 | * The left operand is signed. This means that |
896 | * the operation is (possibly) nonportable. | | 896 | * the operation is (possibly) nonportable. |
897 | */ | | 897 | */ |
898 | if (ln->tn_op != CON) { | | 898 | if (ln->tn_op != CON) { |
899 | /* bitwise '%s' on signed value possibly nonportable */ | | 899 | /* bitwise '%s' on signed value possibly nonportable */ |
900 | warning(117, mp->m_name); | | 900 | warning(117, mp->m_name); |
901 | } else if (ln->tn_val->v_quad < 0) { | | 901 | } else if (ln->tn_val->v_quad < 0) { |
902 | /* bitwise '%s' on signed value nonportable */ | | 902 | /* bitwise '%s' on signed value nonportable */ |
903 | warning(120, mp->m_name); | | 903 | warning(120, mp->m_name); |
904 | } | | 904 | } |
905 | } else if (!tflag && !sflag && !is_uinteger(olt) && is_uinteger(ort)) { | | 905 | } else if (!tflag && !sflag && !is_uinteger(olt) && is_uinteger(ort)) { |
906 | /* | | 906 | /* |
907 | * The left operand would become unsigned in | | 907 | * The left operand would become unsigned in |
908 | * traditional C. | | 908 | * traditional C. |
909 | */ | | 909 | */ |
910 | if (hflag && | | 910 | if (hflag && |
911 | (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { | | 911 | (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { |
912 | /* semantics of '%s' change in ANSI C; use ... */ | | 912 | /* semantics of '%s' change in ANSI C; use ... */ |
913 | warning(118, mp->m_name); | | 913 | warning(118, mp->m_name); |
914 | } | | 914 | } |
915 | } else if (!tflag && !sflag && !is_uinteger(olt) && !is_uinteger(ort) && | | 915 | } else if (!tflag && !sflag && !is_uinteger(olt) && !is_uinteger(ort) && |
916 | portable_size_in_bits(lt) < portable_size_in_bits(rt)) { | | 916 | portable_size_in_bits(lt) < portable_size_in_bits(rt)) { |
917 | /* | | 917 | /* |
918 | * In traditional C the left operand would be extended, | | 918 | * In traditional C the left operand would be extended, |
919 | * possibly with 1, and then shifted. | | 919 | * possibly with 1, and then shifted. |
920 | */ | | 920 | */ |
921 | if (hflag && | | 921 | if (hflag && |
922 | (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { | | 922 | (ln->tn_op != CON || ln->tn_val->v_quad < 0)) { |
923 | /* semantics of '%s' change in ANSI C; use ... */ | | 923 | /* semantics of '%s' change in ANSI C; use ... */ |
924 | warning(118, mp->m_name); | | 924 | warning(118, mp->m_name); |
925 | } | | 925 | } |
926 | } | | 926 | } |
927 | } | | 927 | } |
928 | | | 928 | |
929 | static void | | 929 | static void |
930 | typeok_shl(const mod_t *mp, tspec_t lt, tspec_t rt) | | 930 | typeok_shl(const mod_t *mp, tspec_t lt, tspec_t rt) |
931 | { | | 931 | { |
932 | /* | | 932 | /* |
933 | * C90 does not perform balancing for shift operations, | | 933 | * C90 does not perform balancing for shift operations, |
934 | * but traditional C does. If the width of the right operand | | 934 | * but traditional C does. If the width of the right operand |
935 | * is greater than the width of the left operand, then in | | 935 | * is greater than the width of the left operand, then in |
936 | * traditional C the left operand would be extended to the | | 936 | * traditional C the left operand would be extended to the |
937 | * width of the right operand. For SHL this may result in | | 937 | * width of the right operand. For SHL this may result in |
938 | * different results. | | 938 | * different results. |
939 | */ | | 939 | */ |
940 | if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { | | 940 | if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { |
941 | /* | | 941 | /* |
942 | * XXX If both operands are constant, make sure | | 942 | * XXX If both operands are constant, make sure |
943 | * that there is really a difference between | | 943 | * that there is really a difference between |
944 | * ANSI C and traditional C. | | 944 | * ANSI C and traditional C. |
945 | */ | | 945 | */ |
946 | if (hflag) | | 946 | if (hflag) |
947 | /* semantics of '%s' change in ANSI C; use ... */ | | 947 | /* semantics of '%s' change in ANSI C; use ... */ |
948 | warning(118, mp->m_name); | | 948 | warning(118, mp->m_name); |
949 | } | | 949 | } |
950 | } | | 950 | } |
951 | | | 951 | |
952 | static void | | 952 | static void |
953 | typeok_shift(tspec_t lt, const tnode_t *rn, tspec_t rt) | | 953 | typeok_shift(tspec_t lt, const tnode_t *rn, tspec_t rt) |
954 | { | | 954 | { |
955 | if (rn->tn_op == CON) { | | 955 | if (rn->tn_op == CON) { |
956 | if (!is_uinteger(rt) && rn->tn_val->v_quad < 0) { | | 956 | if (!is_uinteger(rt) && rn->tn_val->v_quad < 0) { |
957 | /* negative shift */ | | 957 | /* negative shift */ |
958 | warning(121); | | 958 | warning(121); |
959 | } else if ((uint64_t)rn->tn_val->v_quad == | | 959 | } else if ((uint64_t)rn->tn_val->v_quad == |
960 | (uint64_t)size_in_bits(lt)) { | | 960 | (uint64_t)size_in_bits(lt)) { |
961 | /* shift equal to size of object */ | | 961 | /* shift equal to size of object */ |
962 | warning(267); | | 962 | warning(267); |
963 | } else if ((uint64_t)rn->tn_val->v_quad > | | 963 | } else if ((uint64_t)rn->tn_val->v_quad > |
964 | (uint64_t)size_in_bits(lt)) { | | 964 | (uint64_t)size_in_bits(lt)) { |
965 | /* shift greater than size of object */ | | 965 | /* shift greater than size of object */ |
966 | warning(122); | | 966 | warning(122); |
967 | } | | 967 | } |
968 | } | | 968 | } |
969 | } | | 969 | } |
970 | | | 970 | |
971 | static bool | | 971 | static bool |
972 | is_typeok_eq(const tnode_t *ln, tspec_t lt, const tnode_t *rn, tspec_t rt) | | 972 | is_typeok_eq(const tnode_t *ln, tspec_t lt, const tnode_t *rn, tspec_t rt) |
973 | { | | 973 | { |
974 | if (lt == PTR && is_null_pointer(rn)) | | 974 | if (lt == PTR && is_null_pointer(rn)) |
975 | return true; | | 975 | return true; |
976 | if (rt == PTR && is_null_pointer(ln)) | | 976 | if (rt == PTR && is_null_pointer(ln)) |
977 | return true; | | 977 | return true; |
978 | return false; | | 978 | return false; |
979 | } | | 979 | } |
980 | | | 980 | |
981 | static bool | | 981 | static bool |
982 | typeok_ordered_comparison(op_t op, | | 982 | typeok_ordered_comparison(op_t op, |
983 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | | 983 | const tnode_t *ln, const type_t *ltp, tspec_t lt, |
984 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | | 984 | const tnode_t *rn, const type_t *rtp, tspec_t rt) |
985 | { | | 985 | { |
986 | if (lt == PTR && rt == PTR) { | | 986 | if (lt == PTR && rt == PTR) { |
987 | check_pointer_comparison(op, ln, rn); | | 987 | check_pointer_comparison(op, ln, rn); |
988 | return true; | | 988 | return true; |
989 | } | | 989 | } |
990 | | | 990 | |
991 | if (lt != PTR && rt != PTR) | | 991 | if (lt != PTR && rt != PTR) |
992 | return true; | | 992 | return true; |
993 | | | 993 | |
994 | if (!is_integer(lt) && !is_integer(rt)) { | | 994 | if (!is_integer(lt) && !is_integer(rt)) { |
995 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 995 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
996 | return false; | | 996 | return false; |
997 | } | | 997 | } |
998 | | | 998 | |
999 | const char *lx = lt == PTR ? "pointer" : "integer"; | | 999 | const char *lx = lt == PTR ? "pointer" : "integer"; |
1000 | const char *rx = rt == PTR ? "pointer" : "integer"; | | 1000 | const char *rx = rt == PTR ? "pointer" : "integer"; |
1001 | /* illegal combination of %s (%s) and %s (%s), op %s */ | | 1001 | /* illegal combination of %s (%s) and %s (%s), op %s */ |
1002 | warning(123, lx, type_name(ltp), rx, type_name(rtp), op_name(op)); | | 1002 | warning(123, lx, type_name(ltp), rx, type_name(rtp), op_name(op)); |
1003 | return true; | | 1003 | return true; |
1004 | } | | 1004 | } |
1005 | | | 1005 | |
1006 | static bool | | 1006 | static bool |
1007 | typeok_quest(tspec_t lt, const tnode_t **rn) | | 1007 | typeok_quest(tspec_t lt, const tnode_t **rn) |
1008 | { | | 1008 | { |
1009 | if (!is_scalar(lt)) { | | 1009 | if (!is_scalar(lt)) { |
1010 | /* first operand must have scalar type, op ? : */ | | 1010 | /* first operand must have scalar type, op ? : */ |
1011 | error(170); | | 1011 | error(170); |
1012 | return false; | | 1012 | return false; |
1013 | } | | 1013 | } |
1014 | while ((*rn)->tn_op == CVT) | | 1014 | while ((*rn)->tn_op == CVT) |
1015 | *rn = (*rn)->tn_left; | | 1015 | *rn = (*rn)->tn_left; |
1016 | lint_assert((*rn)->tn_op == COLON); | | 1016 | lint_assert((*rn)->tn_op == COLON); |
1017 | return true; | | 1017 | return true; |
1018 | } | | 1018 | } |
1019 | | | 1019 | |
1020 | static void | | 1020 | static void |
1021 | typeok_colon_pointer(const mod_t *mp, const type_t *ltp, const type_t *rtp) | | 1021 | typeok_colon_pointer(const mod_t *mp, const type_t *ltp, const type_t *rtp) |
1022 | { | | 1022 | { |
1023 | type_t *lstp = ltp->t_subt; | | 1023 | type_t *lstp = ltp->t_subt; |
1024 | type_t *rstp = rtp->t_subt; | | 1024 | type_t *rstp = rtp->t_subt; |
1025 | tspec_t lst = lstp->t_tspec; | | 1025 | tspec_t lst = lstp->t_tspec; |
1026 | tspec_t rst = rstp->t_tspec; | | 1026 | tspec_t rst = rstp->t_tspec; |
1027 | | | 1027 | |
1028 | if ((lst == VOID && rst == FUNC) || (lst == FUNC && rst == VOID)) { | | 1028 | if ((lst == VOID && rst == FUNC) || (lst == FUNC && rst == VOID)) { |
1029 | /* (void *)0 handled above */ | | 1029 | /* (void *)0 handled above */ |
1030 | if (sflag) | | 1030 | if (sflag) |
1031 | /* ANSI C forbids conv. of %s to %s, op %s */ | | 1031 | /* ANSI C forbids conv. of %s to %s, op %s */ |
1032 | warning(305, "function pointer", "'void *'", | | 1032 | warning(305, "function pointer", "'void *'", |
1033 | mp->m_name); | | 1033 | mp->m_name); |
1034 | return; | | 1034 | return; |
1035 | } | | 1035 | } |
1036 | | | 1036 | |
1037 | if (eqptrtype(lstp, rstp, true)) | | 1037 | if (eqptrtype(lstp, rstp, true)) |
1038 | return; | | 1038 | return; |
1039 | if (!eqtype(lstp, rstp, true, false, NULL)) | | 1039 | if (!eqtype(lstp, rstp, true, false, NULL)) |
1040 | warn_incompatible_pointers(mp, ltp, rtp); | | 1040 | warn_incompatible_pointers(mp, ltp, rtp); |
1041 | } | | 1041 | } |
1042 | | | 1042 | |
1043 | static bool | | 1043 | static bool |
1044 | typeok_colon(const mod_t *mp, | | 1044 | typeok_colon(const mod_t *mp, |
1045 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | | 1045 | const tnode_t *ln, const type_t *ltp, tspec_t lt, |
1046 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | | 1046 | const tnode_t *rn, const type_t *rtp, tspec_t rt) |
1047 | { | | 1047 | { |
1048 | | | 1048 | |
1049 | if (is_arithmetic(lt) && is_arithmetic(rt)) | | 1049 | if (is_arithmetic(lt) && is_arithmetic(rt)) |
1050 | return true; | | 1050 | return true; |
1051 | if (lt == BOOL && rt == BOOL) | | 1051 | if (lt == BOOL && rt == BOOL) |
1052 | return true; | | 1052 | return true; |
1053 | | | 1053 | |
1054 | if (lt == STRUCT && rt == STRUCT && ltp->t_str == rtp->t_str) | | 1054 | if (lt == STRUCT && rt == STRUCT && ltp->t_str == rtp->t_str) |
1055 | return true; | | 1055 | return true; |
1056 | if (lt == UNION && rt == UNION && ltp->t_str == rtp->t_str) | | 1056 | if (lt == UNION && rt == UNION && ltp->t_str == rtp->t_str) |
1057 | return true; | | 1057 | return true; |
1058 | | | 1058 | |
1059 | if (lt == PTR && is_null_pointer(rn)) | | 1059 | if (lt == PTR && is_null_pointer(rn)) |
1060 | return true; | | 1060 | return true; |
1061 | if (rt == PTR && is_null_pointer(ln)) | | 1061 | if (rt == PTR && is_null_pointer(ln)) |
1062 | return true; | | 1062 | return true; |
1063 | | | 1063 | |
1064 | if ((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)) { | | 1064 | if ((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)) { |
1065 | const char *lx = lt == PTR ? "pointer" : "integer"; | | 1065 | const char *lx = lt == PTR ? "pointer" : "integer"; |
1066 | const char *rx = rt == PTR ? "pointer" : "integer"; | | 1066 | const char *rx = rt == PTR ? "pointer" : "integer"; |
1067 | /* illegal combination of %s (%s) and %s (%s), op %s */ | | 1067 | /* illegal combination of %s (%s) and %s (%s), op %s */ |
1068 | warning(123, lx, type_name(ltp), | | 1068 | warning(123, lx, type_name(ltp), |
1069 | rx, type_name(rtp), mp->m_name); | | 1069 | rx, type_name(rtp), mp->m_name); |
1070 | return true; | | 1070 | return true; |
1071 | } | | 1071 | } |
1072 | | | 1072 | |
1073 | if (lt == VOID || rt == VOID) { | | 1073 | if (lt == VOID || rt == VOID) { |
1074 | if (lt != VOID || rt != VOID) | | 1074 | if (lt != VOID || rt != VOID) |
1075 | /* incompatible types '%s' and '%s' in conditional */ | | 1075 | /* incompatible types '%s' and '%s' in conditional */ |
1076 | warning(126, type_name(ltp), type_name(rtp)); | | 1076 | warning(126, type_name(ltp), type_name(rtp)); |
1077 | return true; | | 1077 | return true; |
1078 | } | | 1078 | } |
1079 | | | 1079 | |
1080 | if (lt == PTR && rt == PTR) { | | 1080 | if (lt == PTR && rt == PTR) { |
1081 | typeok_colon_pointer(mp, ltp, rtp); | | 1081 | typeok_colon_pointer(mp, ltp, rtp); |
1082 | return true; | | 1082 | return true; |
1083 | } | | 1083 | } |
1084 | | | 1084 | |
1085 | /* incompatible types '%s' and '%s' in conditional */ | | 1085 | /* incompatible types '%s' and '%s' in conditional */ |
1086 | error(126, type_name(ltp), type_name(rtp)); | | 1086 | error(126, type_name(ltp), type_name(rtp)); |
1087 | return false; | | 1087 | return false; |
1088 | } | | 1088 | } |
1089 | | | 1089 | |
1090 | static bool | | 1090 | static bool |
1091 | typeok_assign(const mod_t *mp, const tnode_t *ln, const type_t *ltp, tspec_t lt) | | 1091 | typeok_assign(const mod_t *mp, const tnode_t *ln, const type_t *ltp, tspec_t lt) |
1092 | { | | 1092 | { |
1093 | if (!ln->tn_lvalue) { | | 1093 | if (!ln->tn_lvalue) { |
1094 | if (ln->tn_op == CVT && ln->tn_cast && | | 1094 | if (ln->tn_op == CVT && ln->tn_cast && |
1095 | ln->tn_left->tn_op == LOAD) { | | 1095 | ln->tn_left->tn_op == LOAD) { |
1096 | if (ln->tn_type->t_tspec == PTR) | | 1096 | if (ln->tn_type->t_tspec == PTR) |
1097 | return true; | | 1097 | return true; |
1098 | /* a cast does not yield an lvalue */ | | 1098 | /* a cast does not yield an lvalue */ |
1099 | error(163); | | 1099 | error(163); |
1100 | } | | 1100 | } |
1101 | /* %soperand of '%s' must be lvalue */ | | 1101 | /* %soperand of '%s' must be lvalue */ |
1102 | error(114, "left ", mp->m_name); | | 1102 | error(114, "left ", mp->m_name); |
1103 | return false; | | 1103 | return false; |
1104 | } else if (ltp->t_const || ((lt == STRUCT || lt == UNION) && | | 1104 | } else if (ltp->t_const || ((lt == STRUCT || lt == UNION) && |
1105 | has_constant_member(ltp))) { | | 1105 | has_constant_member(ltp))) { |
1106 | if (!tflag) | | 1106 | if (!tflag) |
1107 | /* %soperand of '%s' must be modifiable lvalue */ | | 1107 | /* %soperand of '%s' must be modifiable lvalue */ |
1108 | warning(115, "left ", mp->m_name); | | 1108 | warning(115, "left ", mp->m_name); |
1109 | } | | 1109 | } |
1110 | return true; | | 1110 | return true; |
1111 | } | | 1111 | } |
1112 | | | 1112 | |
1113 | /* | | 1113 | /* |
1114 | * See if in strict bool mode, the operator takes either two bool operands | | 1114 | * See if in strict bool mode, the operator takes either two bool operands |
1115 | * or two arbitrary other operands. | | 1115 | * or two arbitrary other operands. |
1116 | */ | | 1116 | */ |
1117 | static bool | | 1117 | static bool |
1118 | is_assignment_bool_or_other(op_t op) | | 1118 | is_assignment_bool_or_other(op_t op) |
1119 | { | | 1119 | { |
1120 | return op == ASSIGN || | | 1120 | return op == ASSIGN || |
1121 | op == ANDASS || op == XORASS || op == ORASS || | | 1121 | op == ANDASS || op == XORASS || op == ORASS || |
1122 | op == RETURN || op == INIT || op == FARG; | | 1122 | op == RETURN || op == INIT || op == FARG; |
1123 | } | | 1123 | } |
1124 | | | 1124 | |
1125 | static bool | | 1125 | static bool |
1126 | is_symmetric_bool_or_other(op_t op) | | 1126 | is_symmetric_bool_or_other(op_t op) |
1127 | { | | 1127 | { |
1128 | return op == EQ || op == NE || | | 1128 | return op == EQ || op == NE || |
1129 | op == BITAND || op == BITXOR || op == BITOR || | | 1129 | op == BITAND || op == BITXOR || op == BITOR || |
1130 | op == COLON; | | 1130 | op == COLON; |
1131 | } | | 1131 | } |
1132 | | | 1132 | |
1133 | static bool | | 1133 | static bool |
1134 | is_int_constant_zero(const tnode_t *tn, tspec_t t) | | 1134 | is_int_constant_zero(const tnode_t *tn, tspec_t t) |
1135 | { | | 1135 | { |
1136 | return t == INT && tn->tn_op == CON && tn->tn_val->v_quad == 0; | | 1136 | return t == INT && tn->tn_op == CON && tn->tn_val->v_quad == 0; |
1137 | } | | 1137 | } |
1138 | | | 1138 | |
1139 | static bool | | 1139 | static bool |
1140 | is_typeok_strict_bool(op_t op, | | 1140 | is_typeok_strict_bool(op_t op, |
1141 | const tnode_t *ln, tspec_t lt, | | 1141 | const tnode_t *ln, tspec_t lt, |
1142 | const tnode_t *rn, tspec_t rt) | | 1142 | const tnode_t *rn, tspec_t rt) |
1143 | { | | 1143 | { |
1144 | if (rn == NULL) | | 1144 | if (rn == NULL) |
1145 | return true; /* TODO: check unary operators as well. */ | | 1145 | return true; /* TODO: check unary operators as well. */ |
1146 | | | 1146 | |
1147 | if ((lt == BOOL) == (rt == BOOL)) | | 1147 | if ((lt == BOOL) == (rt == BOOL)) |
1148 | return true; | | 1148 | return true; |
1149 | | | 1149 | |
1150 | if ((ln->tn_from_system_header || rn->tn_from_system_header) && | | 1150 | if ((ln->tn_from_system_header || rn->tn_from_system_header) && |
1151 | (is_int_constant_zero(ln, lt) || is_int_constant_zero(rn, rt))) | | 1151 | (is_int_constant_zero(ln, lt) || is_int_constant_zero(rn, rt))) |
1152 | return true; | | 1152 | return true; |
1153 | | | 1153 | |
1154 | if (is_assignment_bool_or_other(op)) { | | 1154 | if (is_assignment_bool_or_other(op)) { |
1155 | return lt != BOOL && | | 1155 | return lt != BOOL && |
1156 | (ln->tn_from_system_header || rn->tn_from_system_header); | | 1156 | (ln->tn_from_system_header || rn->tn_from_system_header); |
1157 | } | | 1157 | } |
1158 | | | 1158 | |
1159 | return !is_symmetric_bool_or_other(op); | | 1159 | return !is_symmetric_bool_or_other(op); |
1160 | } | | 1160 | } |
1161 | | | 1161 | |
1162 | /* | | 1162 | /* |
1163 | * Some operators require that either both operands are bool or both are | | 1163 | * Some operators require that either both operands are bool or both are |
1164 | * scalar. | | 1164 | * scalar. |
1165 | * | | 1165 | * |
1166 | * Code that passes this check can be compiled in a pre-C99 environment that | | 1166 | * Code that passes this check can be compiled in a pre-C99 environment that |
1167 | * doesn't implement the special rule C99 6.3.1.2, without silent change in | | 1167 | * doesn't implement the special rule C99 6.3.1.2, without silent change in |
1168 | * behavior. | | 1168 | * behavior. |
1169 | */ | | 1169 | */ |
1170 | static bool | | 1170 | static bool |
1171 | typeok_strict_bool_compatible(op_t op, int arg, | | 1171 | typeok_strict_bool_compatible(op_t op, int arg, |
1172 | const tnode_t *ln, tspec_t lt, | | 1172 | const tnode_t *ln, tspec_t lt, |
1173 | const tnode_t *rn, tspec_t rt) | | 1173 | const tnode_t *rn, tspec_t rt) |
1174 | { | | 1174 | { |
1175 | | | 1175 | |
1176 | if (is_typeok_strict_bool(op, ln, lt, rn, rt)) | | 1176 | if (is_typeok_strict_bool(op, ln, lt, rn, rt)) |
1177 | return true; | | 1177 | return true; |
1178 | | | 1178 | |
1179 | if (op == FARG) { | | 1179 | if (op == FARG) { |
1180 | /* argument #%d expects '%s', gets passed '%s' */ | | 1180 | /* argument #%d expects '%s', gets passed '%s' */ |
1181 | error(334, arg, tspec_name(lt), tspec_name(rt)); | | 1181 | error(334, arg, tspec_name(lt), tspec_name(rt)); |
1182 | } else if (op == RETURN) { | | 1182 | } else if (op == RETURN) { |
1183 | /* return value type mismatch (%s) and (%s) */ | | 1183 | /* return value type mismatch (%s) and (%s) */ |
1184 | error(211, tspec_name(lt), tspec_name(rt)); | | 1184 | error(211, tspec_name(lt), tspec_name(rt)); |
1185 | } else { | | 1185 | } else { |
1186 | /* operands of '%s' have incompatible types (%s != %s) */ | | 1186 | /* operands of '%s' have incompatible types (%s != %s) */ |
1187 | error(107, op_name(op), tspec_name(lt), tspec_name(rt)); | | 1187 | error(107, op_name(op), tspec_name(lt), tspec_name(rt)); |
1188 | } | | 1188 | } |
1189 | | | 1189 | |
1190 | return false; | | 1190 | return false; |
1191 | } | | 1191 | } |
1192 | | | 1192 | |
1193 | /* | | 1193 | /* |
1194 | * In strict bool mode, check whether the types of the operands match the | | 1194 | * In strict bool mode, check whether the types of the operands match the |
1195 | * operator. | | 1195 | * operator. |
1196 | */ | | 1196 | */ |
1197 | static bool | | 1197 | static bool |
1198 | typeok_scalar_strict_bool(op_t op, const mod_t *mp, int arg, | | 1198 | typeok_scalar_strict_bool(op_t op, const mod_t *mp, int arg, |
1199 | const tnode_t *ln, | | 1199 | const tnode_t *ln, |
1200 | const tnode_t *rn) | | 1200 | const tnode_t *rn) |
1201 | | | 1201 | |
1202 | { | | 1202 | { |
1203 | tspec_t lt, rt; | | 1203 | tspec_t lt, rt; |
1204 | | | 1204 | |
1205 | ln = before_conversion(ln); | | 1205 | ln = before_conversion(ln); |
1206 | lt = ln->tn_type->t_tspec; | | 1206 | lt = ln->tn_type->t_tspec; |
1207 | | | 1207 | |
1208 | if (rn != NULL) { | | 1208 | if (rn != NULL) { |
1209 | rn = before_conversion(rn); | | 1209 | rn = before_conversion(rn); |
1210 | rt = rn->tn_type->t_tspec; | | 1210 | rt = rn->tn_type->t_tspec; |
1211 | } else { | | 1211 | } else { |
1212 | rt = NOTSPEC; | | 1212 | rt = NOTSPEC; |
1213 | } | | 1213 | } |
1214 | | | 1214 | |
1215 | if (!typeok_strict_bool_compatible(op, arg, ln, lt, rn, rt)) | | 1215 | if (!typeok_strict_bool_compatible(op, arg, ln, lt, rn, rt)) |
1216 | return false; | | 1216 | return false; |
1217 | | | 1217 | |
1218 | if (mp->m_requires_bool || op == QUEST) { | | 1218 | if (mp->m_requires_bool || op == QUEST) { |
1219 | bool binary = mp->m_binary; | | 1219 | bool binary = mp->m_binary; |
1220 | bool lbool = is_typeok_bool_operand(ln); | | 1220 | bool lbool = is_typeok_bool_operand(ln); |
1221 | bool ok = true; | | 1221 | bool ok = true; |
1222 | | | 1222 | |
1223 | if (!binary && !lbool) { | | 1223 | if (!binary && !lbool) { |
1224 | /* operand of '%s' must be bool, not '%s' */ | | 1224 | /* operand of '%s' must be bool, not '%s' */ |
1225 | error(330, op_name(op), tspec_name(lt)); | | 1225 | error(330, op_name(op), tspec_name(lt)); |
1226 | ok = false; | | 1226 | ok = false; |
1227 | } | | 1227 | } |
1228 | if (binary && !lbool) { | | 1228 | if (binary && !lbool) { |
1229 | /* left operand of '%s' must be bool, not '%s' */ | | 1229 | /* left operand of '%s' must be bool, not '%s' */ |
1230 | error(331, op_name(op), tspec_name(lt)); | | 1230 | error(331, op_name(op), tspec_name(lt)); |
1231 | ok = false; | | 1231 | ok = false; |
1232 | } | | 1232 | } |
1233 | if (binary && op != QUEST && !is_typeok_bool_operand(rn)) { | | 1233 | if (binary && op != QUEST && !is_typeok_bool_operand(rn)) { |
1234 | /* right operand of '%s' must be bool, not '%s' */ | | 1234 | /* right operand of '%s' must be bool, not '%s' */ |
1235 | error(332, op_name(op), tspec_name(rt)); | | 1235 | error(332, op_name(op), tspec_name(rt)); |
1236 | ok = false; | | 1236 | ok = false; |
1237 | } | | 1237 | } |
1238 | return ok; | | 1238 | return ok; |
1239 | } | | 1239 | } |
1240 | | | 1240 | |
1241 | if (!mp->m_takes_bool) { | | 1241 | if (!mp->m_takes_bool) { |
1242 | bool binary = mp->m_binary; | | 1242 | bool binary = mp->m_binary; |
1243 | bool lbool = ln->tn_type->t_tspec == BOOL; | | 1243 | bool lbool = ln->tn_type->t_tspec == BOOL; |
1244 | bool ok = true; | | 1244 | bool ok = true; |
1245 | | | 1245 | |
1246 | if (!binary && lbool) { | | 1246 | if (!binary && lbool) { |
1247 | /* operand of '%s' must not be bool */ | | 1247 | /* operand of '%s' must not be bool */ |
1248 | error(335, op_name(op)); | | 1248 | error(335, op_name(op)); |
1249 | ok = false; | | 1249 | ok = false; |
1250 | } | | 1250 | } |
1251 | if (binary && lbool) { | | 1251 | if (binary && lbool) { |
1252 | /* left operand of '%s' must not be bool */ | | 1252 | /* left operand of '%s' must not be bool */ |
1253 | error(336, op_name(op)); | | 1253 | error(336, op_name(op)); |
1254 | ok = false; | | 1254 | ok = false; |
1255 | } | | 1255 | } |
1256 | if (binary && rn->tn_type->t_tspec == BOOL) { | | 1256 | if (binary && rn->tn_type->t_tspec == BOOL) { |
1257 | /* right operand of '%s' must not be bool */ | | 1257 | /* right operand of '%s' must not be bool */ |
1258 | error(337, op_name(op)); | | 1258 | error(337, op_name(op)); |
1259 | ok = false; | | 1259 | ok = false; |
1260 | } | | 1260 | } |
1261 | return ok; | | 1261 | return ok; |
1262 | } | | 1262 | } |
1263 | | | 1263 | |
1264 | return true; | | 1264 | return true; |
1265 | } | | 1265 | } |
1266 | | | 1266 | |
1267 | /* Check the types using the information from modtab[]. */ | | 1267 | /* Check the types using the information from modtab[]. */ |
1268 | static bool | | 1268 | static bool |
1269 | typeok_scalar(op_t op, const mod_t *mp, | | 1269 | typeok_scalar(op_t op, const mod_t *mp, |
1270 | const type_t *ltp, tspec_t lt, | | 1270 | const type_t *ltp, tspec_t lt, |
1271 | const type_t *rtp, tspec_t rt) | | 1271 | const type_t *rtp, tspec_t rt) |
1272 | { | | 1272 | { |
1273 | if (mp->m_takes_bool && lt == BOOL && rt == BOOL) | | 1273 | if (mp->m_takes_bool && lt == BOOL && rt == BOOL) |
1274 | return true; | | 1274 | return true; |
1275 | if (mp->m_requires_integer) { | | 1275 | if (mp->m_requires_integer) { |
1276 | if (!is_integer(lt) || (mp->m_binary && !is_integer(rt))) { | | 1276 | if (!is_integer(lt) || (mp->m_binary && !is_integer(rt))) { |
1277 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 1277 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
1278 | return false; | | 1278 | return false; |
1279 | } | | 1279 | } |
1280 | } else if (mp->m_requires_integer_or_complex) { | | 1280 | } else if (mp->m_requires_integer_or_complex) { |
1281 | if ((!is_integer(lt) && !is_complex(lt)) || | | 1281 | if ((!is_integer(lt) && !is_complex(lt)) || |
1282 | (mp->m_binary && (!is_integer(rt) && !is_complex(rt)))) { | | 1282 | (mp->m_binary && (!is_integer(rt) && !is_complex(rt)))) { |
1283 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 1283 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
1284 | return false; | | 1284 | return false; |
1285 | } | | 1285 | } |
1286 | } else if (mp->m_requires_scalar) { | | 1286 | } else if (mp->m_requires_scalar) { |
1287 | if (!is_scalar(lt) || (mp->m_binary && !is_scalar(rt))) { | | 1287 | if (!is_scalar(lt) || (mp->m_binary && !is_scalar(rt))) { |
1288 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 1288 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
1289 | return false; | | 1289 | return false; |
1290 | } | | 1290 | } |
1291 | } else if (mp->m_requires_arith) { | | 1291 | } else if (mp->m_requires_arith) { |
1292 | if (!is_arithmetic(lt) || | | 1292 | if (!is_arithmetic(lt) || |
1293 | (mp->m_binary && !is_arithmetic(rt))) { | | 1293 | (mp->m_binary && !is_arithmetic(rt))) { |
1294 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 1294 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
1295 | return false; | | 1295 | return false; |
1296 | } | | 1296 | } |
1297 | } | | 1297 | } |
1298 | return true; | | 1298 | return true; |
1299 | } | | 1299 | } |
1300 | | | 1300 | |
1301 | /* Check the types for specific operators and type combinations. */ | | 1301 | /* Check the types for specific operators and type combinations. */ |
1302 | static bool | | 1302 | static bool |
1303 | typeok_op(op_t op, const mod_t *mp, int arg, | | 1303 | typeok_op(op_t op, const mod_t *mp, int arg, |
1304 | const tnode_t *ln, const type_t *ltp, tspec_t lt, | | 1304 | const tnode_t *ln, const type_t *ltp, tspec_t lt, |
1305 | const tnode_t *rn, const type_t *rtp, tspec_t rt) | | 1305 | const tnode_t *rn, const type_t *rtp, tspec_t rt) |
1306 | { | | 1306 | { |
1307 | switch (op) { | | 1307 | switch (op) { |
1308 | case POINT: | | 1308 | case POINT: |
1309 | /* | | 1309 | /* |
1310 | * Most errors required by ANSI C are reported in | | 1310 | * Most errors required by ANSI C are reported in |
1311 | * struct_or_union_member(). | | 1311 | * struct_or_union_member(). |
1312 | * Here we only must check for totally wrong things. | | 1312 | * Here we only must check for totally wrong things. |
1313 | */ | | 1313 | */ |
1314 | if (lt == FUNC || lt == VOID || ltp->t_bitfield || | | 1314 | if (lt == FUNC || lt == VOID || ltp->t_bitfield || |
1315 | ((lt != STRUCT && lt != UNION) && !ln->tn_lvalue)) { | | 1315 | ((lt != STRUCT && lt != UNION) && !ln->tn_lvalue)) { |
1316 | /* Without tflag we got already an error */ | | 1316 | /* Without tflag we got already an error */ |
1317 | if (tflag) | | 1317 | if (tflag) |
1318 | /* unacceptable operand of '%s' */ | | 1318 | /* unacceptable operand of '%s' */ |
1319 | error(111, mp->m_name); | | 1319 | error(111, mp->m_name); |
1320 | return false; | | 1320 | return false; |
1321 | } | | 1321 | } |
1322 | /* Now we have an object we can create a pointer to */ | | 1322 | /* Now we have an object we can create a pointer to */ |
1323 | break; | | 1323 | break; |
1324 | case ARROW: | | 1324 | case ARROW: |
1325 | if (lt != PTR && !(tflag && is_integer(lt))) { | | 1325 | if (lt != PTR && !(tflag && is_integer(lt))) { |
1326 | /* Without tflag we got already an error */ | | 1326 | /* Without tflag we got already an error */ |
1327 | if (tflag) | | 1327 | if (tflag) |
1328 | /* unacceptable operand of '%s' */ | | 1328 | /* unacceptable operand of '%s' */ |
1329 | error(111, mp->m_name); | | 1329 | error(111, mp->m_name); |
1330 | return false; | | 1330 | return false; |
1331 | } | | 1331 | } |
1332 | break; | | 1332 | break; |
1333 | case INCAFT: | | 1333 | case INCAFT: |
1334 | case DECAFT: | | 1334 | case DECAFT: |
1335 | case INCBEF: | | 1335 | case INCBEF: |
1336 | case DECBEF: | | 1336 | case DECBEF: |
1337 | if (!typeok_incdec(mp, ln, ltp)) | | 1337 | if (!typeok_incdec(op, ln, ltp)) |
1338 | return false; | | 1338 | return false; |
1339 | break; | | 1339 | break; |
1340 | case ADDR: | | 1340 | case ADDR: |
1341 | if (!typeok_address(mp, ln, ltp, lt)) | | 1341 | if (!typeok_address(mp, ln, ltp, lt)) |
1342 | return false; | | 1342 | return false; |
1343 | break; | | 1343 | break; |
1344 | case INDIR: | | 1344 | case INDIR: |
1345 | if (!typeok_star(lt)) | | 1345 | if (!typeok_star(lt)) |
1346 | return false; | | 1346 | return false; |
1347 | break; | | 1347 | break; |
1348 | case PLUS: | | 1348 | case PLUS: |
1349 | if (!typeok_plus(op, ltp, lt, rtp, rt)) | | 1349 | if (!typeok_plus(op, ltp, lt, rtp, rt)) |
1350 | return false; | | 1350 | return false; |
1351 | break; | | 1351 | break; |
1352 | case MINUS: | | 1352 | case MINUS: |
1353 | if (!typeok_minus(op, ltp, lt, rtp, rt)) | | 1353 | if (!typeok_minus(op, ltp, lt, rtp, rt)) |
1354 | return false; | | 1354 | return false; |
1355 | break; | | 1355 | break; |
1356 | case SHR: | | 1356 | case SHR: |
1357 | typeok_shr(mp, ln, lt, rn, rt); | | 1357 | typeok_shr(mp, ln, lt, rn, rt); |
1358 | goto shift; | | 1358 | goto shift; |
1359 | case SHL: | | 1359 | case SHL: |
1360 | typeok_shl(mp, lt, rt); | | 1360 | typeok_shl(mp, lt, rt); |
1361 | shift: | | 1361 | shift: |
1362 | typeok_shift(lt, rn, rt); | | 1362 | typeok_shift(lt, rn, rt); |
1363 | break; | | 1363 | break; |
1364 | case EQ: | | 1364 | case EQ: |
1365 | case NE: | | 1365 | case NE: |
1366 | /* | | 1366 | /* |
1367 | * Accept some things which are allowed with EQ and NE, | | 1367 | * Accept some things which are allowed with EQ and NE, |
1368 | * but not with ordered comparisons. | | 1368 | * but not with ordered comparisons. |
1369 | */ | | 1369 | */ |
1370 | if (is_typeok_eq(ln, lt, rn, rt)) | | 1370 | if (is_typeok_eq(ln, lt, rn, rt)) |
1371 | break; | | 1371 | break; |
1372 | /* FALLTHROUGH */ | | 1372 | /* FALLTHROUGH */ |
1373 | case LT: | | 1373 | case LT: |
1374 | case GT: | | 1374 | case GT: |
1375 | case LE: | | 1375 | case LE: |
1376 | case GE: | | 1376 | case GE: |
1377 | if (!typeok_ordered_comparison(op, ln, ltp, lt, rn, rtp, rt)) | | 1377 | if (!typeok_ordered_comparison(op, ln, ltp, lt, rn, rtp, rt)) |
1378 | return false; | | 1378 | return false; |
1379 | break; | | 1379 | break; |
1380 | case QUEST: | | 1380 | case QUEST: |
1381 | if (!typeok_quest(lt, &rn)) | | 1381 | if (!typeok_quest(lt, &rn)) |
1382 | return false; | | 1382 | return false; |
1383 | break; | | 1383 | break; |
1384 | case COLON: | | 1384 | case COLON: |
1385 | if (!typeok_colon(mp, ln, ltp, lt, rn, rtp, rt)) | | 1385 | if (!typeok_colon(mp, ln, ltp, lt, rn, rtp, rt)) |
1386 | return false; | | 1386 | return false; |
1387 | break; | | 1387 | break; |
1388 | case ASSIGN: | | 1388 | case ASSIGN: |
1389 | case INIT: | | 1389 | case INIT: |
1390 | case FARG: | | 1390 | case FARG: |
1391 | case RETURN: | | 1391 | case RETURN: |
1392 | if (!check_assign_types_compatible(op, arg, ln, rn)) | | 1392 | if (!check_assign_types_compatible(op, arg, ln, rn)) |
1393 | return false; | | 1393 | return false; |
1394 | goto assign; | | 1394 | goto assign; |
1395 | case MULASS: | | 1395 | case MULASS: |
1396 | case DIVASS: | | 1396 | case DIVASS: |
1397 | case MODASS: | | 1397 | case MODASS: |
1398 | goto assign; | | 1398 | goto assign; |
1399 | case ADDASS: | | 1399 | case ADDASS: |
1400 | case SUBASS: | | 1400 | case SUBASS: |
1401 | /* operands have scalar types (checked above) */ | | 1401 | /* operands have scalar types (checked above) */ |
1402 | if ((lt == PTR && !is_integer(rt)) || rt == PTR) { | | 1402 | if ((lt == PTR && !is_integer(rt)) || rt == PTR) { |
1403 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 1403 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
1404 | return false; | | 1404 | return false; |
1405 | } | | 1405 | } |
1406 | goto assign; | | 1406 | goto assign; |
1407 | case SHLASS: | | 1407 | case SHLASS: |
1408 | goto assign; | | 1408 | goto assign; |
1409 | case SHRASS: | | 1409 | case SHRASS: |
1410 | if (pflag && !is_uinteger(lt) && !(tflag && is_uinteger(rt))) { | | 1410 | if (pflag && !is_uinteger(lt) && !(tflag && is_uinteger(rt))) { |
1411 | /* bitwise '%s' on signed value possibly nonportable */ | | 1411 | /* bitwise '%s' on signed value possibly nonportable */ |
1412 | warning(117, mp->m_name); | | 1412 | warning(117, mp->m_name); |
1413 | } | | 1413 | } |
1414 | goto assign; | | 1414 | goto assign; |
1415 | case ANDASS: | | 1415 | case ANDASS: |
1416 | case XORASS: | | 1416 | case XORASS: |
1417 | case ORASS: | | 1417 | case ORASS: |
1418 | goto assign; | | 1418 | goto assign; |
1419 | assign: | | 1419 | assign: |
1420 | if (!typeok_assign(mp, ln, ltp, lt)) | | 1420 | if (!typeok_assign(mp, ln, ltp, lt)) |
1421 | return false; | | 1421 | return false; |
1422 | break; | | 1422 | break; |
1423 | case COMMA: | | 1423 | case COMMA: |
1424 | if (!modtab[ln->tn_op].m_has_side_effect) | | 1424 | if (!modtab[ln->tn_op].m_has_side_effect) |
1425 | check_null_effect(ln); | | 1425 | check_null_effect(ln); |
1426 | break; | | 1426 | break; |
1427 | /* LINTED206: (enumeration values not handled in switch) */ | | 1427 | /* LINTED206: (enumeration values not handled in switch) */ |
1428 | case CON: | | 1428 | case CON: |
1429 | case CASE: | | 1429 | case CASE: |
1430 | case PUSH: | | 1430 | case PUSH: |
1431 | case LOAD: | | 1431 | case LOAD: |
1432 | case ICALL: | | 1432 | case ICALL: |
1433 | case CVT: | | 1433 | case CVT: |
1434 | case CALL: | | 1434 | case CALL: |
1435 | case FSEL: | | 1435 | case FSEL: |
1436 | case STRING: | | 1436 | case STRING: |
1437 | case NAME: | | 1437 | case NAME: |
1438 | case LOGOR: | | 1438 | case LOGOR: |
1439 | case LOGAND: | | 1439 | case LOGAND: |
1440 | case BITOR: | | 1440 | case BITOR: |
1441 | case BITXOR: | | 1441 | case BITXOR: |
1442 | case BITAND: | | 1442 | case BITAND: |
1443 | case MOD: | | 1443 | case MOD: |
1444 | case DIV: | | 1444 | case DIV: |
1445 | case MULT: | | 1445 | case MULT: |
1446 | case UMINUS: | | 1446 | case UMINUS: |
1447 | case UPLUS: | | 1447 | case UPLUS: |
1448 | case DEC: | | 1448 | case DEC: |
1449 | case INC: | | 1449 | case INC: |
1450 | case COMPL: | | 1450 | case COMPL: |
1451 | case NOT: | | 1451 | case NOT: |
1452 | case NOOP: | | 1452 | case NOOP: |
1453 | case REAL: | | 1453 | case REAL: |
1454 | case IMAG: | | 1454 | case IMAG: |
1455 | break; | | 1455 | break; |
1456 | } | | 1456 | } |
1457 | return true; | | 1457 | return true; |
1458 | } | | 1458 | } |
1459 | | | 1459 | |
1460 | static void | | 1460 | static void |
1461 | typeok_enum(op_t op, const mod_t *mp, int arg, | | 1461 | typeok_enum(op_t op, const mod_t *mp, int arg, |
1462 | const tnode_t *ln, const type_t *ltp, | | 1462 | const tnode_t *ln, const type_t *ltp, |
1463 | const tnode_t *rn, const type_t *rtp) | | 1463 | const tnode_t *rn, const type_t *rtp) |
1464 | { | | 1464 | { |
1465 | if (mp->m_bad_on_enum && | | 1465 | if (mp->m_bad_on_enum && |
1466 | (ltp->t_is_enum || (mp->m_binary && rtp->t_is_enum))) { | | 1466 | (ltp->t_is_enum || (mp->m_binary && rtp->t_is_enum))) { |
1467 | check_bad_enum_operation(op, ln, rn); | | 1467 | check_bad_enum_operation(op, ln, rn); |
1468 | } else if (mp->m_valid_on_enum && | | 1468 | } else if (mp->m_valid_on_enum && |
1469 | (ltp->t_is_enum && rtp != NULL && rtp->t_is_enum)) { | | 1469 | (ltp->t_is_enum && rtp != NULL && rtp->t_is_enum)) { |
1470 | check_enum_type_mismatch(op, arg, ln, rn); | | 1470 | check_enum_type_mismatch(op, arg, ln, rn); |
1471 | } else if (mp->m_valid_on_enum && | | 1471 | } else if (mp->m_valid_on_enum && |
1472 | (ltp->t_is_enum || (rtp != NULL && rtp->t_is_enum))) { | | 1472 | (ltp->t_is_enum || (rtp != NULL && rtp->t_is_enum))) { |
1473 | check_enum_int_mismatch(op, arg, ln, rn); | | 1473 | check_enum_int_mismatch(op, arg, ln, rn); |
1474 | } | | 1474 | } |
1475 | } | | 1475 | } |
1476 | | | 1476 | |
1477 | /* Perform most type checks. Return whether the types are ok. */ | | 1477 | /* Perform most type checks. Return whether the types are ok. */ |
1478 | bool | | 1478 | bool |
1479 | typeok(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) | | 1479 | typeok(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) |
1480 | { | | 1480 | { |
1481 | const mod_t *mp; | | 1481 | const mod_t *mp; |
1482 | tspec_t lt, rt; | | 1482 | tspec_t lt, rt; |
1483 | type_t *ltp, *rtp; | | 1483 | type_t *ltp, *rtp; |
1484 | | | 1484 | |
1485 | mp = &modtab[op]; | | 1485 | mp = &modtab[op]; |
1486 | | | 1486 | |
1487 | lint_assert((ltp = ln->tn_type) != NULL); | | 1487 | lint_assert((ltp = ln->tn_type) != NULL); |
1488 | lt = ltp->t_tspec; | | 1488 | lt = ltp->t_tspec; |
1489 | | | 1489 | |
1490 | if (mp->m_binary) { | | 1490 | if (mp->m_binary) { |
1491 | lint_assert((rtp = rn->tn_type) != NULL); | | 1491 | lint_assert((rtp = rn->tn_type) != NULL); |
1492 | rt = rtp->t_tspec; | | 1492 | rt = rtp->t_tspec; |
1493 | } else { | | 1493 | } else { |
1494 | rtp = NULL; | | 1494 | rtp = NULL; |
1495 | rt = NOTSPEC; | | 1495 | rt = NOTSPEC; |
1496 | } | | 1496 | } |
1497 | | | 1497 | |
1498 | if (Tflag && !typeok_scalar_strict_bool(op, mp, arg, ln, rn)) | | 1498 | if (Tflag && !typeok_scalar_strict_bool(op, mp, arg, ln, rn)) |
1499 | return false; | | 1499 | return false; |
1500 | if (!typeok_scalar(op, mp, ltp, lt, rtp, rt)) | | 1500 | if (!typeok_scalar(op, mp, ltp, lt, rtp, rt)) |
1501 | return false; | | 1501 | return false; |
1502 | | | 1502 | |
1503 | if (!typeok_op(op, mp, arg, ln, ltp, lt, rn, rtp, rt)) | | 1503 | if (!typeok_op(op, mp, arg, ln, ltp, lt, rn, rtp, rt)) |
1504 | return false; | | 1504 | return false; |
1505 | | | 1505 | |
1506 | typeok_enum(op, mp, arg, ln, ltp, rn, rtp); | | 1506 | typeok_enum(op, mp, arg, ln, ltp, rn, rtp); |
1507 | return true; | | 1507 | return true; |
1508 | } | | 1508 | } |
1509 | | | 1509 | |
1510 | static void | | 1510 | static void |
1511 | check_pointer_comparison(op_t op, const tnode_t *ln, const tnode_t *rn) | | 1511 | check_pointer_comparison(op_t op, const tnode_t *ln, const tnode_t *rn) |
1512 | { | | 1512 | { |
1513 | type_t *ltp, *rtp; | | 1513 | type_t *ltp, *rtp; |
1514 | tspec_t lst, rst; | | 1514 | tspec_t lst, rst; |
1515 | const char *lsts, *rsts; | | 1515 | const char *lsts, *rsts; |
1516 | | | 1516 | |
1517 | lst = (ltp = ln->tn_type)->t_subt->t_tspec; | | 1517 | lst = (ltp = ln->tn_type)->t_subt->t_tspec; |
1518 | rst = (rtp = rn->tn_type)->t_subt->t_tspec; | | 1518 | rst = (rtp = rn->tn_type)->t_subt->t_tspec; |
1519 | | | 1519 | |
1520 | if (lst == VOID || rst == VOID) { | | 1520 | if (lst == VOID || rst == VOID) { |
1521 | if (sflag && (lst == FUNC || rst == FUNC)) { | | 1521 | if (sflag && (lst == FUNC || rst == FUNC)) { |
1522 | /* (void *)0 already handled in typeok() */ | | 1522 | /* (void *)0 already handled in typeok() */ |
1523 | *(lst == FUNC ? &lsts : &rsts) = "function pointer"; | | 1523 | *(lst == FUNC ? &lsts : &rsts) = "function pointer"; |
1524 | *(lst == VOID ? &lsts : &rsts) = "'void *'"; | | 1524 | *(lst == VOID ? &lsts : &rsts) = "'void *'"; |
1525 | /* ANSI C forbids comparison of %s with %s */ | | 1525 | /* ANSI C forbids comparison of %s with %s */ |
1526 | warning(274, lsts, rsts); | | 1526 | warning(274, lsts, rsts); |
1527 | } | | 1527 | } |
1528 | return; | | 1528 | return; |
1529 | } | | 1529 | } |
1530 | | | 1530 | |
1531 | if (!eqtype(ltp->t_subt, rtp->t_subt, true, false, NULL)) { | | 1531 | if (!eqtype(ltp->t_subt, rtp->t_subt, true, false, NULL)) { |
1532 | warn_incompatible_pointers(&modtab[op], ltp, rtp); | | 1532 | warn_incompatible_pointers(&modtab[op], ltp, rtp); |
1533 | return; | | 1533 | return; |
1534 | } | | 1534 | } |
1535 | | | 1535 | |
1536 | if (lst == FUNC && rst == FUNC) { | | 1536 | if (lst == FUNC && rst == FUNC) { |
1537 | if (sflag && op != EQ && op != NE) | | 1537 | if (sflag && op != EQ && op != NE) |
1538 | /* ANSI C forbids ordered comparisons of ... */ | | 1538 | /* ANSI C forbids ordered comparisons of ... */ |
1539 | warning(125); | | 1539 | warning(125); |
1540 | } | | 1540 | } |
1541 | } | | 1541 | } |
1542 | | | 1542 | |
1543 | /* | | 1543 | /* |
1544 | * Checks type compatibility for ASSIGN, INIT, FARG and RETURN | | 1544 | * Checks type compatibility for ASSIGN, INIT, FARG and RETURN |
1545 | * and prints warnings/errors if necessary. | | 1545 | * and prints warnings/errors if necessary. |
1546 | * If the types are (almost) compatible, 1 is returned, otherwise 0. | | 1546 | * If the types are (almost) compatible, 1 is returned, otherwise 0. |
1547 | */ | | 1547 | */ |
1548 | static bool | | 1548 | static bool |
1549 | check_assign_types_compatible(op_t op, int arg, | | 1549 | check_assign_types_compatible(op_t op, int arg, |
1550 | const tnode_t *ln, const tnode_t *rn) | | 1550 | const tnode_t *ln, const tnode_t *rn) |
1551 | { | | 1551 | { |
1552 | tspec_t lt, rt, lst = NOTSPEC, rst = NOTSPEC; | | 1552 | tspec_t lt, rt, lst = NOTSPEC, rst = NOTSPEC; |
1553 | type_t *ltp, *rtp, *lstp = NULL, *rstp = NULL; | | 1553 | type_t *ltp, *rtp, *lstp = NULL, *rstp = NULL; |
1554 | const mod_t *mp; | | 1554 | const mod_t *mp; |
1555 | const char *lts, *rts; | | 1555 | const char *lts, *rts; |
1556 | | | 1556 | |
1557 | if ((lt = (ltp = ln->tn_type)->t_tspec) == PTR) | | 1557 | if ((lt = (ltp = ln->tn_type)->t_tspec) == PTR) |
1558 | lst = (lstp = ltp->t_subt)->t_tspec; | | 1558 | lst = (lstp = ltp->t_subt)->t_tspec; |
1559 | if ((rt = (rtp = rn->tn_type)->t_tspec) == PTR) | | 1559 | if ((rt = (rtp = rn->tn_type)->t_tspec) == PTR) |
1560 | rst = (rstp = rtp->t_subt)->t_tspec; | | 1560 | rst = (rstp = rtp->t_subt)->t_tspec; |
1561 | mp = &modtab[op]; | | 1561 | mp = &modtab[op]; |
1562 | | | 1562 | |
1563 | if (lt == BOOL && is_scalar(rt)) /* C99 6.3.1.2 */ | | 1563 | if (lt == BOOL && is_scalar(rt)) /* C99 6.3.1.2 */ |
1564 | return true; | | 1564 | return true; |
1565 | | | 1565 | |
1566 | if (is_arithmetic(lt) && (is_arithmetic(rt) || rt == BOOL)) | | 1566 | if (is_arithmetic(lt) && (is_arithmetic(rt) || rt == BOOL)) |
1567 | return true; | | 1567 | return true; |
1568 | | | 1568 | |
1569 | if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) | | 1569 | if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) |
1570 | /* both are struct or union */ | | 1570 | /* both are struct or union */ |
1571 | return ltp->t_str == rtp->t_str; | | 1571 | return ltp->t_str == rtp->t_str; |
1572 | | | 1572 | |
1573 | /* a null pointer may be assigned to any pointer */ | | 1573 | /* a null pointer may be assigned to any pointer */ |
1574 | if (lt == PTR && is_null_pointer(rn)) | | 1574 | if (lt == PTR && is_null_pointer(rn)) |
1575 | return true; | | 1575 | return true; |
1576 | | | 1576 | |
1577 | if (lt == PTR && rt == PTR && (lst == VOID || rst == VOID)) { | | 1577 | if (lt == PTR && rt == PTR && (lst == VOID || rst == VOID)) { |
1578 | /* two pointers, at least one pointer to void */ | | 1578 | /* two pointers, at least one pointer to void */ |
1579 | if (sflag && (lst == FUNC || rst == FUNC)) { | | 1579 | if (sflag && (lst == FUNC || rst == FUNC)) { |
1580 | /* comb. of ptr to func and ptr to void */ | | 1580 | /* comb. of ptr to func and ptr to void */ |
1581 | *(lst == FUNC ? <s : &rts) = "function pointer"; | | 1581 | *(lst == FUNC ? <s : &rts) = "function pointer"; |
1582 | *(lst == VOID ? <s : &rts) = "'void *'"; | | 1582 | *(lst == VOID ? <s : &rts) = "'void *'"; |
1583 | switch (op) { | | 1583 | switch (op) { |
1584 | case INIT: | | 1584 | case INIT: |
1585 | case RETURN: | | 1585 | case RETURN: |
1586 | /* ANSI C forbids conversion of %s to %s */ | | 1586 | /* ANSI C forbids conversion of %s to %s */ |
1587 | warning(303, rts, lts); | | 1587 | warning(303, rts, lts); |
1588 | break; | | 1588 | break; |
1589 | case FARG: | | 1589 | case FARG: |
1590 | /* ANSI C forbids conv. of %s to %s, arg #%d */ | | 1590 | /* ANSI C forbids conv. of %s to %s, arg #%d */ |
1591 | warning(304, rts, lts, arg); | | 1591 | warning(304, rts, lts, arg); |
1592 | break; | | 1592 | break; |
1593 | default: | | 1593 | default: |
1594 | /* ANSI C forbids conv. of %s to %s, op %s */ | | 1594 | /* ANSI C forbids conv. of %s to %s, op %s */ |
1595 | warning(305, rts, lts, mp->m_name); | | 1595 | warning(305, rts, lts, mp->m_name); |
1596 | break; | | 1596 | break; |
1597 | } | | 1597 | } |
1598 | } | | 1598 | } |
1599 | } | | 1599 | } |
1600 | | | 1600 | |
1601 | if (lt == PTR && rt == PTR && (lst == VOID || rst == VOID || | | 1601 | if (lt == PTR && rt == PTR && (lst == VOID || rst == VOID || |
1602 | eqtype(lstp, rstp, true, false, NULL))) { | | 1602 | eqtype(lstp, rstp, true, false, NULL))) { |
1603 | /* compatible pointer types (qualifiers ignored) */ | | 1603 | /* compatible pointer types (qualifiers ignored) */ |
1604 | if (!tflag && | | 1604 | if (!tflag && |
1605 | ((!lstp->t_const && rstp->t_const) || | | 1605 | ((!lstp->t_const && rstp->t_const) || |
1606 | (!lstp->t_volatile && rstp->t_volatile))) { | | 1606 | (!lstp->t_volatile && rstp->t_volatile))) { |
1607 | /* left side has not all qualifiers of right */ | | 1607 | /* left side has not all qualifiers of right */ |
1608 | switch (op) { | | 1608 | switch (op) { |
1609 | case INIT: | | 1609 | case INIT: |
1610 | case RETURN: | | 1610 | case RETURN: |
1611 | /* incompatible pointer types (%s != %s) */ | | 1611 | /* incompatible pointer types (%s != %s) */ |
1612 | warning(182, type_name(lstp), type_name(rstp)); | | 1612 | warning(182, type_name(lstp), type_name(rstp)); |
1613 | break; | | 1613 | break; |
1614 | case FARG: | | 1614 | case FARG: |
1615 | /* converting '%s' to incompatible '%s' ... */ | | 1615 | /* converting '%s' to incompatible '%s' ... */ |
1616 | warning(153, | | 1616 | warning(153, |
1617 | type_name(rtp), type_name(ltp), arg); | | 1617 | type_name(rtp), type_name(ltp), arg); |
1618 | break; | | 1618 | break; |
1619 | default: | | 1619 | default: |
1620 | /* operands have incompatible pointer type... */ | | 1620 | /* operands have incompatible pointer type... */ |
1621 | warning(128, mp->m_name, | | 1621 | warning(128, mp->m_name, |
1622 | type_name(lstp), type_name(rstp)); | | 1622 | type_name(lstp), type_name(rstp)); |
1623 | break; | | 1623 | break; |
1624 | } | | 1624 | } |
1625 | } | | 1625 | } |
1626 | return true; | | 1626 | return true; |
1627 | } | | 1627 | } |
1628 | | | 1628 | |
1629 | if ((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)) { | | 1629 | if ((lt == PTR && is_integer(rt)) || (is_integer(lt) && rt == PTR)) { |
1630 | const char *lx = lt == PTR ? "pointer" : "integer"; | | 1630 | const char *lx = lt == PTR ? "pointer" : "integer"; |
1631 | const char *rx = rt == PTR ? "pointer" : "integer"; | | 1631 | const char *rx = rt == PTR ? "pointer" : "integer"; |
1632 | | | 1632 | |
1633 | switch (op) { | | 1633 | switch (op) { |
1634 | case INIT: | | 1634 | case INIT: |
1635 | case RETURN: | | 1635 | case RETURN: |
1636 | /* illegal combination of %s (%s) and %s (%s) */ | | 1636 | /* illegal combination of %s (%s) and %s (%s) */ |
1637 | warning(183, lx, type_name(ltp), rx, type_name(rtp)); | | 1637 | warning(183, lx, type_name(ltp), rx, type_name(rtp)); |
1638 | break; | | 1638 | break; |
1639 | case FARG: | | 1639 | case FARG: |
1640 | /* illegal comb. of %s (%s) and %s (%s), arg #%d */ | | 1640 | /* illegal comb. of %s (%s) and %s (%s), arg #%d */ |
1641 | warning(154, | | 1641 | warning(154, |
1642 | lx, type_name(ltp), rx, type_name(rtp), arg); | | 1642 | lx, type_name(ltp), rx, type_name(rtp), arg); |
1643 | break; | | 1643 | break; |
1644 | default: | | 1644 | default: |
1645 | /* illegal combination of %s (%s) and %s (%s), op %s */ | | 1645 | /* illegal combination of %s (%s) and %s (%s), op %s */ |
1646 | warning(123, | | 1646 | warning(123, |
1647 | lx, type_name(ltp), rx, type_name(rtp), mp->m_name); | | 1647 | lx, type_name(ltp), rx, type_name(rtp), mp->m_name); |
1648 | break; | | 1648 | break; |
1649 | } | | 1649 | } |
1650 | return true; | | 1650 | return true; |
1651 | } | | 1651 | } |
1652 | | | 1652 | |
1653 | if (lt == PTR && rt == PTR) { | | 1653 | if (lt == PTR && rt == PTR) { |
1654 | switch (op) { | | 1654 | switch (op) { |
1655 | case INIT: | | 1655 | case INIT: |
1656 | case RETURN: | | 1656 | case RETURN: |
1657 | warn_incompatible_pointers(NULL, ltp, rtp); | | 1657 | warn_incompatible_pointers(NULL, ltp, rtp); |
1658 | break; | | 1658 | break; |
1659 | case FARG: | | 1659 | case FARG: |
1660 | /* converting '%s' to incompatible '%s' for ... */ | | 1660 | /* converting '%s' to incompatible '%s' for ... */ |
1661 | warning(153, type_name(rtp), type_name(ltp), arg); | | 1661 | warning(153, type_name(rtp), type_name(ltp), arg); |
1662 | break; | | 1662 | break; |
1663 | default: | | 1663 | default: |
1664 | warn_incompatible_pointers(mp, ltp, rtp); | | 1664 | warn_incompatible_pointers(mp, ltp, rtp); |
1665 | break; | | 1665 | break; |
1666 | } | | 1666 | } |
1667 | return true; | | 1667 | return true; |
1668 | } | | 1668 | } |
1669 | | | 1669 | |
1670 | switch (op) { | | 1670 | switch (op) { |
1671 | case INIT: | | 1671 | case INIT: |
1672 | /* cannot initialize '%s' from '%s' */ | | 1672 | /* cannot initialize '%s' from '%s' */ |
1673 | error(185, type_name(ltp), type_name(rtp)); | | 1673 | error(185, type_name(ltp), type_name(rtp)); |
1674 | break; | | 1674 | break; |
1675 | case RETURN: | | 1675 | case RETURN: |
1676 | /* return value type mismatch (%s) and (%s) */ | | 1676 | /* return value type mismatch (%s) and (%s) */ |
1677 | error(211, type_name(ltp), type_name(rtp)); | | 1677 | error(211, type_name(ltp), type_name(rtp)); |
1678 | break; | | 1678 | break; |
1679 | case FARG: | | 1679 | case FARG: |
1680 | /* argument is incompatible with prototype, arg #%d */ | | 1680 | /* argument is incompatible with prototype, arg #%d */ |
1681 | warning(155, arg); | | 1681 | warning(155, arg); |
1682 | break; | | 1682 | break; |
1683 | default: | | 1683 | default: |
1684 | warn_incompatible_types(op, ltp, lt, rtp, rt); | | 1684 | warn_incompatible_types(op, ltp, lt, rtp, rt); |
1685 | break; | | 1685 | break; |
1686 | } | | 1686 | } |
1687 | | | 1687 | |
1688 | return false; | | 1688 | return false; |
1689 | } | | 1689 | } |
1690 | | | 1690 | |
1691 | /* Prints a warning if a strange operator is used on an enum type. */ | | 1691 | /* Prints a warning if a strange operator is used on an enum type. */ |
1692 | static void | | 1692 | static void |
1693 | check_bad_enum_operation(op_t op, const tnode_t *ln, const tnode_t *rn) | | 1693 | check_bad_enum_operation(op_t op, const tnode_t *ln, const tnode_t *rn) |
1694 | { | | 1694 | { |
1695 | | | 1695 | |
1696 | if (!eflag) | | 1696 | if (!eflag) |
1697 | return; | | 1697 | return; |
1698 | | | 1698 | |
1699 | if (!(ln->tn_type->t_is_enum || | | 1699 | if (!(ln->tn_type->t_is_enum || |
1700 | (modtab[op].m_binary && rn->tn_type->t_is_enum))) { | | 1700 | (modtab[op].m_binary && rn->tn_type->t_is_enum))) { |
1701 | return; | | 1701 | return; |
1702 | } | | 1702 | } |
1703 | | | 1703 | |
1704 | /* | | 1704 | /* |
1705 | * Enum as offset to a pointer is an exception (otherwise enums | | 1705 | * Enum as offset to a pointer is an exception (otherwise enums |
1706 | * could not be used as array indices). | | 1706 | * could not be used as array indices). |
1707 | */ | | 1707 | */ |
1708 | if (op == PLUS && | | 1708 | if (op == PLUS && |
1709 | ((ln->tn_type->t_is_enum && rn->tn_type->t_tspec == PTR) || | | 1709 | ((ln->tn_type->t_is_enum && rn->tn_type->t_tspec == PTR) || |
1710 | (rn->tn_type->t_is_enum && ln->tn_type->t_tspec == PTR))) { | | 1710 | (rn->tn_type->t_is_enum && ln->tn_type->t_tspec == PTR))) { |
1711 | return; | | 1711 | return; |
1712 | } | | 1712 | } |
1713 | | | 1713 | |
1714 | /* dubious operation on enum, op %s */ | | 1714 | /* dubious operation on enum, op %s */ |
1715 | warning(241, op_name(op)); | | 1715 | warning(241, op_name(op)); |
1716 | | | 1716 | |
1717 | } | | 1717 | } |
1718 | | | 1718 | |
1719 | /* | | 1719 | /* |
1720 | * Prints a warning if an operator is applied to two different enum types. | | 1720 | * Prints a warning if an operator is applied to two different enum types. |
1721 | */ | | 1721 | */ |
1722 | static void | | 1722 | static void |
1723 | check_enum_type_mismatch(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) | | 1723 | check_enum_type_mismatch(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) |
1724 | { | | 1724 | { |
1725 | const mod_t *mp; | | 1725 | const mod_t *mp; |
1726 | | | 1726 | |
1727 | mp = &modtab[op]; | | 1727 | mp = &modtab[op]; |
1728 | | | 1728 | |
1729 | if (ln->tn_type->t_enum != rn->tn_type->t_enum) { | | 1729 | if (ln->tn_type->t_enum != rn->tn_type->t_enum) { |
1730 | switch (op) { | | 1730 | switch (op) { |
1731 | case INIT: | | 1731 | case INIT: |
1732 | /* enum type mismatch between '%s' and '%s' in ... */ | | 1732 | /* enum type mismatch between '%s' and '%s' in ... */ |
1733 | warning(210, | | 1733 | warning(210, |
1734 | type_name(ln->tn_type), type_name(rn->tn_type)); | | 1734 | type_name(ln->tn_type), type_name(rn->tn_type)); |
1735 | break; | | 1735 | break; |
1736 | case FARG: | | 1736 | case FARG: |
1737 | /* enum type mismatch, arg #%d (%s != %s) */ | | 1737 | /* enum type mismatch, arg #%d (%s != %s) */ |
1738 | warning(156, arg, | | 1738 | warning(156, arg, |
1739 | type_name(ln->tn_type), type_name(rn->tn_type)); | | 1739 | type_name(ln->tn_type), type_name(rn->tn_type)); |
1740 | break; | | 1740 | break; |
1741 | case RETURN: | | 1741 | case RETURN: |
1742 | /* return value type mismatch (%s) and (%s) */ | | 1742 | /* return value type mismatch (%s) and (%s) */ |
1743 | warning(211, | | 1743 | warning(211, |
1744 | type_name(ln->tn_type), type_name(rn->tn_type)); | | 1744 | type_name(ln->tn_type), type_name(rn->tn_type)); |
1745 | break; | | 1745 | break; |
1746 | default: | | 1746 | default: |
1747 | /* enum type mismatch: '%s' '%s' '%s' */ | | 1747 | /* enum type mismatch: '%s' '%s' '%s' */ |
1748 | warning(130, type_name(ln->tn_type), mp->m_name, | | 1748 | warning(130, type_name(ln->tn_type), mp->m_name, |
1749 | type_name(rn->tn_type)); | | 1749 | type_name(rn->tn_type)); |
1750 | break; | | 1750 | break; |
1751 | } | | 1751 | } |
1752 | } else if (Pflag && mp->m_comparison && op != EQ && op != NE) { | | 1752 | } else if (Pflag && mp->m_comparison && op != EQ && op != NE) { |
1753 | if (eflag) | | 1753 | if (eflag) |
1754 | /* dubious comparison of enums, op %s */ | | 1754 | /* dubious comparison of enums, op %s */ |
1755 | warning(243, mp->m_name); | | 1755 | warning(243, mp->m_name); |
1756 | } | | 1756 | } |
1757 | } | | 1757 | } |
1758 | | | 1758 | |
1759 | /* Prints a warning if the operands mix between enum and integer. */ | | 1759 | /* Prints a warning if the operands mix between enum and integer. */ |
1760 | static void | | 1760 | static void |
1761 | check_enum_int_mismatch(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) | | 1761 | check_enum_int_mismatch(op_t op, int arg, const tnode_t *ln, const tnode_t *rn) |
1762 | { | | 1762 | { |
1763 | | | 1763 | |
1764 | if (!eflag) | | 1764 | if (!eflag) |
1765 | return; | | 1765 | return; |
1766 | | | 1766 | |
1767 | switch (op) { | | 1767 | switch (op) { |
1768 | case INIT: | | 1768 | case INIT: |
1769 | /* | | 1769 | /* |
1770 | * Initialization with 0 is allowed. Otherwise, all implicit | | 1770 | * Initialization with 0 is allowed. Otherwise, all implicit |
1771 | * initializations would need to be warned upon as well. | | 1771 | * initializations would need to be warned upon as well. |
1772 | */ | | 1772 | */ |
1773 | if (!rn->tn_type->t_is_enum && rn->tn_op == CON && | | 1773 | if (!rn->tn_type->t_is_enum && rn->tn_op == CON && |
1774 | is_integer(rn->tn_type->t_tspec) && | | 1774 | is_integer(rn->tn_type->t_tspec) && |
1775 | rn->tn_val->v_quad == 0) { | | 1775 | rn->tn_val->v_quad == 0) { |
1776 | return; | | 1776 | return; |
1777 | } | | 1777 | } |
1778 | /* initialization of '%s' with '%s' */ | | 1778 | /* initialization of '%s' with '%s' */ |
1779 | warning(277, type_name(ln->tn_type), type_name(rn->tn_type)); | | 1779 | warning(277, type_name(ln->tn_type), type_name(rn->tn_type)); |
1780 | break; | | 1780 | break; |
1781 | case FARG: | | 1781 | case FARG: |
1782 | /* combination of '%s' and '%s', arg #%d */ | | 1782 | /* combination of '%s' and '%s', arg #%d */ |
1783 | warning(278, | | 1783 | warning(278, |
1784 | type_name(ln->tn_type), type_name(rn->tn_type), arg); | | 1784 | type_name(ln->tn_type), type_name(rn->tn_type), arg); |
1785 | break; | | 1785 | break; |
1786 | case RETURN: | | 1786 | case RETURN: |
1787 | /* combination of '%s' and '%s' in return */ | | 1787 | /* combination of '%s' and '%s' in return */ |
1788 | warning(279, type_name(ln->tn_type), type_name(rn->tn_type)); | | 1788 | warning(279, type_name(ln->tn_type), type_name(rn->tn_type)); |
1789 | break; | | 1789 | break; |
1790 | default: | | 1790 | default: |
1791 | /* combination of '%s' and '%s', op %s */ | | 1791 | /* combination of '%s' and '%s', op %s */ |
1792 | warning(242, type_name(ln->tn_type), type_name(rn->tn_type), | | 1792 | warning(242, type_name(ln->tn_type), type_name(rn->tn_type), |
1793 | op_name(op)); | | 1793 | op_name(op)); |
1794 | break; | | 1794 | break; |
1795 | } | | 1795 | } |
1796 | } | | 1796 | } |
1797 | | | 1797 | |
1798 | /* | | 1798 | /* |
1799 | * Build and initialize a new node. | | 1799 | * Build and initialize a new node. |
1800 | */ | | 1800 | */ |
1801 | static tnode_t * | | 1801 | static tnode_t * |
1802 | new_tnode(op_t op, type_t *type, tnode_t *ln, tnode_t *rn) | | 1802 | new_tnode(op_t op, type_t *type, tnode_t *ln, tnode_t *rn) |
1803 | { | | 1803 | { |
1804 | tnode_t *ntn; | | 1804 | tnode_t *ntn; |
1805 | tspec_t t; | | 1805 | tspec_t t; |
1806 | #ifdef notyet | | 1806 | #ifdef notyet |
1807 | size_t l; | | 1807 | size_t l; |
1808 | uint64_t rnum; | | 1808 | uint64_t rnum; |
1809 | #endif | | 1809 | #endif |
1810 | | | 1810 | |
1811 | ntn = expr_zalloc_tnode(); | | 1811 | ntn = expr_zalloc_tnode(); |
1812 | | | 1812 | |
1813 | ntn->tn_op = op; | | 1813 | ntn->tn_op = op; |
1814 | ntn->tn_type = type; | | 1814 | ntn->tn_type = type; |
1815 | if (ln->tn_from_system_header) | | 1815 | if (ln->tn_from_system_header) |
1816 | ntn->tn_from_system_header = true; | | 1816 | ntn->tn_from_system_header = true; |
1817 | if (rn != NULL && rn->tn_from_system_header) | | 1817 | if (rn != NULL && rn->tn_from_system_header) |
1818 | ntn->tn_from_system_header = true; | | 1818 | ntn->tn_from_system_header = true; |
1819 | ntn->tn_left = ln; | | 1819 | ntn->tn_left = ln; |
1820 | ntn->tn_right = rn; | | 1820 | ntn->tn_right = rn; |
1821 | | | 1821 | |
1822 | switch (op) { | | 1822 | switch (op) { |
1823 | #ifdef notyet | | 1823 | #ifdef notyet |
1824 | case SHR: | | 1824 | case SHR: |
1825 | if (rn->tn_op != CON) | | 1825 | if (rn->tn_op != CON) |
1826 | break; | | 1826 | break; |
1827 | rnum = rn->tn_val->v_quad; | | 1827 | rnum = rn->tn_val->v_quad; |
1828 | l = type_size_in_bits(ln->tn_type) / CHAR_SIZE; | | 1828 | l = type_size_in_bits(ln->tn_type) / CHAR_SIZE; |
1829 | t = ln->tn_type->t_tspec; | | 1829 | t = ln->tn_type->t_tspec; |
1830 | switch (l) { | | 1830 | switch (l) { |
1831 | case 8: | | 1831 | case 8: |
1832 | if (rnum >= 56) | | 1832 | if (rnum >= 56) |
1833 | t = UCHAR; | | 1833 | t = UCHAR; |
1834 | else if (rnum >= 48) | | 1834 | else if (rnum >= 48) |
1835 | t = USHORT; | | 1835 | t = USHORT; |
1836 | else if (rnum >= 32) | | 1836 | else if (rnum >= 32) |
1837 | t = UINT; | | 1837 | t = UINT; |
1838 | break; | | 1838 | break; |
1839 | case 4: | | 1839 | case 4: |
1840 | if (rnum >= 24) | | 1840 | if (rnum >= 24) |
1841 | t = UCHAR; | | 1841 | t = UCHAR; |
1842 | else if (rnum >= 16) | | 1842 | else if (rnum >= 16) |
1843 | t = USHORT; | | 1843 | t = USHORT; |
1844 | break; | | 1844 | break; |
1845 | case 2: | | 1845 | case 2: |
1846 | if (rnum >= 8) | | 1846 | if (rnum >= 8) |
1847 | t = UCHAR; | | 1847 | t = UCHAR; |
1848 | break; | | 1848 | break; |
1849 | default: | | 1849 | default: |
1850 | break; | | 1850 | break; |
1851 | } | | 1851 | } |
1852 | if (t != ln->tn_type->t_tspec) | | 1852 | if (t != ln->tn_type->t_tspec) |
1853 | ntn->tn_type->t_tspec = t; | | 1853 | ntn->tn_type->t_tspec = t; |
1854 | break; | | 1854 | break; |
1855 | #endif | | 1855 | #endif |
1856 | case INDIR: | | 1856 | case INDIR: |
1857 | case FSEL: | | 1857 | case FSEL: |
1858 | lint_assert(ln->tn_type->t_tspec == PTR); | | 1858 | lint_assert(ln->tn_type->t_tspec == PTR); |
1859 | t = ln->tn_type->t_subt->t_tspec; | | 1859 | t = ln->tn_type->t_subt->t_tspec; |
1860 | if (t != FUNC && t != VOID) | | 1860 | if (t != FUNC && t != VOID) |
1861 | ntn->tn_lvalue = true; | | 1861 | ntn->tn_lvalue = true; |
1862 | break; | | 1862 | break; |
1863 | default: | | 1863 | default: |
1864 | break; | | 1864 | break; |
1865 | } | | 1865 | } |
1866 | | | 1866 | |
1867 | return ntn; | | 1867 | return ntn; |
1868 | } | | 1868 | } |
1869 | | | 1869 | |
1870 | /* | | 1870 | /* |
1871 | * Performs the "integer promotions" (C99 6.3.1.1p2), which convert small | | 1871 | * Performs the "integer promotions" (C99 6.3.1.1p2), which convert small |
1872 | * integer types to either int or unsigned int. | | 1872 | * integer types to either int or unsigned int. |
1873 | * | | 1873 | * |
1874 | * If tflag is set or the operand is a function argument with no type | | 1874 | * If tflag is set or the operand is a function argument with no type |
1875 | * information (no prototype or variable # of args), converts float to double. | | 1875 | * information (no prototype or variable # of args), converts float to double. |
1876 | */ | | 1876 | */ |
1877 | tnode_t * | | 1877 | tnode_t * |
1878 | promote(op_t op, bool farg, tnode_t *tn) | | 1878 | promote(op_t op, bool farg, tnode_t *tn) |
1879 | { | | 1879 | { |
1880 | tspec_t t; | | 1880 | tspec_t t; |
1881 | type_t *ntp; | | 1881 | type_t *ntp; |
1882 | u_int len; | | 1882 | u_int len; |
1883 | | | 1883 | |
1884 | t = tn->tn_type->t_tspec; | | 1884 | t = tn->tn_type->t_tspec; |
1885 | | | 1885 | |
1886 | if (!is_arithmetic(t)) | | 1886 | if (!is_arithmetic(t)) |
1887 | return tn; | | 1887 | return tn; |
1888 | | | 1888 | |
1889 | if (!tflag) { | | 1889 | if (!tflag) { |
1890 | /* | | 1890 | /* |
1891 | * ANSI C requires that the result is always of type INT | | 1891 | * ANSI C requires that the result is always of type INT |
1892 | * if INT can represent all possible values of the previous | | 1892 | * if INT can represent all possible values of the previous |
1893 | * type. | | 1893 | * type. |
1894 | */ | | 1894 | */ |
1895 | if (tn->tn_type->t_bitfield) { | | 1895 | if (tn->tn_type->t_bitfield) { |
1896 | len = tn->tn_type->t_flen; | | 1896 | len = tn->tn_type->t_flen; |
1897 | if (size_in_bits(INT) > len) { | | 1897 | if (size_in_bits(INT) > len) { |
1898 | t = INT; | | 1898 | t = INT; |
1899 | } else { | | 1899 | } else { |
1900 | lint_assert(len == size_in_bits(INT)); | | 1900 | lint_assert(len == size_in_bits(INT)); |
1901 | if (is_uinteger(t)) { | | 1901 | if (is_uinteger(t)) { |
1902 | t = UINT; | | 1902 | t = UINT; |
1903 | } else { | | 1903 | } else { |
1904 | t = INT; | | 1904 | t = INT; |
1905 | } | | 1905 | } |
1906 | } | | 1906 | } |
1907 | } else if (t == CHAR || t == UCHAR || t == SCHAR) { | | 1907 | } else if (t == CHAR || t == UCHAR || t == SCHAR) { |
1908 | t = (size_in_bits(CHAR) < size_in_bits(INT) | | 1908 | t = (size_in_bits(CHAR) < size_in_bits(INT) |
1909 | || t != UCHAR) ? INT : UINT; | | 1909 | || t != UCHAR) ? INT : UINT; |
1910 | } else if (t == SHORT || t == USHORT) { | | 1910 | } else if (t == SHORT || t == USHORT) { |
1911 | t = (size_in_bits(SHORT) < size_in_bits(INT) | | 1911 | t = (size_in_bits(SHORT) < size_in_bits(INT) |
1912 | || t == SHORT) ? INT : UINT; | | 1912 | || t == SHORT) ? INT : UINT; |
1913 | } else if (t == ENUM) { | | 1913 | } else if (t == ENUM) { |
1914 | t = INT; | | 1914 | t = INT; |
1915 | } else if (farg && t == FLOAT) { | | 1915 | } else if (farg && t == FLOAT) { |
1916 | t = DOUBLE; | | 1916 | t = DOUBLE; |
1917 | } | | 1917 | } |
1918 | } else { | | 1918 | } else { |
1919 | /* | | 1919 | /* |
1920 | * In traditional C, keep unsigned and promote FLOAT | | 1920 | * In traditional C, keep unsigned and promote FLOAT |
1921 | * to DOUBLE. | | 1921 | * to DOUBLE. |
1922 | */ | | 1922 | */ |
1923 | if (t == UCHAR || t == USHORT) { | | 1923 | if (t == UCHAR || t == USHORT) { |
1924 | t = UINT; | | 1924 | t = UINT; |
1925 | } else if (t == CHAR || t == SCHAR || t == SHORT) { | | 1925 | } else if (t == CHAR || t == SCHAR || t == SHORT) { |
1926 | t = INT; | | 1926 | t = INT; |
1927 | } else if (t == FLOAT) { | | 1927 | } else if (t == FLOAT) { |
1928 | t = DOUBLE; | | 1928 | t = DOUBLE; |
1929 | } else if (t == ENUM) { | | 1929 | } else if (t == ENUM) { |
1930 | t = INT; | | 1930 | t = INT; |
1931 | } | | 1931 | } |
1932 | } | | 1932 | } |
1933 | | | 1933 | |
1934 | if (t != tn->tn_type->t_tspec) { | | 1934 | if (t != tn->tn_type->t_tspec) { |
1935 | ntp = expr_dup_type(tn->tn_type); | | 1935 | ntp = expr_dup_type(tn->tn_type); |
1936 | ntp->t_tspec = t; | | 1936 | ntp->t_tspec = t; |
1937 | /* | | 1937 | /* |
1938 | * Keep t_is_enum so we are later able to check compatibility | | 1938 | * Keep t_is_enum so we are later able to check compatibility |
1939 | * of enum types. | | 1939 | * of enum types. |
1940 | */ | | 1940 | */ |
1941 | tn = convert(op, 0, ntp, tn); | | 1941 | tn = convert(op, 0, ntp, tn); |
1942 | } | | 1942 | } |
1943 | | | 1943 | |
1944 | return tn; | | 1944 | return tn; |
1945 | } | | 1945 | } |
1946 | | | 1946 | |
1947 | /* | | 1947 | /* |
1948 | * Apply the "usual arithmetic conversions" (C99 6.3.1.8). | | 1948 | * Apply the "usual arithmetic conversions" (C99 6.3.1.8). |
1949 | * | | 1949 | * |
1950 | * This gives both operands the same type. | | 1950 | * This gives both operands the same type. |
1951 | * This is done in different ways for traditional C and C90. | | 1951 | * This is done in different ways for traditional C and C90. |
1952 | */ | | 1952 | */ |
1953 | static void | | 1953 | static void |
1954 | balance(op_t op, tnode_t **lnp, tnode_t **rnp) | | 1954 | balance(op_t op, tnode_t **lnp, tnode_t **rnp) |
1955 | { | | 1955 | { |
1956 | tspec_t lt, rt, t; | | 1956 | tspec_t lt, rt, t; |
1957 | int i; | | 1957 | int i; |
1958 | bool u; | | 1958 | bool u; |
1959 | type_t *ntp; | | 1959 | type_t *ntp; |
1960 | static const tspec_t tl[] = { | | 1960 | static const tspec_t tl[] = { |
1961 | LDOUBLE, DOUBLE, FLOAT, UQUAD, QUAD, ULONG, LONG, UINT, INT, | | 1961 | LDOUBLE, DOUBLE, FLOAT, UQUAD, QUAD, ULONG, LONG, UINT, INT, |
1962 | }; | | 1962 | }; |
1963 | | | 1963 | |
1964 | lt = (*lnp)->tn_type->t_tspec; | | 1964 | lt = (*lnp)->tn_type->t_tspec; |
1965 | rt = (*rnp)->tn_type->t_tspec; | | 1965 | rt = (*rnp)->tn_type->t_tspec; |
1966 | | | 1966 | |
1967 | if (!is_arithmetic(lt) || !is_arithmetic(rt)) | | 1967 | if (!is_arithmetic(lt) || !is_arithmetic(rt)) |
1968 | return; | | 1968 | return; |
1969 | | | 1969 | |
1970 | if (!tflag) { | | 1970 | if (!tflag) { |
1971 | if (lt == rt) { | | 1971 | if (lt == rt) { |
1972 | t = lt; | | 1972 | t = lt; |
1973 | } else if (lt == LCOMPLEX || rt == LCOMPLEX) { | | 1973 | } else if (lt == LCOMPLEX || rt == LCOMPLEX) { |
1974 | t = LCOMPLEX; | | 1974 | t = LCOMPLEX; |
1975 | } else if (lt == DCOMPLEX || rt == DCOMPLEX) { | | 1975 | } else if (lt == DCOMPLEX || rt == DCOMPLEX) { |
1976 | t = DCOMPLEX; | | 1976 | t = DCOMPLEX; |
1977 | } else if (lt == COMPLEX || rt == COMPLEX) { | | 1977 | } else if (lt == COMPLEX || rt == COMPLEX) { |
1978 | t = COMPLEX; | | 1978 | t = COMPLEX; |
1979 | } else if (lt == FCOMPLEX || rt == FCOMPLEX) { | | 1979 | } else if (lt == FCOMPLEX || rt == FCOMPLEX) { |
1980 | t = FCOMPLEX; | | 1980 | t = FCOMPLEX; |
1981 | } else if (lt == LDOUBLE || rt == LDOUBLE) { | | 1981 | } else if (lt == LDOUBLE || rt == LDOUBLE) { |
1982 | t = LDOUBLE; | | 1982 | t = LDOUBLE; |
1983 | } else if (lt == DOUBLE || rt == DOUBLE) { | | 1983 | } else if (lt == DOUBLE || rt == DOUBLE) { |
1984 | t = DOUBLE; | | 1984 | t = DOUBLE; |
1985 | } else if (lt == FLOAT || rt == FLOAT) { | | 1985 | } else if (lt == FLOAT || rt == FLOAT) { |
1986 | t = FLOAT; | | 1986 | t = FLOAT; |
1987 | } else { | | 1987 | } else { |
1988 | /* | | 1988 | /* |
1989 | * If type A has more bits than type B it should | | 1989 | * If type A has more bits than type B it should |
1990 | * be able to hold all possible values of type B. | | 1990 | * be able to hold all possible values of type B. |
1991 | */ | | 1991 | */ |
1992 | if (size_in_bits(lt) > size_in_bits(rt)) { | | 1992 | if (size_in_bits(lt) > size_in_bits(rt)) { |
1993 | t = lt; | | 1993 | t = lt; |
1994 | } else if (size_in_bits(lt) < size_in_bits(rt)) { | | 1994 | } else if (size_in_bits(lt) < size_in_bits(rt)) { |
1995 | t = rt; | | 1995 | t = rt; |
1996 | } else { | | 1996 | } else { |
1997 | for (i = 3; tl[i] != INT; i++) { | | 1997 | for (i = 3; tl[i] != INT; i++) { |
1998 | if (tl[i] == lt || tl[i] == rt) | | 1998 | if (tl[i] == lt || tl[i] == rt) |
1999 | break; | | 1999 | break; |
2000 | } | | 2000 | } |
2001 | if ((is_uinteger(lt) || is_uinteger(rt)) && | | 2001 | if ((is_uinteger(lt) || is_uinteger(rt)) && |
2002 | !is_uinteger(tl[i])) { | | 2002 | !is_uinteger(tl[i])) { |
2003 | i--; | | 2003 | i--; |
2004 | } | | 2004 | } |
2005 | t = tl[i]; | | 2005 | t = tl[i]; |
2006 | } | | 2006 | } |
2007 | } | | 2007 | } |
2008 | } else { | | 2008 | } else { |
2009 | /* Keep unsigned in traditional C */ | | 2009 | /* Keep unsigned in traditional C */ |
2010 | u = is_uinteger(lt) || is_uinteger(rt); | | 2010 | u = is_uinteger(lt) || is_uinteger(rt); |
2011 | for (i = 0; tl[i] != INT; i++) { | | 2011 | for (i = 0; tl[i] != INT; i++) { |
2012 | if (lt == tl[i] || rt == tl[i]) | | 2012 | if (lt == tl[i] || rt == tl[i]) |
2013 | break; | | 2013 | break; |
2014 | } | | 2014 | } |
2015 | t = tl[i]; | | 2015 | t = tl[i]; |
2016 | if (u && is_integer(t) && !is_uinteger(t)) | | 2016 | if (u && is_integer(t) && !is_uinteger(t)) |
2017 | t = unsigned_type(t); | | 2017 | t = unsigned_type(t); |
2018 | } | | 2018 | } |
2019 | | | 2019 | |
2020 | if (t != lt) { | | 2020 | if (t != lt) { |
2021 | ntp = expr_dup_type((*lnp)->tn_type); | | 2021 | ntp = expr_dup_type((*lnp)->tn_type); |
2022 | ntp->t_tspec = t; | | 2022 | ntp->t_tspec = t; |
2023 | *lnp = convert(op, 0, ntp, *lnp); | | 2023 | *lnp = convert(op, 0, ntp, *lnp); |
2024 | } | | 2024 | } |
2025 | if (t != rt) { | | 2025 | if (t != rt) { |
2026 | ntp = expr_dup_type((*rnp)->tn_type); | | 2026 | ntp = expr_dup_type((*rnp)->tn_type); |
2027 | ntp->t_tspec = t; | | 2027 | ntp->t_tspec = t; |
2028 | *rnp = convert(op, 0, ntp, *rnp); | | 2028 | *rnp = convert(op, 0, ntp, *rnp); |
2029 | } | | 2029 | } |
2030 | } | | 2030 | } |
2031 | | | 2031 | |
2032 | /* | | 2032 | /* |
2033 | * Insert a conversion operator, which converts the type of the node | | 2033 | * Insert a conversion operator, which converts the type of the node |
2034 | * to another given type. | | 2034 | * to another given type. |
2035 | * If op is FARG, arg is the number of the argument (used for warnings). | | 2035 | * If op is FARG, arg is the number of the argument (used for warnings). |
2036 | */ | | 2036 | */ |
2037 | tnode_t * | | 2037 | tnode_t * |
2038 | convert(op_t op, int arg, type_t *tp, tnode_t *tn) | | 2038 | convert(op_t op, int arg, type_t *tp, tnode_t *tn) |
2039 | { | | 2039 | { |
2040 | tnode_t *ntn; | | 2040 | tnode_t *ntn; |
2041 | tspec_t nt, ot; | | 2041 | tspec_t nt, ot; |
2042 | | | 2042 | |
2043 | nt = tp->t_tspec; | | 2043 | nt = tp->t_tspec; |
2044 | ot = tn->tn_type->t_tspec; | | 2044 | ot = tn->tn_type->t_tspec; |
2045 | | | 2045 | |
2046 | if (!tflag && !sflag && op == FARG) | | 2046 | if (!tflag && !sflag && op == FARG) |
2047 | check_prototype_conversion(arg, nt, ot, tp, tn); | | 2047 | check_prototype_conversion(arg, nt, ot, tp, tn); |
2048 | if (is_integer(nt) && is_integer(ot)) { | | 2048 | if (is_integer(nt) && is_integer(ot)) { |
2049 | check_integer_conversion(op, arg, nt, ot, tp, tn); | | 2049 | check_integer_conversion(op, arg, nt, ot, tp, tn); |
2050 | } else if (nt == PTR && is_null_pointer(tn)) { | | 2050 | } else if (nt == PTR && is_null_pointer(tn)) { |
2051 | /* a null pointer may be assigned to any pointer. */ | | 2051 | /* a null pointer may be assigned to any pointer. */ |
2052 | } else if (is_integer(nt) && nt != BOOL && ot == PTR) { | | 2052 | } else if (is_integer(nt) && nt != BOOL && ot == PTR) { |
2053 | check_pointer_integer_conversion(op, nt, tp, tn); | | 2053 | check_pointer_integer_conversion(op, nt, tp, tn); |
2054 | } else if (nt == PTR && ot == PTR) { | | 2054 | } else if (nt == PTR && ot == PTR) { |
2055 | check_pointer_conversion(op, tn, tp); | | 2055 | check_pointer_conversion(op, tn, tp); |
2056 | } | | 2056 | } |
2057 | | | 2057 | |
2058 | ntn = expr_zalloc_tnode(); | | 2058 | ntn = expr_zalloc_tnode(); |
2059 | ntn->tn_op = CVT; | | 2059 | ntn->tn_op = CVT; |
2060 | ntn->tn_type = tp; | | 2060 | ntn->tn_type = tp; |
2061 | ntn->tn_cast = op == CVT; | | 2061 | ntn->tn_cast = op == CVT; |
2062 | ntn->tn_from_system_header |= tn->tn_from_system_header; | | 2062 | ntn->tn_from_system_header |= tn->tn_from_system_header; |
2063 | ntn->tn_right = NULL; | | 2063 | ntn->tn_right = NULL; |
2064 | if (tn->tn_op != CON || nt == VOID) { | | 2064 | if (tn->tn_op != CON || nt == VOID) { |
2065 | ntn->tn_left = tn; | | 2065 | ntn->tn_left = tn; |
2066 | } else { | | 2066 | } else { |
2067 | ntn->tn_op = CON; | | 2067 | ntn->tn_op = CON; |
2068 | ntn->tn_val = expr_zalloc(sizeof(*ntn->tn_val)); | | 2068 | ntn->tn_val = expr_zalloc(sizeof(*ntn->tn_val)); |
2069 | convert_constant(op, arg, ntn->tn_type, ntn->tn_val, | | 2069 | convert_constant(op, arg, ntn->tn_type, ntn->tn_val, |
2070 | tn->tn_val); | | 2070 | tn->tn_val); |
2071 | } | | 2071 | } |
2072 | | | 2072 | |
2073 | return ntn; | | 2073 | return ntn; |
2074 | } | | 2074 | } |
2075 | | | 2075 | |
2076 | /* | | 2076 | /* |
2077 | * Print a warning if a prototype causes a type conversion that is | | 2077 | * Print a warning if a prototype causes a type conversion that is |
2078 | * different from what would happen to the same argument in the | | 2078 | * different from what would happen to the same argument in the |
2079 | * absence of a prototype. | | 2079 | * absence of a prototype. |
2080 | * | | 2080 | * |
2081 | * Errors/warnings about illegal type combinations are already printed | | 2081 | * Errors/warnings about illegal type combinations are already printed |
2082 | * in check_assign_types_compatible(). | | 2082 | * in check_assign_types_compatible(). |
2083 | */ | | 2083 | */ |
2084 | static void | | 2084 | static void |
2085 | check_prototype_conversion(int arg, tspec_t nt, tspec_t ot, type_t *tp, | | 2085 | check_prototype_conversion(int arg, tspec_t nt, tspec_t ot, type_t *tp, |
2086 | tnode_t *tn) | | 2086 | tnode_t *tn) |
2087 | { | | 2087 | { |
2088 | tnode_t *ptn; | | 2088 | tnode_t *ptn; |
2089 | | | 2089 | |
2090 | if (!is_arithmetic(nt) || !is_arithmetic(ot)) | | 2090 | if (!is_arithmetic(nt) || !is_arithmetic(ot)) |
2091 | return; | | 2091 | return; |
2092 | | | 2092 | |
2093 | /* | | 2093 | /* |
2094 | * If the type of the formal parameter is char/short, a warning | | 2094 | * If the type of the formal parameter is char/short, a warning |
2095 | * would be useless, because functions declared the old style | | 2095 | * would be useless, because functions declared the old style |
2096 | * can't expect char/short arguments. | | 2096 | * can't expect char/short arguments. |
2097 | */ | | 2097 | */ |
2098 | /* XXX: what about SCHAR? */ | | 2098 | /* XXX: what about SCHAR? */ |
2099 | if (nt == CHAR || nt == UCHAR || nt == SHORT || nt == USHORT) | | 2099 | if (nt == CHAR || nt == UCHAR || nt == SHORT || nt == USHORT) |
2100 | return; | | 2100 | return; |
2101 | | | 2101 | |
2102 | /* get default promotion */ | | 2102 | /* get default promotion */ |
2103 | ptn = promote(NOOP, true, tn); | | 2103 | ptn = promote(NOOP, true, tn); |
2104 | ot = ptn->tn_type->t_tspec; | | 2104 | ot = ptn->tn_type->t_tspec; |
2105 | | | 2105 | |
2106 | /* return if types are the same with and without prototype */ | | 2106 | /* return if types are the same with and without prototype */ |
2107 | if (nt == ot || (nt == ENUM && ot == INT)) | | 2107 | if (nt == ot || (nt == ENUM && ot == INT)) |
2108 | return; | | 2108 | return; |
2109 | | | 2109 | |
2110 | if (is_floating(nt) != is_floating(ot) || | | 2110 | if (is_floating(nt) != is_floating(ot) || |
2111 | portable_size_in_bits(nt) != portable_size_in_bits(ot)) { | | 2111 | portable_size_in_bits(nt) != portable_size_in_bits(ot)) { |
2112 | /* representation and/or width change */ | | 2112 | /* representation and/or width change */ |
2113 | if (!is_integer(ot) || | | 2113 | if (!is_integer(ot) || |
2114 | portable_size_in_bits(ot) > portable_size_in_bits(INT)) { | | 2114 | portable_size_in_bits(ot) > portable_size_in_bits(INT)) { |
2115 | /* argument #%d is converted from '%s' to '%s' ... */ | | 2115 | /* argument #%d is converted from '%s' to '%s' ... */ |
2116 | warning(259, | | 2116 | warning(259, |
2117 | arg, type_name(tn->tn_type), type_name(tp)); | | 2117 | arg, type_name(tn->tn_type), type_name(tp)); |
2118 | } | | 2118 | } |
2119 | } else if (hflag) { | | 2119 | } else if (hflag) { |
2120 | /* | | 2120 | /* |
2121 | * they differ in sign or base type (char, short, int, | | 2121 | * they differ in sign or base type (char, short, int, |
2122 | * long, long long, float, double, long double) | | 2122 | * long, long long, float, double, long double) |
2123 | * | | 2123 | * |
2124 | * if they differ only in sign and the argument is a constant | | 2124 | * if they differ only in sign and the argument is a constant |
2125 | * and the msb of the argument is not set, print no warning | | 2125 | * and the msb of the argument is not set, print no warning |
2126 | */ | | 2126 | */ |
2127 | if (ptn->tn_op == CON && is_integer(nt) && | | 2127 | if (ptn->tn_op == CON && is_integer(nt) && |
2128 | signed_type(nt) == signed_type(ot) && | | 2128 | signed_type(nt) == signed_type(ot) && |
2129 | msb(ptn->tn_val->v_quad, ot, -1) == 0) { | | 2129 | msb(ptn->tn_val->v_quad, ot, -1) == 0) { |
2130 | /* ok */ | | 2130 | /* ok */ |
2131 | } else { | | 2131 | } else { |
2132 | /* argument #%d is converted from '%s' to '%s' ... */ | | 2132 | /* argument #%d is converted from '%s' to '%s' ... */ |
2133 | warning(259, | | 2133 | warning(259, |
2134 | arg, type_name(tn->tn_type), type_name(tp)); | | 2134 | arg, type_name(tn->tn_type), type_name(tp)); |
2135 | } | | 2135 | } |
2136 | } | | 2136 | } |
2137 | } | | 2137 | } |
2138 | | | 2138 | |
2139 | /* | | 2139 | /* |
2140 | * Print warnings for conversions of integer types which may cause problems. | | 2140 | * Print warnings for conversions of integer types which may cause problems. |
2141 | */ | | 2141 | */ |
2142 | /* ARGSUSED */ | | 2142 | /* ARGSUSED */ |
2143 | static void | | 2143 | static void |
2144 | check_integer_conversion(op_t op, int arg, tspec_t nt, tspec_t ot, type_t *tp, | | 2144 | check_integer_conversion(op_t op, int arg, tspec_t nt, tspec_t ot, type_t *tp, |
2145 | tnode_t *tn) | | 2145 | tnode_t *tn) |
2146 | { | | 2146 | { |
2147 | char opbuf[16]; | | 2147 | char opbuf[16]; |
2148 | | | 2148 | |
2149 | if (tn->tn_op == CON) | | 2149 | if (tn->tn_op == CON) |
2150 | return; | | 2150 | return; |
2151 | | | 2151 | |
2152 | if (op == CVT) | | 2152 | if (op == CVT) |
2153 | return; | | 2153 | return; |
2154 | | | 2154 | |
2155 | if (Pflag && portable_size_in_bits(nt) > portable_size_in_bits(ot) && | | 2155 | if (Pflag && portable_size_in_bits(nt) > portable_size_in_bits(ot) && |
2156 | is_uinteger(nt) != is_uinteger(ot)) { | | 2156 | is_uinteger(nt) != is_uinteger(ot)) { |
2157 | if (aflag > 0 && pflag) { | | 2157 | if (aflag > 0 && pflag) { |
2158 | if (op == FARG) { | | 2158 | if (op == FARG) { |
2159 | /* conversion to '%s' may sign-extend ... */ | | 2159 | /* conversion to '%s' may sign-extend ... */ |
2160 | warning(297, type_name(tp), arg); | | 2160 | warning(297, type_name(tp), arg); |
2161 | } else { | | 2161 | } else { |
2162 | /* conversion to '%s' may sign-extend ... */ | | 2162 | /* conversion to '%s' may sign-extend ... */ |
2163 | warning(131, type_name(tp)); | | 2163 | warning(131, type_name(tp)); |
2164 | } | | 2164 | } |
2165 | } | | 2165 | } |
2166 | } | | 2166 | } |
2167 | | | 2167 | |
2168 | if (Pflag && portable_size_in_bits(nt) > portable_size_in_bits(ot)) { | | 2168 | if (Pflag && portable_size_in_bits(nt) > portable_size_in_bits(ot)) { |
2169 | switch (tn->tn_op) { | | 2169 | switch (tn->tn_op) { |
2170 | case PLUS: | | 2170 | case PLUS: |
2171 | case MINUS: | | 2171 | case MINUS: |
2172 | case MULT: | | 2172 | case MULT: |
2173 | case SHL: | | 2173 | case SHL: |
2174 | /* suggest cast from '%s' to '%s' on op %s to ... */ | | 2174 | /* suggest cast from '%s' to '%s' on op %s to ... */ |
2175 | warning(324, type_name(gettyp(ot)), type_name(tp), | | 2175 | warning(324, type_name(gettyp(ot)), type_name(tp), |
2176 | print_tnode(opbuf, sizeof(opbuf), tn)); | | 2176 | print_tnode(opbuf, sizeof(opbuf), tn)); |
2177 | break; | | 2177 | break; |
2178 | default: | | 2178 | default: |
2179 | break; | | 2179 | break; |
2180 | } | | 2180 | } |
2181 | } | | 2181 | } |
2182 | | | 2182 | |
2183 | if (portable_size_in_bits(nt) < portable_size_in_bits(ot) && | | 2183 | if (portable_size_in_bits(nt) < portable_size_in_bits(ot) && |
2184 | (ot == LONG || ot == ULONG || ot == QUAD || ot == UQUAD || | | 2184 | (ot == LONG || ot == ULONG || ot == QUAD || ot == UQUAD || |
2185 | aflag > 1)) { | | 2185 | aflag > 1)) { |
2186 | /* conversion from '%s' may lose accuracy */ | | 2186 | /* conversion from '%s' may lose accuracy */ |
2187 | if (aflag > 0) { | | 2187 | if (aflag > 0) { |
2188 | if (op == FARG) { | | 2188 | if (op == FARG) { |
2189 | /* conv. from '%s' to '%s' may lose ... */ | | 2189 | /* conv. from '%s' to '%s' may lose ... */ |
2190 | warning(298, | | 2190 | warning(298, |
2191 | type_name(tn->tn_type), type_name(tp), arg); | | 2191 | type_name(tn->tn_type), type_name(tp), arg); |
2192 | } else { | | 2192 | } else { |
2193 | /* conv. from '%s' to '%s' may lose accuracy */ | | 2193 | /* conv. from '%s' to '%s' may lose accuracy */ |
2194 | warning(132, | | 2194 | warning(132, |
2195 | type_name(tn->tn_type), type_name(tp)); | | 2195 | type_name(tn->tn_type), type_name(tp)); |
2196 | } | | 2196 | } |
2197 | } | | 2197 | } |
2198 | } | | 2198 | } |
2199 | } | | 2199 | } |
2200 | | | 2200 | |
2201 | /* | | 2201 | /* |
2202 | * Print warnings for dubious conversions of pointer to integer. | | 2202 | * Print warnings for dubious conversions of pointer to integer. |
2203 | */ | | 2203 | */ |
2204 | static void | | 2204 | static void |
2205 | check_pointer_integer_conversion(op_t op, tspec_t nt, type_t *tp, tnode_t *tn) | | 2205 | check_pointer_integer_conversion(op_t op, tspec_t nt, type_t *tp, tnode_t *tn) |
2206 | { | | 2206 | { |
2207 | | | 2207 | |
2208 | if (tn->tn_op == CON) | | 2208 | if (tn->tn_op == CON) |
2209 | return; | | 2209 | return; |
2210 | if (op != CVT) | | 2210 | if (op != CVT) |
2211 | return; /* We got already an error. */ | | 2211 | return; /* We got already an error. */ |
2212 | if (portable_size_in_bits(nt) >= portable_size_in_bits(PTR)) | | 2212 | if (portable_size_in_bits(nt) >= portable_size_in_bits(PTR)) |
2213 | return; | | 2213 | return; |
2214 | | | 2214 | |
2215 | if (pflag && size_in_bits(nt) >= size_in_bits(PTR)) { | | 2215 | if (pflag && size_in_bits(nt) >= size_in_bits(PTR)) { |
2216 | /* conversion of pointer to '%s' may lose bits */ | | 2216 | /* conversion of pointer to '%s' may lose bits */ |
2217 | warning(134, type_name(tp)); | | 2217 | warning(134, type_name(tp)); |
2218 | } else { | | 2218 | } else { |
2219 | /* conversion of pointer to '%s' loses bits */ | | 2219 | /* conversion of pointer to '%s' loses bits */ |
2220 | warning(133, type_name(tp)); | | 2220 | warning(133, type_name(tp)); |
2221 | } | | 2221 | } |
2222 | } | | 2222 | } |
2223 | | | 2223 | |
2224 | static bool | | 2224 | static bool |
2225 | should_warn_about_pointer_cast(const type_t *tp, tspec_t nst, | | 2225 | should_warn_about_pointer_cast(const type_t *tp, tspec_t nst, |
2226 | const tnode_t *tn, tspec_t ost) | | 2226 | const tnode_t *tn, tspec_t ost) |
2227 | { | | 2227 | { |
2228 | if (nst == STRUCT || nst == UNION) | | 2228 | if (nst == STRUCT || nst == UNION) |
2229 | if (tp->t_subt->t_str != tn->tn_type->t_subt->t_str) | | 2229 | if (tp->t_subt->t_str != tn->tn_type->t_subt->t_str) |
2230 | return true; | | 2230 | return true; |
2231 | | | 2231 | |
2232 | if (nst == CHAR || nst == UCHAR) | | 2232 | if (nst == CHAR || nst == UCHAR) |
2233 | return false; /* for the sake of traditional C code */ | | 2233 | return false; /* for the sake of traditional C code */ |
2234 | | | 2234 | |
2235 | return portable_size_in_bits(nst) != portable_size_in_bits(ost); | | 2235 | return portable_size_in_bits(nst) != portable_size_in_bits(ost); |
2236 | } | | 2236 | } |
2237 | | | 2237 | |
2238 | /* | | 2238 | /* |
2239 | * Warn about questionable pointer conversions. | | 2239 | * Warn about questionable pointer conversions. |
2240 | */ | | 2240 | */ |
2241 | static void | | 2241 | static void |
2242 | check_pointer_conversion(op_t op, tnode_t *tn, type_t *tp) | | 2242 | check_pointer_conversion(op_t op, tnode_t *tn, type_t *tp) |
2243 | { | | 2243 | { |
2244 | tspec_t nst, ost; | | 2244 | tspec_t nst, ost; |
2245 | const char *nts, *ots; | | 2245 | const char *nts, *ots; |
2246 | | | 2246 | |
2247 | /* | | 2247 | /* |
2248 | * We got already an error (pointers of different types | | 2248 | * We got already an error (pointers of different types |
2249 | * without a cast) or we will not get a warning. | | 2249 | * without a cast) or we will not get a warning. |
2250 | */ | | 2250 | */ |
2251 | if (op != CVT) | | 2251 | if (op != CVT) |
2252 | return; | | 2252 | return; |
2253 | | | 2253 | |
2254 | nst = tp->t_subt->t_tspec; | | 2254 | nst = tp->t_subt->t_tspec; |
2255 | ost = tn->tn_type->t_subt->t_tspec; | | 2255 | ost = tn->tn_type->t_subt->t_tspec; |
2256 | | | 2256 | |
2257 | if (nst == VOID || ost == VOID) { | | 2257 | if (nst == VOID || ost == VOID) { |
2258 | if (sflag && (nst == FUNC || ost == FUNC)) { | | 2258 | if (sflag && (nst == FUNC || ost == FUNC)) { |
2259 | /* null pointers are already handled in convert() */ | | 2259 | /* null pointers are already handled in convert() */ |
2260 | *(nst == FUNC ? &nts : &ots) = "function pointer"; | | 2260 | *(nst == FUNC ? &nts : &ots) = "function pointer"; |
2261 | *(nst == VOID ? &nts : &ots) = "'void *'"; | | 2261 | *(nst == VOID ? &nts : &ots) = "'void *'"; |
2262 | /* ANSI C forbids conversion of %s to %s */ | | 2262 | /* ANSI C forbids conversion of %s to %s */ |
2263 | warning(303, ots, nts); | | 2263 | warning(303, ots, nts); |
2264 | } | | 2264 | } |
2265 | return; | | 2265 | return; |
2266 | } else if (nst == FUNC && ost == FUNC) { | | 2266 | } else if (nst == FUNC && ost == FUNC) { |
2267 | return; | | 2267 | return; |
2268 | } else if (nst == FUNC || ost == FUNC) { | | 2268 | } else if (nst == FUNC || ost == FUNC) { |
2269 | /* converting '%s' to '%s' is questionable */ | | 2269 | /* converting '%s' to '%s' is questionable */ |
2270 | warning(229, type_name(tn->tn_type), type_name(tp)); | | 2270 | warning(229, type_name(tn->tn_type), type_name(tp)); |
2271 | return; | | 2271 | return; |
2272 | } | | 2272 | } |
2273 | | | 2273 | |
2274 | if (hflag && alignment_in_bits(tp->t_subt) > | | 2274 | if (hflag && alignment_in_bits(tp->t_subt) > |
2275 | alignment_in_bits(tn->tn_type->t_subt)) { | | 2275 | alignment_in_bits(tn->tn_type->t_subt)) { |
2276 | /* converting '%s' to '%s' may cause alignment problem */ | | 2276 | /* converting '%s' to '%s' may cause alignment problem */ |
2277 | warning(135, type_name(tn->tn_type), type_name(tp)); | | 2277 | warning(135, type_name(tn->tn_type), type_name(tp)); |
2278 | } | | 2278 | } |
2279 | | | 2279 | |
2280 | if (cflag && should_warn_about_pointer_cast(tp, nst, tn, ost)) { | | 2280 | if (cflag && should_warn_about_pointer_cast(tp, nst, tn, ost)) { |
2281 | /* pointer cast from '%s' to '%s' may be troublesome */ | | 2281 | /* pointer cast from '%s' to '%s' may be troublesome */ |
2282 | warning(247, type_name(tn->tn_type), type_name(tp)); | | 2282 | warning(247, type_name(tn->tn_type), type_name(tp)); |
2283 | } | | 2283 | } |
2284 | } | | 2284 | } |
2285 | | | 2285 | |
2286 | /* | | 2286 | /* |
2287 | * Converts a typed constant to a constant of another type. | | 2287 | * Converts a typed constant to a constant of another type. |
2288 | * | | 2288 | * |
2289 | * op operator which requires conversion | | 2289 | * op operator which requires conversion |
2290 | * arg if op is FARG, # of argument | | 2290 | * arg if op is FARG, # of argument |
2291 | * tp type in which to convert the constant | | 2291 | * tp type in which to convert the constant |
2292 | * nv new constant | | 2292 | * nv new constant |
2293 | * v old constant | | 2293 | * v old constant |
2294 | */ | | 2294 | */ |
2295 | void | | 2295 | void |
2296 | convert_constant(op_t op, int arg, const type_t *tp, val_t *nv, val_t *v) | | 2296 | convert_constant(op_t op, int arg, const type_t *tp, val_t *nv, val_t *v) |
2297 | { | | 2297 | { |
2298 | tspec_t ot, nt; | | 2298 | tspec_t ot, nt; |
2299 | ldbl_t max = 0.0, min = 0.0; | | 2299 | ldbl_t max = 0.0, min = 0.0; |
2300 | int sz; | | 2300 | int sz; |
2301 | bool rchk; | | 2301 | bool rchk; |
2302 | int64_t xmask, xmsk1; | | 2302 | int64_t xmask, xmsk1; |
2303 | int osz, nsz; | | 2303 | int osz, nsz; |
2304 | | | 2304 | |
2305 | ot = v->v_tspec; | | 2305 | ot = v->v_tspec; |
2306 | nt = nv->v_tspec = tp->t_tspec; | | 2306 | nt = nv->v_tspec = tp->t_tspec; |
2307 | rchk = false; | | 2307 | rchk = false; |
2308 | | | 2308 | |
2309 | if (nt == BOOL) { /* C99 6.3.1.2 */ | | 2309 | if (nt == BOOL) { /* C99 6.3.1.2 */ |
2310 | nv->v_ansiu = false; | | 2310 | nv->v_ansiu = false; |
2311 | nv->v_quad = is_nonzero_val(v) ? 1 : 0; | | 2311 | nv->v_quad = is_nonzero_val(v) ? 1 : 0; |
2312 | return; | | 2312 | return; |
2313 | } | | 2313 | } |
2314 | | | 2314 | |
2315 | if (ot == FLOAT || ot == DOUBLE || ot == LDOUBLE) { | | 2315 | if (ot == FLOAT || ot == DOUBLE || ot == LDOUBLE) { |
2316 | switch (nt) { | | 2316 | switch (nt) { |
2317 | case CHAR: | | 2317 | case CHAR: |
2318 | max = TARG_CHAR_MAX; min = TARG_CHAR_MIN; break; | | 2318 | max = TARG_CHAR_MAX; min = TARG_CHAR_MIN; break; |
2319 | case UCHAR: | | 2319 | case UCHAR: |
2320 | max = TARG_UCHAR_MAX; min = 0; break; | | 2320 | max = TARG_UCHAR_MAX; min = 0; break; |
2321 | case SCHAR: | | 2321 | case SCHAR: |
2322 | max = TARG_SCHAR_MAX; min = TARG_SCHAR_MIN; break; | | 2322 | max = TARG_SCHAR_MAX; min = TARG_SCHAR_MIN; break; |
2323 | case SHORT: | | 2323 | case SHORT: |
2324 | max = TARG_SHRT_MAX; min = TARG_SHRT_MIN; break; | | 2324 | max = TARG_SHRT_MAX; min = TARG_SHRT_MIN; break; |
2325 | case USHORT: | | 2325 | case USHORT: |
2326 | max = TARG_USHRT_MAX; min = 0; break; | | 2326 | max = TARG_USHRT_MAX; min = 0; break; |
2327 | case ENUM: | | 2327 | case ENUM: |
2328 | case INT: | | 2328 | case INT: |
2329 | max = TARG_INT_MAX; min = TARG_INT_MIN; break; | | 2329 | max = TARG_INT_MAX; min = TARG_INT_MIN; break; |
2330 | case UINT: | | 2330 | case UINT: |
2331 | max = (u_int)TARG_UINT_MAX;min = 0; break; | | 2331 | max = (u_int)TARG_UINT_MAX;min = 0; break; |
2332 | case LONG: | | 2332 | case LONG: |
2333 | max = TARG_LONG_MAX; min = TARG_LONG_MIN; break; | | 2333 | max = TARG_LONG_MAX; min = TARG_LONG_MIN; break; |
2334 | case ULONG: | | 2334 | case ULONG: |
2335 | max = (u_long)TARG_ULONG_MAX; min = 0; break; | | 2335 | max = (u_long)TARG_ULONG_MAX; min = 0; break; |
2336 | case QUAD: | | 2336 | case QUAD: |
2337 | max = QUAD_MAX; min = QUAD_MIN; break; | | 2337 | max = QUAD_MAX; min = QUAD_MIN; break; |
2338 | case UQUAD: | | 2338 | case UQUAD: |
2339 | max = (uint64_t)UQUAD_MAX; min = 0; break; | | 2339 | max = (uint64_t)UQUAD_MAX; min = 0; break; |
2340 | case FLOAT: | | 2340 | case FLOAT: |
2341 | case FCOMPLEX: | | 2341 | case FCOMPLEX: |
2342 | max = FLT_MAX; min = -FLT_MAX; break; | | 2342 | max = FLT_MAX; min = -FLT_MAX; break; |
2343 | case DOUBLE: | | 2343 | case DOUBLE: |
2344 | case DCOMPLEX: | | 2344 | case DCOMPLEX: |
2345 | max = DBL_MAX; min = -DBL_MAX; break; | | 2345 | max = DBL_MAX; min = -DBL_MAX; break; |
2346 | case PTR: | | 2346 | case PTR: |
2347 | /* Got already an error because of float --> ptr */ | | 2347 | /* Got already an error because of float --> ptr */ |
2348 | case LDOUBLE: | | 2348 | case LDOUBLE: |
2349 | case LCOMPLEX: | | 2349 | case LCOMPLEX: |
2350 | max = LDBL_MAX; min = -LDBL_MAX; break; | | 2350 | max = LDBL_MAX; min = -LDBL_MAX; break; |
2351 | default: | | 2351 | default: |
2352 | lint_assert(/*CONSTCOND*/false); | | 2352 | lint_assert(/*CONSTCOND*/false); |
2353 | } | | 2353 | } |
2354 | if (v->v_ldbl > max || v->v_ldbl < min) { | | 2354 | if (v->v_ldbl > max || v->v_ldbl < min) { |
2355 | lint_assert(nt != LDOUBLE); | | 2355 | lint_assert(nt != LDOUBLE); |
2356 | if (op == FARG) { | | 2356 | if (op == FARG) { |
2357 | /* conv. of '%s' to '%s' is out of range, ... */ | | 2357 | /* conv. of '%s' to '%s' is out of range, ... */ |
2358 | warning(295, | | 2358 | warning(295, |
2359 | type_name(gettyp(ot)), type_name(tp), arg); | | 2359 | type_name(gettyp(ot)), type_name(tp), arg); |
2360 | } else { | | 2360 | } else { |
2361 | /* conversion of '%s' to '%s' is out of range */ | | 2361 | /* conversion of '%s' to '%s' is out of range */ |
2362 | warning(119, | | 2362 | warning(119, |
2363 | type_name(gettyp(ot)), type_name(tp)); | | 2363 | type_name(gettyp(ot)), type_name(tp)); |
2364 | } | | 2364 | } |
2365 | v->v_ldbl = v->v_ldbl > 0 ? max : min; | | 2365 | v->v_ldbl = v->v_ldbl > 0 ? max : min; |
2366 | } | | 2366 | } |
2367 | if (nt == FLOAT) { | | 2367 | if (nt == FLOAT) { |
2368 | nv->v_ldbl = (float)v->v_ldbl; | | 2368 | nv->v_ldbl = (float)v->v_ldbl; |
2369 | } else if (nt == DOUBLE) { | | 2369 | } else if (nt == DOUBLE) { |
2370 | nv->v_ldbl = (double)v->v_ldbl; | | 2370 | nv->v_ldbl = (double)v->v_ldbl; |
2371 | } else if (nt == LDOUBLE) { | | 2371 | } else if (nt == LDOUBLE) { |
2372 | nv->v_ldbl = v->v_ldbl; | | 2372 | nv->v_ldbl = v->v_ldbl; |
2373 | } else { | | 2373 | } else { |
2374 | nv->v_quad = (nt == PTR || is_uinteger(nt)) ? | | 2374 | nv->v_quad = (nt == PTR || is_uinteger(nt)) ? |
2375 | (int64_t)v->v_ldbl : (int64_t)v->v_ldbl; | | 2375 | (int64_t)v->v_ldbl : (int64_t)v->v_ldbl; |
2376 | } | | 2376 | } |
2377 | } else { | | 2377 | } else { |
2378 | if (nt == FLOAT) { | | 2378 | if (nt == FLOAT) { |
2379 | nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? | | 2379 | nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? |
2380 | (float)(uint64_t)v->v_quad : (float)v->v_quad; | | 2380 | (float)(uint64_t)v->v_quad : (float)v->v_quad; |
2381 | } else if (nt == DOUBLE) { | | 2381 | } else if (nt == DOUBLE) { |
2382 | nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? | | 2382 | nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? |
2383 | (double)(uint64_t)v->v_quad : (double)v->v_quad; | | 2383 | (double)(uint64_t)v->v_quad : (double)v->v_quad; |
2384 | } else if (nt == LDOUBLE) { | | 2384 | } else if (nt == LDOUBLE) { |
2385 | nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? | | 2385 | nv->v_ldbl = (ot == PTR || is_uinteger(ot)) ? |
2386 | (ldbl_t)(uint64_t)v->v_quad : (ldbl_t)v->v_quad; | | 2386 | (ldbl_t)(uint64_t)v->v_quad : (ldbl_t)v->v_quad; |
2387 | } else { | | 2387 | } else { |
2388 | rchk = true; /* Check for lost precision. */ | | 2388 | rchk = true; /* Check for lost precision. */ |
2389 | nv->v_quad = v->v_quad; | | 2389 | nv->v_quad = v->v_quad; |
2390 | } | | 2390 | } |
2391 | } | | 2391 | } |
2392 | | | 2392 | |
2393 | if (v->v_ansiu && is_floating(nt)) { | | 2393 | if (v->v_ansiu && is_floating(nt)) { |
2394 | /* ANSI C treats constant as unsigned */ | | 2394 | /* ANSI C treats constant as unsigned */ |
2395 | warning(157); | | 2395 | warning(157); |
2396 | v->v_ansiu = false; | | 2396 | v->v_ansiu = false; |
2397 | } else if (v->v_ansiu && (is_integer(nt) && !is_uinteger(nt) && | | 2397 | } else if (v->v_ansiu && (is_integer(nt) && !is_uinteger(nt) && |
2398 | portable_size_in_bits(nt) > | | 2398 | portable_size_in_bits(nt) > |
2399 | portable_size_in_bits(ot))) { | | 2399 | portable_size_in_bits(ot))) { |
2400 | /* ANSI C treats constant as unsigned */ | | 2400 | /* ANSI C treats constant as unsigned */ |
2401 | warning(157); | | 2401 | warning(157); |
2402 | v->v_ansiu = false; | | 2402 | v->v_ansiu = false; |
2403 | } | | 2403 | } |
2404 | | | 2404 | |
2405 | switch (nt) { | | 2405 | switch (nt) { |
2406 | case FLOAT: | | 2406 | case FLOAT: |
2407 | case FCOMPLEX: | | 2407 | case FCOMPLEX: |
2408 | case DOUBLE: | | 2408 | case DOUBLE: |
2409 | case DCOMPLEX: | | 2409 | case DCOMPLEX: |
2410 | case LDOUBLE: | | 2410 | case LDOUBLE: |
2411 | case LCOMPLEX: | | 2411 | case LCOMPLEX: |
2412 | break; | | 2412 | break; |
2413 | default: | | 2413 | default: |
2414 | sz = tp->t_bitfield ? tp->t_flen : size_in_bits(nt); | | 2414 | sz = tp->t_bitfield ? tp->t_flen : size_in_bits(nt); |
2415 | nv->v_quad = xsign(nv->v_quad, nt, sz); | | 2415 | nv->v_quad = xsign(nv->v_quad, nt, sz); |
2416 | break; | | 2416 | break; |
2417 | } | | 2417 | } |
2418 | | | 2418 | |
2419 | if (rchk && op != CVT) { | | 2419 | if (rchk && op != CVT) { |
2420 | osz = size_in_bits(ot); | | 2420 | osz = size_in_bits(ot); |
2421 | nsz = tp->t_bitfield ? tp->t_flen : size_in_bits(nt); | | 2421 | nsz = tp->t_bitfield ? tp->t_flen : size_in_bits(nt); |
2422 | xmask = qlmasks[nsz] ^ qlmasks[osz]; | | 2422 | xmask = qlmasks[nsz] ^ qlmasks[osz]; |
2423 | xmsk1 = qlmasks[nsz] ^ qlmasks[osz - 1]; | | 2423 | xmsk1 = qlmasks[nsz] ^ qlmasks[osz - 1]; |
2424 | /* | | 2424 | /* |
2425 | * For bitwise operations we are not interested in the | | 2425 | * For bitwise operations we are not interested in the |
2426 | * value, but in the bits itself. | | 2426 | * value, but in the bits itself. |
2427 | */ | | 2427 | */ |
2428 | if (op == ORASS || op == BITOR || op == BITXOR) { | | 2428 | if (op == ORASS || op == BITOR || op == BITXOR) { |
2429 | /* | | 2429 | /* |
2430 | * Print a warning if bits which were set are | | 2430 | * Print a warning if bits which were set are |
2431 | * lost due to the conversion. | | 2431 | * lost due to the conversion. |
2432 | * This can happen with operator ORASS only. | | 2432 | * This can happen with operator ORASS only. |
2433 | */ | | 2433 | */ |
2434 | if (nsz < osz && (v->v_quad & xmask) != 0) { | | 2434 | if (nsz < osz && (v->v_quad & xmask) != 0) { |
2435 | /* constant truncated by conv., op %s */ | | 2435 | /* constant truncated by conv., op %s */ |
2436 | warning(306, op_name(op)); | | 2436 | warning(306, op_name(op)); |
2437 | } | | 2437 | } |
2438 | } else if (op == ANDASS || op == BITAND) { | | 2438 | } else if (op == ANDASS || op == BITAND) { |
2439 | /* | | 2439 | /* |
2440 | * Print a warning if additional bits are not all 1 | | 2440 | * Print a warning if additional bits are not all 1 |
2441 | * and the most significant bit of the old value is 1, | | 2441 | * and the most significant bit of the old value is 1, |
2442 | * or if at least one (but not all) removed bit was 0. | | 2442 | * or if at least one (but not all) removed bit was 0. |
2443 | */ | | 2443 | */ |
2444 | if (nsz > osz && | | 2444 | if (nsz > osz && |
2445 | (nv->v_quad & qbmasks[osz - 1]) != 0 && | | 2445 | (nv->v_quad & qbmasks[osz - 1]) != 0 && |
2446 | (nv->v_quad & xmask) != xmask) { | | 2446 | (nv->v_quad & xmask) != xmask) { |
2447 | /* extra bits set to 0 in conv. of '%s' ... */ | | 2447 | /* extra bits set to 0 in conv. of '%s' ... */ |
2448 | warning(309, type_name(gettyp(ot)), | | 2448 | warning(309, type_name(gettyp(ot)), |
2449 | type_name(tp), op_name(op)); | | 2449 | type_name(tp), op_name(op)); |
2450 | } else if (nsz < osz && | | 2450 | } else if (nsz < osz && |
2451 | (v->v_quad & xmask) != xmask && | | 2451 | (v->v_quad & xmask) != xmask && |
2452 | (v->v_quad & xmask) != 0) { | | 2452 | (v->v_quad & xmask) != 0) { |
2453 | /* constant truncated by conv., op %s */ | | 2453 | /* constant truncated by conv., op %s */ |
2454 | warning(306, op_name(op)); | | 2454 | warning(306, op_name(op)); |
2455 | } | | 2455 | } |
2456 | } else if ((nt != PTR && is_uinteger(nt)) && | | 2456 | } else if ((nt != PTR && is_uinteger(nt)) && |
2457 | (ot != PTR && !is_uinteger(ot)) && | | 2457 | (ot != PTR && !is_uinteger(ot)) && |
2458 | v->v_quad < 0) { | | 2458 | v->v_quad < 0) { |
2459 | if (op == ASSIGN) { | | 2459 | if (op == ASSIGN) { |
2460 | /* assignment of negative constant to ... */ | | 2460 | /* assignment of negative constant to ... */ |
2461 | warning(164); | | 2461 | warning(164); |
2462 | } else if (op == INIT) { | | 2462 | } else if (op == INIT) { |
2463 | /* initialization of unsigned with neg... */ | | 2463 | /* initialization of unsigned with neg... */ |
2464 | warning(221); | | 2464 | warning(221); |
2465 | } else if (op == FARG) { | | 2465 | } else if (op == FARG) { |
2466 | /* conversion of negative constant to ... */ | | 2466 | /* conversion of negative constant to ... */ |
2467 | warning(296, arg); | | 2467 | warning(296, arg); |
2468 | } else if (modtab[op].m_comparison) { | | 2468 | } else if (modtab[op].m_comparison) { |
2469 | /* handled by check_integer_comparison() */ | | 2469 | /* handled by check_integer_comparison() */ |
2470 | } else { | | 2470 | } else { |
2471 | /* conversion of negative constant to ... */ | | 2471 | /* conversion of negative constant to ... */ |
2472 | warning(222); | | 2472 | warning(222); |
2473 | } | | 2473 | } |
2474 | } else if (nv->v_quad != v->v_quad && nsz <= osz && | | 2474 | } else if (nv->v_quad != v->v_quad && nsz <= osz && |
2475 | (v->v_quad & xmask) != 0 && | | 2475 | (v->v_quad & xmask) != 0 && |
2476 | (is_uinteger(ot) || (v->v_quad & xmsk1) != xmsk1)) { | | 2476 | (is_uinteger(ot) || (v->v_quad & xmsk1) != xmsk1)) { |
2477 | /* | | 2477 | /* |
2478 | * Loss of significant bit(s). All truncated bits | | 2478 | * Loss of significant bit(s). All truncated bits |
2479 | * of unsigned types or all truncated bits plus the | | 2479 | * of unsigned types or all truncated bits plus the |
2480 | * msb of the target for signed types are considered | | 2480 | * msb of the target for signed types are considered |
2481 | * to be significant bits. Loss of significant bits | | 2481 | * to be significant bits. Loss of significant bits |
2482 | * means that at least on of the bits was set in an | | 2482 | * means that at least on of the bits was set in an |
2483 | * unsigned type or that at least one, but not all of | | 2483 | * unsigned type or that at least one, but not all of |
2484 | * the bits was set in an signed type. | | 2484 | * the bits was set in an signed type. |
2485 | * Loss of significant bits means that it is not | | 2485 | * Loss of significant bits means that it is not |
2486 | * possible, also not with necessary casts, to convert | | 2486 | * possible, also not with necessary casts, to convert |
2487 | * back to the original type. A example for a | | 2487 | * back to the original type. A example for a |
2488 | * necessary cast is: | | 2488 | * necessary cast is: |
2489 | * char c; int i; c = 128; | | 2489 | * char c; int i; c = 128; |
2490 | * i = c; ** yields -128 ** | | 2490 | * i = c; ** yields -128 ** |
2491 | * i = (unsigned char)c; ** yields 128 ** | | 2491 | * i = (unsigned char)c; ** yields 128 ** |
2492 | */ | | 2492 | */ |
2493 | if (op == ASSIGN && tp->t_bitfield) { | | 2493 | if (op == ASSIGN && tp->t_bitfield) { |
2494 | /* precision lost in bit-field assignment */ | | 2494 | /* precision lost in bit-field assignment */ |
2495 | warning(166); | | 2495 | warning(166); |
2496 | } else if (op == ASSIGN) { | | 2496 | } else if (op == ASSIGN) { |
2497 | /* constant truncated by assignment */ | | 2497 | /* constant truncated by assignment */ |
2498 | warning(165); | | 2498 | warning(165); |
2499 | } else if (op == INIT && tp->t_bitfield) { | | 2499 | } else if (op == INIT && tp->t_bitfield) { |
2500 | /* bit-field initializer does not fit */ | | 2500 | /* bit-field initializer does not fit */ |
2501 | warning(180); | | 2501 | warning(180); |
2502 | } else if (op == INIT) { | | 2502 | } else if (op == INIT) { |
2503 | /* initializer does not fit */ | | 2503 | /* initializer does not fit */ |
2504 | warning(178); | | 2504 | warning(178); |
2505 | } else if (op == CASE) { | | 2505 | } else if (op == CASE) { |
2506 | /* case label affected by conversion */ | | 2506 | /* case label affected by conversion */ |
2507 | warning(196); | | 2507 | warning(196); |
2508 | } else if (op == FARG) { | | 2508 | } else if (op == FARG) { |
2509 | /* conv. of '%s' to '%s' is out of range, ... */ | | 2509 | /* conv. of '%s' to '%s' is out of range, ... */ |
2510 | warning(295, | | 2510 | warning(295, |
2511 | type_name(gettyp(ot)), type_name(tp), arg); | | 2511 | type_name(gettyp(ot)), type_name(tp), arg); |
2512 | } else { | | 2512 | } else { |
2513 | /* conversion of '%s' to '%s' is out of range */ | | 2513 | /* conversion of '%s' to '%s' is out of range */ |
2514 | warning(119, | | 2514 | warning(119, |
2515 | type_name(gettyp(ot)), type_name(tp)); | | 2515 | type_name(gettyp(ot)), type_name(tp)); |
2516 | } | | 2516 | } |
2517 | } else if (nv->v_quad != v->v_quad) { | | 2517 | } else if (nv->v_quad != v->v_quad) { |
2518 | if (op == ASSIGN && tp->t_bitfield) { | | 2518 | if (op == ASSIGN && tp->t_bitfield) { |
2519 | /* precision lost in bit-field assignment */ | | 2519 | /* precision lost in bit-field assignment */ |
2520 | warning(166); | | 2520 | warning(166); |
2521 | } else if (op == INIT && tp->t_bitfield) { | | 2521 | } else if (op == INIT && tp->t_bitfield) { |
2522 | /* bit-field initializer out of range */ | | 2522 | /* bit-field initializer out of range */ |
2523 | warning(11); | | 2523 | warning(11); |
2524 | } else if (op == CASE) { | | 2524 | } else if (op == CASE) { |
2525 | /* case label affected by conversion */ | | 2525 | /* case label affected by conversion */ |
2526 | warning(196); | | 2526 | warning(196); |
2527 | } else if (op == FARG) { | | 2527 | } else if (op == FARG) { |
2528 | /* conv. of '%s' to '%s' is out of range, ... */ | | 2528 | /* conv. of '%s' to '%s' is out of range, ... */ |
2529 | warning(295, | | 2529 | warning(295, |
2530 | type_name(gettyp(ot)), type_name(tp), arg); | | 2530 | type_name(gettyp(ot)), type_name(tp), arg); |
2531 | } else { | | 2531 | } else { |
2532 | /* conversion of '%s' to '%s' is out of range */ | | 2532 | /* conversion of '%s' to '%s' is out of range */ |
2533 | warning(119, | | 2533 | warning(119, |
2534 | type_name(gettyp(ot)), type_name(tp)); | | 2534 | type_name(gettyp(ot)), type_name(tp)); |
2535 | } | | 2535 | } |
2536 | } | | 2536 | } |
2537 | } | | 2537 | } |
2538 | } | | 2538 | } |
2539 | | | 2539 | |
2540 | /* | | 2540 | /* |
2541 | * Called if incompatible types were detected. | | 2541 | * Called if incompatible types were detected. |
2542 | * Prints a appropriate warning. | | 2542 | * Prints a appropriate warning. |
2543 | */ | | 2543 | */ |
2544 | static void | | 2544 | static void |
2545 | warn_incompatible_types(op_t op, | | 2545 | warn_incompatible_types(op_t op, |
2546 | const type_t *ltp, tspec_t lt, | | 2546 | const type_t *ltp, tspec_t lt, |
2547 | const type_t *rtp, tspec_t rt) | | 2547 | const type_t *rtp, tspec_t rt) |
2548 | { | | 2548 | { |
2549 | const mod_t *mp; | | 2549 | const mod_t *mp; |
2550 | | | 2550 | |
2551 | mp = &modtab[op]; | | 2551 | mp = &modtab[op]; |
2552 | | | 2552 | |
2553 | if (lt == VOID || (mp->m_binary && rt == VOID)) { | | 2553 | if (lt == VOID || (mp->m_binary && rt == VOID)) { |
2554 | /* void type illegal in expression */ | | 2554 | /* void type illegal in expression */ |
2555 | error(109); | | 2555 | error(109); |
2556 | } else if (op == ASSIGN) { | | 2556 | } else if (op == ASSIGN) { |
2557 | if ((lt == STRUCT || lt == UNION) && | | 2557 | if ((lt == STRUCT || lt == UNION) && |
2558 | (rt == STRUCT || rt == UNION)) { | | 2558 | (rt == STRUCT || rt == UNION)) { |
2559 | /* assignment of different structures (%s != %s) */ | | 2559 | /* assignment of different structures (%s != %s) */ |
2560 | error(240, tspec_name(lt), tspec_name(rt)); | | 2560 | error(240, tspec_name(lt), tspec_name(rt)); |
2561 | } else { | | 2561 | } else { |
2562 | /* cannot assign to '%s' from '%s' */ | | 2562 | /* cannot assign to '%s' from '%s' */ |
2563 | error(171, type_name(ltp), type_name(rtp)); | | 2563 | error(171, type_name(ltp), type_name(rtp)); |
2564 | } | | 2564 | } |
2565 | } else if (mp->m_binary) { | | 2565 | } else if (mp->m_binary) { |
2566 | /* operands of '%s' have incompatible types (%s != %s) */ | | 2566 | /* operands of '%s' have incompatible types (%s != %s) */ |
2567 | error(107, mp->m_name, tspec_name(lt), tspec_name(rt)); | | 2567 | error(107, mp->m_name, tspec_name(lt), tspec_name(rt)); |
2568 | } else { | | 2568 | } else { |
2569 | lint_assert(rt == NOTSPEC); | | 2569 | lint_assert(rt == NOTSPEC); |
2570 | /* operand of '%s' has invalid type (%s) */ | | 2570 | /* operand of '%s' has invalid type (%s) */ |
2571 | error(108, mp->m_name, tspec_name(lt)); | | 2571 | error(108, mp->m_name, tspec_name(lt)); |
2572 | } | | 2572 | } |
2573 | } | | 2573 | } |
2574 | | | 2574 | |
2575 | /* | | 2575 | /* |
2576 | * Called if incompatible pointer types are detected. | | 2576 | * Called if incompatible pointer types are detected. |
2577 | * Print an appropriate warning. | | 2577 | * Print an appropriate warning. |
2578 | */ | | 2578 | */ |
2579 | static void | | 2579 | static void |
2580 | warn_incompatible_pointers(const mod_t *mp, | | 2580 | warn_incompatible_pointers(const mod_t *mp, |
2581 | const type_t *ltp, const type_t *rtp) | | 2581 | const type_t *ltp, const type_t *rtp) |
2582 | { | | 2582 | { |
2583 | tspec_t lt, rt; | | 2583 | tspec_t lt, rt; |
2584 | | | 2584 | |
2585 | lint_assert(ltp->t_tspec == PTR); | | 2585 | lint_assert(ltp->t_tspec == PTR); |
2586 | lint_assert(rtp->t_tspec == PTR); | | 2586 | lint_assert(rtp->t_tspec == PTR); |
2587 | | | 2587 | |
2588 | lt = ltp->t_subt->t_tspec; | | 2588 | lt = ltp->t_subt->t_tspec; |
2589 | rt = rtp->t_subt->t_tspec; | | 2589 | rt = rtp->t_subt->t_tspec; |
2590 | | | 2590 | |
2591 | if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) { | | 2591 | if ((lt == STRUCT || lt == UNION) && (rt == STRUCT || rt == UNION)) { |
2592 | if (mp == NULL) { | | 2592 | if (mp == NULL) { |
2593 | /* illegal structure pointer combination */ | | 2593 | /* illegal structure pointer combination */ |
2594 | warning(244); | | 2594 | warning(244); |
2595 | } else { | | 2595 | } else { |
2596 | /* incompatible structure pointers: '%s' '%s' '%s' */ | | 2596 | /* incompatible structure pointers: '%s' '%s' '%s' */ |
2597 | warning(245, type_name(ltp), mp->m_name, type_name(rtp)); | | 2597 | warning(245, type_name(ltp), mp->m_name, type_name(rtp)); |
2598 | } | | 2598 | } |
2599 | } else { | | 2599 | } else { |
2600 | if (mp == NULL) { | | 2600 | if (mp == NULL) { |
2601 | /* illegal pointer combination */ | | 2601 | /* illegal pointer combination */ |
2602 | warning(184); | | 2602 | warning(184); |
2603 | } else { | | 2603 | } else { |
2604 | /* illegal pointer combination (%s) and (%s), op %s */ | | 2604 | /* illegal pointer combination (%s) and (%s), op %s */ |
2605 | warning(124, | | 2605 | warning(124, |
2606 | type_name(ltp), type_name(rtp), mp->m_name); | | 2606 | type_name(ltp), type_name(rtp), mp->m_name); |
2607 | } | | 2607 | } |
2608 | } | | 2608 | } |
2609 | } | | 2609 | } |
2610 | | | 2610 | |
2611 | /* | | 2611 | /* |
2612 | * Make sure type (*tpp)->t_subt has at least the qualifiers | | 2612 | * Make sure type (*tpp)->t_subt has at least the qualifiers |
2613 | * of tp1->t_subt and tp2->t_subt. | | 2613 | * of tp1->t_subt and tp2->t_subt. |
2614 | */ | | 2614 | */ |
2615 | static void | | 2615 | static void |
2616 | merge_qualifiers(type_t **tpp, type_t *tp1, type_t *tp2) | | 2616 | merge_qualifiers(type_t **tpp, type_t *tp1, type_t *tp2) |
2617 | { | | 2617 | { |
2618 | | | 2618 | |
2619 | lint_assert((*tpp)->t_tspec == PTR); | | 2619 | lint_assert((*tpp)->t_tspec == PTR); |
2620 | lint_assert(tp1->t_tspec == PTR); | | 2620 | lint_assert(tp1->t_tspec == PTR); |
2621 | lint_assert(tp2->t_tspec == PTR); | | 2621 | lint_assert(tp2->t_tspec == PTR); |
2622 | | | 2622 | |
2623 | if ((*tpp)->t_subt->t_const == | | 2623 | if ((*tpp)->t_subt->t_const == |
2624 | (tp1->t_subt->t_const | tp2->t_subt->t_const) && | | 2624 | (tp1->t_subt->t_const | tp2->t_subt->t_const) && |
2625 | (*tpp)->t_subt->t_volatile == | | 2625 | (*tpp)->t_subt->t_volatile == |
2626 | (tp1->t_subt->t_volatile | tp2->t_subt->t_volatile)) { | | 2626 | (tp1->t_subt->t_volatile | tp2->t_subt->t_volatile)) { |
2627 | return; | | 2627 | return; |
2628 | } | | 2628 | } |
2629 | | | 2629 | |
2630 | *tpp = expr_dup_type(*tpp); | | 2630 | *tpp = expr_dup_type(*tpp); |
2631 | (*tpp)->t_subt = expr_dup_type((*tpp)->t_subt); | | 2631 | (*tpp)->t_subt = expr_dup_type((*tpp)->t_subt); |
2632 | (*tpp)->t_subt->t_const = | | 2632 | (*tpp)->t_subt->t_const = |
2633 | tp1->t_subt->t_const | tp2->t_subt->t_const; | | 2633 | tp1->t_subt->t_const | tp2->t_subt->t_const; |
2634 | (*tpp)->t_subt->t_volatile = | | 2634 | (*tpp)->t_subt->t_volatile = |
2635 | tp1->t_subt->t_volatile | tp2->t_subt->t_volatile; | | 2635 | tp1->t_subt->t_volatile | tp2->t_subt->t_volatile; |
2636 | } | | 2636 | } |
2637 | | | 2637 | |
2638 | /* | | 2638 | /* |
2639 | * Returns true if the given structure or union has a constant member | | 2639 | * Returns true if the given structure or union has a constant member |
2640 | * (maybe recursively). | | 2640 | * (maybe recursively). |
2641 | */ | | 2641 | */ |
2642 | static bool | | 2642 | static bool |
2643 | has_constant_member(const type_t *tp) | | 2643 | has_constant_member(const type_t *tp) |
2644 | { | | 2644 | { |
2645 | sym_t *m; | | 2645 | sym_t *m; |
2646 | tspec_t t; | | 2646 | tspec_t t; |
2647 | | | 2647 | |
2648 | lint_assert((t = tp->t_tspec) == STRUCT || t == UNION); | | 2648 | lint_assert((t = tp->t_tspec) == STRUCT || t == UNION); |
2649 | | | 2649 | |
2650 | for (m = tp->t_str->sou_first_member; m != NULL; m = m->s_next) { | | 2650 | for (m = tp->t_str->sou_first_member; m != NULL; m = m->s_next) { |
2651 | tp = m->s_type; | | 2651 | tp = m->s_type; |
2652 | if (tp->t_const) | | 2652 | if (tp->t_const) |
2653 | return true; | | 2653 | return true; |
2654 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { | | 2654 | if ((t = tp->t_tspec) == STRUCT || t == UNION) { |
2655 | if (has_constant_member(m->s_type)) | | 2655 | if (has_constant_member(m->s_type)) |
2656 | return true; | | 2656 | return true; |
2657 | } | | 2657 | } |
2658 | } | | 2658 | } |
2659 | return false; | | 2659 | return false; |
2660 | } | | 2660 | } |
2661 | | | 2661 | |
2662 | /* | | 2662 | /* |
2663 | * Create a new node for one of the operators POINT and ARROW. | | 2663 | * Create a new node for one of the operators POINT and ARROW. |
2664 | */ | | 2664 | */ |
2665 | static tnode_t * | | 2665 | static tnode_t * |
2666 | build_struct_access(op_t op, tnode_t *ln, tnode_t *rn) | | 2666 | build_struct_access(op_t op, tnode_t *ln, tnode_t *rn) |
2667 | { | | 2667 | { |
2668 | tnode_t *ntn, *ctn; | | 2668 | tnode_t *ntn, *ctn; |
2669 | bool nolval; | | 2669 | bool nolval; |
2670 | | | 2670 | |
2671 | lint_assert(rn->tn_op == NAME); | | 2671 | lint_assert(rn->tn_op == NAME); |
2672 | lint_assert(rn->tn_sym->s_value.v_tspec == INT); | | 2672 | lint_assert(rn->tn_sym->s_value.v_tspec == INT); |
2673 | lint_assert(rn->tn_sym->s_scl == MOS || rn->tn_sym->s_scl == MOU); | | 2673 | lint_assert(rn->tn_sym->s_scl == MOS || rn->tn_sym->s_scl == MOU); |
2674 | | | 2674 | |
2675 | /* | | 2675 | /* |
2676 | * Remember if the left operand is an lvalue (structure members | | 2676 | * Remember if the left operand is an lvalue (structure members |
2677 | * are lvalues if and only if the structure itself is an lvalue). | | 2677 | * are lvalues if and only if the structure itself is an lvalue). |
2678 | */ | | 2678 | */ |
2679 | nolval = op == POINT && !ln->tn_lvalue; | | 2679 | nolval = op == POINT && !ln->tn_lvalue; |
2680 | | | 2680 | |
2681 | if (op == POINT) { | | 2681 | if (op == POINT) { |
2682 | ln = build_address(ln, true); | | 2682 | ln = build_address(ln, true); |
2683 | } else if (ln->tn_type->t_tspec != PTR) { | | 2683 | } else if (ln->tn_type->t_tspec != PTR) { |
2684 | lint_assert(tflag); | | 2684 | lint_assert(tflag); |
2685 | lint_assert(is_integer(ln->tn_type->t_tspec)); | | 2685 | lint_assert(is_integer(ln->tn_type->t_tspec)); |
2686 | ln = convert(NOOP, 0, expr_derive_type(gettyp(VOID), PTR), ln); | | 2686 | ln = convert(NOOP, 0, expr_derive_type(gettyp(VOID), PTR), ln); |
2687 | } | | 2687 | } |
2688 | | | 2688 | |
2689 | ctn = expr_new_integer_constant(PTRDIFF_TSPEC, | | 2689 | ctn = expr_new_integer_constant(PTRDIFF_TSPEC, |
2690 | rn->tn_sym->s_value.v_quad / CHAR_SIZE); | | 2690 | rn->tn_sym->s_value.v_quad / CHAR_SIZE); |
2691 | | | 2691 | |
2692 | ntn = new_tnode(PLUS, expr_derive_type(rn->tn_type, PTR), ln, ctn); | | 2692 | ntn = new_tnode(PLUS, expr_derive_type(rn->tn_type, PTR), ln, ctn); |
2693 | if (ln->tn_op == CON) | | 2693 | if (ln->tn_op == CON) |
2694 | ntn = fold(ntn); | | 2694 | ntn = fold(ntn); |
2695 | | | 2695 | |
2696 | if (rn->tn_type->t_bitfield) { | | 2696 | if (rn->tn_type->t_bitfield) { |
2697 | ntn = new_tnode(FSEL, ntn->tn_type->t_subt, ntn, NULL); | | 2697 | ntn = new_tnode(FSEL, ntn->tn_type->t_subt, ntn, NULL); |
2698 | } else { | | 2698 | } else { |
2699 | ntn = new_tnode(INDIR, ntn->tn_type->t_subt, ntn, NULL); | | 2699 | ntn = new_tnode(INDIR, ntn->tn_type->t_subt, ntn, NULL); |
2700 | } | | 2700 | } |
2701 | | | 2701 | |
2702 | if (nolval) | | 2702 | if (nolval) |
2703 | ntn->tn_lvalue = false; | | 2703 | ntn->tn_lvalue = false; |
2704 | | | 2704 | |
2705 | return ntn; | | 2705 | return ntn; |
2706 | } | | 2706 | } |
2707 | | | 2707 | |
2708 | /* | | 2708 | /* |
2709 | * Create a node for INCAFT, INCBEF, DECAFT and DECBEF. | | 2709 | * Create a node for INCAFT, INCBEF, DECAFT and DECBEF. |
2710 | */ | | 2710 | */ |
2711 | static tnode_t * | | 2711 | static tnode_t * |
2712 | build_prepost_incdec(op_t op, tnode_t *ln) | | 2712 | build_prepost_incdec(op_t op, tnode_t *ln) |
2713 | { | | 2713 | { |
2714 | tnode_t *cn, *ntn; | | 2714 | tnode_t *cn, *ntn; |
2715 | | | 2715 | |
2716 | lint_assert(ln != NULL); | | 2716 | lint_assert(ln != NULL); |
2717 | | | 2717 | |
2718 | if (ln->tn_type->t_tspec == PTR) { | | 2718 | if (ln->tn_type->t_tspec == PTR) { |
2719 | cn = plength(ln->tn_type); | | 2719 | cn = plength(ln->tn_type); |
2720 | } else { | | 2720 | } else { |
2721 | cn = expr_new_integer_constant(INT, (int64_t)1); | | 2721 | cn = expr_new_integer_constant(INT, (int64_t)1); |
2722 | } | | 2722 | } |
2723 | ntn = new_tnode(op, ln->tn_type, ln, cn); | | 2723 | ntn = new_tnode(op, ln->tn_type, ln, cn); |
2724 | | | 2724 | |
2725 | return ntn; | | 2725 | return ntn; |
2726 | } | | 2726 | } |
2727 | | | 2727 | |
2728 | /* | | 2728 | /* |
2729 | * Create a node for REAL, IMAG | | 2729 | * Create a node for REAL, IMAG |
2730 | */ | | 2730 | */ |
2731 | static tnode_t * | | 2731 | static tnode_t * |
2732 | build_real_imag(op_t op, tnode_t *ln) | | 2732 | build_real_imag(op_t op, tnode_t *ln) |
2733 | { | | 2733 | { |
2734 | tnode_t *cn, *ntn; | | 2734 | tnode_t *cn, *ntn; |
2735 | | | 2735 | |
2736 | lint_assert(ln != NULL); | | 2736 | lint_assert(ln != NULL); |
2737 | | | 2737 | |
2738 | switch (ln->tn_type->t_tspec) { | | 2738 | switch (ln->tn_type->t_tspec) { |
2739 | case LCOMPLEX: | | 2739 | case LCOMPLEX: |
2740 | /* XXX: integer and LDOUBLE don't match. */ | | 2740 | /* XXX: integer and LDOUBLE don't match. */ |
2741 | cn = expr_new_integer_constant(LDOUBLE, (int64_t)1); | | 2741 | cn = expr_new_integer_constant(LDOUBLE, (int64_t)1); |
2742 | break; | | 2742 | break; |
2743 | case DCOMPLEX: | | 2743 | case DCOMPLEX: |
2744 | /* XXX: integer and DOUBLE don't match. */ | | 2744 | /* XXX: integer and DOUBLE don't match. */ |
2745 | cn = expr_new_integer_constant(DOUBLE, (int64_t)1); | | 2745 | cn = expr_new_integer_constant(DOUBLE, (int64_t)1); |
2746 | break; | | 2746 | break; |
2747 | case FCOMPLEX: | | 2747 | case FCOMPLEX: |
2748 | /* XXX: integer and FLOAT don't match. */ | | 2748 | /* XXX: integer and FLOAT don't match. */ |
2749 | cn = expr_new_integer_constant(FLOAT, (int64_t)1); | | 2749 | cn = expr_new_integer_constant(FLOAT, (int64_t)1); |
2750 | break; | | 2750 | break; |
2751 | default: | | 2751 | default: |
2752 | /* __%s__ is illegal for type %s */ | | 2752 | /* __%s__ is illegal for type %s */ |
2753 | error(276, op == REAL ? "real" : "imag", | | 2753 | error(276, op == REAL ? "real" : "imag", |
2754 | type_name(ln->tn_type)); | | 2754 | type_name(ln->tn_type)); |
2755 | return NULL; | | 2755 | return NULL; |
2756 | } | | 2756 | } |
2757 | ntn = new_tnode(op, cn->tn_type, ln, cn); | | 2757 | ntn = new_tnode(op, cn->tn_type, ln, cn); |
2758 | ntn->tn_lvalue = true; | | 2758 | ntn->tn_lvalue = true; |
2759 | | | 2759 | |
2760 | return ntn; | | 2760 | return ntn; |
2761 | } | | 2761 | } |
2762 | /* | | 2762 | /* |
2763 | * Create a tree node for the unary & operator | | 2763 | * Create a tree node for the unary & operator |
2764 | */ | | 2764 | */ |
2765 | static tnode_t * | | 2765 | static tnode_t * |
2766 | build_address(tnode_t *tn, bool noign) | | 2766 | build_address(tnode_t *tn, bool noign) |
2767 | { | | 2767 | { |
2768 | tspec_t t; | | 2768 | tspec_t t; |
2769 | | | 2769 | |
2770 | if (!noign && ((t = tn->tn_type->t_tspec) == ARRAY || t == FUNC)) { | | 2770 | if (!noign && ((t = tn->tn_type->t_tspec) == ARRAY || t == FUNC)) { |
2771 | if (tflag) | | 2771 | if (tflag) |
2772 | /* '&' before array or function: ignored */ | | 2772 | /* '&' before array or function: ignored */ |
2773 | warning(127); | | 2773 | warning(127); |
2774 | return tn; | | 2774 | return tn; |
2775 | } | | 2775 | } |
2776 | | | 2776 | |
2777 | /* eliminate &* */ | | 2777 | /* eliminate &* */ |
2778 | if (tn->tn_op == INDIR && | | 2778 | if (tn->tn_op == INDIR && |
2779 | tn->tn_left->tn_type->t_tspec == PTR && | | 2779 | tn->tn_left->tn_type->t_tspec == PTR && |
2780 | tn->tn_left->tn_type->t_subt == tn->tn_type) { | | 2780 | tn->tn_left->tn_type->t_subt == tn->tn_type) { |
2781 | return tn->tn_left; | | 2781 | return tn->tn_left; |
2782 | } | | 2782 | } |
2783 | | | 2783 | |
2784 | return new_tnode(ADDR, expr_derive_type(tn->tn_type, PTR), tn, NULL); | | 2784 | return new_tnode(ADDR, expr_derive_type(tn->tn_type, PTR), tn, NULL); |
2785 | } | | 2785 | } |
2786 | | | 2786 | |
2787 | /* | | 2787 | /* |
2788 | * Create a node for operators PLUS and MINUS. | | 2788 | * Create a node for operators PLUS and MINUS. |
2789 | */ | | 2789 | */ |
2790 | static tnode_t * | | 2790 | static tnode_t * |
2791 | build_plus_minus(op_t op, tnode_t *ln, tnode_t *rn) | | 2791 | build_plus_minus(op_t op, tnode_t *ln, tnode_t *rn) |
2792 | { | | 2792 | { |
2793 | tnode_t *ntn, *ctn; | | 2793 | tnode_t *ntn, *ctn; |
2794 | type_t *tp; | | 2794 | type_t *tp; |
2795 | | | 2795 | |
2796 | /* If pointer and integer, then pointer to the lhs. */ | | 2796 | /* If pointer and integer, then pointer to the lhs. */ |
2797 | if (rn->tn_type->t_tspec == PTR && is_integer(ln->tn_type->t_tspec)) { | | 2797 | if (rn->tn_type->t_tspec == PTR && is_integer(ln->tn_type->t_tspec)) { |
2798 | ntn = ln; | | 2798 | ntn = ln; |
2799 | ln = rn; | | 2799 | ln = rn; |
2800 | rn = ntn; | | 2800 | rn = ntn; |
2801 | } | | 2801 | } |
2802 | | | 2802 | |
2803 | if (ln->tn_type->t_tspec == PTR && rn->tn_type->t_tspec != PTR) { | | 2803 | if (ln->tn_type->t_tspec == PTR && rn->tn_type->t_tspec != PTR) { |
2804 | | | 2804 | |
2805 | lint_assert(is_integer(rn->tn_type->t_tspec)); | | 2805 | lint_assert(is_integer(rn->tn_type->t_tspec)); |
2806 | | | 2806 | |
2807 | ctn = plength(ln->tn_type); | | 2807 | ctn = plength(ln->tn_type); |
2808 | if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) | | 2808 | if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) |
2809 | rn = convert(NOOP, 0, ctn->tn_type, rn); | | 2809 | rn = convert(NOOP, 0, ctn->tn_type, rn); |
2810 | rn = new_tnode(MULT, rn->tn_type, rn, ctn); | | 2810 | rn = new_tnode(MULT, rn->tn_type, rn, ctn); |
2811 | if (rn->tn_left->tn_op == CON) | | 2811 | if (rn->tn_left->tn_op == CON) |
2812 | rn = fold(rn); | | 2812 | rn = fold(rn); |
2813 | ntn = new_tnode(op, ln->tn_type, ln, rn); | | 2813 | ntn = new_tnode(op, ln->tn_type, ln, rn); |
2814 | | | 2814 | |
2815 | } else if (rn->tn_type->t_tspec == PTR) { | | 2815 | } else if (rn->tn_type->t_tspec == PTR) { |
2816 | | | 2816 | |
2817 | lint_assert(ln->tn_type->t_tspec == PTR); | | 2817 | lint_assert(ln->tn_type->t_tspec == PTR); |
2818 | lint_assert(op == MINUS); | | 2818 | lint_assert(op == MINUS); |
2819 | tp = gettyp(PTRDIFF_TSPEC); | | 2819 | tp = gettyp(PTRDIFF_TSPEC); |
2820 | ntn = new_tnode(op, tp, ln, rn); | | 2820 | ntn = new_tnode(op, tp, ln, rn); |
2821 | if (ln->tn_op == CON && rn->tn_op == CON) | | 2821 | if (ln->tn_op == CON && rn->tn_op == CON) |
2822 | ntn = fold(ntn); | | 2822 | ntn = fold(ntn); |
2823 | ctn = plength(ln->tn_type); | | 2823 | ctn = plength(ln->tn_type); |
2824 | balance(NOOP, &ntn, &ctn); | | 2824 | balance(NOOP, &ntn, &ctn); |
2825 | ntn = new_tnode(DIV, tp, ntn, ctn); | | 2825 | ntn = new_tnode(DIV, tp, ntn, ctn); |
2826 | | | 2826 | |
2827 | } else { | | 2827 | } else { |
2828 | | | 2828 | |
2829 | ntn = new_tnode(op, ln->tn_type, ln, rn); | | 2829 | ntn = new_tnode(op, ln->tn_type, ln, rn); |
2830 | | | 2830 | |
2831 | } | | 2831 | } |
2832 | return ntn; | | 2832 | return ntn; |
2833 | } | | 2833 | } |
2834 | | | 2834 | |
2835 | /* | | 2835 | /* |
2836 | * Create a node for operators SHL and SHR. | | 2836 | * Create a node for operators SHL and SHR. |
2837 | */ | | 2837 | */ |
2838 | static tnode_t * | | 2838 | static tnode_t * |
2839 | build_bit_shift(op_t op, tnode_t *ln, tnode_t *rn) | | 2839 | build_bit_shift(op_t op, tnode_t *ln, tnode_t *rn) |
2840 | { | | 2840 | { |
2841 | tspec_t t; | | 2841 | tspec_t t; |
2842 | tnode_t *ntn; | | 2842 | tnode_t *ntn; |
2843 | | | 2843 | |
2844 | if ((t = rn->tn_type->t_tspec) != INT && t != UINT) | | 2844 | if ((t = rn->tn_type->t_tspec) != INT && t != UINT) |
2845 | rn = convert(CVT, 0, gettyp(INT), rn); | | 2845 | rn = convert(CVT, 0, gettyp(INT), rn); |
2846 | ntn = new_tnode(op, ln->tn_type, ln, rn); | | 2846 | ntn = new_tnode(op, ln->tn_type, ln, rn); |
2847 | return ntn; | | 2847 | return ntn; |
2848 | } | | 2848 | } |
2849 | | | 2849 | |
2850 | /* | | 2850 | /* |
2851 | * Create a node for COLON. | | 2851 | * Create a node for COLON. |
2852 | */ | | 2852 | */ |
2853 | static tnode_t * | | 2853 | static tnode_t * |
2854 | build_colon(tnode_t *ln, tnode_t *rn) | | 2854 | build_colon(tnode_t *ln, tnode_t *rn) |
2855 | { | | 2855 | { |
2856 | tspec_t lt, rt, pdt; | | 2856 | tspec_t lt, rt, pdt; |
2857 | type_t *rtp; | | 2857 | type_t *rtp; |
2858 | tnode_t *ntn; | | 2858 | tnode_t *ntn; |
2859 | | | 2859 | |
2860 | lt = ln->tn_type->t_tspec; | | 2860 | lt = ln->tn_type->t_tspec; |
2861 | rt = rn->tn_type->t_tspec; | | 2861 | rt = rn->tn_type->t_tspec; |
2862 | pdt = PTRDIFF_TSPEC; | | 2862 | pdt = PTRDIFF_TSPEC; |
2863 | | | 2863 | |
2864 | /* | | 2864 | /* |
2865 | * Arithmetic types are balanced, all other type combinations | | 2865 | * Arithmetic types are balanced, all other type combinations |
2866 | * still need to be handled. | | 2866 | * still need to be handled. |
2867 | */ | | 2867 | */ |
2868 | if (is_arithmetic(lt) && is_arithmetic(rt)) { | | 2868 | if (is_arithmetic(lt) && is_arithmetic(rt)) { |
2869 | rtp = ln->tn_type; | | 2869 | rtp = ln->tn_type; |
2870 | } else if (lt == BOOL && rt == BOOL) { | | 2870 | } else if (lt == BOOL && rt == BOOL) { |
2871 | rtp = ln->tn_type; | | 2871 | rtp = ln->tn_type; |
2872 | } else if (lt == VOID || rt == VOID) { | | 2872 | } else if (lt == VOID || rt == VOID) { |
2873 | rtp = gettyp(VOID); | | 2873 | rtp = gettyp(VOID); |
2874 | } else if (lt == STRUCT || lt == UNION) { | | 2874 | } else if (lt == STRUCT || lt == UNION) { |
2875 | /* Both types must be identical. */ | | 2875 | /* Both types must be identical. */ |
2876 | lint_assert(rt == STRUCT || rt == UNION); | | 2876 | lint_assert(rt == STRUCT || rt == UNION); |
2877 | lint_assert(ln->tn_type->t_str == rn->tn_type->t_str); | | 2877 | lint_assert(ln->tn_type->t_str == rn->tn_type->t_str); |
2878 | if (is_incomplete(ln->tn_type)) { | | 2878 | if (is_incomplete(ln->tn_type)) { |
2879 | /* unknown operand size, op %s */ | | 2879 | /* unknown operand size, op %s */ |
2880 | error(138, modtab[COLON].m_name); | | 2880 | error(138, op_name(COLON)); |
2881 | return NULL; | | 2881 | return NULL; |
2882 | } | | 2882 | } |
2883 | rtp = ln->tn_type; | | 2883 | rtp = ln->tn_type; |
2884 | } else if (lt == PTR && is_integer(rt)) { | | 2884 | } else if (lt == PTR && is_integer(rt)) { |
2885 | if (rt != pdt) { | | 2885 | if (rt != pdt) { |
2886 | rn = convert(NOOP, 0, gettyp(pdt), rn); | | 2886 | rn = convert(NOOP, 0, gettyp(pdt), rn); |
2887 | rt = pdt; | | 2887 | rt = pdt; |
2888 | } | | 2888 | } |
2889 | rtp = ln->tn_type; | | 2889 | rtp = ln->tn_type; |
2890 | } else if (rt == PTR && is_integer(lt)) { | | 2890 | } else if (rt == PTR && is_integer(lt)) { |
2891 | if (lt != pdt) { | | 2891 | if (lt != pdt) { |
2892 | ln = convert(NOOP, 0, gettyp(pdt), ln); | | 2892 | ln = convert(NOOP, 0, gettyp(pdt), ln); |
2893 | lt = pdt; | | 2893 | lt = pdt; |
2894 | } | | 2894 | } |
2895 | rtp = rn->tn_type; | | 2895 | rtp = rn->tn_type; |
2896 | } else if (lt == PTR && ln->tn_type->t_subt->t_tspec == VOID) { | | 2896 | } else if (lt == PTR && ln->tn_type->t_subt->t_tspec == VOID) { |
2897 | lint_assert(rt == PTR); | | 2897 | lint_assert(rt == PTR); |
2898 | rtp = rn->tn_type; | | 2898 | rtp = rn->tn_type; |
2899 | merge_qualifiers(&rtp, ln->tn_type, rn->tn_type); | | 2899 | merge_qualifiers(&rtp, ln->tn_type, rn->tn_type); |
2900 | } else if (rt == PTR && rn->tn_type->t_subt->t_tspec == VOID) { | | 2900 | } else if (rt == PTR && rn->tn_type->t_subt->t_tspec == VOID) { |
2901 | lint_assert(lt == PTR); | | 2901 | lint_assert(lt == PTR); |
2902 | rtp = ln->tn_type; | | 2902 | rtp = ln->tn_type; |
2903 | merge_qualifiers(&rtp, ln->tn_type, rn->tn_type); | | 2903 | merge_qualifiers(&rtp, ln->tn_type, rn->tn_type); |
2904 | } else { | | 2904 | } else { |
2905 | lint_assert(lt == PTR); | | 2905 | lint_assert(lt == PTR); |
2906 | lint_assert(rt == PTR); | | 2906 | lint_assert(rt == PTR); |
2907 | /* | | 2907 | /* |
2908 | * XXX For now we simply take the left type. This is | | 2908 | * XXX For now we simply take the left type. This is |
2909 | * probably wrong, if one type contains a function prototype | | 2909 | * probably wrong, if one type contains a function prototype |
2910 | * and the other one, at the same place, only an old style | | 2910 | * and the other one, at the same place, only an old style |
2911 | * declaration. | | 2911 | * declaration. |
2912 | */ | | 2912 | */ |
2913 | rtp = ln->tn_type; | | 2913 | rtp = ln->tn_type; |
2914 | merge_qualifiers(&rtp, ln->tn_type, rn->tn_type); | | 2914 | merge_qualifiers(&rtp, ln->tn_type, rn->tn_type); |
2915 | } | | 2915 | } |
2916 | | | 2916 | |
2917 | ntn = new_tnode(COLON, rtp, ln, rn); | | 2917 | ntn = new_tnode(COLON, rtp, ln, rn); |
2918 | | | 2918 | |
2919 | return ntn; | | 2919 | return ntn; |
2920 | } | | 2920 | } |
2921 | | | 2921 | |
2922 | /* | | 2922 | /* |
2923 | * Create a node for an assignment operator (both = and op= ). | | 2923 | * Create a node for an assignment operator (both = and op= ). |
2924 | */ | | 2924 | */ |
2925 | static tnode_t * | | 2925 | static tnode_t * |
2926 | build_assignment(op_t op, tnode_t *ln, tnode_t *rn) | | 2926 | build_assignment(op_t op, tnode_t *ln, tnode_t *rn) |
2927 | { | | 2927 | { |
2928 | tspec_t lt, rt; | | 2928 | tspec_t lt, rt; |
2929 | tnode_t *ntn, *ctn; | | 2929 | tnode_t *ntn, *ctn; |
2930 | | | 2930 | |
2931 | lint_assert(ln != NULL); | | 2931 | lint_assert(ln != NULL); |
2932 | lint_assert(rn != NULL); | | 2932 | lint_assert(rn != NULL); |
2933 | | | 2933 | |
2934 | lt = ln->tn_type->t_tspec; | | 2934 | lt = ln->tn_type->t_tspec; |
2935 | rt = rn->tn_type->t_tspec; | | 2935 | rt = rn->tn_type->t_tspec; |
2936 | | | 2936 | |
2937 | if ((op == ADDASS || op == SUBASS) && lt == PTR) { | | 2937 | if ((op == ADDASS || op == SUBASS) && lt == PTR) { |
2938 | lint_assert(is_integer(rt)); | | 2938 | lint_assert(is_integer(rt)); |
2939 | ctn = plength(ln->tn_type); | | 2939 | ctn = plength(ln->tn_type); |
2940 | if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) | | 2940 | if (rn->tn_type->t_tspec != ctn->tn_type->t_tspec) |
2941 | rn = convert(NOOP, 0, ctn->tn_type, rn); | | 2941 | rn = convert(NOOP, 0, ctn->tn_type, rn); |
2942 | rn = new_tnode(MULT, rn->tn_type, rn, ctn); | | 2942 | rn = new_tnode(MULT, rn->tn_type, rn, ctn); |
2943 | if (rn->tn_left->tn_op == CON) | | 2943 | if (rn->tn_left->tn_op == CON) |
2944 | rn = fold(rn); | | 2944 | rn = fold(rn); |
2945 | } | | 2945 | } |
2946 | | | 2946 | |
2947 | if ((op == ASSIGN || op == RETURN) && (lt == STRUCT || rt == STRUCT)) { | | 2947 | if ((op == ASSIGN || op == RETURN) && (lt == STRUCT || rt == STRUCT)) { |
2948 | lint_assert(lt == rt); | | 2948 | lint_assert(lt == rt); |
2949 | lint_assert(ln->tn_type->t_str == rn->tn_type->t_str); | | 2949 | lint_assert(ln->tn_type->t_str == rn->tn_type->t_str); |
2950 | if (is_incomplete(ln->tn_type)) { | | 2950 | if (is_incomplete(ln->tn_type)) { |
2951 | if (op == RETURN) { | | 2951 | if (op == RETURN) { |
2952 | /* cannot return incomplete type */ | | 2952 | /* cannot return incomplete type */ |
2953 | error(212); | | 2953 | error(212); |
2954 | } else { | | 2954 | } else { |
2955 | /* unknown operand size, op %s */ | | 2955 | /* unknown operand size, op %s */ |
2956 | error(138, op_name(op)); | | 2956 | error(138, op_name(op)); |
2957 | } | | 2957 | } |
2958 | return NULL; | | 2958 | return NULL; |
2959 | } | | 2959 | } |
2960 | } | | 2960 | } |
2961 | | | 2961 | |
2962 | if (op == SHLASS) { | | 2962 | if (op == SHLASS) { |
2963 | if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { | | 2963 | if (portable_size_in_bits(lt) < portable_size_in_bits(rt)) { |
2964 | if (hflag) | | 2964 | if (hflag) |
2965 | /* semantics of '%s' change in ANSI C; ... */ | | 2965 | /* semantics of '%s' change in ANSI C; ... */ |
2966 | warning(118, "<<="); | | 2966 | warning(118, "<<="); |
2967 | } | | 2967 | } |
2968 | } else if (op != SHRASS) { | | 2968 | } else if (op != SHRASS) { |
2969 | if (op == ASSIGN || lt != PTR) { | | 2969 | if (op == ASSIGN || lt != PTR) { |
2970 | if (lt != rt || | | 2970 | if (lt != rt || |
2971 | (ln->tn_type->t_bitfield && rn->tn_op == CON)) { | | 2971 | (ln->tn_type->t_bitfield && rn->tn_op == CON)) { |
2972 | rn = convert(op, 0, ln->tn_type, rn); | | 2972 | rn = convert(op, 0, ln->tn_type, rn); |
2973 | rt = lt; | | 2973 | rt = lt; |
2974 | } | | 2974 | } |
2975 | } | | 2975 | } |
2976 | } | | 2976 | } |
2977 | | | 2977 | |
2978 | ntn = new_tnode(op, ln->tn_type, ln, rn); | | 2978 | ntn = new_tnode(op, ln->tn_type, ln, rn); |
2979 | | | 2979 | |
2980 | return ntn; | | 2980 | return ntn; |
2981 | } | | 2981 | } |
2982 | | | 2982 | |
2983 | /* | | 2983 | /* |
2984 | * Get length of type tp->t_subt. | | 2984 | * Get length of type tp->t_subt. |
2985 | */ | | 2985 | */ |
2986 | static tnode_t * | | 2986 | static tnode_t * |
2987 | plength(type_t *tp) | | 2987 | plength(type_t *tp) |
2988 | { | | 2988 | { |
2989 | int elem, elsz; | | 2989 | int elem, elsz; |
2990 | | | 2990 | |
2991 | lint_assert(tp->t_tspec == PTR); | | 2991 | lint_assert(tp->t_tspec == PTR); |
2992 | tp = tp->t_subt; | | 2992 | tp = tp->t_subt; |
2993 | | | 2993 | |
2994 | elem = 1; | | 2994 | elem = 1; |
2995 | elsz = 0; | | 2995 | elsz = 0; |
2996 | | | 2996 | |
2997 | while (tp->t_tspec == ARRAY) { | | 2997 | while (tp->t_tspec == ARRAY) { |
2998 | elem *= tp->t_dim; | | 2998 | elem *= tp->t_dim; |
2999 | tp = tp->t_subt; | | 2999 | tp = tp->t_subt; |
3000 | } | | 3000 | } |
3001 | | | 3001 | |
3002 | switch (tp->t_tspec) { | | 3002 | switch (tp->t_tspec) { |
3003 | case FUNC: | | 3003 | case FUNC: |
3004 | /* pointer to function is not allowed here */ | | 3004 | /* pointer to function is not allowed here */ |
3005 | error(110); | | 3005 | error(110); |
3006 | break; | | 3006 | break; |
3007 | case VOID: | | 3007 | case VOID: |
3008 | /* cannot do pointer arithmetic on operand of unknown size */ | | 3008 | /* cannot do pointer arithmetic on operand of unknown size */ |
3009 | gnuism(136); | | 3009 | gnuism(136); |
3010 | break; | | 3010 | break; |
3011 | case STRUCT: | | 3011 | case STRUCT: |
3012 | case UNION: | | 3012 | case UNION: |
3013 | if ((elsz = tp->t_str->sou_size_in_bits) == 0) | | 3013 | if ((elsz = tp->t_str->sou_size_in_bits) == 0) |
3014 | /* cannot do pointer arithmetic on operand of ... */ | | 3014 | /* cannot do pointer arithmetic on operand of ... */ |
3015 | error(136); | | 3015 | error(136); |
3016 | break; | | 3016 | break; |
3017 | case ENUM: | | 3017 | case ENUM: |
3018 | if (is_incomplete(tp)) { | | 3018 | if (is_incomplete(tp)) { |
3019 | /* cannot do pointer arithmetic on operand of ... */ | | 3019 | /* cannot do pointer arithmetic on operand of ... */ |
3020 | warning(136); | | 3020 | warning(136); |
3021 | } | | 3021 | } |
3022 | /* FALLTHROUGH */ | | 3022 | /* FALLTHROUGH */ |
3023 | default: | | 3023 | default: |
3024 | if ((elsz = size_in_bits(tp->t_tspec)) == 0) { | | 3024 | if ((elsz = size_in_bits(tp->t_tspec)) == 0) { |
3025 | /* cannot do pointer arithmetic on operand of ... */ | | 3025 | /* cannot do pointer arithmetic on operand of ... */ |
3026 | error(136); | | 3026 | error(136); |
3027 | } else { | | 3027 | } else { |
3028 | lint_assert(elsz != -1); | | 3028 | lint_assert(elsz != -1); |
3029 | } | | 3029 | } |
3030 | break; | | 3030 | break; |
3031 | } | | 3031 | } |
3032 | | | 3032 | |
3033 | if (elem == 0 && elsz != 0) { | | 3033 | if (elem == 0 && elsz != 0) { |
3034 | /* cannot do pointer arithmetic on operand of unknown size */ | | 3034 | /* cannot do pointer arithmetic on operand of unknown size */ |
3035 | error(136); | | 3035 | error(136); |
3036 | } | | 3036 | } |
3037 | | | 3037 | |
3038 | if (elsz == 0) | | 3038 | if (elsz == 0) |
3039 | elsz = CHAR_SIZE; | | 3039 | elsz = CHAR_SIZE; |
3040 | | | 3040 | |
3041 | return expr_new_integer_constant(PTRDIFF_TSPEC, | | 3041 | return expr_new_integer_constant(PTRDIFF_TSPEC, |
3042 | (int64_t)(elem * elsz / CHAR_SIZE)); | | 3042 | (int64_t)(elem * elsz / CHAR_SIZE)); |
3043 | } | | 3043 | } |
3044 | | | 3044 | |
3045 | /* | | 3045 | /* |
3046 | * XXX | | 3046 | * XXX |
3047 | * Note: There appear to be a number of bugs in detecting overflow in | | 3047 | * Note: There appear to be a number of bugs in detecting overflow in |
3048 | * this function. An audit and a set of proper regression tests are needed. | | 3048 | * this function. An audit and a set of proper regression tests are needed. |
3049 | * --Perry Metzger, Nov. 16, 2001 | | 3049 | * --Perry Metzger, Nov. 16, 2001 |
3050 | */ | | 3050 | */ |
3051 | /* | | 3051 | /* |
3052 | * Do only as much as necessary to compute constant expressions. | | 3052 | * Do only as much as necessary to compute constant expressions. |
3053 | * Called only if the operator allows folding and all operands are constants. | | 3053 | * Called only if the operator allows folding and all operands are constants. |
3054 | */ | | 3054 | */ |
3055 | static tnode_t * | | 3055 | static tnode_t * |
3056 | fold(tnode_t *tn) | | 3056 | fold(tnode_t *tn) |
3057 | { | | 3057 | { |
3058 | val_t *v; | | 3058 | val_t *v; |
3059 | tspec_t t; | | 3059 | tspec_t t; |
3060 | bool utyp, ovfl; | | 3060 | bool utyp, ovfl; |
3061 | int64_t sl, sr = 0, q = 0, mask; | | 3061 | int64_t sl, sr = 0, q = 0, mask; |
3062 | uint64_t ul, ur = 0; | | 3062 | uint64_t ul, ur = 0; |
3063 | tnode_t *cn; | | 3063 | tnode_t *cn; |
3064 | | | 3064 | |
3065 | v = xcalloc(1, sizeof(*v)); | | 3065 | v = xcalloc(1, sizeof(*v)); |
3066 | v->v_tspec = t = tn->tn_type->t_tspec; | | 3066 | v->v_tspec = t = tn->tn_type->t_tspec; |
3067 | | | 3067 | |
3068 | utyp = t == PTR || is_uinteger(t); | | 3068 | utyp = t == PTR || is_uinteger(t); |
3069 | ul = sl = tn->tn_left->tn_val->v_quad; | | 3069 | ul = sl = tn->tn_left->tn_val->v_quad; |
3070 | if (modtab[tn->tn_op].m_binary) | | 3070 | if (modtab[tn->tn_op].m_binary) |
3071 | ur = sr = tn->tn_right->tn_val->v_quad; | | 3071 | ur = sr = tn->tn_right->tn_val->v_quad; |
3072 | | | 3072 | |
3073 | mask = qlmasks[size_in_bits(t)]; | | 3073 | mask = qlmasks[size_in_bits(t)]; |
3074 | ovfl = false; | | 3074 | ovfl = false; |
3075 | | | 3075 | |
3076 | switch (tn->tn_op) { | | 3076 | switch (tn->tn_op) { |
3077 | case UPLUS: | | 3077 | case UPLUS: |
3078 | q = sl; | | 3078 | q = sl; |
3079 | break; | | 3079 | break; |
3080 | case UMINUS: | | 3080 | case UMINUS: |
3081 | q = -sl; | | 3081 | q = -sl; |
3082 | if (sl != 0 && msb(q, t, -1) == msb(sl, t, -1)) | | 3082 | if (sl != 0 && msb(q, t, -1) == msb(sl, t, -1)) |
3083 | ovfl = true; | | 3083 | ovfl = true; |
3084 | break; | | 3084 | break; |
3085 | case COMPL: | | 3085 | case COMPL: |
3086 | q = ~sl; | | 3086 | q = ~sl; |
3087 | break; | | 3087 | break; |
3088 | case MULT: | | 3088 | case MULT: |
3089 | if (utyp) { | | 3089 | if (utyp) { |
3090 | q = ul * ur; | | 3090 | q = ul * ur; |
3091 | if (q != (q & mask)) | | 3091 | if (q != (q & mask)) |
3092 | ovfl = true; | | 3092 | ovfl = true; |
3093 | else if ((ul != 0) && ((q / ul) != ur)) | | 3093 | else if ((ul != 0) && ((q / ul) != ur)) |
3094 | ovfl = true; | | 3094 | ovfl = true; |
3095 | } else { | | 3095 | } else { |
3096 | q = sl * sr; | | 3096 | q = sl * sr; |
3097 | if (msb(q, t, -1) != (msb(sl, t, -1) ^ msb(sr, t, -1))) | | 3097 | if (msb(q, t, -1) != (msb(sl, t, -1) ^ msb(sr, t, -1))) |
3098 | ovfl = true; | | 3098 | ovfl = true; |
3099 | } | | 3099 | } |
3100 | break; | | 3100 | break; |
3101 | case DIV: | | 3101 | case DIV: |
3102 | if (sr == 0) { | | 3102 | if (sr == 0) { |
3103 | /* division by 0 */ | | 3103 | /* division by 0 */ |
3104 | error(139); | | 3104 | error(139); |
3105 | q = utyp ? UQUAD_MAX : QUAD_MAX; | | 3105 | q = utyp ? UQUAD_MAX : QUAD_MAX; |
3106 | } else { | | 3106 | } else { |
3107 | q = utyp ? (int64_t)(ul / ur) : sl / sr; | | 3107 | q = utyp ? (int64_t)(ul / ur) : sl / sr; |
3108 | } | | 3108 | } |
3109 | break; | | 3109 | break; |
3110 | case MOD: | | 3110 | case MOD: |
3111 | if (sr == 0) { | | 3111 | if (sr == 0) { |
3112 | /* modulus by 0 */ | | 3112 | /* modulus by 0 */ |
3113 | error(140); | | 3113 | error(140); |
3114 | q = 0; | | 3114 | q = 0; |
3115 | } else { | | 3115 | } else { |
3116 | q = utyp ? (int64_t)(ul % ur) : sl % sr; | | 3116 | q = utyp ? (int64_t)(ul % ur) : sl % sr; |
3117 | } | | 3117 | } |
3118 | break; | | 3118 | break; |
3119 | case PLUS: | | 3119 | case PLUS: |
3120 | q = utyp ? (int64_t)(ul + ur) : sl + sr; | | 3120 | q = utyp ? (int64_t)(ul + ur) : sl + sr; |
3121 | if (msb(sl, t, -1) != 0 && msb(sr, t, -1) != 0) { | | 3121 | if (msb(sl, t, -1) != 0 && msb(sr, t, -1) != 0) { |
3122 | if (msb(q, t, -1) == 0) | | 3122 | if (msb(q, t, -1) == 0) |
3123 | ovfl = true; | | 3123 | ovfl = true; |
3124 | } else if (msb(sl, t, -1) == 0 && msb(sr, t, -1) == 0) { | | 3124 | } else if (msb(sl, t, -1) == 0 && msb(sr, t, -1) == 0) { |
3125 | if (msb(q, t, -1) != 0) | | 3125 | if (msb(q, t, -1) != 0) |
3126 | ovfl = true; | | 3126 | ovfl = true; |
3127 | } | | 3127 | } |
3128 | break; | | 3128 | break; |
3129 | case MINUS: | | 3129 | case MINUS: |
3130 | q = utyp ? (int64_t)(ul - ur) : sl - sr; | | 3130 | q = utyp ? (int64_t)(ul - ur) : sl - sr; |
3131 | if (msb(sl, t, -1) != 0 && msb(sr, t, -1) == 0) { | | 3131 | if (msb(sl, t, -1) != 0 && msb(sr, t, -1) == 0) { |
3132 | if (msb(q, t, -1) == 0) | | 3132 | if (msb(q, t, -1) == 0) |
3133 | ovfl = true; | | 3133 | ovfl = true; |
3134 | } else if (msb(sl, t, -1) == 0 && msb(sr, t, -1) != 0) { | | 3134 | } else if (msb(sl, t, -1) == 0 && msb(sr, t, -1) != 0) { |
3135 | if (msb(q, t, -1) != 0) | | 3135 | if (msb(q, t, -1) != 0) |
3136 | ovfl = true; | | 3136 | ovfl = true; |
3137 | } | | 3137 | } |
3138 | break; | | 3138 | break; |
3139 | case SHL: | | 3139 | case SHL: |
3140 | q = utyp ? (int64_t)(ul << sr) : sl << sr; | | 3140 | q = utyp ? (int64_t)(ul << sr) : sl << sr; |
3141 | break; | | 3141 | break; |
3142 | case SHR: | | 3142 | case SHR: |
3143 | /* | | 3143 | /* |
3144 | * The sign must be explicitly extended because | | 3144 | * The sign must be explicitly extended because |
3145 | * shifts of signed values are implementation dependent. | | 3145 | * shifts of signed values are implementation dependent. |
3146 | */ | | 3146 | */ |
3147 | q = ul >> sr; | | 3147 | q = ul >> sr; |
3148 | q = xsign(q, t, size_in_bits(t) - (int)sr); | | 3148 | q = xsign(q, t, size_in_bits(t) - (int)sr); |
3149 | break; | | 3149 | break; |
3150 | case LT: | | 3150 | case LT: |
3151 | q = (utyp ? ul < ur : sl < sr) ? 1 : 0; | | 3151 | q = (utyp ? ul < ur : sl < sr) ? 1 : 0; |
3152 | break; | | 3152 | break; |
3153 | case LE: | | 3153 | case LE: |
3154 | q = (utyp ? ul <= ur : sl <= sr) ? 1 : 0; | | 3154 | q = (utyp ? ul <= ur : sl <= sr) ? 1 : 0; |
3155 | break; | | 3155 | break; |
3156 | case GE: | | 3156 | case GE: |
3157 | q = (utyp ? ul >= ur : sl >= sr) ? 1 : 0; | | 3157 | q = (utyp ? ul >= ur : sl >= sr) ? 1 : 0; |
3158 | break; | | 3158 | break; |
3159 | case GT: | | 3159 | case GT: |
3160 | q = (utyp ? ul > ur : sl > sr) ? 1 : 0; | | 3160 | q = (utyp ? ul > ur : sl > sr) ? 1 : 0; |
3161 | break; | | 3161 | break; |
3162 | case EQ: | | 3162 | case EQ: |
3163 | q = (utyp ? ul == ur : sl == sr) ? 1 : 0; | | 3163 | q = (utyp ? ul == ur : sl == sr) ? 1 : 0; |
3164 | break; | | 3164 | break; |
3165 | case NE: | | 3165 | case NE: |
3166 | q = (utyp ? ul != ur : sl != sr) ? 1 : 0; | | 3166 | q = (utyp ? ul != ur : sl != sr) ? 1 : 0; |
3167 | break; | | 3167 | break; |
3168 | case BITAND: | | 3168 | case BITAND: |
3169 | q = utyp ? (int64_t)(ul & ur) : sl & sr; | | 3169 | q = utyp ? (int64_t)(ul & ur) : sl & sr; |
3170 | break; | | 3170 | break; |
3171 | case BITXOR: | | 3171 | case BITXOR: |
3172 | q = utyp ? (int64_t)(ul ^ ur) : sl ^ sr; | | 3172 | q = utyp ? (int64_t)(ul ^ ur) : sl ^ sr; |
3173 | break; | | 3173 | break; |
3174 | case BITOR: | | 3174 | case BITOR: |
3175 | q = utyp ? (int64_t)(ul | ur) : sl | sr; | | 3175 | q = utyp ? (int64_t)(ul | ur) : sl | sr; |
3176 | break; | | 3176 | break; |
3177 | default: | | 3177 | default: |
3178 | lint_assert(/*CONSTCOND*/false); | | 3178 | lint_assert(/*CONSTCOND*/false); |
3179 | } | | 3179 | } |
3180 | | | 3180 | |
3181 | /* XXX does not work for quads. */ | | 3181 | /* XXX does not work for quads. */ |
3182 | if (ovfl || ((uint64_t)(q | mask) != ~(uint64_t)0 && | | 3182 | if (ovfl || ((uint64_t)(q | mask) != ~(uint64_t)0 && |
3183 | (q & ~mask) != 0)) { | | 3183 | (q & ~mask) != 0)) { |
3184 | if (hflag) | | 3184 | if (hflag) |
3185 | /* integer overflow detected, op %s */ | | 3185 | /* integer overflow detected, op %s */ |
3186 | warning(141, modtab[tn->tn_op].m_name); | | 3186 | warning(141, op_name(tn->tn_op)); |
3187 | } | | 3187 | } |
3188 | | | 3188 | |
3189 | v->v_quad = xsign(q, t, -1); | | 3189 | v->v_quad = xsign(q, t, -1); |
3190 | | | 3190 | |
3191 | cn = expr_new_constant(tn->tn_type, v); | | 3191 | cn = expr_new_constant(tn->tn_type, v); |
3192 | if (tn->tn_left->tn_system_dependent) | | 3192 | if (tn->tn_left->tn_system_dependent) |
3193 | cn->tn_system_dependent = true; | | 3193 | cn->tn_system_dependent = true; |
3194 | if (modtab[tn->tn_op].m_binary && tn->tn_right->tn_system_dependent) | | 3194 | if (modtab[tn->tn_op].m_binary && tn->tn_right->tn_system_dependent) |
3195 | cn->tn_system_dependent = true; | | 3195 | cn->tn_system_dependent = true; |
3196 | | | 3196 | |
3197 | return cn; | | 3197 | return cn; |
3198 | } | | 3198 | } |
3199 | | | 3199 | |
3200 | /* | | 3200 | /* |
3201 | * Fold constant nodes, as much as is needed for comparing the value with 0 | | 3201 | * Fold constant nodes, as much as is needed for comparing the value with 0 |
3202 | * (test context, for controlling expressions). | | 3202 | * (test context, for controlling expressions). |
3203 | */ | | 3203 | */ |
3204 | static tnode_t * | | 3204 | static tnode_t * |
3205 | fold_test(tnode_t *tn) | | 3205 | fold_test(tnode_t *tn) |
3206 | { | | 3206 | { |
3207 | bool l, r; | | 3207 | bool l, r; |
3208 | val_t *v; | | 3208 | val_t *v; |
3209 | | | 3209 | |
3210 | v = xcalloc(1, sizeof(*v)); | | 3210 | v = xcalloc(1, sizeof(*v)); |
3211 | v->v_tspec = tn->tn_type->t_tspec; | | 3211 | v->v_tspec = tn->tn_type->t_tspec; |
3212 | lint_assert(v->v_tspec == INT || (Tflag && v->v_tspec == BOOL)); | | 3212 | lint_assert(v->v_tspec == INT || (Tflag && v->v_tspec == BOOL)); |
3213 | | | 3213 | |
3214 | l = constant_is_nonzero(tn->tn_left); | | 3214 | l = constant_is_nonzero(tn->tn_left); |
3215 | r = modtab[tn->tn_op].m_binary && constant_is_nonzero(tn->tn_right); | | 3215 | r = modtab[tn->tn_op].m_binary && constant_is_nonzero(tn->tn_right); |
3216 | | | 3216 | |
3217 | switch (tn->tn_op) { | | 3217 | switch (tn->tn_op) { |
3218 | case NOT: | | 3218 | case NOT: |
3219 | if (hflag && !constcond_flag) | | 3219 | if (hflag && !constcond_flag) |
3220 | /* constant argument to NOT */ | | 3220 | /* constant argument to NOT */ |
3221 | warning(239); | | 3221 | warning(239); |
3222 | v->v_quad = !l ? 1 : 0; | | 3222 | v->v_quad = !l ? 1 : 0; |
3223 | break; | | 3223 | break; |
3224 | case LOGAND: | | 3224 | case LOGAND: |
3225 | v->v_quad = l && r ? 1 : 0; | | 3225 | v->v_quad = l && r ? 1 : 0; |
3226 | break; | | 3226 | break; |
3227 | case LOGOR: | | 3227 | case LOGOR: |
3228 | v->v_quad = l || r ? 1 : 0; | | 3228 | v->v_quad = l || r ? 1 : 0; |
3229 | break; | | 3229 | break; |
3230 | default: | | 3230 | default: |
3231 | lint_assert(/*CONSTCOND*/false); | | 3231 | lint_assert(/*CONSTCOND*/false); |
3232 | } | | 3232 | } |
3233 | | | 3233 | |
3234 | return expr_new_constant(tn->tn_type, v); | | 3234 | return expr_new_constant(tn->tn_type, v); |
3235 | } | | 3235 | } |
3236 | | | 3236 | |
3237 | /* | | 3237 | /* |
3238 | * Fold constant nodes having operands with floating point type. | | 3238 | * Fold constant nodes having operands with floating point type. |
3239 | */ | | 3239 | */ |
3240 | static tnode_t * | | 3240 | static tnode_t * |
3241 | fold_float(tnode_t *tn) | | 3241 | fold_float(tnode_t *tn) |
3242 | { | | 3242 | { |
3243 | val_t *v; | | 3243 | val_t *v; |
3244 | tspec_t t; | | 3244 | tspec_t t; |
3245 | ldbl_t l, r = 0; | | 3245 | ldbl_t l, r = 0; |
3246 | | | 3246 | |
3247 | fpe = 0; | | 3247 | fpe = 0; |
3248 | v = xcalloc(1, sizeof(*v)); | | 3248 | v = xcalloc(1, sizeof(*v)); |
3249 | v->v_tspec = t = tn->tn_type->t_tspec; | | 3249 | v->v_tspec = t = tn->tn_type->t_tspec; |
3250 | | | 3250 | |
3251 | lint_assert(is_floating(t)); | | 3251 | lint_assert(is_floating(t)); |
3252 | lint_assert(t == tn->tn_left->tn_type->t_tspec); | | 3252 | lint_assert(t == tn->tn_left->tn_type->t_tspec); |
3253 | lint_assert(!modtab[tn->tn_op].m_binary || | | 3253 | lint_assert(!modtab[tn->tn_op].m_binary || |
3254 | t == tn->tn_right->tn_type->t_tspec); | | 3254 | t == tn->tn_right->tn_type->t_tspec); |
3255 | | | 3255 | |
3256 | l = tn->tn_left->tn_val->v_ldbl; | | 3256 | l = tn->tn_left->tn_val->v_ldbl; |
3257 | if (modtab[tn->tn_op].m_binary) | | 3257 | if (modtab[tn->tn_op].m_binary) |
3258 | r = tn->tn_right->tn_val->v_ldbl; | | 3258 | r = tn->tn_right->tn_val->v_ldbl; |
3259 | | | 3259 | |
3260 | switch (tn->tn_op) { | | 3260 | switch (tn->tn_op) { |
3261 | case UPLUS: | | 3261 | case UPLUS: |
3262 | v->v_ldbl = l; | | 3262 | v->v_ldbl = l; |
3263 | break; | | 3263 | break; |
3264 | case UMINUS: | | 3264 | case UMINUS: |
3265 | v->v_ldbl = -l; | | 3265 | v->v_ldbl = -l; |
3266 | break; | | 3266 | break; |
3267 | case MULT: | | 3267 | case MULT: |
3268 | v->v_ldbl = l * r; | | 3268 | v->v_ldbl = l * r; |
3269 | break; | | 3269 | break; |
3270 | case DIV: | | 3270 | case DIV: |
3271 | if (r == 0.0) { | | 3271 | if (r == 0.0) { |
3272 | /* division by 0 */ | | 3272 | /* division by 0 */ |
3273 | error(139); | | 3273 | error(139); |
3274 | if (t == FLOAT) { | | 3274 | if (t == FLOAT) { |
3275 | v->v_ldbl = l < 0 ? -FLT_MAX : FLT_MAX; | | 3275 | v->v_ldbl = l < 0 ? -FLT_MAX : FLT_MAX; |
3276 | } else if (t == DOUBLE) { | | 3276 | } else if (t == DOUBLE) { |
3277 | v->v_ldbl = l < 0 ? -DBL_MAX : DBL_MAX; | | 3277 | v->v_ldbl = l < 0 ? -DBL_MAX : DBL_MAX; |
3278 | } else { | | 3278 | } else { |
3279 | v->v_ldbl = l < 0 ? -LDBL_MAX : LDBL_MAX; | | 3279 | v->v_ldbl = l < 0 ? -LDBL_MAX : LDBL_MAX; |
3280 | } | | 3280 | } |
3281 | } else { | | 3281 | } else { |
3282 | v->v_ldbl = l / r; | | 3282 | v->v_ldbl = l / r; |
3283 | } | | 3283 | } |
3284 | break; | | 3284 | break; |
3285 | case PLUS: | | 3285 | case PLUS: |
3286 | v->v_ldbl = l + r; | | 3286 | v->v_ldbl = l + r; |
3287 | break; | | 3287 | break; |
3288 | case MINUS: | | 3288 | case MINUS: |
3289 | v->v_ldbl = l - r; | | 3289 | v->v_ldbl = l - r; |
3290 | break; | | 3290 | break; |
3291 | case LT: | | 3291 | case LT: |
3292 | v->v_quad = l < r ? 1 : 0; | | 3292 | v->v_quad = l < r ? 1 : 0; |
3293 | break; | | 3293 | break; |
3294 | case LE: | | 3294 | case LE: |
3295 | v->v_quad = l <= r ? 1 : 0; | | 3295 | v->v_quad = l <= r ? 1 : 0; |
3296 | break; | | 3296 | break; |
3297 | case GE: | | 3297 | case GE: |
3298 | v->v_quad = l >= r ? 1 : 0; | | 3298 | v->v_quad = l >= r ? 1 : 0; |
3299 | break; | | 3299 | break; |
3300 | case GT: | | 3300 | case GT: |
3301 | v->v_quad = l > r ? 1 : 0; | | 3301 | v->v_quad = l > r ? 1 : 0; |
3302 | break; | | 3302 | break; |
3303 | case EQ: | | 3303 | case EQ: |
3304 | v->v_quad = l == r ? 1 : 0; | | 3304 | v->v_quad = l == r ? 1 : 0; |
3305 | break; | | 3305 | break; |
3306 | case NE: | | 3306 | case NE: |
3307 | v->v_quad = l != r ? 1 : 0; | | 3307 | v->v_quad = l != r ? 1 : 0; |
3308 | break; | | 3308 | break; |
3309 | default: | | 3309 | default: |
3310 | lint_assert(/*CONSTCOND*/false); | | 3310 | lint_assert(/*CONSTCOND*/false); |
3311 | } | | 3311 | } |
3312 | | | 3312 | |
3313 | lint_assert(fpe != 0 || isnan((double)v->v_ldbl) == 0); | | 3313 | lint_assert(fpe != 0 || isnan((double)v->v_ldbl) == 0); |
3314 | if (fpe != 0 || finite((double)v->v_ldbl) == 0 || | | 3314 | if (fpe != 0 || finite((double)v->v_ldbl) == 0 || |
3315 | (t == FLOAT && | | 3315 | (t == FLOAT && |
3316 | (v->v_ldbl > FLT_MAX || v->v_ldbl < -FLT_MAX)) || | | 3316 | (v->v_ldbl > FLT_MAX || v->v_ldbl < -FLT_MAX)) || |
3317 | (t == DOUBLE && | | 3317 | (t == DOUBLE && |
3318 | (v->v_ldbl > DBL_MAX || v->v_ldbl < -DBL_MAX))) { | | 3318 | (v->v_ldbl > DBL_MAX || v->v_ldbl < -DBL_MAX))) { |
3319 | /* floating point overflow detected, op %s */ | | 3319 | /* floating point overflow detected, op %s */ |
3320 | warning(142, modtab[tn->tn_op].m_name); | | 3320 | warning(142, op_name(tn->tn_op)); |
3321 | if (t == FLOAT) { | | 3321 | if (t == FLOAT) { |
3322 | v->v_ldbl = v->v_ldbl < 0 ? -FLT_MAX : FLT_MAX; | | 3322 | v->v_ldbl = v->v_ldbl < 0 ? -FLT_MAX : FLT_MAX; |
3323 | } else if (t == DOUBLE) { | | 3323 | } else if (t == DOUBLE) { |
3324 | v->v_ldbl = v->v_ldbl < 0 ? -DBL_MAX : DBL_MAX; | | 3324 | v->v_ldbl = v->v_ldbl < 0 ? -DBL_MAX : DBL_MAX; |
3325 | } else { | | 3325 | } else { |
3326 | v->v_ldbl = v->v_ldbl < 0 ? -LDBL_MAX: LDBL_MAX; | | 3326 | v->v_ldbl = v->v_ldbl < 0 ? -LDBL_MAX: LDBL_MAX; |
3327 | } | | 3327 | } |
3328 | fpe = 0; | | 3328 | fpe = 0; |
3329 | } | | 3329 | } |
3330 | | | 3330 | |
3331 | return expr_new_constant(tn->tn_type, v); | | 3331 | return expr_new_constant(tn->tn_type, v); |
3332 | } | | 3332 | } |
3333 | | | 3333 | |
3334 | | | 3334 | |
3335 | /* | | 3335 | /* |
3336 | * Create a constant node for sizeof. | | 3336 | * Create a constant node for sizeof. |
3337 | */ | | 3337 | */ |
3338 | tnode_t * | | 3338 | tnode_t * |
3339 | build_sizeof(const type_t *tp) | | 3339 | build_sizeof(const type_t *tp) |
3340 | { | | 3340 | { |
3341 | int64_t size_in_bytes = type_size_in_bits(tp) / CHAR_SIZE; | | 3341 | int64_t size_in_bytes = type_size_in_bits(tp) / CHAR_SIZE; |
3342 | tnode_t *tn = expr_new_integer_constant(SIZEOF_TSPEC, size_in_bytes); | | 3342 | tnode_t *tn = expr_new_integer_constant(SIZEOF_TSPEC, size_in_bytes); |
3343 | tn->tn_system_dependent = true; | | 3343 | tn->tn_system_dependent = true; |
3344 | return tn; | | 3344 | return tn; |
3345 | } | | 3345 | } |
3346 | | | 3346 | |
3347 | /* | | 3347 | /* |
3348 | * Create a constant node for offsetof. | | 3348 | * Create a constant node for offsetof. |
3349 | */ | | 3349 | */ |
3350 | tnode_t * | | 3350 | tnode_t * |
3351 | build_offsetof(const type_t *tp, const sym_t *sym) | | 3351 | build_offsetof(const type_t *tp, const sym_t *sym) |
3352 | { | | 3352 | { |
3353 | tspec_t t = tp->t_tspec; | | 3353 | tspec_t t = tp->t_tspec; |
3354 | if (t != STRUCT && t != UNION) | | 3354 | if (t != STRUCT && t != UNION) |
3355 | /* unacceptable operand of '%s' */ | | 3355 | /* unacceptable operand of '%s' */ |
3356 | error(111, "offsetof"); | | 3356 | error(111, "offsetof"); |
3357 | | | 3357 | |
3358 | // XXX: wrong size, no checking for sym fixme | | 3358 | // XXX: wrong size, no checking for sym fixme |
3359 | int64_t offset_in_bytes = type_size_in_bits(tp) / CHAR_SIZE; | | 3359 | int64_t offset_in_bytes = type_size_in_bits(tp) / CHAR_SIZE; |
3360 | tnode_t *tn = expr_new_integer_constant(SIZEOF_TSPEC, offset_in_bytes); | | 3360 | tnode_t *tn = expr_new_integer_constant(SIZEOF_TSPEC, offset_in_bytes); |
3361 | tn->tn_system_dependent = true; | | 3361 | tn->tn_system_dependent = true; |
3362 | return tn; | | 3362 | return tn; |
3363 | } | | 3363 | } |
3364 | | | 3364 | |
3365 | int64_t | | 3365 | int64_t |
3366 | type_size_in_bits(const type_t *tp) | | 3366 | type_size_in_bits(const type_t *tp) |
3367 | { | | 3367 | { |
3368 | int elem, elsz; | | 3368 | int elem, elsz; |
3369 | bool flex; | | 3369 | bool flex; |
3370 | | | 3370 | |
3371 | elem = 1; | | 3371 | elem = 1; |
3372 | flex = false; | | 3372 | flex = false; |
3373 | while (tp->t_tspec == ARRAY) { | | 3373 | while (tp->t_tspec == ARRAY) { |
3374 | flex = true; /* allow c99 flex arrays [] [0] */ | | 3374 | flex = true; /* allow c99 flex arrays [] [0] */ |
3375 | elem *= tp->t_dim; | | 3375 | elem *= tp->t_dim; |
3376 | tp = tp->t_subt; | | 3376 | tp = tp->t_subt; |
3377 | } | | 3377 | } |
3378 | if (elem == 0) { | | 3378 | if (elem == 0) { |
3379 | if (!flex) { | | 3379 | if (!flex) { |
3380 | /* cannot take size/alignment of incomplete type */ | | 3380 | /* cannot take size/alignment of incomplete type */ |
3381 | error(143); | | 3381 | error(143); |
3382 | elem = 1; | | 3382 | elem = 1; |
3383 | } | | 3383 | } |
3384 | } | | 3384 | } |
3385 | switch (tp->t_tspec) { | | 3385 | switch (tp->t_tspec) { |
3386 | case FUNC: | | 3386 | case FUNC: |
3387 | /* cannot take size/alignment of function */ | | 3387 | /* cannot take size/alignment of function */ |
3388 | error(144); | | 3388 | error(144); |
3389 | elsz = 1; | | 3389 | elsz = 1; |
3390 | break; | | 3390 | break; |
3391 | case STRUCT: | | 3391 | case STRUCT: |
3392 | case UNION: | | 3392 | case UNION: |
3393 | if (is_incomplete(tp)) { | | 3393 | if (is_incomplete(tp)) { |
3394 | /* cannot take size/alignment of incomplete type */ | | 3394 | /* cannot take size/alignment of incomplete type */ |
3395 | error(143); | | 3395 | error(143); |
3396 | elsz = 1; | | 3396 | elsz = 1; |
3397 | } else { | | 3397 | } else { |
3398 | elsz = tp->t_str->sou_size_in_bits; | | 3398 | elsz = tp->t_str->sou_size_in_bits; |
3399 | } | | 3399 | } |
3400 | break; | | 3400 | break; |
3401 | case ENUM: | | 3401 | case ENUM: |
3402 | if (is_incomplete(tp)) { | | 3402 | if (is_incomplete(tp)) { |
3403 | /* cannot take size/alignment of incomplete type */ | | 3403 | /* cannot take size/alignment of incomplete type */ |
3404 | warning(143); | | 3404 | warning(143); |
3405 | } | | 3405 | } |
3406 | /* FALLTHROUGH */ | | 3406 | /* FALLTHROUGH */ |
3407 | default: | | 3407 | default: |
3408 | if (tp->t_bitfield) { | | 3408 | if (tp->t_bitfield) { |
3409 | /* cannot take size/alignment of bit-field */ | | 3409 | /* cannot take size/alignment of bit-field */ |
3410 | error(145); | | 3410 | error(145); |
3411 | } | | 3411 | } |
3412 | if (tp->t_tspec == VOID) { | | 3412 | if (tp->t_tspec == VOID) { |
3413 | /* cannot take size/alignment of void */ | | 3413 | /* cannot take size/alignment of void */ |
3414 | error(146); | | 3414 | error(146); |
3415 | elsz = 1; | | 3415 | elsz = 1; |
3416 | } else { | | 3416 | } else { |
3417 | elsz = size_in_bits(tp->t_tspec); | | 3417 | elsz = size_in_bits(tp->t_tspec); |
3418 | lint_assert(elsz > 0); | | 3418 | lint_assert(elsz > 0); |
3419 | } | | 3419 | } |
3420 | break; | | 3420 | break; |
3421 | } | | 3421 | } |
3422 | | | 3422 | |
3423 | return (int64_t)elem * elsz; | | 3423 | return (int64_t)elem * elsz; |
3424 | } | | 3424 | } |
3425 | | | 3425 | |
3426 | tnode_t * | | 3426 | tnode_t * |
3427 | build_alignof(const type_t *tp) | | 3427 | build_alignof(const type_t *tp) |
3428 | { | | 3428 | { |
3429 | switch (tp->t_tspec) { | | 3429 | switch (tp->t_tspec) { |
3430 | case ARRAY: | | 3430 | case ARRAY: |
3431 | break; | | 3431 | break; |
3432 | | | 3432 | |
3433 | case FUNC: | | 3433 | case FUNC: |
3434 | /* cannot take size/alignment of function */ | | 3434 | /* cannot take size/alignment of function */ |
3435 | error(144); | | 3435 | error(144); |
3436 | return 0; | | 3436 | return 0; |
3437 | | | 3437 | |
3438 | case STRUCT: | | 3438 | case STRUCT: |
3439 | case UNION: | | 3439 | case UNION: |
3440 | if (is_incomplete(tp)) { | | 3440 | if (is_incomplete(tp)) { |
3441 | /* cannot take size/alignment of incomplete type */ | | 3441 | /* cannot take size/alignment of incomplete type */ |
3442 | error(143); | | 3442 | error(143); |
3443 | return 0; | | 3443 | return 0; |
3444 | } | | 3444 | } |
3445 | break; | | 3445 | break; |
3446 | case ENUM: | | 3446 | case ENUM: |
3447 | break; | | 3447 | break; |
3448 | default: | | 3448 | default: |
3449 | if (tp->t_bitfield) { | | 3449 | if (tp->t_bitfield) { |
3450 | /* cannot take size/alignment of bit-field */ | | 3450 | /* cannot take size/alignment of bit-field */ |
3451 | error(145); | | 3451 | error(145); |
3452 | return 0; | | 3452 | return 0; |
3453 | } | | 3453 | } |
3454 | if (tp->t_tspec == VOID) { | | 3454 | if (tp->t_tspec == VOID) { |
3455 | /* cannot take size/alignment of void */ | | 3455 | /* cannot take size/alignment of void */ |
3456 | error(146); | | 3456 | error(146); |
3457 | return 0; | | 3457 | return 0; |
3458 | } | | 3458 | } |
3459 | break; | | 3459 | break; |
3460 | } | | 3460 | } |
3461 | | | 3461 | |
3462 | return expr_new_integer_constant(SIZEOF_TSPEC, | | 3462 | return expr_new_integer_constant(SIZEOF_TSPEC, |
3463 | (int64_t)alignment_in_bits(tp) / CHAR_SIZE); | | 3463 | (int64_t)alignment_in_bits(tp) / CHAR_SIZE); |
3464 | } | | 3464 | } |
3465 | | | 3465 | |
3466 | /* | | 3466 | /* |
3467 | * Type casts. | | 3467 | * Type casts. |
3468 | */ | | 3468 | */ |
3469 | tnode_t * | | 3469 | tnode_t * |
3470 | cast(tnode_t *tn, type_t *tp) | | 3470 | cast(tnode_t *tn, type_t *tp) |
3471 | { | | 3471 | { |
3472 | tspec_t nt, ot; | | 3472 | tspec_t nt, ot; |
3473 | | | 3473 | |
3474 | if (tn == NULL) | | 3474 | if (tn == NULL) |
3475 | return NULL; | | 3475 | return NULL; |
3476 | | | 3476 | |
3477 | /* | | 3477 | /* |
3478 | * XXX: checking for tp == NULL is only a quick fix for PR 22119. | | 3478 | * XXX: checking for tp == NULL is only a quick fix for PR 22119. |
3479 | * The proper fix needs to be investigated properly. | | 3479 | * The proper fix needs to be investigated properly. |
3480 | * See d_pr_22119.c for how to get here. | | 3480 | * See d_pr_22119.c for how to get here. |
3481 | */ | | 3481 | */ |
3482 | if (tp == NULL) | | 3482 | if (tp == NULL) |
3483 | return NULL; | | 3483 | return NULL; |
3484 | | | 3484 | |
3485 | tn = cconv(tn); | | 3485 | tn = cconv(tn); |
3486 | | | 3486 | |
3487 | nt = tp->t_tspec; | | 3487 | nt = tp->t_tspec; |
3488 | ot = tn->tn_type->t_tspec; | | 3488 | ot = tn->tn_type->t_tspec; |
3489 | | | 3489 | |
3490 | if (nt == VOID) { | | 3490 | if (nt == VOID) { |
3491 | /* | | 3491 | /* |
3492 | * XXX ANSI C requires scalar types or void (Plauger & Brodie). | | 3492 | * XXX ANSI C requires scalar types or void (Plauger & Brodie). |
3493 | * But this seems really questionable. | | 3493 | * But this seems really questionable. |
3494 | */ | | 3494 | */ |
3495 | } else if (nt == UNION) { | | 3495 | } else if (nt == UNION) { |
3496 | sym_t *m; | | 3496 | sym_t *m; |
3497 | struct_or_union *str = tp->t_str; | | 3497 | struct_or_union *str = tp->t_str; |
3498 | if (!Sflag) { | | 3498 | if (!Sflag) { |
3499 | /* union cast is a C9X feature */ | | 3499 | /* union cast is a C9X feature */ |
3500 | error(328); | | 3500 | error(328); |
3501 | return NULL; | | 3501 | return NULL; |
3502 | } | | 3502 | } |
3503 | for (m = str->sou_first_member; m != NULL; m = m->s_next) { | | 3503 | for (m = str->sou_first_member; m != NULL; m = m->s_next) { |
3504 | if (sametype(m->s_type, tn->tn_type)) { | | 3504 | if (sametype(m->s_type, tn->tn_type)) { |
3505 | tn = expr_zalloc_tnode(); | | 3505 | tn = expr_zalloc_tnode(); |
3506 | tn->tn_op = CVT; | | 3506 | tn->tn_op = CVT; |
3507 | tn->tn_type = tp; | | 3507 | tn->tn_type = tp; |
3508 | tn->tn_cast = true; | | 3508 | tn->tn_cast = true; |
3509 | tn->tn_right = NULL; | | 3509 | tn->tn_right = NULL; |
3510 | return tn; | | 3510 | return tn; |
3511 | } | | 3511 | } |
3512 | } | | 3512 | } |
3513 | /* type '%s' is not a member of '%s' */ | | 3513 | /* type '%s' is not a member of '%s' */ |
3514 | error(329, type_name(tn->tn_type), type_name(tp)); | | 3514 | error(329, type_name(tn->tn_type), type_name(tp)); |
3515 | return NULL; | | 3515 | return NULL; |
3516 | } else if (nt == STRUCT || nt == ARRAY || nt == FUNC) { | | 3516 | } else if (nt == STRUCT || nt == ARRAY || nt == FUNC) { |
3517 | if (!Sflag || nt == ARRAY || nt == FUNC) { | | 3517 | if (!Sflag || nt == ARRAY || nt == FUNC) { |
3518 | /* invalid cast expression */ | | 3518 | /* invalid cast expression */ |
3519 | error(147); | | 3519 | error(147); |
3520 | return NULL; | | 3520 | return NULL; |
3521 | } | | 3521 | } |
3522 | } else if (ot == STRUCT || ot == UNION) { | | 3522 | } else if (ot == STRUCT || ot == UNION) { |
3523 | /* invalid cast expression */ | | 3523 | /* invalid cast expression */ |
3524 | error(147); | | 3524 | error(147); |
3525 | return NULL; | | 3525 | return NULL; |
3526 | } else if (ot == VOID) { | | 3526 | } else if (ot == VOID) { |
3527 | /* improper cast of void expression */ | | 3527 | /* improper cast of void expression */ |
3528 | error(148); | | 3528 | error(148); |
3529 | return NULL; | | 3529 | return NULL; |
3530 | } else if (is_integer(nt) && is_scalar(ot)) { | | 3530 | } else if (is_integer(nt) && is_scalar(ot)) { |
3531 | /* ok */ | | 3531 | /* ok */ |
3532 | } else if (is_floating(nt) && is_arithmetic(ot)) { | | 3532 | } else if (is_floating(nt) && is_arithmetic(ot)) { |
3533 | /* ok */ | | 3533 | /* ok */ |
3534 | } else if (nt == PTR && is_integer(ot)) { | | 3534 | } else if (nt == PTR && is_integer(ot)) { |
3535 | /* ok */ | | 3535 | /* ok */ |
3536 | } else if (nt == PTR && ot == PTR) { | | 3536 | } else if (nt == PTR && ot == PTR) { |
3537 | if (!tp->t_subt->t_const && tn->tn_type->t_subt->t_const) { | | 3537 | if (!tp->t_subt->t_const && tn->tn_type->t_subt->t_const) { |
3538 | if (hflag) | | 3538 | if (hflag) |
3539 | /* cast discards 'const' from type '%s' */ | | 3539 | /* cast discards 'const' from type '%s' */ |
3540 | warning(275, type_name(tn->tn_type)); | | 3540 | warning(275, type_name(tn->tn_type)); |
3541 | } | | 3541 | } |
3542 | } else { | | 3542 | } else { |
3543 | /* invalid cast expression */ | | 3543 | /* invalid cast expression */ |
3544 | error(147); | | 3544 | error(147); |
3545 | return NULL; | | 3545 | return NULL; |
3546 | } | | 3546 | } |
3547 | | | 3547 | |
3548 | tn = convert(CVT, 0, tp, tn); | | 3548 | tn = convert(CVT, 0, tp, tn); |
3549 | tn->tn_cast = true; | | 3549 | tn->tn_cast = true; |
3550 | | | 3550 | |
3551 | return tn; | | 3551 | return tn; |
3552 | } | | 3552 | } |
3553 | | | 3553 | |
3554 | /* | | 3554 | /* |
3555 | * Create the node for a function argument. | | 3555 | * Create the node for a function argument. |
3556 | * All necessary conversions and type checks are done in | | 3556 | * All necessary conversions and type checks are done in |
3557 | * new_function_call_node because new_function_argument_node has no | | 3557 | * new_function_call_node because new_function_argument_node has no |
3558 | * information about expected argument types. | | 3558 | * information about expected argument types. |
3559 | */ | | 3559 | */ |
3560 | tnode_t * | | 3560 | tnode_t * |
3561 | new_function_argument_node(tnode_t *args, tnode_t *arg) | | 3561 | new_function_argument_node(tnode_t *args, tnode_t *arg) |
3562 | { | | 3562 | { |
3563 | tnode_t *ntn; | | 3563 | tnode_t *ntn; |
3564 | | | 3564 | |
3565 | /* | | 3565 | /* |
3566 | * If there was a serious error in the expression for the argument, | | 3566 | * If there was a serious error in the expression for the argument, |
3567 | * create a dummy argument so the positions of the remaining arguments | | 3567 | * create a dummy argument so the positions of the remaining arguments |
3568 | * will not change. | | 3568 | * will not change. |
3569 | */ | | 3569 | */ |
3570 | if (arg == NULL) | | 3570 | if (arg == NULL) |
3571 | arg = expr_new_integer_constant(INT, 0); | | 3571 | arg = expr_new_integer_constant(INT, 0); |
3572 | | | 3572 | |
3573 | ntn = new_tnode(PUSH, arg->tn_type, arg, args); | | 3573 | ntn = new_tnode(PUSH, arg->tn_type, arg, args); |
3574 | | | 3574 | |
3575 | return ntn; | | 3575 | return ntn; |
3576 | } | | 3576 | } |
3577 | | | 3577 | |
3578 | /* | | 3578 | /* |
3579 | * Create the node for a function call. Also check types of | | 3579 | * Create the node for a function call. Also check types of |
3580 | * function arguments and insert conversions, if necessary. | | 3580 | * function arguments and insert conversions, if necessary. |
3581 | */ | | 3581 | */ |
3582 | tnode_t * | | 3582 | tnode_t * |
3583 | new_function_call_node(tnode_t *func, tnode_t *args) | | 3583 | new_function_call_node(tnode_t *func, tnode_t *args) |
3584 | { | | 3584 | { |
3585 | tnode_t *ntn; | | 3585 | tnode_t *ntn; |
3586 | op_t fcop; | | 3586 | op_t fcop; |
3587 | | | 3587 | |
3588 | if (func == NULL) | | 3588 | if (func == NULL) |
3589 | return NULL; | | 3589 | return NULL; |
3590 | | | 3590 | |
3591 | if (func->tn_op == NAME && func->tn_type->t_tspec == FUNC) { | | 3591 | if (func->tn_op == NAME && func->tn_type->t_tspec == FUNC) { |
3592 | fcop = CALL; | | 3592 | fcop = CALL; |
3593 | } else { | | 3593 | } else { |
3594 | fcop = ICALL; | | 3594 | fcop = ICALL; |
3595 | } | | 3595 | } |
3596 | | | 3596 | |
3597 | /* | | 3597 | /* |
3598 | * after cconv() func will always be a pointer to a function | | 3598 | * after cconv() func will always be a pointer to a function |
3599 | * if it is a valid function designator. | | 3599 | * if it is a valid function designator. |
3600 | */ | | 3600 | */ |
3601 | func = cconv(func); | | 3601 | func = cconv(func); |
3602 | | | 3602 | |
3603 | if (func->tn_type->t_tspec != PTR || | | 3603 | if (func->tn_type->t_tspec != PTR || |
3604 | func->tn_type->t_subt->t_tspec != FUNC) { | | 3604 | func->tn_type->t_subt->t_tspec != FUNC) { |
3605 | /* illegal function (type %s) */ | | 3605 | /* illegal function (type %s) */ |
3606 | error(149, type_name(func->tn_type)); | | 3606 | error(149, type_name(func->tn_type)); |
3607 | return NULL; | | 3607 | return NULL; |
3608 | } | | 3608 | } |
3609 | | | 3609 | |
3610 | args = check_function_arguments(func->tn_type->t_subt, args); | | 3610 | args = check_function_arguments(func->tn_type->t_subt, args); |
3611 | | | 3611 | |
3612 | ntn = new_tnode(fcop, func->tn_type->t_subt->t_subt, func, args); | | 3612 | ntn = new_tnode(fcop, func->tn_type->t_subt->t_subt, func, args); |
3613 | | | 3613 | |
3614 | return ntn; | | 3614 | return ntn; |
3615 | } | | 3615 | } |
3616 | | | 3616 | |
3617 | /* | | 3617 | /* |
3618 | * Check types of all function arguments and insert conversions, | | 3618 | * Check types of all function arguments and insert conversions, |
3619 | * if necessary. | | 3619 | * if necessary. |
3620 | */ | | 3620 | */ |
3621 | static tnode_t * | | 3621 | static tnode_t * |
3622 | check_function_arguments(type_t *ftp, tnode_t *args) | | 3622 | check_function_arguments(type_t *ftp, tnode_t *args) |
3623 | { | | 3623 | { |
3624 | tnode_t *arg; | | 3624 | tnode_t *arg; |
3625 | sym_t *asym; | | 3625 | sym_t *asym; |
3626 | tspec_t at; | | 3626 | tspec_t at; |
3627 | int narg, npar, n, i; | | 3627 | int narg, npar, n, i; |
3628 | | | 3628 | |
3629 | /* get # of args in the prototype */ | | 3629 | /* get # of args in the prototype */ |
3630 | npar = 0; | | 3630 | npar = 0; |
3631 | for (asym = ftp->t_args; asym != NULL; asym = asym->s_next) | | 3631 | for (asym = ftp->t_args; asym != NULL; asym = asym->s_next) |
3632 | npar++; | | 3632 | npar++; |
3633 | | | 3633 | |
3634 | /* get # of args in function call */ | | 3634 | /* get # of args in function call */ |
3635 | narg = 0; | | 3635 | narg = 0; |
3636 | for (arg = args; arg != NULL; arg = arg->tn_right) | | 3636 | for (arg = args; arg != NULL; arg = arg->tn_right) |
3637 | narg++; | | 3637 | narg++; |
3638 | | | 3638 | |
3639 | asym = ftp->t_args; | | 3639 | asym = ftp->t_args; |
3640 | if (ftp->t_proto && npar != narg && !(ftp->t_vararg && npar < narg)) { | | 3640 | if (ftp->t_proto && npar != narg && !(ftp->t_vararg && npar < narg)) { |
3641 | /* argument mismatch: %d arg%s passed, %d expected */ | | 3641 | /* argument mismatch: %d arg%s passed, %d expected */ |
3642 | error(150, narg, narg > 1 ? "s" : "", npar); | | 3642 | error(150, narg, narg > 1 ? "s" : "", npar); |
3643 | asym = NULL; | | 3643 | asym = NULL; |
3644 | } | | 3644 | } |
3645 | | | 3645 | |
3646 | for (n = 1; n <= narg; n++) { | | 3646 | for (n = 1; n <= narg; n++) { |
3647 | | | 3647 | |
3648 | /* | | 3648 | /* |
3649 | * The rightmost argument is at the top of the argument | | 3649 | * The rightmost argument is at the top of the argument |
3650 | * subtree. | | 3650 | * subtree. |
3651 | */ | | 3651 | */ |
3652 | for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) | | 3652 | for (i = narg, arg = args; i > n; i--, arg = arg->tn_right) |
3653 | continue; | | 3653 | continue; |
3654 | | | 3654 | |
3655 | /* some things which are always not allowed */ | | 3655 | /* some things which are always not allowed */ |
3656 | if ((at = arg->tn_left->tn_type->t_tspec) == VOID) { | | 3656 | if ((at = arg->tn_left->tn_type->t_tspec) == VOID) { |
3657 | /* void expressions may not be arguments, arg #%d */ | | 3657 | /* void expressions may not be arguments, arg #%d */ |
3658 | error(151, n); | | 3658 | error(151, n); |
3659 | return NULL; | | 3659 | return NULL; |
3660 | } else if ((at == STRUCT || at == UNION) && | | 3660 | } else if ((at == STRUCT || at == UNION) && |
3661 | is_incomplete(arg->tn_left->tn_type)) { | | 3661 | is_incomplete(arg->tn_left->tn_type)) { |
3662 | /* argument cannot have unknown size, arg #%d */ | | 3662 | /* argument cannot have unknown size, arg #%d */ |
3663 | error(152, n); | | 3663 | error(152, n); |
3664 | return NULL; | | 3664 | return NULL; |
3665 | } else if (is_integer(at) && | | 3665 | } else if (is_integer(at) && |
3666 | arg->tn_left->tn_type->t_is_enum && | | 3666 | arg->tn_left->tn_type->t_is_enum && |
3667 | is_incomplete(arg->tn_left->tn_type)) { | | 3667 | is_incomplete(arg->tn_left->tn_type)) { |
3668 | /* argument cannot have unknown size, arg #%d */ | | 3668 | /* argument cannot have unknown size, arg #%d */ |
3669 | warning(152, n); | | 3669 | warning(152, n); |
3670 | } | | 3670 | } |
3671 | | | 3671 | |
3672 | /* class conversions (arg in value context) */ | | 3672 | /* class conversions (arg in value context) */ |
3673 | arg->tn_left = cconv(arg->tn_left); | | 3673 | arg->tn_left = cconv(arg->tn_left); |
3674 | | | 3674 | |
3675 | if (asym != NULL) { | | 3675 | if (asym != NULL) { |
3676 | arg->tn_left = check_prototype_argument( | | 3676 | arg->tn_left = check_prototype_argument( |
3677 | n, asym->s_type, arg->tn_left); | | 3677 | n, asym->s_type, arg->tn_left); |
3678 | } else { | | 3678 | } else { |
3679 | arg->tn_left = promote(NOOP, true, arg->tn_left); | | 3679 | arg->tn_left = promote(NOOP, true, arg->tn_left); |
3680 | } | | 3680 | } |
3681 | arg->tn_type = arg->tn_left->tn_type; | | 3681 | arg->tn_type = arg->tn_left->tn_type; |
3682 | | | 3682 | |
3683 | if (asym != NULL) | | 3683 | if (asym != NULL) |
3684 | asym = asym->s_next; | | 3684 | asym = asym->s_next; |
3685 | } | | 3685 | } |
3686 | | | 3686 | |
3687 | return args; | | 3687 | return args; |
3688 | } | | 3688 | } |
3689 | | | 3689 | |
3690 | /* | | 3690 | /* |
3691 | * Compare the type of an argument with the corresponding type of a | | 3691 | * Compare the type of an argument with the corresponding type of a |
3692 | * prototype parameter. If it is a valid combination, but both types | | 3692 | * prototype parameter. If it is a valid combination, but both types |
3693 | * are not the same, insert a conversion to convert the argument into | | 3693 | * are not the same, insert a conversion to convert the argument into |
3694 | * the type of the parameter. | | 3694 | * the type of the parameter. |
3695 | */ | | 3695 | */ |
3696 | static tnode_t * | | 3696 | static tnode_t * |
3697 | check_prototype_argument( | | 3697 | check_prototype_argument( |
3698 | int n, /* pos of arg */ | | 3698 | int n, /* pos of arg */ |
3699 | type_t *tp, /* expected type (from prototype) */ | | 3699 | type_t *tp, /* expected type (from prototype) */ |
3700 | tnode_t *tn) /* argument */ | | 3700 | tnode_t *tn) /* argument */ |
3701 | { | | 3701 | { |
3702 | tnode_t *ln; | | 3702 | tnode_t *ln; |
3703 | bool dowarn; | | 3703 | bool dowarn; |
3704 | | | 3704 | |
3705 | ln = xcalloc(1, sizeof(*ln)); | | 3705 | ln = xcalloc(1, sizeof(*ln)); |
3706 | ln->tn_type = expr_dup_type(tp); | | 3706 | ln->tn_type = expr_dup_type(tp); |
3707 | ln->tn_type->t_const = false; | | 3707 | ln->tn_type->t_const = false; |
3708 | ln->tn_lvalue = true; | | 3708 | ln->tn_lvalue = true; |
3709 | if (typeok(FARG, n, ln, tn)) { | | 3709 | if (typeok(FARG, n, ln, tn)) { |
3710 | if (!eqtype(tp, tn->tn_type, | | 3710 | if (!eqtype(tp, tn->tn_type, |
3711 | true, false, (dowarn = false, &dowarn)) || dowarn) | | 3711 | true, false, (dowarn = false, &dowarn)) || dowarn) |
3712 | tn = convert(FARG, n, tp, tn); | | 3712 | tn = convert(FARG, n, tp, tn); |
3713 | } | | 3713 | } |
3714 | free(ln); | | 3714 | free(ln); |
3715 | return tn; | | 3715 | return tn; |
3716 | } | | 3716 | } |
3717 | | | 3717 | |
3718 | /* | | 3718 | /* |
3719 | * Return the value of an integral constant expression. | | 3719 | * Return the value of an integral constant expression. |
3720 | * If the expression is not constant or its type is not an integer | | 3720 | * If the expression is not constant or its type is not an integer |
3721 | * type, an error message is printed. | | 3721 | * type, an error message is printed. |
3722 | */ | | 3722 | */ |
3723 | val_t * | | 3723 | val_t * |
3724 | constant(tnode_t *tn, bool required) | | 3724 | constant(tnode_t *tn, bool required) |
3725 | { | | 3725 | { |
3726 | val_t *v; | | 3726 | val_t *v; |
3727 | | | 3727 | |
3728 | if (tn != NULL) | | 3728 | if (tn != NULL) |
3729 | tn = cconv(tn); | | 3729 | tn = cconv(tn); |
3730 | if (tn != NULL) | | 3730 | if (tn != NULL) |
3731 | tn = promote(NOOP, false, tn); | | 3731 | tn = promote(NOOP, false, tn); |
3732 | | | 3732 | |
3733 | v = xcalloc(1, sizeof(*v)); | | 3733 | v = xcalloc(1, sizeof(*v)); |
3734 | | | 3734 | |
3735 | if (tn == NULL) { | | 3735 | if (tn == NULL) { |
3736 | lint_assert(nerr != 0); | | 3736 | lint_assert(nerr != 0); |
3737 | if (dflag) | | 3737 | if (dflag) |
3738 | printf("constant node is null; returning 1 instead\n"); | | 3738 | printf("constant node is null; returning 1 instead\n"); |
3739 | v->v_tspec = INT; | | 3739 | v->v_tspec = INT; |
3740 | v->v_quad = 1; | | 3740 | v->v_quad = 1; |
3741 | return v; | | 3741 | return v; |
3742 | } | | 3742 | } |
3743 | | | 3743 | |
3744 | v->v_tspec = tn->tn_type->t_tspec; | | 3744 | v->v_tspec = tn->tn_type->t_tspec; |
3745 | | | 3745 | |
3746 | if (tn->tn_op == CON) { | | 3746 | if (tn->tn_op == CON) { |
3747 | lint_assert(tn->tn_type->t_tspec == tn->tn_val->v_tspec); | | 3747 | lint_assert(tn->tn_type->t_tspec == tn->tn_val->v_tspec); |
3748 | if (is_integer(tn->tn_val->v_tspec)) { | | 3748 | if (is_integer(tn->tn_val->v_tspec)) { |
3749 | v->v_ansiu = tn->tn_val->v_ansiu; | | 3749 | v->v_ansiu = tn->tn_val->v_ansiu; |
3750 | v->v_quad = tn->tn_val->v_quad; | | 3750 | v->v_quad = tn->tn_val->v_quad; |
3751 | return v; | | 3751 | return v; |
3752 | } | | 3752 | } |
3753 | v->v_quad = tn->tn_val->v_ldbl; | | 3753 | v->v_quad = tn->tn_val->v_ldbl; |
3754 | } else { | | 3754 | } else { |
3755 | v->v_quad = 1; | | 3755 | v->v_quad = 1; |
3756 | } | | 3756 | } |
3757 | | | 3757 | |
3758 | if (required) | | 3758 | if (required) |
3759 | /* integral constant expression expected */ | | 3759 | /* integral constant expression expected */ |
3760 | error(55); | | 3760 | error(55); |
3761 | else | | 3761 | else |
3762 | /* variable array dimension is a C99/GCC extension */ | | 3762 | /* variable array dimension is a C99/GCC extension */ |
3763 | c99ism(318); | | 3763 | c99ism(318); |
3764 | | | 3764 | |
3765 | if (!is_integer(v->v_tspec)) | | 3765 | if (!is_integer(v->v_tspec)) |
3766 | v->v_tspec = INT; | | 3766 | v->v_tspec = INT; |
3767 | | | 3767 | |
3768 | return v; | | 3768 | return v; |
3769 | } | | 3769 | } |
3770 | | | 3770 | |
3771 | static bool | | 3771 | static bool |
3772 | is_constcond_false(const tnode_t *tn, tspec_t t) | | 3772 | is_constcond_false(const tnode_t *tn, tspec_t t) |
3773 | { | | 3773 | { |
3774 | return (t == BOOL || t == INT) && | | 3774 | return (t == BOOL || t == INT) && |
3775 | tn->tn_op == CON && tn->tn_val->v_quad == 0; | | 3775 | tn->tn_op == CON && tn->tn_val->v_quad == 0; |
3776 | } | | 3776 | } |
3777 | | | 3777 | |
3778 | /* | | 3778 | /* |
3779 | * Perform some tests on expressions which can't be done in build() and | | 3779 | * Perform some tests on expressions which can't be done in build() and |
3780 | * functions called by build(). These tests must be done here because | | 3780 | * functions called by build(). These tests must be done here because |
3781 | * we need some information about the context in which the operations | | 3781 | * we need some information about the context in which the operations |
3782 | * are performed. | | 3782 | * are performed. |
3783 | * After all tests are performed and dofreeblk is true, expr() frees the | | 3783 | * After all tests are performed and dofreeblk is true, expr() frees the |
3784 | * memory which is used for the expression. | | 3784 | * memory which is used for the expression. |
3785 | */ | | 3785 | */ |
3786 | void | | 3786 | void |
3787 | expr(tnode_t *tn, bool vctx, bool tctx, bool dofreeblk, bool constcond_false_ok) | | 3787 | expr(tnode_t *tn, bool vctx, bool tctx, bool dofreeblk, bool constcond_false_ok) |
3788 | { | | 3788 | { |
3789 | | | 3789 | |
3790 | lint_assert(tn != NULL || nerr != 0); | | 3790 | lint_assert(tn != NULL || nerr != 0); |
3791 | | | 3791 | |
3792 | if (tn == NULL) { | | 3792 | if (tn == NULL) { |
3793 | expr_free_all(); | | 3793 | expr_free_all(); |
3794 | return; | | 3794 | return; |
3795 | } | | 3795 | } |
3796 | | | 3796 | |
3797 | /* expr() is also called in global initializations */ | | 3797 | /* expr() is also called in global initializations */ |
3798 | /* TODO: rename constcond_false_ok */ | | 3798 | /* TODO: rename constcond_false_ok */ |
3799 | if (dcs->d_ctx != EXTERN && !constcond_false_ok) | | 3799 | if (dcs->d_ctx != EXTERN && !constcond_false_ok) |
3800 | check_statement_reachable(); | | 3800 | check_statement_reachable(); |
3801 | | | 3801 | |
3802 | check_expr_misc(tn, vctx, tctx, !tctx, false, false, false); | | 3802 | check_expr_misc(tn, vctx, tctx, !tctx, false, false, false); |
3803 | if (tn->tn_op == ASSIGN) { | | 3803 | if (tn->tn_op == ASSIGN) { |
3804 | if (hflag && tctx) | | 3804 | if (hflag && tctx) |
3805 | /* assignment in conditional context */ | | 3805 | /* assignment in conditional context */ |
3806 | warning(159); | | 3806 | warning(159); |
3807 | } else if (tn->tn_op == CON) { | | 3807 | } else if (tn->tn_op == CON) { |
3808 | if (hflag && tctx && !constcond_flag && | | 3808 | if (hflag && tctx && !constcond_flag && |
3809 | !tn->tn_system_dependent && | | 3809 | !tn->tn_system_dependent && |
3810 | !(constcond_false_ok && | | 3810 | !(constcond_false_ok && |
3811 | is_constcond_false(tn, tn->tn_type->t_tspec))) | | 3811 | is_constcond_false(tn, tn->tn_type->t_tspec))) |
3812 | /* constant in conditional context */ | | 3812 | /* constant in conditional context */ |
3813 | warning(161); | | 3813 | warning(161); |
3814 | } | | 3814 | } |
3815 | if (!modtab[tn->tn_op].m_has_side_effect) { | | 3815 | if (!modtab[tn->tn_op].m_has_side_effect) { |
3816 | /* | | 3816 | /* |
3817 | * for left operands of COMMA this warning is already | | 3817 | * for left operands of COMMA this warning is already |
3818 | * printed | | 3818 | * printed |
3819 | */ | | 3819 | */ |
3820 | if (tn->tn_op != COMMA && !vctx && !tctx) | | 3820 | if (tn->tn_op != COMMA && !vctx && !tctx) |
3821 | check_null_effect(tn); | | 3821 | check_null_effect(tn); |
3822 | } | | 3822 | } |
3823 | if (dflag) | | 3823 | if (dflag) |
3824 | display_expression(tn, 0); | | 3824 | display_expression(tn, 0); |
3825 | | | 3825 | |
3826 | /* free the tree memory */ | | 3826 | /* free the tree memory */ |
3827 | if (dofreeblk) | | 3827 | if (dofreeblk) |
3828 | expr_free_all(); | | 3828 | expr_free_all(); |
3829 | } | | 3829 | } |
3830 | | | 3830 | |
3831 | static bool | | 3831 | static bool |
3832 | has_side_effect(const tnode_t *tn) // NOLINT(misc-no-recursion) | | 3832 | has_side_effect(const tnode_t *tn) // NOLINT(misc-no-recursion) |
3833 | { | | 3833 | { |
3834 | op_t op = tn->tn_op; | | 3834 | op_t op = tn->tn_op; |
3835 | | | 3835 | |
3836 | if (modtab[op].m_has_side_effect) | | 3836 | if (modtab[op].m_has_side_effect) |
3837 | return true; | | 3837 | return true; |
3838 | | | 3838 | |
3839 | if (op == CVT && tn->tn_type->t_tspec == VOID) | | 3839 | if (op == CVT && tn->tn_type->t_tspec == VOID) |
3840 | return has_side_effect(tn->tn_left); | | 3840 | return has_side_effect(tn->tn_left); |
3841 | | | 3841 | |
3842 | /* XXX: Why not has_side_effect(tn->tn_left) as well? */ | | 3842 | /* XXX: Why not has_side_effect(tn->tn_left) as well? */ |
3843 | if (op == LOGAND || op == LOGOR) | | 3843 | if (op == LOGAND || op == LOGOR) |
3844 | return has_side_effect(tn->tn_right); | | 3844 | return has_side_effect(tn->tn_right); |
3845 | | | 3845 | |
3846 | /* XXX: Why not has_side_effect(tn->tn_left) as well? */ | | 3846 | /* XXX: Why not has_side_effect(tn->tn_left) as well? */ |
3847 | if (op == QUEST) | | 3847 | if (op == QUEST) |
3848 | return has_side_effect(tn->tn_right); | | 3848 | return has_side_effect(tn->tn_right); |
3849 | | | 3849 | |
3850 | if (op == COLON || op == COMMA) { | | 3850 | if (op == COLON || op == COMMA) { |
3851 | return has_side_effect(tn->tn_left) || | | 3851 | return has_side_effect(tn->tn_left) || |
3852 | has_side_effect(tn->tn_right); | | 3852 | has_side_effect(tn->tn_right); |
3853 | } | | 3853 | } |
3854 | | | 3854 | |
3855 | return false; | | 3855 | return false; |
3856 | } | | 3856 | } |
3857 | | | 3857 | |
3858 | static void | | 3858 | static void |
3859 | check_null_effect(const tnode_t *tn) | | 3859 | check_null_effect(const tnode_t *tn) |
3860 | { | | 3860 | { |
3861 | | | 3861 | |
3862 | if (hflag && !has_side_effect(tn)) { | | 3862 | if (hflag && !has_side_effect(tn)) { |
3863 | /* expression has null effect */ | | 3863 | /* expression has null effect */ |
3864 | warning(129); | | 3864 | warning(129); |
3865 | } | | 3865 | } |
3866 | } | | 3866 | } |
3867 | | | 3867 | |
3868 | /* | | 3868 | /* |
3869 | * Dump an expression to stdout | | 3869 | * Dump an expression to stdout |
3870 | * only used for debugging | | 3870 | * only used for debugging |
3871 | */ | | 3871 | */ |
3872 | static void | | 3872 | static void |
3873 | display_expression(const tnode_t *tn, int offs) | | 3873 | display_expression(const tnode_t *tn, int offs) |
3874 | { | | 3874 | { |
3875 | uint64_t uq; | | 3875 | uint64_t uq; |
3876 | | | 3876 | |
3877 | if (tn == NULL) { | | 3877 | if (tn == NULL) { |
3878 | (void)printf("%*s%s\n", offs, "", "NULL"); | | 3878 | (void)printf("%*s%s\n", offs, "", "NULL"); |
3879 | return; | | 3879 | return; |
3880 | } | | 3880 | } |
3881 | (void)printf("%*sop %s ", offs, "", modtab[tn->tn_op].m_name); | | 3881 | (void)printf("%*sop %s ", offs, "", op_name(tn->tn_op)); |
3882 | | | 3882 | |
3883 | if (tn->tn_op == NAME) { | | 3883 | if (tn->tn_op == NAME) { |
3884 | (void)printf("%s: %s ", | | 3884 | (void)printf("%s: %s ", |
3885 | tn->tn_sym->s_name, | | 3885 | tn->tn_sym->s_name, |
3886 | storage_class_name(tn->tn_sym->s_scl)); | | 3886 | storage_class_name(tn->tn_sym->s_scl)); |
3887 | } else if (tn->tn_op == CON && is_floating(tn->tn_type->t_tspec)) { | | 3887 | } else if (tn->tn_op == CON && is_floating(tn->tn_type->t_tspec)) { |
3888 | (void)printf("%#g ", (double)tn->tn_val->v_ldbl); | | 3888 | (void)printf("%#g ", (double)tn->tn_val->v_ldbl); |
3889 | } else if (tn->tn_op == CON && is_integer(tn->tn_type->t_tspec)) { | | 3889 | } else if (tn->tn_op == CON && is_integer(tn->tn_type->t_tspec)) { |
3890 | uq = tn->tn_val->v_quad; | | 3890 | uq = tn->tn_val->v_quad; |
3891 | (void)printf("0x %08lx %08lx ", | | 3891 | (void)printf("0x %08lx %08lx ", |
3892 | (long)(uq >> 32) & 0xffffffffl, | | 3892 | (long)(uq >> 32) & 0xffffffffl, |
3893 | (long)uq & 0xffffffffl); | | 3893 | (long)uq & 0xffffffffl); |
3894 | } else if (tn->tn_op == CON) { | | 3894 | } else if (tn->tn_op == CON) { |
3895 | lint_assert(tn->tn_type->t_tspec == PTR); | | 3895 | lint_assert(tn->tn_type->t_tspec == PTR); |
3896 | (void)printf("0x%0*lx ", (int)(sizeof(void *) * CHAR_BIT / 4), | | 3896 | (void)printf("0x%0*lx ", (int)(sizeof(void *) * CHAR_BIT / 4), |
3897 | (u_long)tn->tn_val->v_quad); | | 3897 | (u_long)tn->tn_val->v_quad); |
3898 | } else if (tn->tn_op == STRING) { | | 3898 | } else if (tn->tn_op == STRING) { |
3899 | if (tn->tn_string->st_tspec == CHAR) { | | 3899 | if (tn->tn_string->st_tspec == CHAR) { |
3900 | (void)printf("\"%s\"", tn->tn_string->st_cp); | | 3900 | (void)printf("\"%s\"", tn->tn_string->st_cp); |
3901 | } else { | | 3901 | } else { |
3902 | char *s; | | 3902 | char *s; |
3903 | size_t n; | | 3903 | size_t n; |
3904 | n = MB_CUR_MAX * (tn->tn_string->st_len + 1); | | 3904 | n = MB_CUR_MAX * (tn->tn_string->st_len + 1); |
3905 | s = xmalloc(n); | | 3905 | s = xmalloc(n); |
3906 | (void)wcstombs(s, tn->tn_string->st_wcp, n); | | 3906 | (void)wcstombs(s, tn->tn_string->st_wcp, n); |
3907 | (void)printf("L\"%s\"", s); | | 3907 | (void)printf("L\"%s\"", s); |
3908 | free(s); | | 3908 | free(s); |
3909 | } | | 3909 | } |
3910 | (void)printf(" "); | | 3910 | (void)printf(" "); |
3911 | } else if (tn->tn_op == FSEL) { | | 3911 | } else if (tn->tn_op == FSEL) { |
3912 | (void)printf("o=%d, l=%d ", tn->tn_type->t_foffs, | | 3912 | (void)printf("o=%d, l=%d ", tn->tn_type->t_foffs, |
3913 | tn->tn_type->t_flen); | | 3913 | tn->tn_type->t_flen); |
3914 | } | | 3914 | } |
3915 | (void)printf("%s\n", ttos(tn->tn_type)); | | 3915 | (void)printf("%s\n", ttos(tn->tn_type)); |
3916 | if (tn->tn_op == NAME || tn->tn_op == CON || tn->tn_op == STRING) | | 3916 | if (tn->tn_op == NAME || tn->tn_op == CON || tn->tn_op == STRING) |
3917 | return; | | 3917 | return; |
3918 | display_expression(tn->tn_left, offs + 2); | | 3918 | display_expression(tn->tn_left, offs + 2); |
3919 | if (modtab[tn->tn_op].m_binary || | | 3919 | if (modtab[tn->tn_op].m_binary || |
3920 | (tn->tn_op == PUSH && tn->tn_right != NULL)) { | | 3920 | (tn->tn_op == PUSH && tn->tn_right != NULL)) { |
3921 | display_expression(tn->tn_right, offs + 2); | | 3921 | display_expression(tn->tn_right, offs + 2); |
3922 | } | | 3922 | } |
3923 | } | | 3923 | } |
3924 | | | 3924 | |
3925 | /* | | 3925 | /* |
3926 | * Called by expr() to recursively perform some tests. | | 3926 | * Called by expr() to recursively perform some tests. |
3927 | */ | | 3927 | */ |
3928 | /* ARGSUSED */ | | 3928 | /* ARGSUSED */ |
3929 | void | | 3929 | void |
3930 | check_expr_misc(const tnode_t *tn, bool vctx, bool tctx, | | 3930 | check_expr_misc(const tnode_t *tn, bool vctx, bool tctx, |
3931 | bool eqwarn, bool fcall, bool rvdisc, bool szof) | | 3931 | bool eqwarn, bool fcall, bool rvdisc, bool szof) |
3932 | { | | 3932 | { |
3933 | tnode_t *ln, *rn; | | 3933 | tnode_t *ln, *rn; |
3934 | const mod_t *mp; | | 3934 | const mod_t *mp; |
3935 | op_t op; | | 3935 | op_t op; |
3936 | scl_t sc; | | 3936 | scl_t sc; |
3937 | dinfo_t *di; | | 3937 | dinfo_t *di; |
3938 | | | 3938 | |
3939 | if (tn == NULL) | | 3939 | if (tn == NULL) |
3940 | return; | | 3940 | return; |
3941 | | | 3941 | |
3942 | ln = tn->tn_left; | | 3942 | ln = tn->tn_left; |
3943 | rn = tn->tn_right; | | 3943 | rn = tn->tn_right; |
3944 | mp = &modtab[op = tn->tn_op]; | | 3944 | mp = &modtab[op = tn->tn_op]; |
3945 | | | 3945 | |
3946 | switch (op) { | | 3946 | switch (op) { |
3947 | case ADDR: | | 3947 | case ADDR: |
3948 | /* XXX: Taking warn_about_unreachable into account here feels wrong. */ | | 3948 | /* XXX: Taking warn_about_unreachable into account here feels wrong. */ |
3949 | if (ln->tn_op == NAME && (reached || !warn_about_unreachable)) { | | 3949 | if (ln->tn_op == NAME && (reached || !warn_about_unreachable)) { |
3950 | if (!szof) | | 3950 | if (!szof) |
3951 | mark_as_set(ln->tn_sym); | | 3951 | mark_as_set(ln->tn_sym); |
3952 | mark_as_used(ln->tn_sym, fcall, szof); | | 3952 | mark_as_used(ln->tn_sym, fcall, szof); |
3953 | } | | 3953 | } |
3954 | if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) | | 3954 | if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) |
3955 | /* check the range of array indices */ | | 3955 | /* check the range of array indices */ |
3956 | check_array_index(ln->tn_left, true); | | 3956 | check_array_index(ln->tn_left, true); |
3957 | break; | | 3957 | break; |
3958 | case LOAD: | | 3958 | case LOAD: |
3959 | if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) | | 3959 | if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) |
3960 | /* check the range of array indices */ | | 3960 | /* check the range of array indices */ |
3961 | check_array_index(ln->tn_left, false); | | 3961 | check_array_index(ln->tn_left, false); |
3962 | /* FALLTHROUGH */ | | 3962 | /* FALLTHROUGH */ |
3963 | case PUSH: | | 3963 | case PUSH: |
3964 | case INCBEF: | | 3964 | case INCBEF: |
3965 | case DECBEF: | | 3965 | case DECBEF: |
3966 | case INCAFT: | | 3966 | case INCAFT: |
3967 | case DECAFT: | | 3967 | case DECAFT: |
3968 | case ADDASS: | | 3968 | case ADDASS: |
3969 | case SUBASS: | | 3969 | case SUBASS: |
3970 | case MULASS: | | 3970 | case MULASS: |
3971 | case DIVASS: | | 3971 | case DIVASS: |
3972 | case MODASS: | | 3972 | case MODASS: |
3973 | case ANDASS: | | 3973 | case ANDASS: |
3974 | case ORASS: | | 3974 | case ORASS: |
3975 | case XORASS: | | 3975 | case XORASS: |
3976 | case SHLASS: | | 3976 | case SHLASS: |
3977 | case SHRASS: | | 3977 | case SHRASS: |
3978 | case REAL: | | 3978 | case REAL: |
3979 | case IMAG: | | 3979 | case IMAG: |
3980 | /* XXX: Taking warn_about_unreachable into account here feels wrong. */ | | 3980 | /* XXX: Taking warn_about_unreachable into account here feels wrong. */ |
3981 | if (ln->tn_op == NAME && (reached || !warn_about_unreachable)) { | | 3981 | if (ln->tn_op == NAME && (reached || !warn_about_unreachable)) { |
3982 | sc = ln->tn_sym->s_scl; | | 3982 | sc = ln->tn_sym->s_scl; |
3983 | /* | | 3983 | /* |
3984 | * Look if there was a asm statement in one of the | | 3984 | * Look if there was a asm statement in one of the |
3985 | * compound statements we are in. If not, we don't | | 3985 | * compound statements we are in. If not, we don't |
3986 | * print a warning. | | 3986 | * print a warning. |
3987 | */ | | 3987 | */ |
3988 | for (di = dcs; di != NULL; di = di->d_next) { | | 3988 | for (di = dcs; di != NULL; di = di->d_next) { |
3989 | if (di->d_asm) | | 3989 | if (di->d_asm) |
3990 | break; | | 3990 | break; |
3991 | } | | 3991 | } |
3992 | if (sc != EXTERN && sc != STATIC && | | 3992 | if (sc != EXTERN && sc != STATIC && |
3993 | !ln->tn_sym->s_set && !szof && di == NULL) { | | 3993 | !ln->tn_sym->s_set && !szof && di == NULL) { |
3994 | /* %s may be used before set */ | | 3994 | /* %s may be used before set */ |
3995 | warning(158, ln->tn_sym->s_name); | | 3995 | warning(158, ln->tn_sym->s_name); |
3996 | mark_as_set(ln->tn_sym); | | 3996 | mark_as_set(ln->tn_sym); |
3997 | } | | 3997 | } |
3998 | mark_as_used(ln->tn_sym, false, false); | | 3998 | mark_as_used(ln->tn_sym, false, false); |
3999 | } | | 3999 | } |
4000 | break; | | 4000 | break; |
4001 | case ASSIGN: | | 4001 | case ASSIGN: |
4002 | /* XXX: Taking warn_about_unreachable into account here feels wrong. */ | | 4002 | /* XXX: Taking warn_about_unreachable into account here feels wrong. */ |
4003 | if (ln->tn_op == NAME && !szof && (reached || !warn_about_unreachable)) { | | 4003 | if (ln->tn_op == NAME && !szof && (reached || !warn_about_unreachable)) { |
4004 | mark_as_set(ln->tn_sym); | | 4004 | mark_as_set(ln->tn_sym); |
4005 | if (ln->tn_sym->s_scl == EXTERN) | | 4005 | if (ln->tn_sym->s_scl == EXTERN) |
4006 | outusg(ln->tn_sym); | | 4006 | outusg(ln->tn_sym); |
4007 | } | | 4007 | } |
4008 | if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) | | 4008 | if (ln->tn_op == INDIR && ln->tn_left->tn_op == PLUS) |
4009 | /* check the range of array indices */ | | 4009 | /* check the range of array indices */ |
4010 | check_array_index(ln->tn_left, false); | | 4010 | check_array_index(ln->tn_left, false); |
4011 | break; | | 4011 | break; |
4012 | case CALL: | | 4012 | case CALL: |
4013 | lint_assert(ln->tn_op == ADDR); | | 4013 | lint_assert(ln->tn_op == ADDR); |
4014 | lint_assert(ln->tn_left->tn_op == NAME); | | 4014 | lint_assert(ln->tn_left->tn_op == NAME); |
4015 | if (!szof) | | 4015 | if (!szof) |
4016 | outcall(tn, vctx || tctx, rvdisc); | | 4016 | outcall(tn, vctx || tctx, rvdisc); |
4017 | break; | | 4017 | break; |
4018 | case EQ: | | 4018 | case EQ: |
4019 | if (hflag && eqwarn) | | 4019 | if (hflag && eqwarn) |
4020 | /* operator '==' found where '=' was expected */ | | 4020 | /* operator '==' found where '=' was expected */ |
4021 | warning(160); | | 4021 | warning(160); |
4022 | break; | | 4022 | break; |
4023 | case CON: | | 4023 | case CON: |
4024 | case NAME: | | 4024 | case NAME: |
4025 | case STRING: | | 4025 | case STRING: |
4026 | return; | | 4026 | return; |
4027 | /* LINTED206: (enumeration values not handled in switch) */ | | 4027 | /* LINTED206: (enumeration values not handled in switch) */ |
4028 | case BITOR: | | 4028 | case BITOR: |
4029 | case BITXOR: | | 4029 | case BITXOR: |
4030 | case NE: | | 4030 | case NE: |
4031 | case GE: | | 4031 | case GE: |
4032 | case GT: | | 4032 | case GT: |
4033 | case LE: | | 4033 | case LE: |
4034 | case LT: | | 4034 | case LT: |
4035 | case SHR: | | 4035 | case SHR: |
4036 | case SHL: | | 4036 | case SHL: |
4037 | case MINUS: | | 4037 | case MINUS: |
4038 | case PLUS: | | 4038 | case PLUS: |
4039 | case MOD: | | 4039 | case MOD: |
4040 | case DIV: | | 4040 | case DIV: |
4041 | case MULT: | | 4041 | case MULT: |
4042 | case INDIR: | | 4042 | case INDIR: |
4043 | case UMINUS: | | 4043 | case UMINUS: |
4044 | case UPLUS: | | 4044 | case UPLUS: |
4045 | case DEC: | | 4045 | case DEC: |
4046 | case INC: | | 4046 | case INC: |
4047 | case COMPL: | | 4047 | case COMPL: |
4048 | case NOT: | | 4048 | case NOT: |
4049 | case POINT: | | 4049 | case POINT: |
4050 | case ARROW: | | 4050 | case ARROW: |
4051 | case NOOP: | | 4051 | case NOOP: |
4052 | case BITAND: | | 4052 | case BITAND: |
4053 | case FARG: | | 4053 | case FARG: |
4054 | case CASE: | | 4054 | case CASE: |
4055 | case INIT: | | 4055 | case INIT: |
4056 | case RETURN: | | 4056 | case RETURN: |
4057 | case ICALL: | | 4057 | case ICALL: |
4058 | case CVT: | | 4058 | case CVT: |
4059 | case COMMA: | | 4059 | case COMMA: |
4060 | case FSEL: | | 4060 | case FSEL: |
4061 | case COLON: | | 4061 | case COLON: |
4062 | case QUEST: | | 4062 | case QUEST: |
4063 | case LOGOR: | | 4063 | case LOGOR: |
4064 | case LOGAND: | | 4064 | case LOGAND: |
4065 | break; | | 4065 | break; |
4066 | } | | 4066 | } |
4067 | | | 4067 | |
4068 | bool cvctx = mp->m_left_value_context; | | 4068 | bool cvctx = mp->m_left_value_context; |
4069 | bool ctctx = mp->m_left_test_context; | | 4069 | bool ctctx = mp->m_left_test_context; |
4070 | bool eq = mp->m_warn_if_operand_eq && | | 4070 | bool eq = mp->m_warn_if_operand_eq && |
4071 | !ln->tn_parenthesized && | | 4071 | !ln->tn_parenthesized && |
4072 | rn != NULL && !rn->tn_parenthesized; | | 4072 | rn != NULL && !rn->tn_parenthesized; |
4073 | | | 4073 | |
4074 | /* | | 4074 | /* |
4075 | * values of operands of ':' are not used if the type of at least | | 4075 | * values of operands of ':' are not used if the type of at least |
4076 | * one of the operands (for gcc compatibility) is void | | 4076 | * one of the operands (for gcc compatibility) is void |
4077 | * XXX test/value context of QUEST should probably be used as | | 4077 | * XXX test/value context of QUEST should probably be used as |
4078 | * context for both operands of COLON | | 4078 | * context for both operands of COLON |
4079 | */ | | 4079 | */ |
4080 | if (op == COLON && tn->tn_type->t_tspec == VOID) | | 4080 | if (op == COLON && tn->tn_type->t_tspec == VOID) |
4081 | cvctx = ctctx = false; | | 4081 | cvctx = ctctx = false; |
4082 | bool discard = op == CVT && tn->tn_type->t_tspec == VOID; | | 4082 | bool discard = op == CVT && tn->tn_type->t_tspec == VOID; |
4083 | check_expr_misc(ln, cvctx, ctctx, eq, op == CALL, discard, szof); | | 4083 | check_expr_misc(ln, cvctx, ctctx, eq, op == CALL, discard, szof); |
4084 | | | 4084 | |
4085 | switch (op) { | | 4085 | switch (op) { |
4086 | case PUSH: | | 4086 | case PUSH: |
4087 | if (rn != NULL) | | 4087 | if (rn != NULL) |
4088 | check_expr_misc(rn, false, false, eq, false, false, | | 4088 | check_expr_misc(rn, false, false, eq, false, false, |
4089 | szof); | | 4089 | szof); |
4090 | break; | | 4090 | break; |
4091 | case LOGAND: | | 4091 | case LOGAND: |
4092 | case LOGOR: | | 4092 | case LOGOR: |
4093 | check_expr_misc(rn, false, true, eq, false, false, szof); | | 4093 | check_expr_misc(rn, false, true, eq, false, false, szof); |
4094 | break; | | 4094 | break; |
4095 | case COLON: | | 4095 | case COLON: |
4096 | check_expr_misc(rn, cvctx, ctctx, eq, false, false, szof); | | 4096 | check_expr_misc(rn, cvctx, ctctx, eq, false, false, szof); |
4097 | break; | | 4097 | break; |
4098 | case COMMA: | | 4098 | case COMMA: |
4099 | check_expr_misc(rn, vctx, tctx, eq, false, false, szof); | | 4099 | check_expr_misc(rn, vctx, tctx, eq, false, false, szof); |
4100 | break; | | 4100 | break; |
4101 | default: | | 4101 | default: |
4102 | if (mp->m_binary) | | 4102 | if (mp->m_binary) |
4103 | check_expr_misc(rn, true, false, eq, false, false, | | 4103 | check_expr_misc(rn, true, false, eq, false, false, |
4104 | szof); | | 4104 | szof); |
4105 | break; | | 4105 | break; |
4106 | } | | 4106 | } |
4107 | | | 4107 | |
4108 | } | | 4108 | } |
4109 | | | 4109 | |
4110 | /* | | 4110 | /* |
4111 | * Checks the range of array indices, if possible. | | 4111 | * Checks the range of array indices, if possible. |
4112 | * amper is set if only the address of the element is used. This | | 4112 | * amper is set if only the address of the element is used. This |
4113 | * means that the index is allowed to refer to the first element | | 4113 | * means that the index is allowed to refer to the first element |
4114 | * after the array. | | 4114 | * after the array. |
4115 | */ | | 4115 | */ |
4116 | static void | | 4116 | static void |
4117 | check_array_index(tnode_t *tn, bool amper) | | 4117 | check_array_index(tnode_t *tn, bool amper) |
4118 | { | | 4118 | { |
4119 | int dim; | | 4119 | int dim; |
4120 | tnode_t *ln, *rn; | | 4120 | tnode_t *ln, *rn; |
4121 | int elsz; | | 4121 | int elsz; |
4122 | int64_t con; | | 4122 | int64_t con; |
4123 | | | 4123 | |
4124 | ln = tn->tn_left; | | 4124 | ln = tn->tn_left; |
4125 | rn = tn->tn_right; | | 4125 | rn = tn->tn_right; |
4126 | | | 4126 | |
4127 | /* We can only check constant indices. */ | | 4127 | /* We can only check constant indices. */ |
4128 | if (rn->tn_op != CON) | | 4128 | if (rn->tn_op != CON) |
4129 | return; | | 4129 | return; |
4130 | | | 4130 | |
4131 | /* Return if the left node does not stem from an array. */ | | 4131 | /* Return if the left node does not stem from an array. */ |
4132 | if (ln->tn_op != ADDR) | | 4132 | if (ln->tn_op != ADDR) |
4133 | return; | | 4133 | return; |
4134 | if (ln->tn_left->tn_op != STRING && ln->tn_left->tn_op != NAME) | | 4134 | if (ln->tn_left->tn_op != STRING && ln->tn_left->tn_op != NAME) |
4135 | return; | | 4135 | return; |
4136 | if (ln->tn_left->tn_type->t_tspec != ARRAY) | | 4136 | if (ln->tn_left->tn_type->t_tspec != ARRAY) |
4137 | return; | | 4137 | return; |
4138 | | | 4138 | |
4139 | /* | | 4139 | /* |
4140 | * For incomplete array types, we can print a warning only if | | 4140 | * For incomplete array types, we can print a warning only if |
4141 | * the index is negative. | | 4141 | * the index is negative. |
4142 | */ | | 4142 | */ |
4143 | if (is_incomplete(ln->tn_left->tn_type) && rn->tn_val->v_quad >= 0) | | 4143 | if (is_incomplete(ln->tn_left->tn_type) && rn->tn_val->v_quad >= 0) |
4144 | return; | | 4144 | return; |
4145 | | | 4145 | |
4146 | /* Get the size of one array element */ | | 4146 | /* Get the size of one array element */ |
4147 | if ((elsz = length(ln->tn_type->t_subt, NULL)) == 0) | | 4147 | if ((elsz = length(ln->tn_type->t_subt, NULL)) == 0) |
4148 | return; | | 4148 | return; |
4149 | elsz /= CHAR_SIZE; | | 4149 | elsz /= CHAR_SIZE; |
4150 | | | 4150 | |
4151 | /* Change the unit of the index from bytes to element size. */ | | 4151 | /* Change the unit of the index from bytes to element size. */ |
4152 | if (is_uinteger(rn->tn_type->t_tspec)) { | | 4152 | if (is_uinteger(rn->tn_type->t_tspec)) { |
4153 | con = (uint64_t)rn->tn_val->v_quad / elsz; | | 4153 | con = (uint64_t)rn->tn_val->v_quad / elsz; |
4154 | } else { | | 4154 | } else { |
4155 | con = rn->tn_val->v_quad / elsz; | | 4155 | con = rn->tn_val->v_quad / elsz; |
4156 | } | | 4156 | } |
4157 | | | 4157 | |
4158 | dim = ln->tn_left->tn_type->t_dim + (amper ? 1 : 0); | | 4158 | dim = ln->tn_left->tn_type->t_dim + (amper ? 1 : 0); |
4159 | | | 4159 | |
4160 | if (!is_uinteger(rn->tn_type->t_tspec) && con < 0) { | | 4160 | if (!is_uinteger(rn->tn_type->t_tspec) && con < 0) { |
4161 | /* array subscript cannot be negative: %ld */ | | 4161 | /* array subscript cannot be negative: %ld */ |
4162 | warning(167, (long)con); | | 4162 | warning(167, (long)con); |
4163 | } else if (dim > 0 && (uint64_t)con >= (uint64_t)dim) { | | 4163 | } else if (dim > 0 && (uint64_t)con >= (uint64_t)dim) { |
4164 | /* array subscript cannot be > %d: %ld */ | | 4164 | /* array subscript cannot be > %d: %ld */ |
4165 | warning(168, dim - 1, (long)con); | | 4165 | warning(168, dim - 1, (long)con); |
4166 | } | | 4166 | } |
4167 | } | | 4167 | } |
4168 | | | 4168 | |
4169 | /* | | 4169 | /* |
4170 | * Check for ordered comparisons of unsigned values with 0. | | 4170 | * Check for ordered comparisons of unsigned values with 0. |
4171 | */ | | 4171 | */ |
4172 | static void | | 4172 | static void |
4173 | check_integer_comparison(op_t op, tnode_t *ln, tnode_t *rn) | | 4173 | check_integer_comparison(op_t op, tnode_t *ln, tnode_t *rn) |
4174 | { | | 4174 | { |
4175 | tspec_t lt, rt; | | 4175 | tspec_t lt, rt; |
4176 | const mod_t *mp; | | | |
4177 | | | 4176 | |
4178 | lt = ln->tn_type->t_tspec; | | 4177 | lt = ln->tn_type->t_tspec; |
4179 | rt = rn->tn_type->t_tspec; | | 4178 | rt = rn->tn_type->t_tspec; |
4180 | mp = &modtab[op]; | | | |
4181 | | | 4179 | |
4182 | if (ln->tn_op != CON && rn->tn_op != CON) | | 4180 | if (ln->tn_op != CON && rn->tn_op != CON) |
4183 | return; | | 4181 | return; |
4184 | | | 4182 | |
4185 | if (!is_integer(lt) || !is_integer(rt)) | | 4183 | if (!is_integer(lt) || !is_integer(rt)) |
4186 | return; | | 4184 | return; |
4187 | | | 4185 | |
4188 | if ((hflag || pflag) && lt == CHAR && rn->tn_op == CON && | | 4186 | if ((hflag || pflag) && lt == CHAR && rn->tn_op == CON && |
4189 | (rn->tn_val->v_quad < 0 || | | 4187 | (rn->tn_val->v_quad < 0 || |
4190 | rn->tn_val->v_quad > (int)~(~0U << (CHAR_SIZE - 1)))) { | | 4188 | rn->tn_val->v_quad > (int)~(~0U << (CHAR_SIZE - 1)))) { |
4191 | /* nonportable character comparison, op %s */ | | 4189 | /* nonportable character comparison, op %s */ |
4192 | warning(230, mp->m_name); | | 4190 | warning(230, op_name(op)); |
4193 | return; | | 4191 | return; |
4194 | } | | 4192 | } |
4195 | if ((hflag || pflag) && rt == CHAR && ln->tn_op == CON && | | 4193 | if ((hflag || pflag) && rt == CHAR && ln->tn_op == CON && |
4196 | (ln->tn_val->v_quad < 0 || | | 4194 | (ln->tn_val->v_quad < 0 || |
4197 | ln->tn_val->v_quad > (int)~(~0U << (CHAR_SIZE - 1)))) { | | 4195 | ln->tn_val->v_quad > (int)~(~0U << (CHAR_SIZE - 1)))) { |
4198 | /* nonportable character comparison, op %s */ | | 4196 | /* nonportable character comparison, op %s */ |
4199 | warning(230, mp->m_name); | | 4197 | warning(230, op_name(op)); |
4200 | return; | | 4198 | return; |
4201 | } | | 4199 | } |
4202 | if (is_uinteger(lt) && !is_uinteger(rt) && | | 4200 | if (is_uinteger(lt) && !is_uinteger(rt) && |
4203 | rn->tn_op == CON && rn->tn_val->v_quad <= 0) { | | 4201 | rn->tn_op == CON && rn->tn_val->v_quad <= 0) { |
4204 | if (rn->tn_val->v_quad < 0) { | | 4202 | if (rn->tn_val->v_quad < 0) { |
4205 | /* comparison of %s with %s, op %s */ | | 4203 | /* comparison of %s with %s, op %s */ |
4206 | warning(162, type_name(ln->tn_type), | | 4204 | warning(162, type_name(ln->tn_type), |
4207 | "negative constant", mp->m_name); | | 4205 | "negative constant", op_name(op)); |
4208 | } else if (op == LT || op == GE || (hflag && op == LE)) { | | 4206 | } else if (op == LT || op == GE || (hflag && op == LE)) { |
4209 | /* comparison of %s with %s, op %s */ | | 4207 | /* comparison of %s with %s, op %s */ |
4210 | warning(162, type_name(ln->tn_type), "0", mp->m_name); | | 4208 | warning(162, type_name(ln->tn_type), "0", op_name(op)); |
4211 | } | | 4209 | } |
4212 | return; | | 4210 | return; |
4213 | } | | 4211 | } |
4214 | if (is_uinteger(rt) && !is_uinteger(lt) && | | 4212 | if (is_uinteger(rt) && !is_uinteger(lt) && |
4215 | ln->tn_op == CON && ln->tn_val->v_quad <= 0) { | | 4213 | ln->tn_op == CON && ln->tn_val->v_quad <= 0) { |
4216 | if (ln->tn_val->v_quad < 0) { | | 4214 | if (ln->tn_val->v_quad < 0) { |
4217 | /* comparison of %s with %s, op %s */ | | 4215 | /* comparison of %s with %s, op %s */ |
4218 | warning(162, "negative constant", | | 4216 | warning(162, "negative constant", |
4219 | type_name(rn->tn_type), mp->m_name); | | 4217 | type_name(rn->tn_type), op_name(op)); |
4220 | } else if (op == GT || op == LE || (hflag && op == GE)) { | | 4218 | } else if (op == GT || op == LE || (hflag && op == GE)) { |
4221 | /* comparison of %s with %s, op %s */ | | 4219 | /* comparison of %s with %s, op %s */ |
4222 | warning(162, "0", type_name(rn->tn_type), mp->m_name); | | 4220 | warning(162, "0", type_name(rn->tn_type), op_name(op)); |
4223 | } | | 4221 | } |
4224 | return; | | 4222 | return; |
4225 | } | | 4223 | } |
4226 | } | | 4224 | } |
4227 | | | 4225 | |
4228 | /* | | 4226 | /* |
4229 | * Return whether the expression can be used for static initialization. | | 4227 | * Return whether the expression can be used for static initialization. |
4230 | * | | 4228 | * |
4231 | * Constant initialization expressions must be constant or an address | | 4229 | * Constant initialization expressions must be constant or an address |
4232 | * of a static object with an optional offset. In the first case, | | 4230 | * of a static object with an optional offset. In the first case, |
4233 | * the result is returned in *offsp. In the second case, the static | | 4231 | * the result is returned in *offsp. In the second case, the static |
4234 | * object is returned in *symp and the offset in *offsp. | | 4232 | * object is returned in *symp and the offset in *offsp. |
4235 | * | | 4233 | * |
4236 | * The expression can consist of PLUS, MINUS, ADDR, NAME, STRING and | | 4234 | * The expression can consist of PLUS, MINUS, ADDR, NAME, STRING and |
4237 | * CON. Type conversions are allowed if they do not change binary | | 4235 | * CON. Type conversions are allowed if they do not change binary |
4238 | * representation (including width). | | 4236 | * representation (including width). |
4239 | */ | | 4237 | */ |
4240 | bool | | 4238 | bool |
4241 | constant_addr(const tnode_t *tn, const sym_t **symp, ptrdiff_t *offsp) | | 4239 | constant_addr(const tnode_t *tn, const sym_t **symp, ptrdiff_t *offsp) |
4242 | { | | 4240 | { |
4243 | const sym_t *sym; | | 4241 | const sym_t *sym; |
4244 | ptrdiff_t offs1, offs2; | | 4242 | ptrdiff_t offs1, offs2; |
4245 | tspec_t t, ot; | | 4243 | tspec_t t, ot; |
4246 | | | 4244 | |
4247 | switch (tn->tn_op) { | | 4245 | switch (tn->tn_op) { |
4248 | case MINUS: | | 4246 | case MINUS: |
4249 | if (tn->tn_right->tn_op == CVT) | | 4247 | if (tn->tn_right->tn_op == CVT) |
4250 | return constant_addr(tn->tn_right, symp, offsp); | | 4248 | return constant_addr(tn->tn_right, symp, offsp); |
4251 | else if (tn->tn_right->tn_op != CON) | | 4249 | else if (tn->tn_right->tn_op != CON) |
4252 | return false; | | 4250 | return false; |
4253 | /* FALLTHROUGH */ | | 4251 | /* FALLTHROUGH */ |
4254 | case PLUS: | | 4252 | case PLUS: |
4255 | offs1 = offs2 = 0; | | 4253 | offs1 = offs2 = 0; |
4256 | if (tn->tn_left->tn_op == CON) { | | 4254 | if (tn->tn_left->tn_op == CON) { |
4257 | offs1 = (ptrdiff_t)tn->tn_left->tn_val->v_quad; | | 4255 | offs1 = (ptrdiff_t)tn->tn_left->tn_val->v_quad; |
4258 | if (!constant_addr(tn->tn_right, &sym, &offs2)) | | 4256 | if (!constant_addr(tn->tn_right, &sym, &offs2)) |
4259 | return false; | | 4257 | return false; |
4260 | } else if (tn->tn_right->tn_op == CON) { | | 4258 | } else if (tn->tn_right->tn_op == CON) { |
4261 | offs2 = (ptrdiff_t)tn->tn_right->tn_val->v_quad; | | 4259 | offs2 = (ptrdiff_t)tn->tn_right->tn_val->v_quad; |
4262 | if (tn->tn_op == MINUS) | | 4260 | if (tn->tn_op == MINUS) |
4263 | offs2 = -offs2; | | 4261 | offs2 = -offs2; |
4264 | if (!constant_addr(tn->tn_left, &sym, &offs1)) | | 4262 | if (!constant_addr(tn->tn_left, &sym, &offs1)) |
4265 | return false; | | 4263 | return false; |
4266 | } else { | | 4264 | } else { |
4267 | return false; | | 4265 | return false; |
4268 | } | | 4266 | } |
4269 | *symp = sym; | | 4267 | *symp = sym; |
4270 | *offsp = offs1 + offs2; | | 4268 | *offsp = offs1 + offs2; |
4271 | return true; | | 4269 | return true; |
4272 | case ADDR: | | 4270 | case ADDR: |
4273 | if (tn->tn_left->tn_op == NAME) { | | 4271 | if (tn->tn_left->tn_op == NAME) { |
4274 | *symp = tn->tn_left->tn_sym; | | 4272 | *symp = tn->tn_left->tn_sym; |
4275 | *offsp = 0; | | 4273 | *offsp = 0; |
4276 | return true; | | 4274 | return true; |
4277 | } else { | | 4275 | } else { |
4278 | /* | | 4276 | /* |
4279 | * If this would be the front end of a compiler we | | 4277 | * If this would be the front end of a compiler we |
4280 | * would return a label instead of 0, at least if | | 4278 | * would return a label instead of 0, at least if |
4281 | * 'tn->tn_left->tn_op == STRING'. | | 4279 | * 'tn->tn_left->tn_op == STRING'. |
4282 | */ | | 4280 | */ |
4283 | *symp = NULL; | | 4281 | *symp = NULL; |
4284 | *offsp = 0; | | 4282 | *offsp = 0; |
4285 | return true; | | 4283 | return true; |
4286 | } | | 4284 | } |
4287 | case CVT: | | 4285 | case CVT: |
4288 | t = tn->tn_type->t_tspec; | | 4286 | t = tn->tn_type->t_tspec; |
4289 | ot = tn->tn_left->tn_type->t_tspec; | | 4287 | ot = tn->tn_left->tn_type->t_tspec; |
4290 | if ((!is_integer(t) && t != PTR) || | | 4288 | if ((!is_integer(t) && t != PTR) || |
4291 | (!is_integer(ot) && ot != PTR)) { | | 4289 | (!is_integer(ot) && ot != PTR)) { |
4292 | return false; | | 4290 | return false; |
4293 | } | | 4291 | } |
4294 | #ifdef notdef | | 4292 | #ifdef notdef |
4295 | /* | | 4293 | /* |
4296 | * consider: | | 4294 | * consider: |
4297 | * struct foo { | | 4295 | * struct foo { |
4298 | * unsigned char a; | | 4296 | * unsigned char a; |
4299 | * } f = { | | 4297 | * } f = { |
4300 | * (u_char)(u_long)(&(((struct foo *)0)->a)) | | 4298 | * (u_char)(u_long)(&(((struct foo *)0)->a)) |
4301 | * }; | | 4299 | * }; |
4302 | * since psize(u_long) != psize(u_char) this fails. | | 4300 | * since psize(u_long) != psize(u_char) this fails. |
4303 | */ | | 4301 | */ |
4304 | else if (psize(t) != psize(ot)) | | 4302 | else if (psize(t) != psize(ot)) |
4305 | return -1; | | 4303 | return -1; |
4306 | #endif | | 4304 | #endif |
4307 | return constant_addr(tn->tn_left, symp, offsp); | | 4305 | return constant_addr(tn->tn_left, symp, offsp); |
4308 | default: | | 4306 | default: |
4309 | return false; | | 4307 | return false; |
4310 | } | | 4308 | } |
4311 | } | | 4309 | } |
4312 | | | 4310 | |
4313 | /* | | 4311 | /* |
4314 | * Concatenate two string constants. | | 4312 | * Concatenate two string constants. |
4315 | */ | | 4313 | */ |
4316 | strg_t * | | 4314 | strg_t * |
4317 | cat_strings(strg_t *strg1, strg_t *strg2) | | 4315 | cat_strings(strg_t *strg1, strg_t *strg2) |
4318 | { | | 4316 | { |
4319 | size_t len1, len2, len; | | 4317 | size_t len1, len2, len; |
4320 | | | 4318 | |
4321 | if (strg1->st_tspec != strg2->st_tspec) { | | 4319 | if (strg1->st_tspec != strg2->st_tspec) { |
4322 | /* cannot concatenate wide and regular string literals */ | | 4320 | /* cannot concatenate wide and regular string literals */ |
4323 | error(292); | | 4321 | error(292); |
4324 | return strg1; | | 4322 | return strg1; |
4325 | } | | 4323 | } |
4326 | | | 4324 | |
4327 | len1 = strg1->st_len; | | 4325 | len1 = strg1->st_len; |
4328 | len2 = strg2->st_len + 1; /* + NUL */ | | 4326 | len2 = strg2->st_len + 1; /* + NUL */ |
4329 | len = len1 + len2; | | 4327 | len = len1 + len2; |
4330 | | | 4328 | |
4331 | #define COPY(F) \ | | 4329 | #define COPY(F) \ |
4332 | do { \ | | 4330 | do { \ |
4333 | strg1->F = xrealloc(strg1->F, len * sizeof(*strg1->F)); \ | | 4331 | strg1->F = xrealloc(strg1->F, len * sizeof(*strg1->F)); \ |
4334 | (void)memcpy(strg1->F + len1, strg2->F, len2 * sizeof(*strg1->F)); \ | | 4332 | (void)memcpy(strg1->F + len1, strg2->F, len2 * sizeof(*strg1->F)); \ |
4335 | free(strg2->F); \ | | 4333 | free(strg2->F); \ |
4336 | } while (/*CONSTCOND*/false) | | 4334 | } while (/*CONSTCOND*/false) |
4337 | | | 4335 | |
4338 | if (strg1->st_tspec == CHAR) | | 4336 | if (strg1->st_tspec == CHAR) |
4339 | COPY(st_cp); | | 4337 | COPY(st_cp); |
4340 | else | | 4338 | else |
4341 | COPY(st_wcp); | | 4339 | COPY(st_wcp); |
4342 | | | 4340 | |
4343 | strg1->st_len = len - 1; /* - NUL */ | | 4341 | strg1->st_len = len - 1; /* - NUL */ |
4344 | free(strg2); | | 4342 | free(strg2); |
4345 | | | 4343 | |
4346 | return strg1; | | 4344 | return strg1; |
4347 | } | | 4345 | } |
4348 | | | 4346 | |
4349 | static bool | | 4347 | static bool |
4350 | is_confusing_precedence(op_t op, op_t lop, bool lparen, op_t rop, bool rparen) | | 4348 | is_confusing_precedence(op_t op, op_t lop, bool lparen, op_t rop, bool rparen) |
4351 | { | | 4349 | { |
4352 | | | 4350 | |
4353 | if (op == SHL || op == SHR) { | | 4351 | if (op == SHL || op == SHR) { |
4354 | if (!lparen && (lop == PLUS || lop == MINUS)) | | 4352 | if (!lparen && (lop == PLUS || lop == MINUS)) |
4355 | return true; | | 4353 | return true; |
4356 | if (!rparen && (rop == PLUS || rop == MINUS)) | | 4354 | if (!rparen && (rop == PLUS || rop == MINUS)) |
4357 | return true; | | 4355 | return true; |
4358 | return false; | | 4356 | return false; |
4359 | } | | 4357 | } |
4360 | | | 4358 | |
4361 | if (op == LOGOR) { | | 4359 | if (op == LOGOR) { |
4362 | if (!lparen && lop == LOGAND) | | 4360 | if (!lparen && lop == LOGAND) |
4363 | return true; | | 4361 | return true; |
4364 | if (!rparen && rop == LOGAND) | | 4362 | if (!rparen && rop == LOGAND) |
4365 | return true; | | 4363 | return true; |
4366 | return false; | | 4364 | return false; |
4367 | } | | 4365 | } |
4368 | | | 4366 | |
4369 | lint_assert(op == BITAND || op == BITXOR || op == BITOR); | | 4367 | lint_assert(op == BITAND || op == BITXOR || op == BITOR); |
4370 | if (!lparen && lop != op) { | | 4368 | if (!lparen && lop != op) { |
4371 | if (lop == PLUS || lop == MINUS) | | 4369 | if (lop == PLUS || lop == MINUS) |
4372 | return true; | | 4370 | return true; |
4373 | if (lop == BITAND || lop == BITXOR) | | 4371 | if (lop == BITAND || lop == BITXOR) |
4374 | return true; | | 4372 | return true; |
4375 | } | | 4373 | } |
4376 | if (!rparen && rop != op) { | | 4374 | if (!rparen && rop != op) { |
4377 | if (rop == PLUS || rop == MINUS) | | 4375 | if (rop == PLUS || rop == MINUS) |
4378 | return true; | | 4376 | return true; |
4379 | if (rop == BITAND || rop == BITXOR) | | 4377 | if (rop == BITAND || rop == BITXOR) |
4380 | return true; | | 4378 | return true; |
4381 | } | | 4379 | } |
4382 | return false; | | 4380 | return false; |
4383 | } | | 4381 | } |
4384 | | | 4382 | |
4385 | /* | | 4383 | /* |
4386 | * Print a warning if the given node has operands which should be | | 4384 | * Print a warning if the given node has operands which should be |
4387 | * parenthesized. | | 4385 | * parenthesized. |
4388 | * | | 4386 | * |
4389 | * XXX Does not work if an operand is a constant expression. Constant | | 4387 | * XXX Does not work if an operand is a constant expression. Constant |
4390 | * expressions are already folded. | | 4388 | * expressions are already folded. |
4391 | */ | | 4389 | */ |
4392 | static void | | 4390 | static void |
4393 | check_precedence_confusion(tnode_t *tn) | | 4391 | check_precedence_confusion(tnode_t *tn) |
4394 | { | | 4392 | { |
4395 | tnode_t *ln, *rn; | | 4393 | tnode_t *ln, *rn; |
4396 | | | 4394 | |
4397 | if (!hflag) | | 4395 | if (!hflag) |
4398 | return; | | 4396 | return; |
4399 | | | 4397 | |
4400 | debug_node(tn, 0); | | 4398 | debug_node(tn, 0); |
4401 | | | 4399 | |
4402 | lint_assert(modtab[tn->tn_op].m_binary); | | 4400 | lint_assert(modtab[tn->tn_op].m_binary); |
4403 | for (ln = tn->tn_left; ln->tn_op == CVT; ln = ln->tn_left) | | 4401 | for (ln = tn->tn_left; ln->tn_op == CVT; ln = ln->tn_left) |
4404 | continue; | | 4402 | continue; |
4405 | for (rn = tn->tn_right; rn->tn_op == CVT; rn = rn->tn_left) | | 4403 | for (rn = tn->tn_right; rn->tn_op == CVT; rn = rn->tn_left) |
4406 | continue; | | 4404 | continue; |
4407 | | | 4405 | |
4408 | if (is_confusing_precedence(tn->tn_op, | | 4406 | if (is_confusing_precedence(tn->tn_op, |
4409 | ln->tn_op, ln->tn_parenthesized, | | 4407 | ln->tn_op, ln->tn_parenthesized, |
4410 | rn->tn_op, rn->tn_parenthesized)) { | | 4408 | rn->tn_op, rn->tn_parenthesized)) { |
4411 | /* precedence confusion possible: parenthesize! */ | | 4409 | /* precedence confusion possible: parenthesize! */ |
4412 | warning(169); | | 4410 | warning(169); |
4413 | } | | 4411 | } |
4414 | } | | 4412 | } |