| @@ -1,14 +1,14 @@ | | | @@ -1,14 +1,14 @@ |
1 | /* $NetBSD: init.c,v 1.169 2021/03/28 18:21:28 rillig Exp $ */ | | 1 | /* $NetBSD: init.c,v 1.170 2021/03/28 18:28:22 rillig Exp $ */ |
2 | | | 2 | |
3 | /* | | 3 | /* |
4 | * Copyright (c) 1994, 1995 Jochen Pohl | | 4 | * Copyright (c) 1994, 1995 Jochen Pohl |
5 | * All Rights Reserved. | | 5 | * All Rights Reserved. |
6 | * | | 6 | * |
7 | * Redistribution and use in source and binary forms, with or without | | 7 | * Redistribution and use in source and binary forms, with or without |
8 | * modification, are permitted provided that the following conditions | | 8 | * modification, are permitted provided that the following conditions |
9 | * are met: | | 9 | * are met: |
10 | * 1. Redistributions of source code must retain the above copyright | | 10 | * 1. Redistributions of source code must retain the above copyright |
11 | * notice, this list of conditions and the following disclaimer. | | 11 | * notice, this list of conditions and the following disclaimer. |
12 | * 2. Redistributions in binary form must reproduce the above copyright | | 12 | * 2. Redistributions in binary form must reproduce the above copyright |
13 | * notice, this list of conditions and the following disclaimer in the | | 13 | * notice, this list of conditions and the following disclaimer in the |
14 | * documentation and/or other materials provided with the distribution. | | 14 | * documentation and/or other materials provided with the distribution. |
| @@ -27,27 +27,27 @@ | | | @@ -27,27 +27,27 @@ |
27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, | | 27 | * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, |
28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY | | 28 | * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY |
29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT | | 29 | * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT |
30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF | | 30 | * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF |
31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. | | 31 | * THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. |
32 | */ | | 32 | */ |
33 | | | 33 | |
34 | #if HAVE_NBTOOL_CONFIG_H | | 34 | #if HAVE_NBTOOL_CONFIG_H |
35 | #include "nbtool_config.h" | | 35 | #include "nbtool_config.h" |
36 | #endif | | 36 | #endif |
37 | | | 37 | |
38 | #include <sys/cdefs.h> | | 38 | #include <sys/cdefs.h> |
39 | #if defined(__RCSID) && !defined(lint) | | 39 | #if defined(__RCSID) && !defined(lint) |
40 | __RCSID("$NetBSD: init.c,v 1.169 2021/03/28 18:21:28 rillig Exp $"); | | 40 | __RCSID("$NetBSD: init.c,v 1.170 2021/03/28 18:28:22 rillig Exp $"); |
41 | #endif | | 41 | #endif |
42 | | | 42 | |
43 | #include <stdlib.h> | | 43 | #include <stdlib.h> |
44 | #include <string.h> | | 44 | #include <string.h> |
45 | | | 45 | |
46 | #include "lint1.h" | | 46 | #include "lint1.h" |
47 | | | 47 | |
48 | | | 48 | |
49 | /* | | 49 | /* |
50 | * Initialization | | 50 | * Initialization |
51 | * | | 51 | * |
52 | * Handles initializations of global or local objects, like in: | | 52 | * Handles initializations of global or local objects, like in: |
53 | * | | 53 | * |
| @@ -1156,91 +1156,72 @@ initialization_add_designator_subscript( | | | @@ -1156,91 +1156,72 @@ initialization_add_designator_subscript( |
1156 | int auto_dim = (int)range.hi; | | 1156 | int auto_dim = (int)range.hi; |
1157 | if (auto_dim > level->bl_type->t_dim) | | 1157 | if (auto_dim > level->bl_type->t_dim) |
1158 | brace_level_set_array_dimension(level, auto_dim); | | 1158 | brace_level_set_array_dimension(level, auto_dim); |
1159 | } | | 1159 | } |
1160 | | | 1160 | |
1161 | debug_leave(); | | 1161 | debug_leave(); |
1162 | } | | 1162 | } |
1163 | | | 1163 | |
1164 | static bool | | 1164 | static bool |
1165 | is_string_array(const type_t *tp, tspec_t t) | | 1165 | is_string_array(const type_t *tp, tspec_t t) |
1166 | { | | 1166 | { |
1167 | tspec_t st; | | 1167 | tspec_t st; |
1168 | | | 1168 | |
1169 | if (tp->t_tspec != ARRAY) | | 1169 | if (tp == NULL || tp->t_tspec != ARRAY) |
1170 | return false; | | 1170 | return false; |
1171 | st = tp->t_subt->t_tspec; | | 1171 | st = tp->t_subt->t_tspec; |
1172 | return t == CHAR | | 1172 | return t == CHAR |
1173 | ? st == CHAR || st == UCHAR || st == SCHAR | | 1173 | ? st == CHAR || st == UCHAR || st == SCHAR |
1174 | : st == WCHAR; | | 1174 | : st == WCHAR; |
1175 | } | | 1175 | } |
1176 | | | 1176 | |
1177 | /* Initialize a character array or wchar_t array with a string literal. */ | | 1177 | /* Initialize a character array or wchar_t array with a string literal. */ |
1178 | static bool | | 1178 | static bool |
1179 | initialization_init_array_using_string(struct initialization *in, tnode_t *tn) | | 1179 | initialization_init_array_using_string(struct initialization *in, tnode_t *tn) |
1180 | { | | 1180 | { |
1181 | struct brace_level *level; | | 1181 | struct brace_level *level; |
1182 | int len; | | 1182 | int len; |
1183 | strg_t *strg; | | 1183 | strg_t *strg; |
1184 | | | 1184 | |
1185 | if (tn->tn_op != STRING) | | 1185 | if (tn->tn_op != STRING) |
1186 | return false; | | 1186 | return false; |
1187 | | | 1187 | |
1188 | debug_enter(); | | 1188 | debug_enter(); |
1189 | initialization_debug(in); | | | |
1190 | | | 1189 | |
1191 | level = in->brace_level; | | 1190 | level = in->brace_level; |
1192 | strg = tn->tn_string; | | 1191 | strg = tn->tn_string; |
1193 | | | 1192 | |
1194 | /* | | 1193 | /* |
1195 | * Check if we have an array type which can be initialized by | | 1194 | * Check if we have an array type which can be initialized by |
1196 | * the string. | | 1195 | * the string. |
1197 | */ | | 1196 | */ |
1198 | if (level->bl_subtype != NULL && level->bl_subtype->t_tspec == ARRAY) { | | 1197 | if (is_string_array(level->bl_subtype, strg->st_tspec)) { |
1199 | debug_step("subtype is an array"); | | 1198 | debug_step("subtype is an array"); |
1200 | if (!is_string_array(level->bl_subtype, strg->st_tspec)) { | | | |
1201 | debug_leave(); | | | |
1202 | return false; | | | |
1203 | } | | | |
1204 | | | 1199 | |
1205 | /* Put the array at top of stack */ | | 1200 | /* Put the array at top of stack */ |
1206 | initialization_push(in); | | 1201 | initialization_push(in); |
1207 | level = in->brace_level; | | 1202 | level = in->brace_level; |
1208 | | | 1203 | |
1209 | /* TODO: what if both bl_type and bl_subtype are ARRAY? */ | | 1204 | } else if (is_string_array(level->bl_type, strg->st_tspec)) { |
1210 | | | | |
1211 | } else if (level->bl_type != NULL && level->bl_type->t_tspec == ARRAY) { | | | |
1212 | debug_step("type is an array"); | | 1205 | debug_step("type is an array"); |
1213 | if (!is_string_array(level->bl_type, strg->st_tspec)) { | | | |
1214 | debug_leave(); | | | |
1215 | return false; | | | |
1216 | } | | | |
1217 | | | 1206 | |
1218 | /* | | 1207 | /* |
1219 | * TODO: is this really not needed in the branch above this | | | |
1220 | * one? | | | |
1221 | */ | | | |
1222 | /* | | | |
1223 | * If the array is already partly initialized, we are | | 1208 | * If the array is already partly initialized, we are |
1224 | * wrong here. | | 1209 | * wrong here. |
1225 | */ | | 1210 | */ |
1226 | if (level->bl_remaining != level->bl_type->t_dim) { | | 1211 | if (level->bl_remaining != level->bl_type->t_dim) |
1227 | debug_leave(); | | 1212 | goto nope; |
1228 | return false; | | 1213 | } else |
1229 | } | | 1214 | goto nope; |
1230 | } else { | | | |
1231 | debug_leave(); | | | |
1232 | return false; | | | |
1233 | } | | | |
1234 | | | 1215 | |
1235 | /* Get length without trailing NUL character. */ | | 1216 | /* Get length without trailing NUL character. */ |
1236 | len = strg->st_len; | | 1217 | len = strg->st_len; |
1237 | | | 1218 | |
1238 | if (level->bl_array_of_unknown_size) { | | 1219 | if (level->bl_array_of_unknown_size) { |
1239 | level->bl_array_of_unknown_size = false; | | 1220 | level->bl_array_of_unknown_size = false; |
1240 | level->bl_type->t_dim = len + 1; | | 1221 | level->bl_type->t_dim = len + 1; |
1241 | setcomplete(level->bl_type, true); | | 1222 | setcomplete(level->bl_type, true); |
1242 | } else { | | 1223 | } else { |
1243 | /* | | 1224 | /* |
1244 | * TODO: check for buffer overflow in the object to be | | 1225 | * TODO: check for buffer overflow in the object to be |
1245 | * initialized | | 1226 | * initialized |
1246 | */ | | 1227 | */ |
| @@ -1253,26 +1234,29 @@ initialization_init_array_using_string(s | | | @@ -1253,26 +1234,29 @@ initialization_init_array_using_string(s |
1253 | /* | | 1234 | /* |
1254 | * TODO: C99 6.7.8p14 allows a string literal to be enclosed | | 1235 | * TODO: C99 6.7.8p14 allows a string literal to be enclosed |
1255 | * in optional redundant braces, just like scalars. Add tests | | 1236 | * in optional redundant braces, just like scalars. Add tests |
1256 | * for this. | | 1237 | * for this. |
1257 | */ | | 1238 | */ |
1258 | } | | 1239 | } |
1259 | | | 1240 | |
1260 | /* In every case the array is initialized completely. */ | | 1241 | /* In every case the array is initialized completely. */ |
1261 | level->bl_remaining = 0; | | 1242 | level->bl_remaining = 0; |
1262 | | | 1243 | |
1263 | initialization_debug(in); | | 1244 | initialization_debug(in); |
1264 | debug_leave(); | | 1245 | debug_leave(); |
1265 | return true; | | 1246 | return true; |
| | | 1247 | nope: |
| | | 1248 | debug_leave(); |
| | | 1249 | return false; |
1266 | } | | 1250 | } |
1267 | | | 1251 | |
1268 | /* | | 1252 | /* |
1269 | * Initialize a non-array object with automatic storage duration and only a | | 1253 | * Initialize a non-array object with automatic storage duration and only a |
1270 | * single initializer expression without braces by delegating to ASSIGN. | | 1254 | * single initializer expression without braces by delegating to ASSIGN. |
1271 | */ | | 1255 | */ |
1272 | static bool | | 1256 | static bool |
1273 | initialization_init_using_assign(struct initialization *in, tnode_t *rn) | | 1257 | initialization_init_using_assign(struct initialization *in, tnode_t *rn) |
1274 | { | | 1258 | { |
1275 | tnode_t *ln, *tn; | | 1259 | tnode_t *ln, *tn; |
1276 | | | 1260 | |
1277 | if (in->initsym->s_type->t_tspec == ARRAY) | | 1261 | if (in->initsym->s_type->t_tspec == ARRAY) |
1278 | return false; | | 1262 | return false; |