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