Disable spurious -Wstringop-overflow for setjmp/longjmp (bug 26647)
DJ Delorie
dj@redhat.com
Fri Oct 30 21:06:02 GMT 2020
Joseph Myers <joseph@codesourcery.com> writes:
> diff --git a/misc/sys/cdefs.h b/misc/sys/cdefs.h
>
> +/* Specify that a function such as setjmp or vfork may return
> + twice. */
> +#if __GNUC_PREREQ (4, 1)
> +# define __attribute_returns_twice__ __attribute__ ((__returns_twice__))
> +#else
> +# define __attribute_returns_twice__ /* Ignore. */
> +#endif
> +
> #endif /* sys/cdefs.h */
Ok.
> diff --git a/sysdeps/nptl/pthread.h b/sysdeps/nptl/pthread.h
>
> +struct __cancel_jmp_buf_tag
> +{
> + __jmp_buf __cancel_jmp_buf;
> + int __mask_was_saved;
> +};
> +
> typedef struct
> {
> - struct
> - {
> - __jmp_buf __cancel_jmp_buf;
> - int __mask_was_saved;
> - } __cancel_jmp_buf[1];
> + struct __cancel_jmp_buf_tag __cancel_jmp_buf[1];
> void *__pad[4];
> } __pthread_unwind_buf_t __attribute__ ((__aligned__));
Extracts prefix struct out to its own type. Ok.
> - int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \
> - __cancel_buf.__cancel_jmp_buf, 0); \
> + int __not_first_call = __sigsetjmp_cancel (__cancel_buf.__cancel_jmp_buf, \
> + 0); \
Ok. Same effective arguments, different function.
> - int __not_first_call = __sigsetjmp ((struct __jmp_buf_tag *) (void *) \
> - __cancel_buf.__cancel_jmp_buf, 0); \
> + int __not_first_call = __sigsetjmp_cancel (__cancel_buf.__cancel_jmp_buf, \
> + 0); \
Ok, likewise.
> -/* Function used in the macros. */
> +/* Function used in the macros. Calling __sigsetjmp, with its first
> + argument declared as an array, results in a -Wstringop-overflow
> + warning from GCC 11 because struct pthread_unwind_buf is smaller
> + than jmp_buf. The calls from the macros have __SAVEMASK set to 0,
> + so nothing beyond the common prefix is used and this warning is a
> + false positive. Use an alias with its first argument declared to
> + use the type in the macros if possible to avoid this warning. */
> +#if __GNUC_PREREQ (11, 0)
> +extern int __REDIRECT_NTHNL (__sigsetjmp_cancel,
> + (struct __cancel_jmp_buf_tag __env[1],
> + int __savemask),
> + __sigsetjmp) __attribute_returns_twice__;
> +#else
> +# define __sigsetjmp_cancel(env, savemask) \
> + __sigsetjmp ((struct __jmp_buf_tag *) (void *) (env), (savemask))
> extern int __sigsetjmp (struct __jmp_buf_tag __env[1],
> int __savemask) __THROWNL;
> +#endif
So we're adding a __sigsetjmp_cancel that's the same as __sigsetjmp but
with a different signature just to appease gcc... the name makes it
sound like you're cancelling a sigsetjmp, but what you're really doing
(iirc) is setting up a jump point for a later cancellation.
Maybe __sigsetjmp_for_cancel would make more sense, but I'm not
bikeshedding it.
LGTM.
Reviewed-by: DJ Delorie <dj@redhat.com>
More information about the Libc-alpha
mailing list