From 66a08aa3914a98667f212e79b4f0b9453203d656 Mon Sep 17 00:00:00 2001
From: Misa <[EMAIL REDACTED]>
Date: Mon, 27 Sep 2021 14:38:12 -0700
Subject: [PATCH] Add and use `SDL_FALLTHROUGH` for fallthroughs
Case fallthrough warnings can be suppressed using the __fallthrough__
compiler attribute. Unfortunately, not all compilers have this
attribute, or even have __has_attribute to check if they have the
__fallthrough__ attribute. [[fallthrough]] is also available in C++17
and the next C2x, but not everyone uses C++17 or C2x.
So define the SDL_FALLTHROUGH macro to deal with those problems - if we
are using C++17 or C2x, it expands to [[fallthrough]]; else if the
compiler has __has_attribute and has the __fallthrough__ attribute, then
it expands to __attribute__((__fallthrough__)); else it expands to an
empty statement, with a /* fallthrough */ comment (it's a do {} while
(0) statement, because users of this macro need to use a semicolon,
because [[fallthrough]] and __attribute__((__fallthrough__)) require a
semicolon).
Applications using SDL are also free to use this macro (because it is
defined in begin_code.h).
All existing /* fallthrough */ comments have been replaced with this
macro. Some of them were unnecessary because they were the last case in
a switch; using SDL_FALLTHROUGH in those cases would result in a compile
error on compilers that support __fallthrough__, for having a
__attribute__((__fallthrough__)) statement that didn't immediately
precede a case label.
---
include/SDL_stdinc.h | 20 ++++----------------
include/begin_code.h | 19 +++++++++++++++++++
src/audio/SDL_wave.c | 4 ++--
src/render/software/SDL_draw.h | 8 ++++----
src/stdlib/SDL_iconv.c | 4 ++--
src/stdlib/SDL_string.c | 12 ++++++------
src/video/SDL_blit.h | 24 ++++++++++++------------
src/video/SDL_fillrect.c | 12 ++++++------
src/video/SDL_pixels.c | 2 +-
src/video/directfb/SDL_DirectFB_WM.c | 2 +-
src/video/directfb/SDL_DirectFB_events.c | 2 +-
src/video/windows/SDL_windowsevents.c | 1 +
test/controllermap.c | 4 ++--
test/testgamecontroller.c | 2 +-
test/testjoystick.c | 2 +-
15 files changed, 63 insertions(+), 55 deletions(-)
diff --git a/include/SDL_stdinc.h b/include/SDL_stdinc.h
index c00374d121..15a6354436 100644
--- a/include/SDL_stdinc.h
+++ b/include/SDL_stdinc.h
@@ -496,25 +496,13 @@ SDL_FORCE_INLINE void SDL_memset4(void *dst, Uint32 val, size_t dwords)
if (dwords == 0) {
return;
}
-
- /* !!! FIXME: there are better ways to do this, but this is just to clean this up for now. */
- #ifdef __clang__
- #pragma clang diagnostic push
- #pragma clang diagnostic ignored "-Wimplicit-fallthrough"
- #endif
-
switch (dwords % 4) {
- case 0: do { *_p++ = _val; /* fallthrough */
- case 3: *_p++ = _val; /* fallthrough */
- case 2: *_p++ = _val; /* fallthrough */
- case 1: *_p++ = _val; /* fallthrough */
+ case 0: do { *_p++ = _val; SDL_FALLTHROUGH;
+ case 3: *_p++ = _val; SDL_FALLTHROUGH;
+ case 2: *_p++ = _val; SDL_FALLTHROUGH;
+ case 1: *_p++ = _val;
} while ( --_n );
}
-
- #ifdef __clang__
- #pragma clang diagnostic pop
- #endif
-
#endif
}
diff --git a/include/begin_code.h b/include/begin_code.h
index 37bf9750f4..b821195198 100644
--- a/include/begin_code.h
+++ b/include/begin_code.h
@@ -164,3 +164,22 @@
#endif
#endif /* NULL */
#endif /* ! Mac OS X - breaks precompiled headers */
+
+#ifndef SDL_FALLTHROUGH
+#if (defined(__cplusplus) && __cplusplus >= 201703L) || \
+ (defined(__STDC_VERSION__) && __STDC_VERSION__ >= 202000L)
+#define SDL_FALLTHROUGH [[fallthrough]]
+#else
+#ifdef __has_attribute
+#define _HAS_FALLTHROUGH __has_attribute(__fallthrough__)
+#else
+#define _HAS_FALLTHROUGH 0
+#endif /* __has_attribute */
+#if _HAS_FALLTHROUGH
+#define SDL_FALLTHROUGH __attribute__((__fallthrough__))
+#else
+#define SDL_FALLTHROUGH do {} while (0) /* fallthrough */
+#endif /* _HAS_FALLTHROUGH */
+#undef _HAS_FALLTHROUGH
+#endif /* C++17 or C2x */
+#endif /* SDL_FALLTHROUGH not defined */
diff --git a/src/audio/SDL_wave.c b/src/audio/SDL_wave.c
index 88204fdbe5..bf9fb542bf 100644
--- a/src/audio/SDL_wave.c
+++ b/src/audio/SDL_wave.c
@@ -1715,7 +1715,7 @@ WaveCheckFormat(WaveFile *file, size_t datalength)
if (file->facthint == FactStrict && file->fact.status <= 0) {
return SDL_SetError("Missing fact chunk in WAVE file");
}
- /* fallthrough */
+ SDL_FALLTHROUGH;
case PCM_CODE:
/* All supported formats require a non-zero bit depth. */
if (file->chunk.size < 16) {
@@ -1854,7 +1854,7 @@ WaveLoad(SDL_RWops *src, WaveFile *file, SDL_AudioSpec *spec, Uint8 **audio_buf,
RIFFend = RIFFchunk.position + SDL_MAX_UINT32;
break;
}
- /* fallthrough */
+ SDL_FALLTHROUGH;
case RiffSizeForce:
RIFFend = RIFFchunk.position + RIFFchunk.length;
RIFFlengthknown = SDL_TRUE;
diff --git a/src/render/software/SDL_draw.h b/src/render/software/SDL_draw.h
index d9abb940bf..5c63954f60 100644
--- a/src/render/software/SDL_draw.h
+++ b/src/render/software/SDL_draw.h
@@ -618,10 +618,10 @@ do { \
while (height--) { \
{ int n = (width+3)/4; \
switch (width & 3) { \
- case 0: do { op; pixel++; /* fallthrough */ \
- case 3: op; pixel++; /* fallthrough */ \
- case 2: op; pixel++; /* fallthrough */ \
- case 1: op; pixel++; /* fallthrough */ \
+ case 0: do { op; pixel++; SDL_FALLTHROUGH; \
+ case 3: op; pixel++; SDL_FALLTHROUGH; \
+ case 2: op; pixel++; SDL_FALLTHROUGH; \
+ case 1: op; pixel++; \
} while ( --n > 0 ); \
} \
} \
diff --git a/src/stdlib/SDL_iconv.c b/src/stdlib/SDL_iconv.c
index e235541f31..34246bc4f9 100644
--- a/src/stdlib/SDL_iconv.c
+++ b/src/stdlib/SDL_iconv.c
@@ -758,7 +758,7 @@ SDL_iconv(SDL_iconv_t cd,
if (ch > 0x10FFFF) {
ch = UNKNOWN_UNICODE;
}
- /* fallthrough */
+ SDL_FALLTHROUGH;
case ENCODING_UCS4BE:
if (ch > 0x7FFFFFFF) {
ch = UNKNOWN_UNICODE;
@@ -780,7 +780,7 @@ SDL_iconv(SDL_iconv_t cd,
if (ch > 0x10FFFF) {
ch = UNKNOWN_UNICODE;
}
- /* fallthrough */
+ SDL_FALLTHROUGH;
case ENCODING_UCS4LE:
if (ch > 0x7FFFFFFF) {
ch = UNKNOWN_UNICODE;
diff --git a/src/stdlib/SDL_string.c b/src/stdlib/SDL_string.c
index 6922a24a9f..13d6c542ef 100644
--- a/src/stdlib/SDL_string.c
+++ b/src/stdlib/SDL_string.c
@@ -1275,7 +1275,7 @@ SDL_vsscanf(const char *text, const char *fmt, va_list ap)
}
}
}
- /* Fall through to %d handling */
+ SDL_FALLTHROUGH;
case 'd':
if (inttype == DO_LONGLONG) {
Sint64 value;
@@ -1323,13 +1323,13 @@ SDL_vsscanf(const char *text, const char *fmt, va_list ap)
if (radix == 10) {
radix = 8;
}
- /* Fall through to unsigned handling */
+ SDL_FALLTHROUGH;
case 'x':
case 'X':
if (radix == 10) {
radix = 16;
}
- /* Fall through to unsigned handling */
+ SDL_FALLTHROUGH;
case 'u':
if (inttype == DO_LONGLONG) {
Uint64 value = 0;
@@ -1815,7 +1815,7 @@ SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt,
case 'p':
case 'x':
info.force_case = SDL_CASE_LOWER;
- /* Fall through to 'X' handling */
+ SDL_FALLTHROUGH;
case 'X':
if (info.force_case == SDL_CASE_NOCHANGE) {
info.force_case = SDL_CASE_UPPER;
@@ -1826,12 +1826,12 @@ SDL_vsnprintf(SDL_OUT_Z_CAP(maxlen) char *text, size_t maxlen, const char *fmt,
if (*fmt == 'p') {
inttype = DO_LONG;
}
- /* Fall through to unsigned handling */
+ SDL_FALLTHROUGH;
case 'o':
if (info.radix == 10) {
info.radix = 8;
}
- /* Fall through to unsigned handling */
+ SDL_FALLTHROUGH;
case 'u':
info.force_sign = SDL_FALSE;
if (info.precision >= 0) {
diff --git a/src/video/SDL_blit.h b/src/video/SDL_blit.h
index 4b50c7dc38..8b28138e9b 100644
--- a/src/video/SDL_blit.h
+++ b/src/video/SDL_blit.h
@@ -479,14 +479,14 @@ do { \
#define DUFFS_LOOP8(pixel_copy_increment, width) \
{ int n = (width+7)/8; \
switch (width & 7) { \
- case 0: do { pixel_copy_increment; /* fallthrough */ \
- case 7: pixel_copy_increment; /* fallthrough */ \
- case 6: pixel_copy_increment; /* fallthrough */ \
- case 5: pixel_copy_increment; /* fallthrough */ \
- case 4: pixel_copy_increment; /* fallthrough */ \
- case 3: pixel_copy_increment; /* fallthrough */ \
- case 2: pixel_copy_increment; /* fallthrough */ \
- case 1: pixel_copy_increment; /* fallthrough */ \
+ case 0: do { pixel_copy_increment; SDL_FALLTHROUGH; \
+ case 7: pixel_copy_increment; SDL_FALLTHROUGH; \
+ case 6: pixel_copy_increment; SDL_FALLTHROUGH; \
+ case 5: pixel_copy_increment; SDL_FALLTHROUGH; \
+ case 4: pixel_copy_increment; SDL_FALLTHROUGH; \
+ case 3: pixel_copy_increment; SDL_FALLTHROUGH; \
+ case 2: pixel_copy_increment; SDL_FALLTHROUGH; \
+ case 1: pixel_copy_increment; \
} while ( --n > 0 ); \
} \
}
@@ -495,10 +495,10 @@ do { \
#define DUFFS_LOOP4(pixel_copy_increment, width) \
{ int n = (width+3)/4; \
switch (width & 3) { \
- case 0: do { pixel_copy_increment; /* fallthrough */ \
- case 3: pixel_copy_increment; /* fallthrough */ \
- case 2: pixel_copy_increment; /* fallthrough */ \
- case 1: pixel_copy_increment; /* fallthrough */ \
+ case 0: do { pixel_copy_increment; SDL_FALLTHROUGH; \
+ case 3: pixel_copy_increment; SDL_FALLTHROUGH; \
+ case 2: pixel_copy_increment; SDL_FALLTHROUGH; \
+ case 1: pixel_copy_increment; \
} while (--n > 0); \
} \
}
diff --git a/src/video/SDL_fillrect.c b/src/video/SDL_fillrect.c
index 6385e3ef8e..59f6761e05 100644
--- a/src/video/SDL_fillrect.c
+++ b/src/video/SDL_fillrect.c
@@ -145,13 +145,13 @@ SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
switch ((uintptr_t) p & 3) {
case 1:
*p++ = (Uint8) color;
- --n; /* fallthrough */
+ --n; SDL_FALLTHROUGH;
case 2:
*p++ = (Uint8) color;
- --n; /* fallthrough */
+ --n; SDL_FALLTHROUGH;
case 3:
*p++ = (Uint8) color;
- --n; /* fallthrough */
+ --n;
}
SDL_memset4(p, color, (n >> 2));
}
@@ -159,11 +159,11 @@ SDL_FillRect1(Uint8 * pixels, int pitch, Uint32 color, int w, int h)
p += (n & ~3);
switch (n & 3) {
case 3:
- *p++ = (Uint8) color; /* fallthrough */
+ *p++ = (Uint8) color; SDL_FALLTHROUGH;
case 2:
- *p++ = (Uint8) color; /* fallthrough */
+ *p++ = (Uint8) color; SDL_FALLTHROUGH;
case 1:
- *p++ = (Uint8) color; /* fallthrough */
+ *p++ = (Uint8) color;
}
}
pixels += pitch;
diff --git a/src/video/SDL_pixels.c b/src/video/SDL_pixels.c
index 8015e02134..1402167203 100644
--- a/src/video/SDL_pixels.c
+++ b/src/video/SDL_pixels.c
@@ -333,7 +333,7 @@ SDL_MasksToPixelFormatEnum(int bpp, Uint32 Rmask, Uint32 Gmask, Uint32 Bmask,
if (Rmask == 0) {
return SDL_PIXELFORMAT_RGB555;
}
- /* fallthrough */
+ SDL_FALLTHROUGH;
case 16:
if (Rmask == 0) {
return SDL_PIXELFORMAT_RGB565;
diff --git a/src/video/directfb/SDL_DirectFB_WM.c b/src/video/directfb/SDL_DirectFB_WM.c
index 8dd48a38a0..a90f98d662 100644
--- a/src/video/directfb/SDL_DirectFB_WM.c
+++ b/src/video/directfb/SDL_DirectFB_WM.c
@@ -323,7 +323,7 @@ DirectFB_WM_ProcessEvent(_THIS, SDL_Window * window, DFBWindowEvent * evt)
}
if (window->flags & SDL_WINDOW_MAXIMIZED)
return 1;
- /* fall through */
+ SDL_FALLTHROUGH;
default:
windata->wm_grab = pos;
if (grabbed_window != NULL)
diff --git a/src/video/directfb/SDL_DirectFB_events.c b/src/video/directfb/SDL_DirectFB_events.c
index 146bb99ea9..c8c3368a81 100644
--- a/src/video/directfb/SDL_DirectFB_events.c
+++ b/src/video/directfb/SDL_DirectFB_events.c
@@ -261,7 +261,7 @@ ProcessWindowEvent(_THIS, SDL_Window *sdlwin, DFBWindowEvent * evt)
SDL_SendWindowEvent(sdlwin, SDL_WINDOWEVENT_MOVED,
evt->x, evt->y);
}
- /* fall throught */
+ SDL_FALLTHROUGH;
case DWET_SIZE:
/* FIXME: what about < 0 */
evt->w -= (windata->theme.right_size + windata->theme.left_size);
diff --git a/src/video/windows/SDL_windowsevents.c b/src/video/windows/SDL_windowsevents.c
index d5ffaecd97..2c74265777 100644
--- a/src/video/windows/SDL_windowsevents.c
+++ b/src/video/windows/SDL_windowsevents.c
@@ -729,6 +729,7 @@ WIN_WindowProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam)
}
}
/* don't break here, fall through to check the wParam like the button presses */
+ SDL_FALLTHROUGH;
case WM_LBUTTONUP:
case WM_RBUTTONUP:
case WM_MBUTTONUP:
diff --git a/test/controllermap.c b/test/controllermap.c
index 144c60344a..a70764ab97 100644
--- a/test/controllermap.c
+++ b/test/controllermap.c
@@ -562,7 +562,7 @@ WatchJoystick(SDL_Joystick * joystick)
if ((event.key.keysym.sym != SDLK_ESCAPE)) {
break;
}
- /* Fall through to signal quit */
+ SDL_FALLTHROUGH;
case SDL_QUIT:
done = SDL_TRUE;
break;
@@ -755,7 +755,7 @@ main(int argc, char *argv[])
if ((event.key.keysym.sym != SDLK_ESCAPE)) {
break;
}
- /* Fall through to signal quit */
+ SDL_FALLTHROUGH;
case SDL_QUIT:
done = SDL_TRUE;
break;
diff --git a/test/testgamecontroller.c b/test/testgamecontroller.c
index d0fb990756..6aec600442 100644
--- a/test/testgamecontroller.c
+++ b/test/testgamecontroller.c
@@ -386,7 +386,7 @@ loop(void *arg)
if (event.key.keysym.sym != SDLK_ESCAPE) {
break;
}
- /* Fall through to signal quit */
+ SDL_FALLTHROUGH;
case SDL_QUIT:
done = SDL_TRUE;
break;
diff --git a/test/testjoystick.c b/test/testjoystick.c
index e0ab2708d3..b9e414bde9 100644
--- a/test/testjoystick.c
+++ b/test/testjoystick.c
@@ -183,7 +183,7 @@ loop(void *arg)
(event.key.keysym.sym != SDLK_AC_BACK)) {
break;
}
- /* Fall through to signal quit */
+ SDL_FALLTHROUGH;
case SDL_FINGERDOWN:
case SDL_MOUSEBUTTONDOWN:
case SDL_QUIT: