Git development
 help / color / mirror / Atom feed
From: Jeff King <peff@peff.net>
To: Phillip Wood <phillip.wood123@gmail.com>
Cc: git@vger.kernel.org, Collin Funk <collin.funk1@gmail.com>,
	Michael J Gruber <git@grubix.eu>
Subject: Re: [PATCH 08/12] skip_prefix(): check const match between in and out params
Date: Wed, 1 Apr 2026 15:24:23 -0400	[thread overview]
Message-ID: <20260401192423.GA2905896@coredump.intra.peff.net> (raw)
In-Reply-To: <b77be594-83b4-4d9b-9f89-569f1f335d61@gmail.com>

On Wed, Apr 01, 2026 at 03:04:10PM +0100, Phillip Wood wrote:

> On 01/04/2026 14:17, Phillip Wood wrote:
> > On 01/04/2026 00:50, Jeff King wrote:
> > > 
> > > +/*
> > > + * Check that an out-parameter that is "at least as const as" a matching
> > > + * in-parameter. For example, skip_prefix() will return "out" that
> > > is a subset
> > > + * of "str". So:
> > > + *
> > > + *  const str, const out: ok
> > > + *  non-const str, const out: ok
> > > + *  non-const str, non-const out: ok
> > > + *  const str, non-const out: compile error
> > > + *
> > > + *  See the skip_prefix macro below for an example of use.
> > > + */
> > > +#define CONST_OUTPARAM(in, out) \
> > > +    ((const char **)(0 ? ((*(out) = (in)),(out)) : (out)))
> > > +#define skip_prefix(str, prefix, out) \
> > > +    skip_prefix((str), (prefix), CONST_OUTPARAM((str), (out)))
> > 
> > This is clever but it changes the behavior of skip_prefix() which is
> > documented as not touching out if it returns false.
> 
> Sorry, I've just realized we always take the other branch so this does not
> change the behavior and is in fact a nice solution to the problem.

Yeah, exactly. I was curious if the dead branch would be left in place,
but gcc seems to prune it even at -O0.

I also pondered whether:

  (*out = in,out)

might be a problem, but I think it is OK. The "," is a sequence point,
so it is well defined (of course we would never run this code anyway,
but if we have undefined behavior in the code at all, it may cause
confusing effects).

For reference, this is the more complicated one I came up with:

  /*
   * Note that builtin_types_compatible_p() counts "char" and "const
   * char" as the same type. So we deref and construct our own pointer
   * with const to find out it "x" is const, and then either compare
   * x and y exactly (if it is const, they must both be) or dereferenced
   * (which lets y be either const or not).
   */
  #define CONST_COMPATIBLE(x, y) \
          (__builtin_types_compatible_p(typeof(x), const typeof(*(x)) *) ? \
           __builtin_types_compatible_p(typeof(x), typeof(y)) : \
           __builtin_types_compatible_p(typeof(*(x)), typeof(*(y))))

I also tried using a gcc statement-expression and _Static_assert to get
a nicer message, like this:

  #define CONST_OUTPARAM(in, out, in_name, out_name) ({ \
          _Static_assert(CONST_COMPATIBLE((in),*(out)), \
                         in_name " is not const-compatible with " out_name); \
          (const typeof(*(in)) **)(out); \
  })
  #define skip_prefix(str, prefix, out) \
          skip_prefix(str, prefix, CONST_OUTPARAM((str), (out), #str, #out))

It does produce slightly nicer output:

  foo.c: In function ‘bad’:
  foo.c:8:9: error: static assertion failed: "my_in_var is not const-compatible with my_out_var"
      8 |         _Static_assert(CONST_COMPATIBLE((in),*(out)), \
        |         ^~~~~~~~~~~~~~
  foo.c:13:34: note: in expansion of macro ‘CONST_OUTPARAM’
     13 |         skip_prefix(str, prefix, CONST_OUTPARAM((str), (out), #str, #out))
        |                                  ^~~~~~~~~~~~~~
  foo.c:16:9: note: in expansion of macro ‘skip_prefix’
     16 |         skip_prefix(my_in_var, "foo", my_out_var);

but I don't think the extra complexity and portability headache is worth
it.

-Peff

  reply	other threads:[~2026-04-01 19:31 UTC|newest]

Thread overview: 50+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-03-31 23:38 [PATCH 0/12] fixing the remainder of the C23 strchr warnings Jeff King
2026-03-31 23:41 ` [PATCH 01/12] convert: add const to fix strchr() warnings Jeff King
2026-03-31 23:41 ` [PATCH 02/12] http: " Jeff King
2026-03-31 23:41 ` [PATCH 03/12] transport-helper: drop " Jeff King
2026-04-01 13:46   ` Patrick Steinhardt
2026-03-31 23:42 ` [PATCH 04/12] pager: explicitly cast away strchr() constness Jeff King
2026-04-01 20:50   ` Junio C Hamano
2026-04-02  3:54     ` Jeff King
2026-03-31 23:42 ` [PATCH 05/12] run-command: explicitly cast away constness when assigning to void Jeff King
2026-03-31 23:44 ` [PATCH 06/12] find_last_dir_sep(): convert inline function to macro Jeff King
2026-03-31 23:46 ` [PATCH 07/12] pseudo-merge: fix disk reads from find_pseudo_merge() Jeff King
2026-03-31 23:56   ` Jeff King
2026-04-01 21:40     ` Junio C Hamano
2026-04-02 23:51     ` Taylor Blau
2026-03-31 23:50 ` [PATCH 08/12] skip_prefix(): check const match between in and out params Jeff King
2026-04-01 13:17   ` Phillip Wood
2026-04-01 14:04     ` Phillip Wood
2026-04-01 19:24       ` Jeff King [this message]
2026-04-01 22:13         ` Junio C Hamano
2026-04-02 15:05         ` Phillip Wood
2026-04-01 13:46   ` Patrick Steinhardt
2026-03-31 23:51 ` [PATCH 09/12] pkt-line: make packet_reader.line non-const Jeff King
2026-04-01 22:18   ` Junio C Hamano
2026-04-02  3:55     ` Jeff King
2026-03-31 23:52 ` [PATCH 10/12] range-diff: drop const to fix strstr() warnings Jeff King
2026-03-31 23:52 ` [PATCH 11/12] http: drop const to fix strstr() warning Jeff King
2026-03-31 23:53 ` [PATCH 12/12] refs/files-backend: drop const to fix strchr() warning Jeff King
2026-04-01 13:46   ` Patrick Steinhardt
2026-04-01 22:22     ` Junio C Hamano
2026-04-02  3:56       ` Jeff King
2026-04-02  4:14 ` [PATCH v2 0/12] fixing the remainder of the C23 strchr warnings Jeff King
2026-04-02  4:14   ` [PATCH v2 01/12] convert: add const to fix strchr() warnings Jeff King
2026-04-02  4:14   ` [PATCH v2 02/12] http: " Jeff King
2026-04-02  4:14   ` [PATCH v2 03/12] transport-helper: drop " Jeff King
2026-04-02  4:14   ` [PATCH v2 04/12] pager: explicitly cast away strchr() constness Jeff King
2026-04-02  4:15   ` [PATCH v2 05/12] run-command: explicitly cast away constness when assigning to void Jeff King
2026-04-02  4:15   ` [PATCH v2 06/12] find_last_dir_sep(): convert inline function to macro Jeff King
2026-04-02  4:15   ` [PATCH v2 07/12] pseudo-merge: fix disk reads from find_pseudo_merge() Jeff King
2026-04-02  4:15   ` [PATCH v2 08/12] skip_prefix(): check const match between in and out params Jeff King
2026-04-02  5:11     ` Junio C Hamano
2026-04-02  6:01       ` Jeff King
2026-04-02 15:50         ` Junio C Hamano
2026-04-02 15:41       ` Junio C Hamano
2026-04-03 11:13     ` Toon Claes
2026-04-04  5:42       ` [PATCH v2 13/12] git-compat-util: fix CONST_OUTPARAM typo and indentation Jeff King
2026-04-02  4:15   ` [PATCH v2 09/12] pkt-line: make packet_reader.line non-const Jeff King
2026-04-02  4:15   ` [PATCH v2 10/12] range-diff: drop const to fix strstr() warnings Jeff King
2026-04-02  4:15   ` [PATCH v2 11/12] http: drop const to fix strstr() warning Jeff King
2026-04-02  4:15   ` [PATCH v2 12/12] refs/files-backend: drop const to fix strchr() warning Jeff King
2026-04-03 11:14   ` [PATCH v2 0/12] fixing the remainder of the C23 strchr warnings Toon Claes

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=20260401192423.GA2905896@coredump.intra.peff.net \
    --to=peff@peff.net \
    --cc=collin.funk1@gmail.com \
    --cc=git@grubix.eu \
    --cc=git@vger.kernel.org \
    --cc=phillip.wood123@gmail.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.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox