summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRalf Baechle <ralf@linux-mips.org>2017-07-26 04:07:57 +0200
committerRalf Baechle <ralf@linux-mips.org>2017-07-26 04:07:57 +0200
commit6553ae600526c04b7340c54aa1daf6a48379ea93 (patch)
tree77fe6ef18bd61c254f5d480f88692ca9137c6a86
parentd9f3adc04f69adebb1ec3a5deb30fab3978430bb (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.c32
-rw-r--r--listen/listen.h20
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