From: Josh Triplett <josh@joshtriplett.org>
To: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Chris Li <sparse@chrisli.org>,
Sparse Mailing-list <linux-sparse@vger.kernel.org>
Subject: Re: Designated initializers for fields in anonymous structs and unions
Date: Thu, 31 Jul 2014 19:41:54 -0700 [thread overview]
Message-ID: <20140801024154.GA21780@thin> (raw)
In-Reply-To: <CA+55aFwinxO5H=5Rtgz37AuOCTHBDWJ6mVRU0HX+fiGP9JRa1Q@mail.gmail.com>
On Thu, Jul 31, 2014 at 07:19:20PM -0700, Linus Torvalds wrote:
> On Thu, Jul 31, 2014 at 11:10 AM, <josh@joshtriplett.org> wrote:
> > Test case:
> >
> > struct S {
> > int a;
> > union {
> > int b;
> > int c;
> > };
> > };
> >
> > static struct S s = {
> > .a = 0,
> > .b = 0,
> > };
>
> So sparse fails on this test-case (differently from what Josh
> reported, because apparently Josh is running 0.5.0) with:
>
> t.c:10:6: warning: Initializer entry defined twice
> t.c:11:6: also defined here
I had the latest bits from the main sparse repo; switching to the
chrisli repo gives me these same results.
> because the offsets are miscomputed. The conversion from
> EXPR_IDENTIFIER (an initializer entry with a named identifier) to
> EXPR_POS (an initializer entry with a byte offset) got this wrong.
>
> We need to use "find_identifier()" that does the proper recursive
> lookup and updates the offset, but the required structure type wasn't
> passed down to convert_designators() and convert_ident(), so the patch
> is a bit bigger than just changing a couple of lines.
>
> I'm quite sure we still screw complex intiializers up . But this makes
> at least Josh's test-case pass, and looks superficially sane.
>
> Hmm?
Comments below.
> From 7670d933e82917ea28a7e5a5df09bcc9744dba34 Mon Sep 17 00:00:00 2001
> From: Linus Torvalds <torvalds@linux-foundation.org>
> Date: Thu, 31 Jul 2014 19:01:36 -0700
> Subject: [PATCH] Make 'convert_ident()' use 'find_identifier()' to get the
> proper member offset
>
> The convert_ident() function used to do
>
> struct symbol *sym = e->field;
> e->init_offset = sym->offset;
>
> which is wrong for embedded unnamed unions. It really wants to do
> "find_identifier()", which looks up the field name in the structure or
> union type, and properly adds the offsets when it looks things up in an
> anonymous structure or union.
>
> However, we didn't pass in the right symbol type, so convert_ident()
> couldn't be just trivially converted with a couple of lines.
>
> This changes the code to pass in the struct/union type, and also
> re-organizes find_identifier() to have a nicer calling convention. We
> now pass in the type, not the name-list, which makes it possible for
> find_identifier() to do the peeling of the SYM_NODE if required,
> simplifying the callers (including the recursive call for the anonymous
> case).
>
> Reported-by: Just Triplett <josh@joshtriplett.org>
s/Just/Josh/
> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
With the above typo fixed:
Reviewed-by: Josh Triplett <josh@joshtriplett.org>
Tested-by: Josh Triplett <josh@joshtriplett.org>
It might make sense to combine this with the handling of array
designated initializers, to allow things like .x[0].y.z[3] = ..., but
this definitely fixes the issue I ran into.
(And now I'm wondering why nobody seems to have ever created an
"unnamed array" extension.)
> ---
> evaluate.c | 47 ++++++++++++++++++++++++++---------------------
> 1 file changed, 26 insertions(+), 21 deletions(-)
>
> diff --git a/evaluate.c b/evaluate.c
> index 03992d03ae1d..5195decd1b2e 100644
> --- a/evaluate.c
> +++ b/evaluate.c
> @@ -1872,13 +1872,19 @@ static struct symbol *evaluate_preop(struct expression *expr)
> return ctype;
> }
>
> -static struct symbol *find_identifier(struct ident *ident, struct symbol_list *_list, int *offset)
> +static struct symbol *find_identifier(struct ident *ident, struct symbol *ctype, int *offset)
> {
> - struct ptr_list *head = (struct ptr_list *)_list;
> - struct ptr_list *list = head;
> + struct ptr_list *head, *list;
>
> + if (ctype->type == SYM_NODE)
> + ctype = ctype->ctype.base_type;
> + if (ctype->type != SYM_UNION && ctype->type != SYM_STRUCT)
> + return NULL;
> +
> + head = (struct ptr_list *)ctype->symbol_list;
> if (!head)
> return NULL;
> + list = head;
> do {
> int i;
> for (i = 0; i < list->nr; i++) {
> @@ -1889,13 +1895,8 @@ static struct symbol *find_identifier(struct ident *ident, struct symbol_list *_
> *offset = sym->offset;
> return sym;
> } else {
> - struct symbol *ctype = sym->ctype.base_type;
> struct symbol *sub;
> - if (!ctype)
> - continue;
> - if (ctype->type != SYM_UNION && ctype->type != SYM_STRUCT)
> - continue;
> - sub = find_identifier(ident, ctype->symbol_list, offset);
> + sub = find_identifier(ident, sym, offset);
> if (!sub)
> continue;
> *offset += sym->offset;
> @@ -1965,7 +1966,7 @@ static struct symbol *evaluate_member_dereference(struct expression *expr)
> return NULL;
> }
> offset = 0;
> - member = find_identifier(ident, ctype->symbol_list, &offset);
> + member = find_identifier(ident, ctype, &offset);
> if (!member) {
> const char *type = ctype->type == SYM_STRUCT ? "struct" : "union";
> const char *name = "<unnamed>";
> @@ -2220,23 +2221,27 @@ static void convert_index(struct expression *e)
> e->init_expr = child;
> }
>
> -static void convert_ident(struct expression *e)
> +static void convert_ident(struct expression *e, struct symbol *ctype)
> {
> + int offset;
> struct expression *child = e->ident_expression;
> - struct symbol *sym = e->field;
> +
> + ctype = find_identifier(e->expr_ident, ctype, &offset);
> + if (!ctype)
> + return;
> e->type = EXPR_POS;
> - e->init_offset = sym->offset;
> + e->init_offset = offset;
> e->init_nr = 1;
> e->init_expr = child;
> }
>
> -static void convert_designators(struct expression *e)
> +static void convert_designators(struct expression *e, struct symbol *ctype)
> {
> while (e) {
> if (e->type == EXPR_INDEX)
> convert_index(e);
> else if (e->type == EXPR_IDENTIFIER)
> - convert_ident(e);
> + convert_ident(e, ctype);
> else
> break;
> e = e->init_expr;
> @@ -2322,7 +2327,7 @@ static struct expression *check_designators(struct expression *e,
> err = "field name not in struct or union";
> break;
> }
> - ctype = find_identifier(e->expr_ident, ctype->symbol_list, &offset);
> + ctype = find_identifier(e->expr_ident, ctype, &offset);
> if (!ctype) {
> err = "unknown field name in";
> break;
> @@ -2392,7 +2397,7 @@ static struct expression *next_designators(struct expression *old,
> if (!copy) {
> field = old->field->next_subobject;
> if (!field) {
> - convert_ident(old);
> + convert_ident(old, ctype);
> return NULL;
> }
> copy = e;
> @@ -2406,7 +2411,7 @@ static struct expression *next_designators(struct expression *old,
> new->expr_ident = field->ident;
> new->ident_expression = copy;
> new->ctype = field;
> - convert_ident(old);
> + convert_ident(old, ctype);
> }
> return new;
> }
> @@ -2465,7 +2470,7 @@ static void handle_list_initializer(struct expression *expr,
> top = next;
> /* deeper than one designator? */
> jumped = top != e;
> - convert_designators(last);
> + convert_designators(last, ctype);
> last = e;
> }
>
> @@ -2497,7 +2502,7 @@ found:
>
> } END_FOR_EACH_PTR(e);
>
> - convert_designators(last);
> + convert_designators(last, ctype);
> expr->ctype = ctype;
> }
>
> @@ -2901,7 +2906,7 @@ static struct symbol *evaluate_offsetof(struct expression *expr)
> return NULL;
> }
>
> - field = find_identifier(expr->ident, ctype->symbol_list, &offset);
> + field = find_identifier(expr->ident, ctype, &offset);
> if (!field) {
> expression_error(expr, "unknown member");
> return NULL;
> --
> 2.1.0.rc0.52.gaa544bf
>
prev parent reply other threads:[~2014-08-01 2:42 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-07-31 18:10 Designated initializers for fields in anonymous structs and unions josh
2014-07-31 18:39 ` Linus Torvalds
2014-07-31 18:50 ` Linus Torvalds
2014-07-31 20:55 ` josh
2014-08-02 8:27 ` Christopher Li
2014-08-02 18:09 ` Christopher Li
2014-08-01 2:19 ` Linus Torvalds
2014-08-01 2:41 ` Linus Torvalds
2014-08-02 1:16 ` Linus Torvalds
2014-08-02 5:16 ` Christopher Li
2014-08-02 18:10 ` Linus Torvalds
2014-08-02 18:31 ` Derek M Jones
2014-08-02 18:40 ` Christopher Li
2014-08-02 19:53 ` Linus Torvalds
2014-08-02 20:09 ` Linus Torvalds
2014-08-06 9:15 ` Christopher Li
2014-08-01 2:41 ` Josh Triplett [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20140801024154.GA21780@thin \
--to=josh@joshtriplett.org \
--cc=linux-sparse@vger.kernel.org \
--cc=sparse@chrisli.org \
--cc=torvalds@linux-foundation.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.