Jim Meyering wrote:

I've pushed this follow-up patch to suppress a new warning:

Thanks, I expect I didn't get that warning because I built on x86-64, which allows unaligned accesses so GCC doesn't complain. (Incidentally, I had already tried modifying the code to exploit the fact that unaligned accesses are OK on x86ish platforms, but that made the word-by-word loop go slower, so no dice.)

Too bad GCC isn't smart enough to notice that the pointer must be aligned. It strikes me that this problem must come up elsewhere, and that it's worth writing a macro to encapsulate the situation. I pushed the attached follow-up patch, which is an attempt to move in that direction.
From 6133b8e00a8876aaa69ce51d2fe25a17040afe1a Mon Sep 17 00:00:00 2001
From: Paul Eggert <egg...@cs.ucla.edu>
Date: Sat, 27 Sep 2014 15:31:12 -0700
Subject: [PATCH] maint: generalize the -Wcast-align fix

* src/grep.c (CAST_ALIGNED): New macro.
(skip_easy_bytes): Use it.
---
 src/grep.c | 24 ++++++++++++++++--------
 1 file changed, 16 insertions(+), 8 deletions(-)

diff --git a/src/grep.c b/src/grep.c
index 207bdea..bb5ba1c 100644
--- a/src/grep.c
+++ b/src/grep.c
@@ -469,6 +469,21 @@ init_easy_encoding (void)
     easy_encoding &= mbclen_cache[i] == 1;
 }
 
+/* A cast to TYPE of VAL.  Use this when TYPE is a pointer type, VAL
+   is properly aligned for TYPE, and 'gcc -Wcast-align' cannot infer
+   the alignment and would otherwise complain about the cast.  */
+#if 4 < __GNUC__ + (6 <= __GNUC_MINOR__)
+# define CAST_ALIGNED(type, val)                           \
+    ({ __typeof__ (val) val_ = val;                        \
+       _Pragma ("GCC diagnostic push")                     \
+       _Pragma ("GCC diagnostic ignored \"-Wcast-align\"") \
+       (type) val_;                                        \
+       _Pragma ("GCC diagnostic pop")                      \
+    })
+#else
+# define CAST_ALIGNED(type, val) ((type) (val))
+#endif
+
 /* An unsigned type suitable for fast matching.  */
 typedef uintmax_t uword;
 
@@ -496,15 +511,8 @@ skip_easy_bytes (char const *buf)
   for (p = buf; (uintptr_t) p % sizeof (uword) != 0; p++)
     if (*p & HIBYTE)
       return p;
-
-#pragma GCC diagnostic push
-#pragma GCC diagnostic ignored "-Wcast-align"
-  /* We have aligned P to a uword boundary, so we can safely
-     tell gcc to suppress its cast-alignment warning.  */
-  for (s = (uword const *) p; ! (*s & hibyte_mask); s++)
+  for (s = CAST_ALIGNED (uword const *, p); ! (*s & hibyte_mask); s++)
     continue;
-#pragma GCC diagnostic pop
-
   for (p = (char const *) s; ! (*p & HIBYTE); p++)
     continue;
   return p;
-- 
1.9.3

Reply via email to