git@vger.kernel.org mailing list mirror (one of many)
 help / color / mirror / code / Atom feed
From: Jeff King <peff@peff.net>
To: Junio C Hamano <gitster@pobox.com>
Cc: "SZEDER Gábor" <szeder.dev@gmail.com>,
	"John Paul Adrian Glaubitz" <glaubitz@physik.fu-berlin.de>,
	"Todd Zullinger" <tmz@pobox.com>,
	git@vger.kernel.org
Subject: Re: [PATCH] test-progress: fix test failures on big-endian systems
Date: Mon, 21 Oct 2019 14:49:55 -0400	[thread overview]
Message-ID: <20191021184954.GA2526@sigill.intra.peff.net> (raw)
In-Reply-To: <xmqqftjmlbvb.fsf@gitster-ct.c.googlers.com>

On Mon, Oct 21, 2019 at 05:51:52PM +0900, Junio C Hamano wrote:

> > -	void *value;
> > +	union {
> > +		int *intp;
> > +		const char *strp;
> > +	} value;
> [...]
> The side that actually use .vale would need to change for obvious
> reasons, which may be painful, but I agree it would have easily
> prevented the regression from happening in the first place.

I was curious just how painful, so here's what I found.

The conversion is indeed annoying. There are 330 sites that need
touched to handle the switch to a union (both declarations and places
that access the variables).

Most of the declarations are hidden by the OPT_*() macros, but there's a
fair bit of changes like this sprinkled around:

@@ -4952,13 +4952,13 @@ int apply_parse_options(int argc, const char **argv,
                        const char * const *apply_usage)
 {
        struct option builtin_apply_options[] = {
-               { OPTION_CALLBACK, 0, "exclude", state, N_("path"),
+               { OPTION_CALLBACK, 0, "exclude", { .voidp = state }, N_("path"),
                        N_("don't apply changes matching the given path"),
                        PARSE_OPT_NONEG, apply_option_parse_exclude },
-               { OPTION_CALLBACK, 0, "include", state, N_("path"),
+               { OPTION_CALLBACK, 0, "include", { .voidp = state }, N_("path"),
                        N_("apply changes matching the given path"),
                        PARSE_OPT_NONEG, apply_option_parse_include },
-               { OPTION_CALLBACK, 'p', NULL, state, N_("num"),
+               { OPTION_CALLBACK, 'p', NULL, { .voidp = state }, N_("num"),
                        N_("remove <num> leading slashes from traditional diff paths"),
                        0, apply_option_parse_p },
                OPT_BOOL(0, "no-add", &state->no_add,

which is strictly worse syntactically, and doesn't give us any type
safety (and won't ever, because parse-options is never going to learn
about "struct apply_state").

Likewise the access side gets slightly uglier, but not too bad:

@@ -4768,7 +4768,7 @@ static int apply_patch(struct apply_state *state,
 static int apply_option_parse_exclude(const struct option *opt,
                                      const char *arg, int unset)
 {
-       struct apply_state *state = opt->value;
+       struct apply_state *state = opt->value.voidp;
 
        BUG_ON_OPT_NEG(unset);
 

For things that actually use intp, I think the access side is fine (and
possibly even slightly nicer):

@@ -101,65 +101,65 @@ static enum parse_opt_result get_value(struct parse_opt_ctx_t *p,
 
        case OPTION_BIT:
                if (unset)
-                       *(int *)opt->value &= ~opt->defval;
+                       *opt->value.intp &= ~opt->defval;
                else
-                       *(int *)opt->value |= opt->defval;
+                       *opt->value.intp |= opt->defval;
                return 0;
 

The declaration side is mostly handled by OPT_INTEGER(), etc, but
hand-written ones still need to adjust as you'd expect:

@@ -298,7 +298,7 @@ static struct option builtin_add_options[] = {
        OPT_BOOL(0, "renormalize", &add_renormalize, N_("renormalize EOL of tracked files (implies -u)")),
        OPT_BOOL('N', "intent-to-add", &intent_to_add, N_("record only the fact that the path will be added later")),
        OPT_BOOL('A', "all", &addremove_explicit, N_("add changes from all tracked and untracked files")),
-       { OPTION_CALLBACK, 0, "ignore-removal", &addremove_explicit,
+       { OPTION_CALLBACK, 0, "ignore-removal", { .intp = &addremove_explicit },
          NULL /* takes no arguments */,
          N_("ignore paths removed in the working tree (same as --no-all)"),
          PARSE_OPT_NOARG, ignore_removal_cb },

That's ugly, but at least we're getting some type safety out of it.

But here's where it gets tricky. In addition to catching any size
mismatches, this will also catch signedness problems. I.e., if we make
OPT_INTEGER() use "intp", then everybody passing in &unsigned_var now
gets a compiler warning. Which maybe is a good thing, I dunno. But it
triggers a lot of warnings. We probably ought to be using a "uintp" for
OPT_BIT(), etc, but that just complains about callers passing in signed
integers. ;)

So that's where I gave up. Converting between signed and unsigned
variables needs to be done very carefully, as there are often subtle
impacts (e.g., loop terminations). And because we have so many sign
issues already, compiling with "-Wsign-compare", etc, isn't likely to
help.

But if anybody wants to take a stab at it, the work I've done so far is
can be fetched from:

  https://github.com/peff/git jk/parseopt-intp-wip

-Peff

  reply	other threads:[~2019-10-21 18:49 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2019-07-31  6:37 [BUG]: Testsuite failures on big-endian targets John Paul Adrian Glaubitz
2019-07-31  7:17 ` Todd Zullinger
2019-10-19 21:38   ` John Paul Adrian Glaubitz
2019-10-19 23:37     ` [PATCH] test-progress: fix test failures on big-endian systems SZEDER Gábor
2019-10-19 23:55       ` John Paul Adrian Glaubitz
2019-10-20  0:19         ` Todd Zullinger
2019-10-21  0:52       ` Junio C Hamano
2019-10-21  3:21         ` Jeff King
2019-10-21  8:51           ` Junio C Hamano
2019-10-21 18:49             ` Jeff King [this message]
2019-10-23  1:58               ` Junio C Hamano
2019-10-24 17:24         ` SZEDER Gábor
2019-10-24 17:55           ` Jeff King
2019-10-20  0:26     ` [BUG]: Testsuite failures on big-endian targets Todd Zullinger

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

  List information: http://vger.kernel.org/majordomo-info.html

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20191021184954.GA2526@sigill.intra.peff.net \
    --to=peff@peff.net \
    --cc=git@vger.kernel.org \
    --cc=gitster@pobox.com \
    --cc=glaubitz@physik.fu-berlin.de \
    --cc=szeder.dev@gmail.com \
    --cc=tmz@pobox.com \
    /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.
Code repositories for project(s) associated with this public inbox

	https://80x24.org/mirrors/git.git

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).