Hi Collin,
> On NetBSD I can see the following warning when compiling
> lib/c-vasnprintf.c:
>
> depbase=`echo c-vasnprintf.o | sed 's|[^/]*$|.deps/&|;s|\.o$||'`; gcc
> -DHAVE_CONFIG_H -I. -I.. -DGNULIB_STRICT_CHECKING=1 -g -O2 -MT
> c-vasnprintf.o -MD -MP -MF $depbase.Tpo -c -o c-vasnprintf.o c-vasnprintf.c
> && mv -f $depbase.Tpo $depbase.Po
> In file included from c-vasnprintf.c:46:
> vasnprintf.c: In function 'c_vasnprintf':
> vasnprintf.c:6662:35: warning: statement will never be executed
> [-Wswitch-unreachable]
> 6662 | pad_ourselves = 1;
> | ~~~~~~~~~~~~~~^~~
>
> The cause is PAD_OURSELVES being initialized in a switch statement with
> no preceding case statement. In the C23 standard ยง 6.8.5.3, Example 7,
> it explains that initilizations and function calls with no preceding
> case statement cannot be reached.
>
> It happens on a few other platforms IIRC, based on skimming the CI a
> while ago.
Yes, I saw this warning too, on some platforms. But warnings on non-GNU
platforms don't bother me enough.
> Any objections to the attached patch?
I prefer to conditionalize the case statements together with the code that
follows.
I also experimented with code like this:
switch (dp->conversion)
{
# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
/* If we need conversion from TCHAR_T[] to DCHAR_T[], we need
to perform the padding after this conversion. Functions
with unistdio extensions perform the padding based on
character count rather than element count. */
case 'c': case 's':
pad_ourselves = 1;
break;
# endif
# if NEED_PRINTF_FLAG_ZERO
case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
case 'a': case 'A':
pad_ourselves = 1;
break;
# endif
default:
pad_ourselves = prec_ourselves | group_ourselves;
break;
}
The advantage would be one less #if statement. gcc optimizes this code nicely.
But clang doesn't: <https://github.com/llvm/llvm-project/issues/147239>
So, I see nothing better than to add another #if statement.
2025-07-07 Bruno Haible <[email protected]>
vasnprintf: Fix -Wswitch-unreachable warning.
Reported by Collin Funk in
<https://lists.gnu.org/archive/html/bug-gnulib/2025-07/msg00026.html>.
* lib/vasnprintf.c (VASNPRINTF): Put a #if around a potentially
unreachable switch case.
diff --git a/lib/vasnprintf.c b/lib/vasnprintf.c
index f46e8701bd..3e421b87e2 100644
--- a/lib/vasnprintf.c
+++ b/lib/vasnprintf.c
@@ -6648,19 +6648,21 @@ VASNPRINTF (DCHAR_T *resultbuf, size_t *lengthp,
#if !((WIDE_CHAR_VERSION && MUSL_LIBC) || NEED_PRINTF_FLAG_LEFTADJUST) &&
(!DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO ||
NEED_PRINTF_FLAG_ALT_PRECISION_ZERO || NEED_PRINTF_UNBOUNDED_PRECISION ||
NEED_PRINTF_FLAG_GROUPING || NEED_PRINTF_FLAG_GROUPING_INT)
switch (dp->conversion)
{
-# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
+# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO || NEED_PRINTF_FLAG_ZERO
+# if !DCHAR_IS_TCHAR || ENABLE_UNISTDIO
/* If we need conversion from TCHAR_T[] to DCHAR_T[], we need
to perform the padding after this conversion. Functions
with unistdio extensions perform the padding based on
character count rather than element count. */
case 'c': case 's':
-# endif
-# if NEED_PRINTF_FLAG_ZERO
+# endif
+# if NEED_PRINTF_FLAG_ZERO
case 'f': case 'F': case 'e': case 'E': case 'g': case 'G':
case 'a': case 'A':
-# endif
+# endif
pad_ourselves = 1;
break;
+# endif
default:
pad_ourselves = prec_ourselves | group_ourselves;
break;