| @@ -1,1073 +1,1071 @@ | | | @@ -1,1073 +1,1071 @@ |
1 | /* $NetBSD: init.c,v 1.191 2021/04/02 14:19:33 rillig Exp $ */ | | 1 | /* $NetBSD: init.c,v 1.192 2021/04/02 14:32:27 rillig Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1994, 1995 Jochen Pohl | | 4 | * Copyright (c) 1994, 1995 Jochen Pohl |
5 | * Copyright (c) 2021 Roland Illig | | 5 | * Copyright (c) 2021 Roland Illig |
6 | * All Rights Reserved. | | 6 | * All Rights Reserved. |
7 | * | | 7 | * |
8 | * Redistribution and use in source and binary forms, with or without | | 8 | * Redistribution and use in source and binary forms, with or without |
9 | * modification, are permitted provided that the following conditions | | 9 | * modification, are permitted provided that the following conditions |
10 | * are met: | | 10 | * are met: |
11 | * 1. Redistributions of source code must retain the above copyright | | 11 | * 1. Redistributions of source code must retain the above copyright |
12 | * notice, this list of conditions and the following disclaimer. | | 12 | * notice, this list of conditions and the following disclaimer. |
13 | * 2. Redistributions in binary form must reproduce the above copyright | | 13 | * 2. Redistributions in binary form must reproduce the above copyright |
14 | * notice, this list of conditions and the following disclaimer in the | | 14 | * notice, this list of conditions and the following disclaimer in the |
15 | * documentation and/or other materials provided with the distribution. | | 15 | * documentation and/or other materials provided with the distribution. |
16 | * 3. All advertising materials mentioning features or use of this software | | 16 | * 3. All advertising materials mentioning features or use of this software |
17 | * must display the following acknowledgement: | | 17 | * must display the following acknowledgement: |
18 | * This product includes software developed by Jochen Pohl for | | 18 | * This product includes software developed by Jochen Pohl for |
19 | * The NetBSD Project. | | 19 | * The NetBSD Project. |
20 | * 4. The name of the author may not be used to endorse or promote products | | 20 | * 4. The name of the author may not be used to endorse or promote products |
21 | * derived from this software without specific prior written permission. | | 21 | * derived from this software without specific prior written permission. |
22 | * | | 22 | * |
23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR | | 23 | * THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR |
24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES | | 24 | * IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES |
25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. | | 25 | * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. |
26 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, | | 26 | * IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, |
27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT | | 27 | * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT |
28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 28 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 29 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 30 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 31 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 32 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
33 | */ | | 33 | */ |
34 | | | 34 | |
35 | #if HAVE_NBTOOL_CONFIG_H | | 35 | #if HAVE_NBTOOL_CONFIG_H |
36 | #include "nbtool_config.h" | | 36 | #include "nbtool_config.h" |
37 | #endif | | 37 | #endif |
38 | | | 38 | |
39 | #include <sys/cdefs.h> | | 39 | #include <sys/cdefs.h> |
40 | #if defined(__RCSID) && !defined(lint) | | 40 | #if defined(__RCSID) && !defined(lint) |
41 | __RCSID("$NetBSD: init.c,v 1.191 2021/04/02 14:19:33 rillig Exp $"); | | 41 | __RCSID("$NetBSD: init.c,v 1.192 2021/04/02 14:32:27 rillig Exp $"); |
42 | #endif | | 42 | #endif |
43 | | | 43 | |
44 | #include <stdlib.h> | | 44 | #include <stdlib.h> |
45 | #include <string.h> | | 45 | #include <string.h> |
46 | | | 46 | |
47 | #include "lint1.h" | | 47 | #include "lint1.h" |
48 | | | 48 | |
49 | | | 49 | |
50 | /* | | 50 | /* |
51 | * Initialization of global or local objects, like in: | | 51 | * Initialization of global or local objects, like in: |
52 | * | | 52 | * |
53 | * int number = 12345; | | 53 | * int number = 12345; |
54 | * int number_with_braces = { 12345 }; | | 54 | * int number_with_braces = { 12345 }; |
55 | * | | 55 | * |
56 | * int array_of_unknown_size[] = { 111, 222, 333 }; | | 56 | * int array_of_unknown_size[] = { 111, 222, 333 }; |
57 | * int array_flat[2][2] = { 11, 12, 21, 22 }; | | 57 | * int array_flat[2][2] = { 11, 12, 21, 22 }; |
58 | * int array_nested[2][2] = { { 11, 12 }, { 21, 22 } }; | | 58 | * int array_nested[2][2] = { { 11, 12 }, { 21, 22 } }; |
59 | * | | 59 | * |
60 | * struct { int x, y; } point = { 3, 4 }; | | 60 | * struct { int x, y; } point = { 3, 4 }; |
61 | * struct { int x, y; } point = { .y = 4, .x = 3 }; | | 61 | * struct { int x, y; } point = { .y = 4, .x = 3 }; |
62 | * | | 62 | * |
63 | * Any scalar expression in the initializer may be surrounded by arbitrarily | | 63 | * Any scalar expression in the initializer may be surrounded by arbitrarily |
64 | * many extra pairs of braces, like in the example 'number_with_braces' (C99 | | 64 | * many extra pairs of braces, like in the example 'number_with_braces' (C99 |
65 | * 6.7.8p11). | | 65 | * 6.7.8p11). |
66 | * | | 66 | * |
67 | * For multi-dimensional arrays, the inner braces may be omitted like in | | 67 | * For multi-dimensional arrays, the inner braces may be omitted like in |
68 | * array_flat or spelled out like in array_nested. This is unusual in | | 68 | * array_flat or spelled out like in array_nested. This is unusual in |
69 | * practice and therefore only supported very basically. | | 69 | * practice and therefore only supported very basically. |
70 | * | | 70 | * |
71 | * During initialization, the grammar parser calls these functions: | | 71 | * During initialization, the grammar parser calls these functions: |
72 | * | | 72 | * |
73 | * begin_initialization | | 73 | * begin_initialization |
74 | * init_lbrace for each '{' | | 74 | * init_lbrace for each '{' |
75 | * add_designator_member for each '.member' before '=' | | 75 | * add_designator_member for each '.member' before '=' |
76 | * add_designator_subscript for each '[123]' before '=' | | 76 | * add_designator_subscript for each '[123]' before '=' |
77 | * init_expr for each expression | | 77 | * init_expr for each expression |
78 | * init_rbrace for each '}' | | 78 | * init_rbrace for each '}' |
79 | * end_initialization | | 79 | * end_initialization |
80 | * | | 80 | * |
81 | * Each '{' begins a new brace level, each '}' ends the current brace level. | | 81 | * Each '{' begins a new brace level, each '}' ends the current brace level. |
82 | * Each brace level has an associated "current object". | | 82 | * Each brace level has an associated "current object". |
83 | * | | 83 | * |
84 | * See also: | | 84 | * See also: |
85 | * C99 6.7.8 "Initialization" | | 85 | * C99 6.7.8 "Initialization" |
86 | * d_c99_init.c for more examples | | 86 | * d_c99_init.c for more examples |
87 | */ | | 87 | */ |
88 | | | 88 | |
89 | /* | | 89 | /* |
90 | * A single component on the path to the sub-object that is initialized by an | | 90 | * A single component on the path to the sub-object that is initialized by an |
91 | * initializer expression. Either a struct or union member, or an array | | 91 | * initializer expression. Either a struct or union member, or an array |
92 | * subscript. | | 92 | * subscript. |
93 | * | | 93 | * |
94 | * C99 6.7.8p6, 6.7.8p7 | | 94 | * C99 6.7.8p6, 6.7.8p7 |
95 | */ | | 95 | */ |
96 | struct designator { | | 96 | struct designator { |
97 | const char *dr_name; /* for struct and union */ | | 97 | const char *dr_name; /* for struct and union */ |
98 | size_t dr_subscript; /* for array */ | | 98 | size_t dr_subscript; /* for array */ |
99 | struct designator *dr_next; | | 99 | struct designator *dr_next; |
100 | }; | | 100 | }; |
101 | | | 101 | |
102 | /* | | 102 | /* |
103 | * The optional designation for an initializer, saying which sub-object to | | 103 | * The optional designation for an initializer, saying which sub-object to |
104 | * initialize. Examples for designations are '.member' or | | 104 | * initialize. Examples for designations are '.member' or |
105 | * '.member[123].member.member[1][1]'. | | 105 | * '.member[123].member.member[1][1]'. |
106 | * | | 106 | * |
107 | * C99 6.7.8p6, 6.7.8p7 | | 107 | * C99 6.7.8p6, 6.7.8p7 |
108 | */ | | 108 | */ |
109 | struct designation { | | 109 | struct designation { |
110 | struct designator *dn_head; | | 110 | struct designator *dn_head; |
111 | struct designator *dn_tail; | | 111 | struct designator *dn_tail; |
112 | }; | | 112 | }; |
113 | | | 113 | |
114 | /* | | 114 | /* |
115 | * Describes a single brace level of an ongoing initialization. | | 115 | * Describes a single brace level of an ongoing initialization. |
116 | * | | 116 | * |
117 | * See C99 6.7.8p17. | | 117 | * See C99 6.7.8p17. |
118 | */ | | 118 | */ |
119 | struct brace_level { | | 119 | struct brace_level { |
120 | /* | | 120 | /* |
121 | * The type of the current object that is initialized at this brace | | 121 | * The type of the current object that is initialized at this brace |
122 | * level. | | 122 | * level. |
123 | */ | | 123 | */ |
124 | const type_t *bl_type; | | 124 | const type_t *bl_type; |
125 | const sym_t *bl_next_member; /* for structs and unions */ | | 125 | |
126 | size_t bl_array_next_subscript; | | 126 | const sym_t *bl_member; /* for structs and unions */ |
| | | 127 | size_t bl_subscript; /* for arrays */ |
127 | bool bl_scalar_done: 1; /* for scalars */ | | 128 | bool bl_scalar_done: 1; /* for scalars */ |
128 | bool bl_confused: 1; /* skip further checks */ | | 129 | bool bl_confused: 1; /* skip further checks */ |
129 | struct designation bl_designation; /* .member[123].member */ | | 130 | struct designation bl_designation; /* .member[123].member */ |
| | | 131 | |
130 | struct brace_level *bl_enclosing; | | 132 | struct brace_level *bl_enclosing; |
131 | }; | | 133 | }; |
132 | | | 134 | |
133 | struct initialization { | | 135 | struct initialization { |
134 | /* | | 136 | /* |
135 | * Is set as soon as a fatal error occurred in the initialization. | | 137 | * Is set as soon as a fatal error occurred in the initialization. |
136 | * The effect is that the rest of the initialization is ignored | | 138 | * The effect is that the rest of the initialization is ignored |
137 | * (parsed by yacc, expression trees built, but no initialization | | 139 | * (parsed by yacc, expression trees built, but no initialization |
138 | * takes place). | | 140 | * takes place). |
139 | */ | | 141 | */ |
140 | bool in_err; | | 142 | bool in_err; |
141 | | | 143 | |
142 | /* The symbol that is to be initialized. */ | | 144 | /* The symbol that is to be initialized. */ |
143 | sym_t *in_sym; | | 145 | sym_t *in_sym; |
144 | | | 146 | |
145 | /* The innermost brace level. */ | | 147 | /* The innermost brace level. */ |
146 | struct brace_level *in_brace_level; | | 148 | struct brace_level *in_brace_level; |
147 | | | 149 | |
148 | struct initialization *in_enclosing; | | 150 | struct initialization *in_enclosing; |
149 | }; | | 151 | }; |
150 | | | 152 | |
151 | | | 153 | |
152 | #ifdef DEBUG | | 154 | #ifdef DEBUG |
153 | static int debug_indentation = 0; | | 155 | static int debug_indentation = 0; |
154 | #endif | | 156 | #endif |
155 | | | 157 | |
156 | | | 158 | |
157 | #ifdef DEBUG | | 159 | #ifdef DEBUG |
158 | | | 160 | |
159 | static void __printflike(1, 2) | | 161 | static void __printflike(1, 2) |
160 | debug_printf(const char *fmt, ...) | | 162 | debug_printf(const char *fmt, ...) |
161 | { | | 163 | { |
162 | va_list va; | | 164 | va_list va; |
163 | | | 165 | |
164 | va_start(va, fmt); | | 166 | va_start(va, fmt); |
165 | vfprintf(stdout, fmt, va); | | 167 | vfprintf(stdout, fmt, va); |
166 | va_end(va); | | 168 | va_end(va); |
167 | } | | 169 | } |
168 | | | 170 | |
169 | static void | | 171 | static void |
170 | debug_indent(void) | | 172 | debug_indent(void) |
171 | { | | 173 | { |
172 | | | 174 | |
173 | debug_printf("%*s", 2 * debug_indentation, ""); | | 175 | debug_printf("%*s", 2 * debug_indentation, ""); |
174 | } | | 176 | } |
175 | | | 177 | |
176 | static void | | 178 | static void |
177 | debug_enter(const char *func) | | 179 | debug_enter(const char *func) |
178 | { | | 180 | { |
179 | | | 181 | |
180 | printf("%*s+ %s\n", 2 * debug_indentation++, "", func); | | 182 | printf("%*s+ %s\n", 2 * debug_indentation++, "", func); |
181 | } | | 183 | } |
182 | | | 184 | |
183 | static void __printflike(1, 2) | | 185 | static void __printflike(1, 2) |
184 | debug_step(const char *fmt, ...) | | 186 | debug_step(const char *fmt, ...) |
185 | { | | 187 | { |
186 | va_list va; | | 188 | va_list va; |
187 | | | 189 | |
188 | debug_indent(); | | 190 | debug_indent(); |
189 | va_start(va, fmt); | | 191 | va_start(va, fmt); |
190 | vfprintf(stdout, fmt, va); | | 192 | vfprintf(stdout, fmt, va); |
191 | va_end(va); | | 193 | va_end(va); |
192 | printf("\n"); | | 194 | printf("\n"); |
193 | } | | 195 | } |
194 | #define debug_step0 debug_step | | 196 | #define debug_step0 debug_step |
195 | #define debug_step1 debug_step | | 197 | #define debug_step1 debug_step |
196 | #define debug_step2 debug_step | | 198 | #define debug_step2 debug_step |
197 | | | 199 | |
198 | static void | | 200 | static void |
199 | debug_leave(const char *func) | | 201 | debug_leave(const char *func) |
200 | { | | 202 | { |
201 | | | 203 | |
202 | printf("%*s- %s\n", 2 * --debug_indentation, "", func); | | 204 | printf("%*s- %s\n", 2 * --debug_indentation, "", func); |
203 | } | | 205 | } |
204 | | | 206 | |
205 | #define debug_enter() (debug_enter)(__func__) | | 207 | #define debug_enter() (debug_enter)(__func__) |
206 | #define debug_leave() (debug_leave)(__func__) | | 208 | #define debug_leave() (debug_leave)(__func__) |
207 | | | 209 | |
208 | #else | | 210 | #else |
209 | | | 211 | |
210 | #define debug_indent() do { } while (false) | | 212 | #define debug_indent() do { } while (false) |
211 | #define debug_enter() do { } while (false) | | 213 | #define debug_enter() do { } while (false) |
212 | #define debug_step0(msg) do { } while (false) | | 214 | #define debug_step0(msg) do { } while (false) |
213 | #define debug_step1(fmt, arg0) do { } while (false) | | 215 | #define debug_step1(fmt, arg0) do { } while (false) |
214 | #define debug_step2(fmt, arg1, arg2) do { } while (false) | | 216 | #define debug_step2(fmt, arg1, arg2) do { } while (false) |
215 | #define debug_leave() do { } while (false) | | 217 | #define debug_leave() do { } while (false) |
216 | | | 218 | |
217 | #endif | | 219 | #endif |
218 | | | 220 | |
219 | | | 221 | |
220 | static void * | | 222 | static void * |
221 | unconst_cast(const void *p) | | 223 | unconst_cast(const void *p) |
222 | { | | 224 | { |
223 | void *r; | | 225 | void *r; |
224 | | | 226 | |
225 | memcpy(&r, &p, sizeof(r)); | | 227 | memcpy(&r, &p, sizeof(r)); |
226 | return r; | | 228 | return r; |
227 | } | | 229 | } |
228 | | | 230 | |
229 | /* C99 6.7.8p7 */ | | 231 | /* C99 6.7.8p7 */ |
230 | static bool | | 232 | static bool |
231 | is_struct_or_union(tspec_t t) | | 233 | is_struct_or_union(tspec_t t) |
232 | { | | 234 | { |
233 | | | 235 | |
234 | return t == STRUCT || t == UNION; | | 236 | return t == STRUCT || t == UNION; |
235 | } | | 237 | } |
236 | | | 238 | |
237 | static bool | | 239 | static bool |
238 | has_automatic_storage_duration(const sym_t *sym) | | 240 | has_automatic_storage_duration(const sym_t *sym) |
239 | { | | 241 | { |
240 | | | 242 | |
241 | return sym->s_scl == AUTO || sym->s_scl == REG; | | 243 | return sym->s_scl == AUTO || sym->s_scl == REG; |
242 | } | | 244 | } |
243 | | | 245 | |
244 | /* C99 6.7.8p14, 6.7.8p15 */ | | 246 | /* C99 6.7.8p14, 6.7.8p15 */ |
245 | static bool | | 247 | static bool |
246 | is_string_array(const type_t *tp, tspec_t t) | | 248 | is_string_array(const type_t *tp, tspec_t t) |
247 | { | | 249 | { |
248 | tspec_t st; | | 250 | tspec_t st; |
249 | | | 251 | |
250 | if (tp == NULL || tp->t_tspec != ARRAY) | | 252 | if (tp == NULL || tp->t_tspec != ARRAY) |
251 | return false; | | 253 | return false; |
252 | | | 254 | |
253 | st = tp->t_subt->t_tspec; | | 255 | st = tp->t_subt->t_tspec; |
254 | return t == CHAR | | 256 | return t == CHAR |
255 | ? st == CHAR || st == UCHAR || st == SCHAR | | 257 | ? st == CHAR || st == UCHAR || st == SCHAR |
256 | : st == WCHAR; | | 258 | : st == WCHAR; |
257 | } | | 259 | } |
258 | | | 260 | |
259 | /* C99 6.7.8p9 */ | | 261 | /* C99 6.7.8p9 */ |
260 | static bool | | 262 | static bool |
261 | is_unnamed(const sym_t *m) | | 263 | is_unnamed(const sym_t *m) |
262 | { | | 264 | { |
263 | | | 265 | |
264 | return m->s_bitfield && m->s_name == unnamed; | | 266 | return m->s_bitfield && m->s_name == unnamed; |
265 | } | | 267 | } |
266 | | | 268 | |
267 | /* C99 6.7.8p9 */ | | 269 | /* C99 6.7.8p9 */ |
268 | static const sym_t * | | 270 | static const sym_t * |
269 | skip_unnamed(const sym_t *m) | | 271 | skip_unnamed(const sym_t *m) |
270 | { | | 272 | { |
271 | | | 273 | |
272 | while (m != NULL && is_unnamed(m)) | | 274 | while (m != NULL && is_unnamed(m)) |
273 | m = m->s_next; | | 275 | m = m->s_next; |
274 | return m; | | 276 | return m; |
275 | } | | 277 | } |
276 | | | 278 | |
277 | static const sym_t * | | 279 | static const sym_t * |
278 | first_named_member(const type_t *tp) | | 280 | first_named_member(const type_t *tp) |
279 | { | | 281 | { |
280 | | | 282 | |
281 | lint_assert(is_struct_or_union(tp->t_tspec)); | | 283 | lint_assert(is_struct_or_union(tp->t_tspec)); |
282 | return skip_unnamed(tp->t_str->sou_first_member); | | 284 | return skip_unnamed(tp->t_str->sou_first_member); |
283 | } | | 285 | } |
284 | | | 286 | |
285 | static const sym_t * | | 287 | static const sym_t * |
286 | look_up_member(const type_t *tp, const char *name) | | 288 | look_up_member(const type_t *tp, const char *name) |
287 | { | | 289 | { |
288 | const sym_t *m; | | 290 | const sym_t *m; |
289 | | | 291 | |
290 | lint_assert(is_struct_or_union(tp->t_tspec)); | | 292 | lint_assert(is_struct_or_union(tp->t_tspec)); |
291 | for (m = tp->t_str->sou_first_member; m != NULL; m = m->s_next) | | 293 | for (m = tp->t_str->sou_first_member; m != NULL; m = m->s_next) |
292 | if (!is_unnamed(m) && strcmp(m->s_name, name) == 0) | | 294 | if (!is_unnamed(m) && strcmp(m->s_name, name) == 0) |
293 | return m; | | 295 | return m; |
294 | return NULL; | | 296 | return NULL; |
295 | } | | 297 | } |
296 | | | 298 | |
297 | static const type_t * | | 299 | static const type_t * |
298 | sym_type(const sym_t *sym) | | 300 | sym_type(const sym_t *sym) |
299 | { | | 301 | { |
300 | | | 302 | |
301 | return sym != NULL ? sym->s_type : NULL; | | 303 | return sym != NULL ? sym->s_type : NULL; |
302 | } | | 304 | } |
303 | | | 305 | |
304 | static const type_t * | | 306 | static const type_t * |
305 | look_up_member_type(const type_t *tp, const char *name) | | 307 | look_up_member_type(const type_t *tp, const char *name) |
306 | { | | 308 | { |
307 | const sym_t *member; | | 309 | const sym_t *member; |
308 | | | 310 | |
309 | member = look_up_member(tp, name); | | 311 | member = look_up_member(tp, name); |
310 | if (member == NULL) { | | 312 | if (member == NULL) { |
311 | /* type '%s' does not have member '%s' */ | | 313 | /* type '%s' does not have member '%s' */ |
312 | error(101, type_name(tp), name); | | 314 | error(101, type_name(tp), name); |
313 | } | | 315 | } |
314 | | | 316 | |
315 | return sym_type(member); | | 317 | return sym_type(member); |
316 | } | | 318 | } |
317 | | | 319 | |
318 | static void | | 320 | static void |
319 | update_type_of_array_of_unknown_size(sym_t *sym, size_t size) | | 321 | update_type_of_array_of_unknown_size(sym_t *sym, size_t size) |
320 | { | | 322 | { |
321 | type_t *tp; | | 323 | type_t *tp; |
322 | | | 324 | |
323 | tp = dup_type(sym->s_type); | | 325 | tp = dup_type(sym->s_type); |
324 | tp->t_dim = (int)size; | | 326 | tp->t_dim = (int)size; |
325 | tp->t_incomplete_array = false; | | 327 | tp->t_incomplete_array = false; |
326 | sym->s_type = tp; | | 328 | sym->s_type = tp; |
327 | } | | 329 | } |
328 | | | 330 | |
329 | | | 331 | |
330 | /* In traditional C, bit-fields can be initialized only by integer constants. */ | | 332 | /* In traditional C, bit-fields can be initialized only by integer constants. */ |
331 | static void | | 333 | static void |
332 | check_bit_field_init(const tnode_t *ln, tspec_t lt, tspec_t rt) | | 334 | check_bit_field_init(const tnode_t *ln, tspec_t lt, tspec_t rt) |
333 | { | | 335 | { |
334 | | | 336 | |
335 | if (tflag && | | 337 | if (tflag && |
336 | is_integer(lt) && | | 338 | is_integer(lt) && |
337 | ln->tn_type->t_bitfield && | | 339 | ln->tn_type->t_bitfield && |
338 | !is_integer(rt)) { | | 340 | !is_integer(rt)) { |
339 | /* bit-field initialization is illegal in traditional C */ | | 341 | /* bit-field initialization is illegal in traditional C */ |
340 | warning(186); | | 342 | warning(186); |
341 | } | | 343 | } |
342 | } | | 344 | } |
343 | | | 345 | |
344 | static void | | 346 | static void |
345 | check_non_constant_initializer(const tnode_t *tn, const sym_t *sym) | | 347 | check_non_constant_initializer(const tnode_t *tn, const sym_t *sym) |
346 | { | | 348 | { |
347 | const sym_t *unused_sym; | | 349 | const sym_t *unused_sym; |
348 | ptrdiff_t unused_offs; | | 350 | ptrdiff_t unused_offs; |
349 | | | 351 | |
350 | if (tn == NULL || tn->tn_op == CON) | | 352 | if (tn == NULL || tn->tn_op == CON) |
351 | return; | | 353 | return; |
352 | | | 354 | |
353 | if (constant_addr(tn, &unused_sym, &unused_offs)) | | 355 | if (constant_addr(tn, &unused_sym, &unused_offs)) |
354 | return; | | 356 | return; |
355 | | | 357 | |
356 | if (has_automatic_storage_duration(sym)) { | | 358 | if (has_automatic_storage_duration(sym)) { |
357 | /* non-constant initializer */ | | 359 | /* non-constant initializer */ |
358 | c99ism(177); | | 360 | c99ism(177); |
359 | } else { | | 361 | } else { |
360 | /* non-constant initializer */ | | 362 | /* non-constant initializer */ |
361 | error(177); | | 363 | error(177); |
362 | } | | 364 | } |
363 | } | | 365 | } |
364 | | | 366 | |
365 | static void | | 367 | static void |
366 | check_no_auto_aggregate(const sym_t *sym) | | 368 | check_no_auto_aggregate(const sym_t *sym) |
367 | { | | 369 | { |
368 | | | 370 | |
369 | if (tflag && | | 371 | if (tflag && |
370 | has_automatic_storage_duration(sym) && | | 372 | has_automatic_storage_duration(sym) && |
371 | !is_scalar(sym->s_type->t_tspec)) { | | 373 | !is_scalar(sym->s_type->t_tspec)) { |
372 | /* no automatic aggregate initialization in trad. C */ | | 374 | /* no automatic aggregate initialization in trad. C */ |
373 | warning(188); | | 375 | warning(188); |
374 | } | | 376 | } |
375 | } | | 377 | } |
376 | | | 378 | |
377 | static void | | 379 | static void |
378 | check_init_expr(const type_t *tp, sym_t *sym, tnode_t *tn) | | 380 | check_init_expr(const type_t *tp, sym_t *sym, tnode_t *tn) |
379 | { | | 381 | { |
380 | tnode_t *ln; | | 382 | tnode_t *ln; |
381 | tspec_t lt, rt; | | 383 | tspec_t lt, rt; |
382 | struct memory_block *tmem; | | 384 | struct memory_block *tmem; |
383 | | | 385 | |
384 | /* Create a temporary node for the left side. */ | | 386 | /* Create a temporary node for the left side. */ |
385 | ln = expr_zalloc(sizeof(*ln)); | | 387 | ln = expr_zalloc(sizeof(*ln)); |
386 | ln->tn_op = NAME; | | 388 | ln->tn_op = NAME; |
387 | ln->tn_type = expr_dup_type(tp); | | 389 | ln->tn_type = expr_dup_type(tp); |
388 | ln->tn_type->t_const = false; | | 390 | ln->tn_type->t_const = false; |
389 | ln->tn_lvalue = true; | | 391 | ln->tn_lvalue = true; |
390 | ln->tn_sym = sym; | | 392 | ln->tn_sym = sym; |
391 | | | 393 | |
392 | tn = cconv(tn); | | 394 | tn = cconv(tn); |
393 | | | 395 | |
394 | lt = ln->tn_type->t_tspec; | | 396 | lt = ln->tn_type->t_tspec; |
395 | rt = tn->tn_type->t_tspec; | | 397 | rt = tn->tn_type->t_tspec; |
396 | | | 398 | |
397 | debug_step2("typeok '%s', '%s'", | | 399 | debug_step2("typeok '%s', '%s'", |
398 | type_name(ln->tn_type), type_name(tn->tn_type)); | | 400 | type_name(ln->tn_type), type_name(tn->tn_type)); |
399 | if (!typeok(INIT, 0, ln, tn)) | | 401 | if (!typeok(INIT, 0, ln, tn)) |
400 | return; | | 402 | return; |
401 | | | 403 | |
402 | /* | | 404 | /* |
403 | * Preserve the tree memory. This is necessary because otherwise | | 405 | * Preserve the tree memory. This is necessary because otherwise |
404 | * expr() would free it. | | 406 | * expr() would free it. |
405 | */ | | 407 | */ |
406 | tmem = expr_save_memory(); | | 408 | tmem = expr_save_memory(); |
407 | expr(tn, true, false, true, false); | | 409 | expr(tn, true, false, true, false); |
408 | expr_restore_memory(tmem); | | 410 | expr_restore_memory(tmem); |
409 | | | 411 | |
410 | check_bit_field_init(ln, lt, rt); | | 412 | check_bit_field_init(ln, lt, rt); |
411 | | | 413 | |
412 | /* | | 414 | /* |
413 | * XXX: Is it correct to do this conversion _after_ the typeok above? | | 415 | * XXX: Is it correct to do this conversion _after_ the typeok above? |
414 | */ | | 416 | */ |
415 | if (lt != rt || (tp->t_bitfield && tn->tn_op == CON)) | | 417 | if (lt != rt || (tp->t_bitfield && tn->tn_op == CON)) |
416 | tn = convert(INIT, 0, unconst_cast(tp), tn); | | 418 | tn = convert(INIT, 0, unconst_cast(tp), tn); |
417 | | | 419 | |
418 | check_non_constant_initializer(tn, sym); | | 420 | check_non_constant_initializer(tn, sym); |
419 | } | | 421 | } |
420 | | | 422 | |
421 | | | 423 | |
422 | static struct designator * | | 424 | static struct designator * |
423 | designator_new(const char *name, size_t subscript) | | 425 | designator_new(const char *name, size_t subscript) |
424 | { | | 426 | { |
425 | struct designator *dr; | | 427 | struct designator *dr; |
426 | | | 428 | |
427 | dr = xcalloc(1, sizeof(*dr)); | | 429 | dr = xcalloc(1, sizeof(*dr)); |
428 | dr->dr_name = name; | | 430 | dr->dr_name = name; |
429 | dr->dr_subscript = subscript; | | 431 | dr->dr_subscript = subscript; |
430 | return dr; | | 432 | return dr; |
431 | } | | 433 | } |
432 | | | 434 | |
433 | static void | | 435 | static void |
434 | designator_free(struct designator *dr) | | 436 | designator_free(struct designator *dr) |
435 | { | | 437 | { |
436 | | | 438 | |
437 | free(dr); | | 439 | free(dr); |
438 | } | | 440 | } |
439 | | | 441 | |
440 | | | 442 | |
441 | static const type_t * | | 443 | static const type_t * |
442 | designator_look_up(const struct designator *dr, const type_t *tp) | | 444 | designator_look_up(const struct designator *dr, const type_t *tp) |
443 | { | | 445 | { |
444 | switch (tp->t_tspec) { | | 446 | switch (tp->t_tspec) { |
445 | case STRUCT: | | 447 | case STRUCT: |
446 | case UNION: | | 448 | case UNION: |
447 | if (dr->dr_name == NULL) { | | 449 | if (dr->dr_name == NULL) { |
448 | /* syntax error '%s' */ | | 450 | /* syntax error '%s' */ |
449 | error(249, "designator '[...]' is only for arrays"); | | 451 | error(249, "designator '[...]' is only for arrays"); |
450 | return sym_type(first_named_member(tp)); | | 452 | return sym_type(first_named_member(tp)); |
451 | } | | 453 | } |
452 | | | 454 | |
453 | return look_up_member_type(tp, dr->dr_name); | | 455 | return look_up_member_type(tp, dr->dr_name); |
454 | case ARRAY: | | 456 | case ARRAY: |
455 | if (dr->dr_name != NULL) { | | 457 | if (dr->dr_name != NULL) { |
456 | /* syntax error '%s' */ | | 458 | /* syntax error '%s' */ |
457 | error(249, | | 459 | error(249, |
458 | "designator '.member' is only for struct/union"); | | 460 | "designator '.member' is only for struct/union"); |
459 | } | | 461 | } |
460 | if (!tp->t_incomplete_array && | | 462 | if (!tp->t_incomplete_array && |
461 | dr->dr_subscript >= (size_t)tp->t_dim) { | | 463 | dr->dr_subscript >= (size_t)tp->t_dim) { |
462 | /* array subscript cannot be > %d: %ld */ | | 464 | /* array subscript cannot be > %d: %ld */ |
463 | error(168, tp->t_dim - 1, (long)dr->dr_subscript); | | 465 | error(168, tp->t_dim - 1, (long)dr->dr_subscript); |
464 | } | | 466 | } |
465 | return tp->t_subt; | | 467 | return tp->t_subt; |
466 | default: | | 468 | default: |
467 | /* syntax error '%s' */ | | 469 | /* syntax error '%s' */ |
468 | error(249, "scalar type cannot use designator"); | | 470 | error(249, "scalar type cannot use designator"); |
469 | return tp; | | 471 | return tp; |
470 | } | | 472 | } |
471 | } | | 473 | } |
472 | | | 474 | |
473 | | | 475 | |
474 | #ifdef DEBUG | | 476 | #ifdef DEBUG |
475 | static void | | 477 | static void |
476 | designation_debug(const struct designation *dn) | | 478 | designation_debug(const struct designation *dn) |
477 | { | | 479 | { |
478 | const struct designator *dr; | | 480 | const struct designator *dr; |
479 | | | 481 | |
480 | if (dn->dn_head == NULL) | | 482 | if (dn->dn_head == NULL) |
481 | return; | | 483 | return; |
482 | | | 484 | |
483 | debug_indent(); | | 485 | debug_indent(); |
484 | debug_printf("designation: "); | | 486 | debug_printf("designation: "); |
485 | for (dr = dn->dn_head; dr != NULL; dr = dr->dr_next) { | | 487 | for (dr = dn->dn_head; dr != NULL; dr = dr->dr_next) { |
486 | if (dr->dr_name != NULL) { | | 488 | if (dr->dr_name != NULL) { |
487 | debug_printf(".%s", dr->dr_name); | | 489 | debug_printf(".%s", dr->dr_name); |
488 | lint_assert(dr->dr_subscript == 0); | | 490 | lint_assert(dr->dr_subscript == 0); |
489 | } else | | 491 | } else |
490 | debug_printf("[%zu]", dr->dr_subscript); | | 492 | debug_printf("[%zu]", dr->dr_subscript); |
491 | } | | 493 | } |
492 | debug_printf("\n"); | | 494 | debug_printf("\n"); |
493 | } | | 495 | } |
494 | #else | | 496 | #else |
495 | #define designation_debug(dn) do { } while (false) | | 497 | #define designation_debug(dn) do { } while (false) |
496 | #endif | | 498 | #endif |
497 | | | 499 | |
498 | static void | | 500 | static void |
499 | designation_add(struct designation *dn, const char *name, size_t subscript) | | 501 | designation_add(struct designation *dn, const char *name, size_t subscript) |
500 | { | | 502 | { |
501 | struct designator *dr; | | 503 | struct designator *dr; |
502 | | | 504 | |
503 | dr = designator_new(name, subscript); | | 505 | dr = designator_new(name, subscript); |
504 | | | 506 | |
505 | if (dn->dn_head != NULL) { | | 507 | if (dn->dn_head != NULL) { |
506 | dn->dn_tail->dr_next = dr; | | 508 | dn->dn_tail->dr_next = dr; |
507 | dn->dn_tail = dr; | | 509 | dn->dn_tail = dr; |
508 | } else { | | 510 | } else { |
509 | dn->dn_head = dr; | | 511 | dn->dn_head = dr; |
510 | dn->dn_tail = dr; | | 512 | dn->dn_tail = dr; |
511 | } | | 513 | } |
512 | } | | 514 | } |
513 | | | 515 | |
514 | /* | | 516 | /* |
515 | * Starting at the type of the current object, resolve the type of the | | 517 | * Starting at the type of the current object, resolve the type of the |
516 | * sub-object by following each designator in the list. | | 518 | * sub-object by following each designator in the list. |
517 | */ | | 519 | */ |
518 | static const type_t * | | 520 | static const type_t * |
519 | designation_look_up(const struct designation *dn, const type_t *tp) | | 521 | designation_look_up(const struct designation *dn, const type_t *tp) |
520 | { | | 522 | { |
521 | const struct designator *dr; | | 523 | const struct designator *dr; |
522 | | | 524 | |
523 | for (dr = dn->dn_head; dr != NULL && tp != NULL; dr = dr->dr_next) | | 525 | for (dr = dn->dn_head; dr != NULL && tp != NULL; dr = dr->dr_next) |
524 | tp = designator_look_up(dr, tp); | | 526 | tp = designator_look_up(dr, tp); |
525 | return tp; | | 527 | return tp; |
526 | } | | 528 | } |
527 | | | 529 | |
528 | static void | | 530 | static void |
529 | designation_reset(struct designation *dn) | | 531 | designation_reset(struct designation *dn) |
530 | { | | 532 | { |
531 | struct designator *dr, *next; | | 533 | struct designator *dr, *next; |
532 | | | 534 | |
533 | for (dr = dn->dn_head; dr != NULL; dr = next) { | | 535 | for (dr = dn->dn_head; dr != NULL; dr = next) { |
534 | next = dr->dr_next; | | 536 | next = dr->dr_next; |
535 | designator_free(dr); | | 537 | designator_free(dr); |
536 | } | | 538 | } |
537 | | | 539 | |
538 | dn->dn_head = NULL; | | 540 | dn->dn_head = NULL; |
539 | dn->dn_tail = NULL; | | 541 | dn->dn_tail = NULL; |
540 | } | | 542 | } |
541 | | | 543 | |
542 | | | 544 | |
543 | static struct brace_level * | | 545 | static struct brace_level * |
544 | brace_level_new(const type_t *tp, struct brace_level *enclosing) | | 546 | brace_level_new(const type_t *tp, struct brace_level *enclosing) |
545 | { | | 547 | { |
546 | struct brace_level *bl; | | 548 | struct brace_level *bl; |
547 | | | 549 | |
548 | bl = xcalloc(1, sizeof(*bl)); | | 550 | bl = xcalloc(1, sizeof(*bl)); |
549 | bl->bl_type = tp; | | 551 | bl->bl_type = tp; |
550 | bl->bl_enclosing = enclosing; | | 552 | bl->bl_enclosing = enclosing; |
551 | if (is_struct_or_union(tp->t_tspec)) | | 553 | if (is_struct_or_union(tp->t_tspec)) |
552 | bl->bl_next_member = first_named_member(tp); | | 554 | bl->bl_member = first_named_member(tp); |
553 | | | 555 | |
554 | return bl; | | 556 | return bl; |
555 | } | | 557 | } |
556 | | | 558 | |
557 | static void | | 559 | static void |
558 | brace_level_free(struct brace_level *bl) | | 560 | brace_level_free(struct brace_level *bl) |
559 | { | | 561 | { |
560 | | | 562 | |
561 | designation_reset(&bl->bl_designation); | | 563 | designation_reset(&bl->bl_designation); |
562 | free(bl); | | 564 | free(bl); |
563 | } | | 565 | } |
564 | | | 566 | |
565 | #ifdef DEBUG | | 567 | #ifdef DEBUG |
566 | static void | | 568 | static void |
567 | brace_level_debug(const struct brace_level *bl) | | 569 | brace_level_debug(const struct brace_level *bl) |
568 | { | | 570 | { |
569 | | | 571 | |
570 | lint_assert(bl->bl_type != NULL); | | 572 | lint_assert(bl->bl_type != NULL); |
571 | lint_assert(bl->bl_next_member == NULL || | | 573 | lint_assert(bl->bl_member == NULL || !is_unnamed(bl->bl_member)); |
572 | !is_unnamed(bl->bl_next_member)); | | | |
573 | | | 574 | |
574 | debug_printf("type '%s'", type_name(bl->bl_type)); | | 575 | debug_printf("type '%s'", type_name(bl->bl_type)); |
575 | | | 576 | |
576 | if (is_struct_or_union(bl->bl_type->t_tspec) && | | 577 | if (is_struct_or_union(bl->bl_type->t_tspec) && bl->bl_member != NULL) |
577 | bl->bl_next_member != NULL) | | 578 | debug_printf(", member '%s'", bl->bl_member->s_name); |
578 | debug_printf(", next member '%s'", | | | |
579 | bl->bl_next_member->s_name); | | | |
580 | if (bl->bl_type->t_tspec == ARRAY) | | 579 | if (bl->bl_type->t_tspec == ARRAY) |
581 | debug_printf(", next array subscript %zu", | | 580 | debug_printf(", subscript %zu", bl->bl_subscript); |
582 | bl->bl_array_next_subscript); | | | |
583 | | | 581 | |
584 | debug_printf("\n"); | | 582 | debug_printf("\n"); |
585 | } | | 583 | } |
586 | #else | | 584 | #else |
587 | #define brace_level_debug(level) do { } while (false) | | 585 | #define brace_level_debug(level) do { } while (false) |
588 | #endif | | 586 | #endif |
589 | | | 587 | |
590 | static const type_t * | | 588 | static const type_t * |
591 | brace_level_sub_type_struct_or_union(const struct brace_level *bl) | | 589 | brace_level_sub_type_struct_or_union(const struct brace_level *bl) |
592 | { | | 590 | { |
593 | | | 591 | |
594 | if (bl->bl_next_member == NULL) { | | 592 | if (bl->bl_member == NULL) { |
595 | /* too many struct/union initializers */ | | 593 | /* too many struct/union initializers */ |
596 | error(172); | | 594 | error(172); |
597 | return NULL; | | 595 | return NULL; |
598 | } | | 596 | } |
599 | | | 597 | |
600 | lint_assert(!is_unnamed(bl->bl_next_member)); | | 598 | lint_assert(!is_unnamed(bl->bl_member)); |
601 | return sym_type(bl->bl_next_member); | | 599 | return sym_type(bl->bl_member); |
602 | } | | 600 | } |
603 | | | 601 | |
604 | static const type_t * | | 602 | static const type_t * |
605 | brace_level_sub_type_array(const struct brace_level *bl) | | 603 | brace_level_sub_type_array(const struct brace_level *bl) |
606 | { | | 604 | { |
607 | | | 605 | |
608 | if (!bl->bl_confused && !bl->bl_type->t_incomplete_array && | | 606 | if (!bl->bl_confused && !bl->bl_type->t_incomplete_array && |
609 | bl->bl_array_next_subscript >= (size_t)bl->bl_type->t_dim) { | | 607 | bl->bl_subscript >= (size_t)bl->bl_type->t_dim) { |
610 | /* too many array initializers, expected %d */ | | 608 | /* too many array initializers, expected %d */ |
611 | error(173, bl->bl_type->t_dim); | | 609 | error(173, bl->bl_type->t_dim); |
612 | } | | 610 | } |
613 | | | 611 | |
614 | return bl->bl_type->t_subt; | | 612 | return bl->bl_type->t_subt; |
615 | } | | 613 | } |
616 | | | 614 | |
617 | static const type_t * | | 615 | static const type_t * |
618 | brace_level_sub_type_scalar(const struct brace_level *bl) | | 616 | brace_level_sub_type_scalar(const struct brace_level *bl) |
619 | { | | 617 | { |
620 | | | 618 | |
621 | if (bl->bl_scalar_done) { | | 619 | if (bl->bl_scalar_done) { |
622 | /* too many initializers */ | | 620 | /* too many initializers */ |
623 | error(174); | | 621 | error(174); |
624 | } | | 622 | } |
625 | | | 623 | |
626 | return bl->bl_type; | | 624 | return bl->bl_type; |
627 | } | | 625 | } |
628 | | | 626 | |
629 | /* Return the type of the sub-object that is currently being initialized. */ | | 627 | /* Return the type of the sub-object that is currently being initialized. */ |
630 | static const type_t * | | 628 | static const type_t * |
631 | brace_level_sub_type(const struct brace_level *bl) | | 629 | brace_level_sub_type(const struct brace_level *bl) |
632 | { | | 630 | { |
633 | | | 631 | |
634 | if (bl->bl_designation.dn_head != NULL) | | 632 | if (bl->bl_designation.dn_head != NULL) |
635 | return designation_look_up(&bl->bl_designation, bl->bl_type); | | 633 | return designation_look_up(&bl->bl_designation, bl->bl_type); |
636 | | | 634 | |
637 | switch (bl->bl_type->t_tspec) { | | 635 | switch (bl->bl_type->t_tspec) { |
638 | case STRUCT: | | 636 | case STRUCT: |
639 | case UNION: | | 637 | case UNION: |
640 | return brace_level_sub_type_struct_or_union(bl); | | 638 | return brace_level_sub_type_struct_or_union(bl); |
641 | case ARRAY: | | 639 | case ARRAY: |
642 | return brace_level_sub_type_array(bl); | | 640 | return brace_level_sub_type_array(bl); |
643 | default: | | 641 | default: |
644 | return brace_level_sub_type_scalar(bl); | | 642 | return brace_level_sub_type_scalar(bl); |
645 | } | | 643 | } |
646 | } | | 644 | } |
647 | | | 645 | |
| | | 646 | /* C99 6.7.8p17 */ |
648 | static void | | 647 | static void |
649 | brace_level_apply_designation(struct brace_level *bl) | | 648 | brace_level_apply_designation(struct brace_level *bl) |
650 | { | | 649 | { |
651 | const struct designator *dr = bl->bl_designation.dn_head; | | 650 | const struct designator *dr = bl->bl_designation.dn_head; |
652 | | | 651 | |
653 | if (dr == NULL) | | 652 | if (dr == NULL) |
654 | return; | | 653 | return; |
655 | | | 654 | |
656 | designation_debug(&bl->bl_designation); | | 655 | designation_debug(&bl->bl_designation); |
657 | | | 656 | |
658 | switch (bl->bl_type->t_tspec) { | | 657 | switch (bl->bl_type->t_tspec) { |
659 | case STRUCT: | | 658 | case STRUCT: |
660 | case UNION: | | 659 | case UNION: |
661 | if (dr->dr_name == NULL) | | 660 | if (dr->dr_name == NULL) |
662 | return; /* error, silently ignored */ | | 661 | return; /* error, silently ignored */ |
663 | bl->bl_next_member = look_up_member(bl->bl_type, dr->dr_name); | | 662 | bl->bl_member = look_up_member(bl->bl_type, dr->dr_name); |
664 | break; | | 663 | break; |
665 | case ARRAY: | | 664 | case ARRAY: |
666 | if (dr->dr_name != NULL) | | 665 | if (dr->dr_name != NULL) |
667 | return; /* error, silently ignored */ | | 666 | return; /* error, silently ignored */ |
668 | bl->bl_array_next_subscript = dr->dr_subscript; | | 667 | bl->bl_subscript = dr->dr_subscript; |
669 | break; | | 668 | break; |
670 | default: | | 669 | default: |
671 | break; /* error, silently ignored */ | | 670 | break; /* error, silently ignored */ |
672 | } | | 671 | } |
673 | } | | 672 | } |
674 | | | 673 | |
675 | /* | | 674 | /* |
676 | * After initializing a sub-object, advance to the next sub-object. | | 675 | * After initializing a sub-object, advance to the next sub-object. |
677 | * | | 676 | * |
678 | * C99 6.7.8p17 | | 677 | * C99 6.7.8p17 |
679 | */ | | 678 | */ |
680 | static void | | 679 | static void |
681 | brace_level_advance(struct brace_level *bl) | | 680 | brace_level_advance(struct brace_level *bl) |
682 | { | | 681 | { |
683 | | | 682 | |
684 | switch (bl->bl_type->t_tspec) { | | 683 | switch (bl->bl_type->t_tspec) { |
685 | case STRUCT: | | 684 | case STRUCT: |
686 | lint_assert(bl->bl_next_member != NULL); | | 685 | lint_assert(bl->bl_member != NULL); |
687 | bl->bl_next_member = skip_unnamed(bl->bl_next_member->s_next); | | 686 | bl->bl_member = skip_unnamed(bl->bl_member->s_next); |
688 | break; | | 687 | break; |
689 | case UNION: | | 688 | case UNION: |
690 | bl->bl_next_member = NULL; | | 689 | bl->bl_member = NULL; |
691 | break; | | 690 | break; |
692 | case ARRAY: | | 691 | case ARRAY: |
693 | bl->bl_array_next_subscript++; | | 692 | bl->bl_subscript++; |
694 | break; | | 693 | break; |
695 | default: | | 694 | default: |
696 | bl->bl_scalar_done = true; | | 695 | bl->bl_scalar_done = true; |
697 | break; | | 696 | break; |
698 | } | | 697 | } |
699 | } | | 698 | } |
700 | | | 699 | |
701 | | | 700 | |
702 | static struct initialization * | | 701 | static struct initialization * |
703 | initialization_new(sym_t *sym) | | 702 | initialization_new(sym_t *sym) |
704 | { | | 703 | { |
705 | struct initialization *in; | | 704 | struct initialization *in; |
706 | | | 705 | |
707 | in = xcalloc(1, sizeof(*in)); | | 706 | in = xcalloc(1, sizeof(*in)); |
708 | in->in_sym = sym; | | 707 | in->in_sym = sym; |
709 | | | 708 | |
710 | return in; | | 709 | return in; |
711 | } | | 710 | } |
712 | | | 711 | |
713 | static void | | 712 | static void |
714 | initialization_free(struct initialization *in) | | 713 | initialization_free(struct initialization *in) |
715 | { | | 714 | { |
716 | struct brace_level *bl, *next; | | 715 | struct brace_level *bl, *next; |
717 | | | 716 | |
718 | for (bl = in->in_brace_level; bl != NULL; bl = next) { | | 717 | for (bl = in->in_brace_level; bl != NULL; bl = next) { |
719 | next = bl->bl_enclosing; | | 718 | next = bl->bl_enclosing; |
720 | brace_level_free(bl); | | 719 | brace_level_free(bl); |
721 | } | | 720 | } |
722 | | | 721 | |
723 | free(in); | | 722 | free(in); |
724 | } | | 723 | } |
725 | | | 724 | |
726 | #ifdef DEBUG | | 725 | #ifdef DEBUG |
727 | static void | | 726 | static void |
728 | initialization_debug(const struct initialization *in) | | 727 | initialization_debug(const struct initialization *in) |
729 | { | | 728 | { |
730 | size_t i; | | 729 | size_t i; |
731 | const struct brace_level *bl; | | 730 | const struct brace_level *bl; |
732 | | | 731 | |
733 | if (in->in_brace_level == NULL) { | | 732 | if (in->in_brace_level == NULL) { |
734 | debug_step("no brace level"); | | 733 | debug_step("no brace level"); |
735 | return; | | 734 | return; |
736 | } | | 735 | } |
737 | | | 736 | |
738 | i = 0; | | 737 | i = 0; |
739 | for (bl = in->in_brace_level; bl != NULL; bl = bl->bl_enclosing) { | | 738 | for (bl = in->in_brace_level; bl != NULL; bl = bl->bl_enclosing) { |
740 | debug_indent(); | | 739 | debug_indent(); |
741 | debug_printf("brace level %zu: ", i); | | 740 | debug_printf("brace level %zu: ", i); |
742 | brace_level_debug(bl); | | 741 | brace_level_debug(bl); |
743 | i++; | | 742 | i++; |
744 | } | | 743 | } |
745 | } | | 744 | } |
746 | #else | | 745 | #else |
747 | #define initialization_debug(in) do { } while (false) | | 746 | #define initialization_debug(in) do { } while (false) |
748 | #endif | | 747 | #endif |
749 | | | 748 | |
750 | /* | | 749 | /* |
751 | * Return the type of the object or sub-object that is currently being | | 750 | * Return the type of the object or sub-object that is currently being |
752 | * initialized. | | 751 | * initialized. |
753 | */ | | 752 | */ |
754 | static const type_t * | | 753 | static const type_t * |
755 | initialization_sub_type(struct initialization *in) | | 754 | initialization_sub_type(struct initialization *in) |
756 | { | | 755 | { |
757 | const type_t *tp; | | 756 | const type_t *tp; |
758 | | | 757 | |
759 | tp = in->in_brace_level != NULL | | 758 | tp = in->in_brace_level != NULL |
760 | ? brace_level_sub_type(in->in_brace_level) | | 759 | ? brace_level_sub_type(in->in_brace_level) |
761 | : in->in_sym->s_type; | | 760 | : in->in_sym->s_type; |
762 | if (tp == NULL) | | 761 | if (tp == NULL) |
763 | in->in_err = true; | | 762 | in->in_err = true; |
764 | return tp; | | 763 | return tp; |
765 | } | | 764 | } |
766 | | | 765 | |
767 | static void | | 766 | static void |
768 | initialization_begin_brace_level(struct initialization *in) | | 767 | initialization_begin_brace_level(struct initialization *in) |
769 | { | | 768 | { |
770 | const type_t *tp; | | 769 | const type_t *tp; |
771 | | | 770 | |
772 | if (in->in_err) | | 771 | if (in->in_err) |
773 | return; | | 772 | return; |
774 | | | 773 | |
775 | debug_enter(); | | 774 | debug_enter(); |
776 | | | 775 | |
777 | tp = initialization_sub_type(in); | | 776 | tp = initialization_sub_type(in); |
778 | if (tp == NULL) { | | 777 | if (tp == NULL) { |
779 | in->in_err = true; | | 778 | in->in_err = true; |
780 | goto done; | | 779 | goto done; |
781 | } | | 780 | } |
782 | | | 781 | |
783 | if (tflag && in->in_brace_level == NULL) | | 782 | if (tflag && in->in_brace_level == NULL) |
784 | check_no_auto_aggregate(in->in_sym); | | 783 | check_no_auto_aggregate(in->in_sym); |
785 | | | 784 | |
786 | if (tflag && tp->t_tspec == UNION) { | | 785 | if (tflag && tp->t_tspec == UNION) { |
787 | /* initialization of union is illegal in traditional C */ | | 786 | /* initialization of union is illegal in traditional C */ |
788 | warning(238); | | 787 | warning(238); |
789 | } | | 788 | } |
790 | | | 789 | |
791 | if (tp->t_tspec == STRUCT && tp->t_str->sou_incomplete) { | | 790 | if (tp->t_tspec == STRUCT && tp->t_str->sou_incomplete) { |
792 | /* initialization of incomplete type '%s' */ | | 791 | /* initialization of incomplete type '%s' */ |
793 | error(175, type_name(tp)); | | 792 | error(175, type_name(tp)); |
794 | in->in_err = true; | | 793 | in->in_err = true; |
795 | goto done; | | 794 | goto done; |
796 | } | | 795 | } |
797 | | | 796 | |
798 | if (in->in_brace_level != NULL) | | 797 | if (in->in_brace_level != NULL) |
799 | brace_level_apply_designation(in->in_brace_level); | | 798 | brace_level_apply_designation(in->in_brace_level); |
800 | | | 799 | |
801 | in->in_brace_level = brace_level_new(tp, in->in_brace_level); | | 800 | in->in_brace_level = brace_level_new(tp, in->in_brace_level); |
802 | | | 801 | |
803 | done: | | 802 | done: |
804 | initialization_debug(in); | | 803 | initialization_debug(in); |
805 | debug_leave(); | | 804 | debug_leave(); |
806 | } | | 805 | } |
807 | | | 806 | |
808 | /* C99 6.7.8p22 */ | | 807 | /* C99 6.7.8p22 */ |
809 | static void | | 808 | static void |
810 | initialization_set_size_of_unknown_array(struct initialization *in) | | 809 | initialization_set_size_of_unknown_array(struct initialization *in) |
811 | { | | 810 | { |
812 | | | 811 | |
813 | if (in->in_sym->s_type->t_incomplete_array && | | 812 | if (in->in_sym->s_type->t_incomplete_array && |
814 | in->in_brace_level->bl_enclosing == NULL) | | 813 | in->in_brace_level->bl_enclosing == NULL) |
815 | update_type_of_array_of_unknown_size(in->in_sym, | | 814 | update_type_of_array_of_unknown_size(in->in_sym, |
816 | in->in_brace_level->bl_array_next_subscript); | | 815 | in->in_brace_level->bl_subscript); |
817 | } | | 816 | } |
818 | | | 817 | |
819 | static void | | 818 | static void |
820 | initialization_end_brace_level(struct initialization *in) | | 819 | initialization_end_brace_level(struct initialization *in) |
821 | { | | 820 | { |
822 | struct brace_level *bl; | | 821 | struct brace_level *bl; |
823 | | | 822 | |
824 | if (in->in_err) | | 823 | if (in->in_err) |
825 | return; | | 824 | return; |
826 | | | 825 | |
827 | debug_enter(); | | 826 | debug_enter(); |
828 | | | 827 | |
829 | initialization_set_size_of_unknown_array(in); | | 828 | initialization_set_size_of_unknown_array(in); |
830 | | | 829 | |
831 | bl = in->in_brace_level; | | 830 | bl = in->in_brace_level; |
832 | in->in_brace_level = bl->bl_enclosing; | | 831 | in->in_brace_level = bl->bl_enclosing; |
833 | brace_level_free(bl); | | 832 | brace_level_free(bl); |
834 | bl = in->in_brace_level; | | 833 | bl = in->in_brace_level; |
835 | | | 834 | |
836 | if (bl != NULL) | | 835 | if (bl != NULL) |
837 | brace_level_advance(bl); | | 836 | brace_level_advance(bl); |
838 | if (bl != NULL) | | 837 | if (bl != NULL) |
839 | designation_reset(&bl->bl_designation); | | 838 | designation_reset(&bl->bl_designation); |
840 | | | 839 | |
841 | initialization_debug(in); | | 840 | initialization_debug(in); |
842 | debug_leave(); | | 841 | debug_leave(); |
843 | } | | 842 | } |
844 | | | 843 | |
845 | static void | | 844 | static void |
846 | initialization_add_designator(struct initialization *in, | | 845 | initialization_add_designator(struct initialization *in, |
847 | const char *name, size_t subscript) | | 846 | const char *name, size_t subscript) |
848 | { | | 847 | { |
849 | | | 848 | |
850 | if (in->in_err) | | 849 | if (in->in_err) |
851 | return; | | 850 | return; |
852 | | | 851 | |
853 | lint_assert(in->in_brace_level != NULL); | | 852 | lint_assert(in->in_brace_level != NULL); |
854 | designation_add(&in->in_brace_level->bl_designation, name, subscript); | | 853 | designation_add(&in->in_brace_level->bl_designation, name, subscript); |
855 | } | | 854 | } |
856 | | | 855 | |
857 | /* | | 856 | /* |
858 | * An object with automatic storage duration that has a single initializer | | 857 | * An object with automatic storage duration that has a single initializer |
859 | * expression without braces and is not an array is initialized by delegating | | 858 | * expression without braces and is not an array is initialized by delegating |
860 | * to the ASSIGN operator. | | 859 | * to the ASSIGN operator. |
861 | */ | | 860 | */ |
862 | static bool | | 861 | static bool |
863 | initialization_expr_using_assign(struct initialization *in, tnode_t *rn) | | 862 | initialization_expr_using_assign(struct initialization *in, tnode_t *rn) |
864 | { | | 863 | { |
865 | tnode_t *ln, *tn; | | 864 | tnode_t *ln, *tn; |
866 | | | 865 | |
867 | if (!has_automatic_storage_duration(in->in_sym)) | | 866 | if (!has_automatic_storage_duration(in->in_sym)) |
868 | return false; | | 867 | return false; |
869 | if (in->in_brace_level != NULL) | | 868 | if (in->in_brace_level != NULL) |
870 | return false; | | 869 | return false; |
871 | if (in->in_sym->s_type->t_tspec == ARRAY) | | 870 | if (in->in_sym->s_type->t_tspec == ARRAY) |
872 | return false; | | 871 | return false; |
873 | | | 872 | |
874 | debug_step0("handing over to ASSIGN"); | | 873 | debug_step0("handing over to ASSIGN"); |
875 | | | 874 | |
876 | ln = new_name_node(in->in_sym, 0); | | 875 | ln = new_name_node(in->in_sym, 0); |
877 | ln->tn_type = expr_dup_type(ln->tn_type); | | 876 | ln->tn_type = expr_dup_type(ln->tn_type); |
878 | ln->tn_type->t_const = false; | | 877 | ln->tn_type->t_const = false; |
879 | | | 878 | |
880 | tn = build(ASSIGN, ln, rn); | | 879 | tn = build(ASSIGN, ln, rn); |
881 | expr(tn, false, false, false, false); | | 880 | expr(tn, false, false, false, false); |
882 | | | 881 | |
883 | return true; | | 882 | return true; |
884 | } | | 883 | } |
885 | | | 884 | |
886 | /* Initialize a character array or wchar_t array with a string literal. */ | | 885 | /* Initialize a character array or wchar_t array with a string literal. */ |
887 | static bool | | 886 | static bool |
888 | initialization_init_array_using_string(struct initialization *in, tnode_t *tn) | | 887 | initialization_init_array_using_string(struct initialization *in, tnode_t *tn) |
889 | { | | 888 | { |
890 | struct brace_level *bl; | | 889 | struct brace_level *bl; |
891 | const type_t *tp; | | 890 | const type_t *tp; |
892 | strg_t *strg; | | 891 | strg_t *strg; |
893 | | | 892 | |
894 | if (tn->tn_op != STRING) | | 893 | if (tn->tn_op != STRING) |
895 | return false; | | 894 | return false; |
896 | | | 895 | |
897 | bl = in->in_brace_level; | | 896 | bl = in->in_brace_level; |
898 | tp = initialization_sub_type(in); | | 897 | tp = initialization_sub_type(in); |
899 | strg = tn->tn_string; | | 898 | strg = tn->tn_string; |
900 | | | 899 | |
901 | if (!is_string_array(tp, strg->st_tspec)) | | 900 | if (!is_string_array(tp, strg->st_tspec)) |
902 | return false; | | 901 | return false; |
903 | if (bl != NULL && tp->t_tspec != ARRAY && | | 902 | if (bl != NULL && tp->t_tspec != ARRAY && bl->bl_subscript != 0) |
904 | bl->bl_array_next_subscript != 0) | | | |
905 | return false; | | 903 | return false; |
906 | | | 904 | |
907 | if (bl != NULL && tp->t_dim < (int)strg->st_len) { | | 905 | if (bl != NULL && tp->t_dim < (int)strg->st_len) { |
908 | /* non-null byte ignored in string initializer */ | | 906 | /* non-null byte ignored in string initializer */ |
909 | warning(187); | | 907 | warning(187); |
910 | } | | 908 | } |
911 | | | 909 | |
912 | if (tp == in->in_sym->s_type && tp->t_incomplete_array) { | | 910 | if (tp == in->in_sym->s_type && tp->t_incomplete_array) { |
913 | if (bl != NULL) { | | 911 | if (bl != NULL) { |
914 | bl->bl_array_next_subscript = strg->st_len + 1; | | 912 | bl->bl_subscript = strg->st_len + 1; |
915 | /* see initialization_set_size_of_unknown_array */ | | 913 | /* see initialization_set_size_of_unknown_array */ |
916 | } else | | 914 | } else |
917 | update_type_of_array_of_unknown_size(in->in_sym, | | 915 | update_type_of_array_of_unknown_size(in->in_sym, |
918 | strg->st_len + 1); | | 916 | strg->st_len + 1); |
919 | } | | 917 | } |
920 | | | 918 | |
921 | return true; | | 919 | return true; |
922 | } | | 920 | } |
923 | | | 921 | |
924 | /* | | 922 | /* |
925 | * Initialize a single sub-object as part of the currently ongoing | | 923 | * Initialize a single sub-object as part of the currently ongoing |
926 | * initialization. | | 924 | * initialization. |
927 | */ | | 925 | */ |
928 | static void | | 926 | static void |
929 | initialization_expr(struct initialization *in, tnode_t *tn) | | 927 | initialization_expr(struct initialization *in, tnode_t *tn) |
930 | { | | 928 | { |
931 | struct brace_level *bl; | | 929 | struct brace_level *bl; |
932 | const type_t *tp; | | 930 | const type_t *tp; |
933 | | | 931 | |
934 | if (in->in_err) | | 932 | if (in->in_err) |
935 | return; | | 933 | return; |
936 | | | 934 | |
937 | bl = in->in_brace_level; | | 935 | bl = in->in_brace_level; |
938 | if (bl != NULL && bl->bl_confused) | | 936 | if (bl != NULL && bl->bl_confused) |
939 | return; | | 937 | return; |
940 | | | 938 | |
941 | debug_enter(); | | 939 | debug_enter(); |
942 | | | 940 | |
943 | if (tn == NULL) | | 941 | if (tn == NULL) |
944 | goto advance; | | 942 | goto advance; |
945 | if (initialization_expr_using_assign(in, tn)) | | 943 | if (initialization_expr_using_assign(in, tn)) |
946 | goto done; | | 944 | goto done; |
947 | if (initialization_init_array_using_string(in, tn)) | | 945 | if (initialization_init_array_using_string(in, tn)) |
948 | goto advance; | | 946 | goto advance; |
949 | | | 947 | |
950 | if (bl != NULL) | | 948 | if (bl != NULL) |
951 | brace_level_apply_designation(bl); | | 949 | brace_level_apply_designation(bl); |
952 | tp = initialization_sub_type(in); | | 950 | tp = initialization_sub_type(in); |
953 | if (tp == NULL) | | 951 | if (tp == NULL) |
954 | goto done; | | 952 | goto done; |
955 | | | 953 | |
956 | if (bl == NULL && !is_scalar(tp->t_tspec)) { | | 954 | if (bl == NULL && !is_scalar(tp->t_tspec)) { |
957 | /* {}-enclosed initializer required */ | | 955 | /* {}-enclosed initializer required */ |
958 | error(181); | | 956 | error(181); |
959 | goto done; | | 957 | goto done; |
960 | } | | 958 | } |
961 | | | 959 | |
962 | /* | | 960 | /* |
963 | * Hack to accept initializations with omitted braces, see | | 961 | * Hack to accept initializations with omitted braces, see |
964 | * c99_6_7_8_p28_example5 in test d_c99_init.c. Since both GCC and | | 962 | * c99_6_7_8_p28_example5 in test d_c99_init.c. Since both GCC and |
965 | * Clang already warn about this at level -Wall, there is no point | | 963 | * Clang already warn about this at level -Wall, there is no point |
966 | * in repeating the same check in lint. If needed, support for these | | 964 | * in repeating the same check in lint. If needed, support for these |
967 | * edge cases could be added, but that would increase the complexity. | | 965 | * edge cases could be added, but that would increase the complexity. |
968 | */ | | 966 | */ |
969 | if (is_scalar(tn->tn_type->t_tspec) && | | 967 | if (is_scalar(tn->tn_type->t_tspec) && |
970 | (tp->t_tspec == ARRAY || is_struct_or_union(tp->t_tspec)) && | | 968 | (tp->t_tspec == ARRAY || is_struct_or_union(tp->t_tspec)) && |
971 | bl != NULL) { | | 969 | bl != NULL) { |
972 | bl->bl_confused = true; | | 970 | bl->bl_confused = true; |
973 | goto done; | | 971 | goto done; |
974 | } | | 972 | } |
975 | | | 973 | |
976 | debug_step2("expecting '%s', expression has '%s'", | | 974 | debug_step2("expecting '%s', expression has '%s'", |
977 | type_name(tp), type_name(tn->tn_type)); | | 975 | type_name(tp), type_name(tn->tn_type)); |
978 | check_init_expr(tp, in->in_sym, tn); | | 976 | check_init_expr(tp, in->in_sym, tn); |
979 | | | 977 | |
980 | advance: | | 978 | advance: |
981 | if (bl != NULL) | | 979 | if (bl != NULL) |
982 | brace_level_advance(bl); | | 980 | brace_level_advance(bl); |
983 | done: | | 981 | done: |
984 | if (bl != NULL) | | 982 | if (bl != NULL) |
985 | designation_reset(&bl->bl_designation); | | 983 | designation_reset(&bl->bl_designation); |
986 | | | 984 | |
987 | initialization_debug(in); | | 985 | initialization_debug(in); |
988 | debug_leave(); | | 986 | debug_leave(); |
989 | } | | 987 | } |
990 | | | 988 | |
991 | | | 989 | |
992 | static struct initialization *init; | | 990 | static struct initialization *init; |
993 | | | 991 | |
994 | | | 992 | |
995 | static struct initialization * | | 993 | static struct initialization * |
996 | current_init(void) | | 994 | current_init(void) |
997 | { | | 995 | { |
998 | | | 996 | |
999 | lint_assert(init != NULL); | | 997 | lint_assert(init != NULL); |
1000 | return init; | | 998 | return init; |
1001 | } | | 999 | } |
1002 | | | 1000 | |
1003 | sym_t ** | | 1001 | sym_t ** |
1004 | current_initsym(void) | | 1002 | current_initsym(void) |
1005 | { | | 1003 | { |
1006 | | | 1004 | |
1007 | return ¤t_init()->in_sym; | | 1005 | return ¤t_init()->in_sym; |
1008 | } | | 1006 | } |
1009 | | | 1007 | |
1010 | void | | 1008 | void |
1011 | begin_initialization(sym_t *sym) | | 1009 | begin_initialization(sym_t *sym) |
1012 | { | | 1010 | { |
1013 | struct initialization *in; | | 1011 | struct initialization *in; |
1014 | | | 1012 | |
1015 | debug_step1("begin initialization of '%s'", type_name(sym->s_type)); | | 1013 | debug_step1("begin initialization of '%s'", type_name(sym->s_type)); |
1016 | #ifdef DEBUG | | 1014 | #ifdef DEBUG |
1017 | debug_indentation++; | | 1015 | debug_indentation++; |
1018 | #endif | | 1016 | #endif |
1019 | | | 1017 | |
1020 | in = initialization_new(sym); | | 1018 | in = initialization_new(sym); |
1021 | in->in_enclosing = init; | | 1019 | in->in_enclosing = init; |
1022 | init = in; | | 1020 | init = in; |
1023 | } | | 1021 | } |
1024 | | | 1022 | |
1025 | void | | 1023 | void |
1026 | end_initialization(void) | | 1024 | end_initialization(void) |
1027 | { | | 1025 | { |
1028 | struct initialization *in; | | 1026 | struct initialization *in; |
1029 | | | 1027 | |
1030 | in = init; | | 1028 | in = init; |
1031 | init = in->in_enclosing; | | 1029 | init = in->in_enclosing; |
1032 | initialization_free(in); | | 1030 | initialization_free(in); |
1033 | | | 1031 | |
1034 | #ifdef DEBUG | | 1032 | #ifdef DEBUG |
1035 | debug_indentation--; | | 1033 | debug_indentation--; |
1036 | #endif | | 1034 | #endif |
1037 | debug_step0("end initialization"); | | 1035 | debug_step0("end initialization"); |
1038 | } | | 1036 | } |
1039 | | | 1037 | |
1040 | void | | 1038 | void |
1041 | add_designator_member(sbuf_t *sb) | | 1039 | add_designator_member(sbuf_t *sb) |
1042 | { | | 1040 | { |
1043 | | | 1041 | |
1044 | initialization_add_designator(current_init(), sb->sb_name, 0); | | 1042 | initialization_add_designator(current_init(), sb->sb_name, 0); |
1045 | } | | 1043 | } |
1046 | | | 1044 | |
1047 | void | | 1045 | void |
1048 | add_designator_subscript(range_t range) | | 1046 | add_designator_subscript(range_t range) |
1049 | { | | 1047 | { |
1050 | | | 1048 | |
1051 | initialization_add_designator(current_init(), NULL, range.hi); | | 1049 | initialization_add_designator(current_init(), NULL, range.hi); |
1052 | } | | 1050 | } |
1053 | | | 1051 | |
1054 | void | | 1052 | void |
1055 | init_lbrace(void) | | 1053 | init_lbrace(void) |
1056 | { | | 1054 | { |
1057 | | | 1055 | |
1058 | initialization_begin_brace_level(current_init()); | | 1056 | initialization_begin_brace_level(current_init()); |
1059 | } | | 1057 | } |
1060 | | | 1058 | |
1061 | void | | 1059 | void |
1062 | init_expr(tnode_t *tn) | | 1060 | init_expr(tnode_t *tn) |
1063 | { | | 1061 | { |
1064 | | | 1062 | |
1065 | initialization_expr(current_init(), tn); | | 1063 | initialization_expr(current_init(), tn); |
1066 | } | | 1064 | } |
1067 | | | 1065 | |
1068 | void | | 1066 | void |
1069 | init_rbrace(void) | | 1067 | init_rbrace(void) |
1070 | { | | 1068 | { |
1071 | | | 1069 | |
1072 | initialization_end_brace_level(current_init()); | | 1070 | initialization_end_brace_level(current_init()); |
1073 | } | | 1071 | } |