From 6c372f981f08dd571f5fc47197fcce9fd076f007 Mon Sep 17 00:00:00 2001 From: George Baltz N3GB Date: Sat, 26 Jul 2025 21:56:39 -0400 Subject: [PATCH] Distinguish wanted from unwanted fall through instances Compile with -Wimplicit-fallthrough; analyze the results. Define macro to mark valid fall through constructs. Mark all of the good ones, and fix the bad. Not available with all compilers - for those without the feature this commit does nothing. --- include/hamlib/rig.h | 17 +++++++++++++++++ rigs/icom/icom.c | 3 +++ rigs/kenwood/kenwood.c | 2 +- rigs/yaesu/ft847.c | 4 ++++ rigs/yaesu/ft920.c | 2 ++ rigs/yaesu/newcat.c | 4 ++-- src/iofunc.c | 2 +- src/rig.c | 2 +- tests/uthash.h | 12 ++++++++++++ 9 files changed, 43 insertions(+), 5 deletions(-) diff --git a/include/hamlib/rig.h b/include/hamlib/rig.h index c5df12297..3441a162b 100644 --- a/include/hamlib/rig.h +++ b/include/hamlib/rig.h @@ -73,6 +73,23 @@ #include //#include +/* Define macros for handling attributes, if the compiler implements them + * Should be available in c23-capable compilers, or c++11 ones + */ +// From ISO/IEC 9899:202y n3301 working draft +#ifndef __has_c_attribute +#define __has_c_attribute(x) 0 +#endif + +// Macro to mark fallthrough as OK +// Squelch warnings if -Wimplicit-fallthrough added to CFLAGS +#if __has_c_attribute(fallthrough) +#define HL_FALLTHROUGH [[fallthrough]]; +#else +/* Fall back */ +#define HL_FALLTHROUGH +#endif + /** * \addtogroup rig * @{ diff --git a/rigs/icom/icom.c b/rigs/icom/icom.c index 346dca79e..e1a00ea67 100644 --- a/rigs/icom/icom.c +++ b/rigs/icom/icom.c @@ -3393,6 +3393,7 @@ int icom_set_vfo(RIG *rig, vfo_t vfo) rig_debug(RIG_DEBUG_ERR, "%s: unknown vfo '%s'\n", __func__, rig_strvfo(rs->current_vfo)); } + HL_FALLTHROUGH // Fall into outer default default: if (priv->x25cmdfails == 0 || priv_caps->x25x26_always) @@ -9111,12 +9112,14 @@ static int icom_parse_spectrum_frame(RIG *rig, size_t length, case SCOPE_MODE_FIXED: cache->spectrum_mode = RIG_SPECTRUM_MODE_FIXED; + HL_FALLTHROUGH case SCOPE_MODE_SCROLL_C: if (cache->spectrum_mode == RIG_SPECTRUM_MODE_NONE) { cache->spectrum_mode = RIG_SPECTRUM_MODE_CENTER_SCROLL; } + HL_FALLTHROUGH case SCOPE_MODE_SCROLL_F: if (cache->spectrum_mode == RIG_SPECTRUM_MODE_NONE) diff --git a/rigs/kenwood/kenwood.c b/rigs/kenwood/kenwood.c index 435bedf4e..ccb13c65a 100644 --- a/rigs/kenwood/kenwood.c +++ b/rigs/kenwood/kenwood.c @@ -5600,7 +5600,7 @@ int kenwood_send_morse(RIG *rig, vfo_t vfo, const char *msg) SNPRINTF(morsebuf, sizeof morsebuf, "KY2%s", m2); break; } - /* FALL THROUGH */ + HL_FALLTHROUGH default: /* the command must consist of 28 bytes 0x20 padded */ diff --git a/rigs/yaesu/ft847.c b/rigs/yaesu/ft847.c index 75af845c1..a166070d3 100644 --- a/rigs/yaesu/ft847.c +++ b/rigs/yaesu/ft847.c @@ -1298,6 +1298,7 @@ static int get_freq_and_mode(RIG *rig, vfo_t vfo, freq_t *freq, rmode_t *mode, case MD_CWN: *width = rig_passband_narrow(rig, RIG_MODE_CW); + HL_FALLTHROUGH case MD_CW: *mode = RIG_MODE_CW; @@ -1305,6 +1306,7 @@ static int get_freq_and_mode(RIG *rig, vfo_t vfo, freq_t *freq, rmode_t *mode, case MD_CWNR: *width = rig_passband_narrow(rig, RIG_MODE_CW); + HL_FALLTHROUGH case MD_CWR: *mode = RIG_MODE_CWR; @@ -1312,6 +1314,7 @@ static int get_freq_and_mode(RIG *rig, vfo_t vfo, freq_t *freq, rmode_t *mode, case MD_AMN: *width = rig_passband_narrow(rig, RIG_MODE_AM); + HL_FALLTHROUGH case MD_AM: *mode = RIG_MODE_AM; @@ -1319,6 +1322,7 @@ static int get_freq_and_mode(RIG *rig, vfo_t vfo, freq_t *freq, rmode_t *mode, case MD_FMN: *width = rig_passband_narrow(rig, RIG_MODE_FM); + HL_FALLTHROUGH case MD_FM: *mode = RIG_MODE_FM; diff --git a/rigs/yaesu/ft920.c b/rigs/yaesu/ft920.c index 41d58b350..bc525594e 100644 --- a/rigs/yaesu/ft920.c +++ b/rigs/yaesu/ft920.c @@ -794,6 +794,7 @@ static int ft920_set_freq(RIG *rig, vfo_t vfo, freq_t freq) { return err; } + HL_FALLTHROUGH case RIG_VFO_MEM: /* MEM TUNE or user doesn't care */ case RIG_VFO_MAIN: @@ -965,6 +966,7 @@ static int ft920_set_mode(RIG *rig, vfo_t vfo, rmode_t mode, pbwidth_t width) { return err; } + HL_FALLTHROUGH case RIG_VFO_MEM: /* MEM TUNE or user doesn't care */ case RIG_VFO_MAIN: diff --git a/rigs/yaesu/newcat.c b/rigs/yaesu/newcat.c index fe88b7880..ccdc9c605 100644 --- a/rigs/yaesu/newcat.c +++ b/rigs/yaesu/newcat.c @@ -4414,9 +4414,9 @@ int newcat_set_level(RIG *rig, vfo_t vfo, setting_t level, value_t val) case RIG_METER_VDD: SNPRINTF(priv->cmd_str, sizeof(priv->cmd_str), format, 5); break; + default: rig_debug(RIG_DEBUG_ERR, "%s: unknown val.i=%d\n", __func__, val.i); - - default: RETURNFUNC(-RIG_EINVAL); + RETURNFUNC(-RIG_EINVAL); } break; diff --git a/src/iofunc.c b/src/iofunc.c index 97d3ca135..99e75414f 100644 --- a/src/iofunc.c +++ b/src/iofunc.c @@ -408,8 +408,8 @@ int HAMLIB_API port_close(hamlib_port_t *p, rig_port_t port_type) default: rig_debug(RIG_DEBUG_ERR, "%s(): Unknown port type %d\n", __func__, port_type); + HL_FALLTHROUGH - /* fall through */ case RIG_PORT_DEVICE: ret = close(p->fd); } diff --git a/src/rig.c b/src/rig.c index dae5add5c..63019fdf8 100644 --- a/src/rig.c +++ b/src/rig.c @@ -3611,8 +3611,8 @@ int HAMLIB_API rig_set_ptt(RIG *rig, vfo_t vfo, ptt_t ptt) { ptt = RIG_PTT_ON; } + HL_FALLTHROUGH - /* fall through */ case RIG_PTT_RIG_MICDATA: if (caps->set_ptt == NULL) { diff --git a/tests/uthash.h b/tests/uthash.h index 77a11c30e..6724600b1 100644 --- a/tests/uthash.h +++ b/tests/uthash.h @@ -412,15 +412,25 @@ do { hashv += keylen; \ switch ( _hj_k ) { \ case 11: hashv += ( (unsigned)_hj_key[10] << 24 ); \ + HL_FALLTHROUGH \ case 10: hashv += ( (unsigned)_hj_key[9] << 16 ); \ + HL_FALLTHROUGH \ case 9: hashv += ( (unsigned)_hj_key[8] << 8 ); \ + HL_FALLTHROUGH \ case 8: _hj_j += ( (unsigned)_hj_key[7] << 24 ); \ + HL_FALLTHROUGH \ case 7: _hj_j += ( (unsigned)_hj_key[6] << 16 ); \ + HL_FALLTHROUGH \ case 6: _hj_j += ( (unsigned)_hj_key[5] << 8 ); \ + HL_FALLTHROUGH \ case 5: _hj_j += _hj_key[4]; \ + HL_FALLTHROUGH \ case 4: _hj_i += ( (unsigned)_hj_key[3] << 24 ); \ + HL_FALLTHROUGH \ case 3: _hj_i += ( (unsigned)_hj_key[2] << 16 ); \ + HL_FALLTHROUGH \ case 2: _hj_i += ( (unsigned)_hj_key[1] << 8 ); \ + HL_FALLTHROUGH \ case 1: _hj_i += _hj_key[0]; \ } \ HASH_JEN_MIX(_hj_i, _hj_j, hashv); \ @@ -547,7 +557,9 @@ do { \ uint32_t _mur_k1=0; \ switch((keylen) & 3) { \ case 3: _mur_k1 ^= _mur_tail[2] << 16; \ + HL_FALLTHROUGH \ case 2: _mur_k1 ^= _mur_tail[1] << 8; \ + HL_FALLTHROUGH \ case 1: _mur_k1 ^= _mur_tail[0]; \ _mur_k1 *= _mur_c1; \ _mur_k1 = MUR_ROTL32(_mur_k1,15); \