From 3bf7994fe27447800102e30888a05bb01396a27c Mon Sep 17 00:00:00 2001 From: Misa 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). Clang before Clang 10 and GCC before GCC 7 have problems with using __attribute__ as a sole statement and warn about a "declaration not declaring anything", so fall back to using the /* fallthrough */ comment if we are using those older compiler versions. 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 | 21 +++++++++++++++++++++ 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, 65 insertions(+), 55 deletions(-) diff --git a/include/SDL_stdinc.h b/include/SDL_stdinc.h index c00374d12..15a635443 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 37bf9750f..9dbd89dc4 100644 --- a/include/begin_code.h +++ b/include/begin_code.h @@ -164,3 +164,24 @@ #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 +#if defined(__has_attribute) +#define _HAS_FALLTHROUGH __has_attribute(__fallthrough__) +#else +#define _HAS_FALLTHROUGH 0 +#endif /* __has_attribute */ +#if _HAS_FALLTHROUGH && \ + ((defined(__GNUC__) && __GNUC__ >= 7) || \ + (defined(__clang_major__) && __clang_major__ >= 10)) +#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 88204fdbe..bf9fb542b 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 d9abb940b..5c63954f6 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 e235541f3..34246bc4f 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 6922a24a9..13d6c542e 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 4b50c7dc3..8b28138e9 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 6385e3ef8..59f6761e0 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 8015e0213..140216720 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 8dd48a38a..a90f98d66 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 146bb99ea..c8c3368a8 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 d5ffaecd9..2c7426577 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 144c60344..a70764ab9 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 9cfc61e18..acd6382f7 100644 --- a/test/testgamecontroller.c +++ b/test/testgamecontroller.c @@ -394,7 +394,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 658e11146..fc8389ff5 100644 --- a/test/testjoystick.c +++ b/test/testjoystick.c @@ -186,7 +186,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: