Module Name: src Committed By: rillig Date: Thu Mar 25 21:07:52 UTC 2021
Modified Files: src/usr.bin/xlint/lint1: init.c Log Message: lint: replace namlist with designation and designator This makes it possible to accurately model C99 initializers, including their optional designators. Previously, array subscripts had not been modeled at all. In the previous commit, debug_designation crashed immediately since I had not run the code in debug mode even once. The condition 'name != head' was a left-over from the old times where the designator was still a circular list. No functional change outside debug mode. To generate a diff of this commit: cvs rdiff -u -r1.127 -r1.128 src/usr.bin/xlint/lint1/init.c Please note that diffs are not public domain; they are subject to the copyright notices on the relevant files.
Modified files: Index: src/usr.bin/xlint/lint1/init.c diff -u src/usr.bin/xlint/lint1/init.c:1.127 src/usr.bin/xlint/lint1/init.c:1.128 --- src/usr.bin/xlint/lint1/init.c:1.127 Thu Mar 25 20:38:16 2021 +++ src/usr.bin/xlint/lint1/init.c Thu Mar 25 21:07:52 2021 @@ -1,4 +1,4 @@ -/* $NetBSD: init.c,v 1.127 2021/03/25 20:38:16 rillig Exp $ */ +/* $NetBSD: init.c,v 1.128 2021/03/25 21:07:52 rillig Exp $ */ /* * Copyright (c) 1994, 1995 Jochen Pohl @@ -37,7 +37,7 @@ #include <sys/cdefs.h> #if defined(__RCSID) && !defined(lint) -__RCSID("$NetBSD: init.c,v 1.127 2021/03/25 20:38:16 rillig Exp $"); +__RCSID("$NetBSD: init.c,v 1.128 2021/03/25 21:07:52 rillig Exp $"); #endif #include <stdlib.h> @@ -215,22 +215,24 @@ typedef struct initstack_element { } initstack_element; /* - * The names for a nested C99 initialization designator, in a circular list. + * Leads the path to the sub-object to initialize using the expression. + * Example designators are '.member' or '.member[123].member.member[1][1]'. * - * Example: - * struct stat st = { - * .st_size = 123, - * .st_mtim.tv_sec = 45, - * .st_mtim.tv_nsec - * }; - * - * During initialization, this list first contains ["st_size"], then - * ["st_mtim", "tv_sec"], then ["st_mtim", "tv_nsec"]. + * See also: C99 6.7.8 "Initialization" + */ +typedef struct designator { + const char *name; /* for struct and union */ + /* TODO: add 'subscript' for arrays */ + struct designator *next; +} designator; + +/* + * See also: C99 6.7.8 "Initialization" */ -typedef struct namlist { - const char *n_name; - struct namlist *n_next; -} namlist_t; +typedef struct { + designator *head; + designator *tail; +} designation; struct initialization { /* @@ -251,8 +253,7 @@ struct initialization { * The C99 designator, if any, for the current initialization * expression. */ - namlist_t *designation; - namlist_t *designation_tail; + designation designation; struct initialization *next; }; @@ -280,14 +281,14 @@ current_initsym(void) return &init->initsym; } -static namlist_t ** +static designation * current_designation_mod(void) { lint_assert(init != NULL); return &init->designation; } -static const namlist_t * +static designation current_designation(void) { return *current_designation_mod(); @@ -375,17 +376,14 @@ debug_leave(const char *func) static void debug_designation(void) { - const namlist_t *head = current_designation(), *name; + const designator *head = current_designation().head, *p; if (head == NULL) return; debug_indent(); debug_printf("designation: "); - name = head; - do { - debug_printf(".%s", name->n_name); - name = name->n_next; - } while (name != head); + for (p = head; p != NULL; p = p->next) + debug_printf(".%s", p->name); debug_printf("\n"); } @@ -475,18 +473,17 @@ end_initialization(void) void designator_push_name(sbuf_t *sb) { - const namlist_t *designation = current_designation(); + designation *dd = current_designation_mod(); - namlist_t *nam = xcalloc(1, sizeof (namlist_t)); - nam->n_name = sb->sb_name; + designator *d = xcalloc(1, sizeof *d); + d->name = sb->sb_name; - /* TODO: remove direct access to 'init' */ - if (designation != NULL) { - init->designation_tail->n_next = nam; - init->designation_tail = nam; + if (dd->head != NULL) { + dd->tail->next = d; + dd->tail = d; } else { - init->designation = nam; - init->designation_tail = nam; + dd->head = d; + dd->tail = d; } debug_designation(); @@ -524,13 +521,14 @@ designator_shift_name(void) { /* TODO: remove direct access to 'init' */ lint_assert(init != NULL); - if (init->designation == init->designation_tail) { - free(init->designation); - init->designation = NULL; - init->designation_tail = NULL; + lint_assert(init->designation.head != NULL); + if (init->designation.head == init->designation.tail) { + free(init->designation.head); + init->designation.head = NULL; + init->designation.tail = NULL; } else { - namlist_t *head = init->designation; - init->designation = init->designation->n_next; + designator *head = init->designation.head; + init->designation.head = init->designation.head->next; free(head); } @@ -552,7 +550,7 @@ initstack_init(void) return; /* TODO: merge into init_using_expr */ - while (current_designation() != NULL) + while (current_designation().head != NULL) designator_shift_name(); debug_enter(); @@ -585,7 +583,7 @@ initstack_pop_item_named_member(void) * related to initializing the named member. */ debug_step("initializing named member '%s'", - current_designation()->n_name); + current_designation().head->name); if (istk->i_type->t_tspec != STRUCT && istk->i_type->t_tspec != UNION) { @@ -601,7 +599,7 @@ initstack_pop_item_named_member(void) if (m->s_bitfield && m->s_name == unnamed) continue; - if (strcmp(m->s_name, current_designation()->n_name) == 0) { + if (strcmp(m->s_name, current_designation().head->name) == 0) { debug_step("found matching member"); istk->i_subt = m->s_type; /* XXX: why ++? */ @@ -613,7 +611,7 @@ initstack_pop_item_named_member(void) } /* undefined struct/union member: %s */ - error(101, current_designation()->n_name); + error(101, current_designation().head->name); designator_shift_name(); istk->i_seen_named_member = true; @@ -666,7 +664,7 @@ initstack_pop_item(void) lint_assert(istk->i_remaining >= 0); debug_step("%d elements remaining", istk->i_remaining); - if (current_designation() != NULL) + if (current_designation().head != NULL) initstack_pop_item_named_member(); else initstack_pop_item_unnamed(); @@ -806,12 +804,12 @@ initstack_push_struct_or_union(void) * look_up_struct_next * look_up_struct_designator */ - if (current_designation() != NULL) { + if (current_designation().head != NULL) { /* XXX: this log entry looks unnecessarily verbose */ debug_step("have member '%s', want member '%s'", - m->s_name, current_designation()->n_name); - if (strcmp(m->s_name, current_designation()->n_name) == - 0) { + m->s_name, current_designation().head->name); + if (strcmp(m->s_name, + current_designation().head->name) == 0) { cnt++; break; } else @@ -823,7 +821,7 @@ initstack_push_struct_or_union(void) } } - if (current_designation() != NULL) { + if (current_designation().head != NULL) { if (m == NULL) { debug_step("pop struct"); return true; @@ -831,7 +829,8 @@ initstack_push_struct_or_union(void) istk->i_next_member = m; istk->i_subt = m->s_type; istk->i_seen_named_member = true; - debug_step("named member '%s'", current_designation()->n_name); + debug_step("named member '%s'", + current_designation().head->name); designator_shift_name(); cnt = istk->i_type->t_tspec == STRUCT ? 2 : 1; } @@ -876,9 +875,9 @@ again: lint_assert(istk->i_type != NULL); switch (istk->i_type->t_tspec) { case ARRAY: - if (current_designation() != NULL) { + if (current_designation().head != NULL) { debug_step("pop array, named member '%s'%s", - current_designation()->n_name, + current_designation().head->name, istk->i_brace ? ", needs closing brace" : ""); goto pop; } @@ -896,7 +895,7 @@ again: goto pop; break; default: - if (current_designation() != NULL) { + if (current_designation().head != NULL) { debug_step("pop scalar"); pop: /* TODO: extract this into end_initializer_level */