diff options
author | Ralf Baechle <ralf@linux-mips.org> | 2017-07-26 04:07:57 +0200 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2017-07-26 04:07:57 +0200 |
commit | 6553ae600526c04b7340c54aa1daf6a48379ea93 (patch) | |
tree | 77fe6ef18bd61c254f5d480f88692ca9137c6a86 | |
parent | d9f3adc04f69adebb1ec3a5deb30fab3978430bb (diff) |
listen: Fix overzealous GCC 7 compiler warnings.
make[2]: Entering directory '/home/ralf/src/ax25/ax25-apps/listen'
gcc -DHAVE_CONFIG_H -I. -I.. -g -O2 -Wall -MT listen.o -MD -MP -MF .deps/listen.Tpo -c -o listen.o listen.c
listen.c: In function ‘ts_format’:
listen.c:53:58: warning: ‘%06u’ directive output may be truncated writing between 6 and 10 bytes into a region of size between 0 and 7 [-Wformat-truncation=]
(void)snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%06u",
^~~~
listen.c:53:42: note: using the range [0, 4294967295] for directive argument
(void)snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%06u",
^~~~~~~~~~~~~~~~~~~~~
listen.c:53:9: note: ‘snprintf’ output between 16 and 27 bytes into a destination of size 16
(void)snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%06u",
^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
sec / 3600, (sec % 3600) / 60, sec % 60, usec);
~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
The value of the variables is such that there is no overflow possible
but GCC is not able to figure this out. Change the code such that GCC
can figure out the value range thus getting us rid of the variables.
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | listen/listen.c | 32 | ||||
-rw-r--r-- | listen/listen.h | 20 |
2 files changed, 46 insertions, 6 deletions
diff --git a/listen/listen.c b/listen/listen.c index 2b05f8b..0b33fb2 100644 --- a/listen/listen.c +++ b/listen/listen.c @@ -47,13 +47,33 @@ static void display_port(char *dev) /* * Format the timestamp */ -static char * ts_format(register int sec, register int usec) +static char * ts_format(unsigned int sec, unsigned int usec) { - static char buf[sizeof("00:00:00.000000")]; - (void)snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%06u", - sec / 3600, (sec % 3600) / 60, sec % 60, usec); - - return buf; + static char buf[sizeof("00:00:00.000000")]; + unsigned int hours, minutes, seconds; + + hours = sec / 3600; + minutes = (sec % 3600) / 60; + seconds = sec % 60; + + /* + * The real purpose of these checks is to let GCC figure out the + * value range of all variables thus avoid bogus warnings. For any + * halfway modern GCC the checks will be optimized away. + */ + if (hours >= 60) + unreachable(); + if (minutes >= 60) + unreachable(); + if (seconds >= 60) + unreachable(); + if (usec >= 1000000) + unreachable(); + + snprintf(buf, sizeof(buf), "%02d:%02d:%02d.%06u", + hours, minutes, seconds, usec); + + return buf; } /* diff --git a/listen/listen.h b/listen/listen.h index 0075bf3..46ec397 100644 --- a/listen/listen.h +++ b/listen/listen.h @@ -1,3 +1,23 @@ +#define GCC_VERSION (__GNUC__ * 10000 \ + + __GNUC_MINOR__ * 100 \ + + __GNUC_PATCHLEVEL__) + +#if GCC_VERSION >= 40500 + +/* + * Mark a position in code as unreachable. This can be used to + * suppress control flow warnings after asm blocks that transfer + * control elsewhere. + * + * Early snapshots of gcc 4.5 don't support this and we can't detect + * this in the preprocessor, but we can live with this because they're + * unreleased. + */ +#define unreachable() \ + do { __builtin_unreachable(); } while (0) +#else +#define unreachable() do { } while (1) +#endif #define T_ERROR 1 #define T_PORT 2 |