All of lore.kernel.org
 help / color / mirror / Atom feed
From: John Keeping <john@keeping.me.uk>
To: Christopher Li <sparse@chrisli.org>
Cc: Linux-Sparse <linux-sparse@vger.kernel.org>
Subject: Re: [PATCH 2/2] Support GCC's transparent unions
Date: Tue, 4 Mar 2014 17:52:52 +0000	[thread overview]
Message-ID: <20140304175252.GE18371@serenity.lan> (raw)
In-Reply-To: <CANeU7Q=ekL+ASkz-v9K14cP8GJox=O7f4C_YRpS0SmTBoy_02w@mail.gmail.com>

On Tue, Mar 04, 2014 at 09:21:50AM -0800, Christopher Li wrote:
> On Sat, Mar 1, 2014 at 3:41 AM, John Keeping <john@keeping.me.uk> wrote:
> > This stops warnings in code using socket operations with a modern glibc,
> > which otherwise result in warnings of the form:
> >
> >         warning: incorrect type in argument 2 (invalid types)
> >            expected union __CONST_SOCKADDR_ARG [usertype] __addr
> >            got struct sockaddr *<noident>
> >
> > Since transparent unions are only applicable to function arguments, we
> > create a new function to check that the types are compatible
> > specifically in this context.
> 
> Can you please keep the option to warning about the transparent union?
> You can change the default to off. While you are there, please make the second
> patch base on the chrisl sparse repository.

Will do.

> > +static int compatible_argument_type(struct expression *expr, struct symbol *target,
> > +       struct expression **rp, const char *where)
> > +{
> > +       const char *typediff;
> > +       struct symbol *source = degenerate(*rp);
> > +       struct symbol *t;
> > +       classify_type(target, &t);
> > +
> > +       if (t->type == SYM_UNION && t->transparent_union) {
> > +               struct symbol *member;
> > +               FOR_EACH_PTR(t->symbol_list, member) {
> > +                       if (check_assignment_types(member, rp, &typediff))
> > +                               return 1;
> > +               } END_FOR_EACH_PTR(member);
> > +       }
> > +
> > +       if (check_assignment_types(target, rp, &typediff))
> > +               return 1;
> > +
> > +       warning(expr->pos, "incorrect type in %s (%s)", where, typediff);
> > +       info(expr->pos, "   expected %s", show_typename(target));
> > +       info(expr->pos, "   got %s", show_typename(source));
> > +       *rp = cast_to(*rp, target);
> > +       return 0;
> > +}
> 
> I found this compatible_argument_type() hard to read. There are code
> copy/paste from the function compatible_assignment_types().
> 
> I think a better way  is:
> static int compatible_argument_type(...)
> {
>      struct symbol *t;
>      classify_type(target, &t);
> 
>      if (t->type == SYM_UNION && t->transparent_union)
>             return compatible_assignment_transparent_union(...);
>      return compatible_assignment_types(...);
> }
> 
> Then you just need to complete the function
> compatible_assignment_transparent_union().
> Call compatible_assignment_types() if needed.

I'm not sure I understand what you mean here.  If I extract
compatible_assignment_transparent_union() then it is essentially the
same as compatible_argument_type() but without the check for
t->transparent_union.

Looking again, I can see that my implementation above is unnecessarily
complicated because the warning() block is identical to that in
compatible_assignment_types() and there's no way for typediff to escape
from the transparent_union look, so the last 8 lines can be replaced by:

    return compatible_assignment_types(target, rp, &typediff);

That also allows us to get rid of 'source', so we end up with:

static int compatible_argument_type(struct expression *expr, struct symbol *target,
       struct expression **rp, const char *where)
{
	struct symbol *t;
	classify_type(target, &t);

	if (t->type == SYM_UNION && t->transparent_union) {
		const char *typediff;
		struct symbol *member;
		FOR_EACH_PTR(t->symbol_list, member) {
			if (check_assignment_types(member, rp, &typediff))
				return 1;
		} END_FOR_EACH_PTR(member);
	}

	return compatible_assignment_types(expr, target, rp, where);
}


I'm not sure moving the contents of the if block into a separate
function improves things much at that point.  What do you think?

  reply	other threads:[~2014-03-04 17:53 UTC|newest]

Thread overview: 10+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2014-03-01 11:41 [PATCH 1/2] evaluate: split out implementation of compatible_assignment_types John Keeping
2014-03-01 11:41 ` [PATCH 2/2] Support GCC's transparent unions John Keeping
2014-03-01 20:21   ` Josh Triplett
2014-03-02 12:11   ` Ramsay Jones
2014-03-04 17:21   ` Christopher Li
2014-03-04 17:52     ` John Keeping [this message]
2014-03-05  0:58       ` Christopher Li
2014-03-09  1:28       ` Christopher Li
2014-03-01 20:16 ` [PATCH 1/2] evaluate: split out implementation of compatible_assignment_types Josh Triplett
2014-03-04  5:05 ` Christopher Li

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=20140304175252.GE18371@serenity.lan \
    --to=john@keeping.me.uk \
    --cc=linux-sparse@vger.kernel.org \
    --cc=sparse@chrisli.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.