Subject: Re: [PATCH 08/12] skip_prefix(): check const match between in and out params

From: Patrick Steinhardt <[email-masked]>
Date: Wed, 1 Apr 2026 15:46:54 +0200

On Tue, Mar 31, 2026 at 07:50:17PM -0400, Jeff King wrote:
> diff --git a/git-compat-util.h b/git-compat-util.h
> index 4bb59b3101..58e494e037 100644
> --- a/git-compat-util.h
> +++ b/git-compat-util.h
> @@ -491,6 +491,23 @@ static inline bool skip_prefix(const char *str, const char *prefix,
>  	return false;
>  }
>  
> +/*
> + * 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)))

Okay. In theory this would cause us to evaluate both `out` and `str`
multiple times. But I guess because this is a dead branch we expect the
compiler to optimize these statements away so that we don't have to
worry about this.

Constructs like this always feel a bit dirty, but I guess this is going
to be fine in practice.

Patrick