threads / patch / 63906

patchrevert: initialize const value

Subject: [PATCH] revert: initialize const value

## tl;dr

5 messages between Aug 4, 2025 and Aug 4, 2025. Diffs are folded; open one to read it.

replies: 4people: 4as markdown or json

Jeff King· Aug 4, 2025, 13:00 UTC · lore

When building with clang-22 and DEVELOPER=1 mode, this warning causes us to fail compilation:

  builtin/revert.c:114:13: error: default initialization of an object of type 'const char' leaves the object uninitialized [-Werror,-Wdefault-const-init-var-unsafe]
    114 |         const char sentinel_value;
        |                    ^

The compiler is right that this code is a bit funny. We declare a const value without an initializer. It cannot be assigned to because of the const, but without an initializer it has no predictable value. So as a variable it can never have any useful function, and if we tried to look at it, we'd get undefined behavior.

But it does have a function. We never use its value, but rather use its address as a sentinel value for some other variables:

        const char *gpg_sign = &sentinel_value;
	...maybe set gpg_sign via parse_options...
	if (gpg_sign != &sentinel_value)
		...we got a non-default value...

Normally we'd use NULL as a sentinel value for a pointer, but it doesn't work here because we also want to detect --no-gpg-sign, which is marked by setting the pointer to NULL. We need a separate "this was not touched" value, which is what this sentinel variable gives us.

So the code is correct as-is, but the sentinel variable itself is funny enough that it's understandable for a compiler warning to flag it. Let's try to appease the compiler.

There are a few possible options:
  1. Instead of a variable, we could just construct an artificial
     sentinel address like "1", "-1", etc. I think these technically
     fall afoul of the C standard (even if we do not access them, even
     constructing invalid pointers is not always allowed). But it's also
     something we do elsewhere, and even happens in some standard
     interfaces (e.g., mmap()'s MMAP_FAILED value). It does involve some
     annoying casts, though.
  2. We can mark it as static. That gives it a definite value, but
     perhaps makes people wonder if the static-ness is important, when
     it's not.
  3. We can just give it a value to shut the compiler up, even though
     nobody cares about that value.
I went with (3) here as the smallest and most obvious change.
Signed-off-by: Jeff King <peff@peff.net>
---
I dunno, maybe the comment just makes things more mysterious and
doing the casts would make it more clear what is going on.
 builtin/revert.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)
Show changes to builtin/revert.c +1 −1
diff --git a/builtin/revert.c b/builtin/revert.c
index e07c2217fe..c3f92b585d 100644
--- a/builtin/revert.c
+++ b/builtin/revert.c
@@ -111,7 +111,7 @@ static int run_sequencer(int argc, const char **argv, const char *prefix,
 	const char * const * usage_str = revert_or_cherry_pick_usage(opts);
 	const char *me = action_name(opts);
 	const char *cleanup_arg = NULL;
-	const char sentinel_value;
+	const char sentinel_value = 0; /* value not important */
 	const char *strategy = &sentinel_value;
 	const char *gpg_sign = &sentinel_value;
 	enum empty_action empty_opt = EMPTY_COMMIT_UNSPECIFIED;
-- 
2.50.1.786.g492fc26cdf
Jeff King· Aug 4, 2025, 13:01 UTC · re: Jeff King · lore

Re: [PATCH] revert: initialize const value

On Mon, Aug 04, 2025 at 09:00:12AM -0400, Jeff King wrote:
Show 23 quoted lines
> There are a few possible options:
> 
>   1. Instead of a variable, we could just construct an artificial
>      sentinel address like "1", "-1", etc. I think these technically
>      fall afoul of the C standard (even if we do not access them, even
>      constructing invalid pointers is not always allowed). But it's also
>      something we do elsewhere, and even happens in some standard
>      interfaces (e.g., mmap()'s MMAP_FAILED value). It does involve some
>      annoying casts, though.
> 
>   2. We can mark it as static. That gives it a definite value, but
>      perhaps makes people wonder if the static-ness is important, when
>      it's not.
> 
>   3. We can just give it a value to shut the compiler up, even though
>      nobody cares about that value.
> 
> I went with (3) here as the smallest and most obvious change.
> 
> Signed-off-by: Jeff King <peff@peff.net>
> ---
> I dunno, maybe the comment just makes things more mysterious and
> doing the casts would make it more clear what is going on.

Hmm, I guess one other option I did not consider: we could just drop the "const". The pointers to it are "const char *", but it is fine for them to point to a non-const variable. Maybe that is less mysterious.

-Peff
Patrick Steinhardt· Aug 4, 2025, 13:35 UTC · re: Jeff King · lore

Re: [PATCH] revert: initialize const value

On Mon, Aug 04, 2025 at 09:01:41AM -0400, Jeff King wrote:
Show 29 quoted lines
> On Mon, Aug 04, 2025 at 09:00:12AM -0400, Jeff King wrote:
> 
> > There are a few possible options:
> > 
> >   1. Instead of a variable, we could just construct an artificial
> >      sentinel address like "1", "-1", etc. I think these technically
> >      fall afoul of the C standard (even if we do not access them, even
> >      constructing invalid pointers is not always allowed). But it's also
> >      something we do elsewhere, and even happens in some standard
> >      interfaces (e.g., mmap()'s MMAP_FAILED value). It does involve some
> >      annoying casts, though.
> > 
> >   2. We can mark it as static. That gives it a definite value, but
> >      perhaps makes people wonder if the static-ness is important, when
> >      it's not.
> > 
> >   3. We can just give it a value to shut the compiler up, even though
> >      nobody cares about that value.
> > 
> > I went with (3) here as the smallest and most obvious change.
> > 
> > Signed-off-by: Jeff King <peff@peff.net>
> > ---
> > I dunno, maybe the comment just makes things more mysterious and
> > doing the casts would make it more clear what is going on.
> 
> Hmm, I guess one other option I did not consider: we could just drop the
> "const". The pointers to it are "const char *", but it is fine for them
> to point to a non-const variable. Maybe that is less mysterious.

Initializing the value feels like a pragmatic choice to me. There is no downside, and anyone who might be puzzled by the comment is likely to git-blame(1) to your commit anyway. So I think the current version is good enough.

Thanks!
Patrick
Phillip Wood· Aug 4, 2025, 13:51 UTC · re: Patrick Steinhardt · lore

Re: [PATCH] revert: initialize const value

On 04/08/2025 14:35, Patrick Steinhardt wrote:
Show 10 quoted lines
> On Mon, Aug 04, 2025 at 09:01:41AM -0400, Jeff King wrote:
>> 
>> Hmm, I guess one other option I did not consider: we could just drop the
>> "const". The pointers to it are "const char *", but it is fine for them
>> to point to a non-const variable. Maybe that is less mysterious.
> 
> Initializing the value feels like a pragmatic choice to me. There is no
> downside, and anyone who might be puzzled by the comment is likely to
> git-blame(1) to your commit anyway. So I think the current version is
> good enough.
Yes the current version looks reasonable to me
Thanks
Phillip
Junio C Hamano· Aug 4, 2025, 14:26 UTC · re: Patrick Steinhardt · lore

Re: [PATCH] revert: initialize const value

Patrick Steinhardt <ps@pks.im> writes:
> Initializing the value feels like a pragmatic choice to me. There is no
> downside, and anyone who might be puzzled by the comment is likely to
> git-blame(1) to your commit anyway. So I think the current version is
> good enough.

I had to run "git blame" to find out who was being overly clever by using a sentinel like this. I am glad that it was not me ;-)

The fix looks good. It may make it even better if we renamed the variable to sentinel_address or something ;-).

← back to recent threads