File 1901-erts-Annotate-all-switch-fallthroughs.patch of Package erlang
From 6598a8c5938d3a5ece730d912234dfd6a2fa459c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Lukas=20Backstr=C3=B6m?= <lukas@erlang.org>
Date: Mon, 28 Oct 2024 09:32:43 +0100
Subject: [PATCH 01/10] erts: Annotate all switch fallthroughs
---
erts/emulator/beam/beam_bp.c | 6 ++++
erts/emulator/beam/bif.c | 5 +++
erts/emulator/beam/break.c | 44 +++++++++++------------
erts/emulator/beam/copy.c | 5 ++-
erts/emulator/beam/dist.c | 11 ++++++
erts/emulator/beam/emu/bs_instrs.tab | 14 ++++----
erts/emulator/beam/erl_arith.c | 30 ++++++++++------
erts/emulator/beam/erl_bif_re.c | 3 +-
erts/emulator/beam/erl_bif_trace.c | 2 ++
erts/emulator/beam/erl_bits.c | 42 +++++++++++-----------
erts/emulator/beam/erl_db_tree.c | 1 +
erts/emulator/beam/erl_gc.c | 6 ++--
erts/emulator/beam/erl_init.c | 4 ++-
erts/emulator/beam/erl_map.c | 7 ++--
erts/emulator/beam/erl_message.c | 2 +-
erts/emulator/beam/erl_monitor_link.c | 3 +-
erts/emulator/beam/erl_nif.c | 8 ++---
erts/emulator/beam/erl_process.c | 15 ++++++++
erts/emulator/beam/erl_term_hashing.c | 48 ++++++++++++-------------
erts/emulator/beam/erl_trace.c | 2 +-
erts/emulator/beam/erl_unicode.c | 2 ++
erts/emulator/beam/external.c | 13 ++++---
erts/emulator/beam/io.c | 1 +
erts/emulator/beam/packet_parser.c | 1 +
erts/emulator/beam/sys.h | 10 ++++++
erts/emulator/beam/utils.c | 4 ++-
erts/emulator/sys/common/erl_check_io.c | 3 +-
erts/epmd/src/epmd.c | 4 ++-
erts/epmd/src/epmd_int.h | 17 ++++++++-
erts/include/internal/ethread.h | 9 +++++
erts/lib_src/common/erl_printf_format.c | 13 +++++++
erts/lib_src/common/ethr_mutex.c | 2 ++
lib/erl_interface/src/misc/ei_format.c | 1 +
lib/erl_interface/src/misc/eidef.h | 10 ++++++
lib/erl_interface/src/misc/get_type.c | 2 ++
lib/erl_interface/src/prog/erl_call.c | 40 ++++++++++++++++-----
36 files changed, 274 insertions(+), 116 deletions(-)
diff --git a/erts/emulator/beam/beam_bp.c b/erts/emulator/beam/beam_bp.c
index 788e4e2bf1..d2481ca930 100644
--- a/erts/emulator/beam/beam_bp.c
+++ b/erts/emulator/beam/beam_bp.c
@@ -221,12 +221,15 @@ erts_bp_match_functions(BpFunctions* f, ErtsCodeMFA *mfa, int specified)
case 3:
if (ci->mfa.arity != mfa->arity)
continue;
+ ERTS_FALLTHROUGH();
case 2:
if (ci->mfa.function != mfa->function)
continue;
+ ERTS_FALLTHROUGH();
case 1:
if (ci->mfa.module != mfa->module)
continue;
+ ERTS_FALLTHROUGH();
case 0:
break;
}
@@ -259,12 +262,15 @@ erts_bp_match_export(BpFunctions* f, ErtsCodeMFA *mfa, int specified)
case 3:
if (mfa->arity != ep->info.mfa.arity)
continue;
+ ERTS_FALLTHROUGH();
case 2:
if (mfa->function != ep->info.mfa.function)
continue;
+ ERTS_FALLTHROUGH();
case 1:
if (mfa->module != ep->info.mfa.module)
continue;
+ ERTS_FALLTHROUGH();
case 0:
break;
default:
diff --git a/erts/emulator/beam/bif.c b/erts/emulator/beam/bif.c
index 3c4591fb1c..e6d4eaea86 100644
--- a/erts/emulator/beam/bif.c
+++ b/erts/emulator/beam/bif.c
@@ -3295,6 +3295,7 @@ BIF_RETTYPE string_list_to_float_1(BIF_ALIST_1)
break;
case EXP0: /* example: "2.3e--" */
LOAD_E(i, i_mem, list, list_mem);
+ ERTS_FALLTHROUGH();
default: /* unexpected - done */
part = END;
}
@@ -3308,6 +3309,7 @@ BIF_RETTYPE string_list_to_float_1(BIF_ALIST_1)
break;
case EXP0: /* example: "2.3e++" */
LOAD_E(i, i_mem, list, list_mem);
+ ERTS_FALLTHROUGH();
default: /* unexpected - done */
part = END;
}
@@ -3318,8 +3320,10 @@ BIF_RETTYPE string_list_to_float_1(BIF_ALIST_1)
break;
case EXP_SIGN: /* example: "2.3e." */
LOAD_E(i, i_mem, list, list_mem);
+ ERTS_FALLTHROUGH();
case EXP0: /* example: "2.3e+." */
LOAD_E(i, i_mem, list, list_mem);
+ ERTS_FALLTHROUGH();
default: /* unexpected - done */
part = END;
}
@@ -3336,6 +3340,7 @@ BIF_RETTYPE string_list_to_float_1(BIF_ALIST_1)
case EXP0: /* example: "2.3e+e" */
case EXP_SIGN: /* example: "2.3ee" */
LOAD_E(i, i_mem, list, list_mem);
+ ERTS_FALLTHROUGH();
case INT: /* would like this to be ok, example "2e2",
but it's not compatible with list_to_float */
default: /* unexpected - done */
diff --git a/erts/emulator/beam/break.c b/erts/emulator/beam/break.c
index 9d9cfdf4dc..561d1d147c 100644
--- a/erts/emulator/beam/break.c
+++ b/erts/emulator/beam/break.c
@@ -127,32 +127,28 @@ process_killer(void)
for (i = max-1; i >= 0; i--) {
rp = erts_pix2proc(i);
if (rp && rp->i != ENULL) {
- int br;
print_process_info(ERTS_PRINT_STDOUT, NULL, rp, 0);
erts_printf("(k)ill (n)ext (r)eturn:\n");
- while(1) {
- if ((j = sys_get_key(0)) <= 0)
- erts_exit(0, "");
- switch(j) {
- case 'k':
- {
- Process *init_proc;
-
- ASSERT(erts_init_process_id != ERTS_INVALID_PID);
- init_proc = erts_proc_lookup_raw(erts_init_process_id);
-
- /* Send a 'kill' exit signal from init process */
- erts_proc_sig_send_exit(&init_proc->common,
- erts_init_process_id,
- rp->common.id,
- am_kill, NIL, 0);
- }
- case 'n': br = 1; break;
- case 'r': return;
- default: return;
- }
- if (br == 1) break;
- }
+ if ((j = sys_get_key(0)) <= 0)
+ erts_exit(0, "");
+ switch(j) {
+ case 'k':
+ {
+ Process *init_proc;
+
+ ASSERT(erts_init_process_id != ERTS_INVALID_PID);
+ init_proc = erts_proc_lookup_raw(erts_init_process_id);
+
+ /* Send a 'kill' exit signal from init process */
+ erts_proc_sig_send_exit(&init_proc->common,
+ erts_init_process_id,
+ rp->common.id,
+ am_kill, NIL, 0);
+ break;
+ }
+ case 'n': break;
+ default: return;
+ }
}
}
}
diff --git a/erts/emulator/beam/copy.c b/erts/emulator/beam/copy.c
index 7ae1e72104..df6b37c876 100644
--- a/erts/emulator/beam/copy.c
+++ b/erts/emulator/beam/copy.c
@@ -898,6 +898,7 @@ Eterm copy_struct_x(Eterm obj, Uint sz, Eterm** hpp, ErlOffHeap* off_heap,
case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
*htop++ = *objp++;
+ ERTS_FALLTHROUGH();
case MAP_HEADER_TAG_HAMT_NODE_BITMAP :
i = 1 + hashmap_bitcount(MAP_HEADER_VAL(hdr));
while (i--) { *htop++ = *objp++; }
@@ -1601,6 +1602,7 @@ Uint copy_shared_perform_x(Eterm obj, Uint size, erts_shcopy_t *info,
case MAP_HEADER_TAG_HAMT_HEAD_BITMAP :
case MAP_HEADER_TAG_HAMT_HEAD_ARRAY :
*hp++ = *++ptr; /* total map size */
+ ERTS_FALLTHROUGH();
case MAP_HEADER_TAG_HAMT_NODE_BITMAP : {
Uint n = hashmap_bitcount(MAP_HEADER_VAL(hdr));
while (n--) {
@@ -1987,7 +1989,7 @@ Eterm* copy_shallow_x(Eterm *ERTS_RESTRICT ptr, Uint sz, Eterm **hpp,
erts_refc_inc(&mreft->mb->intern.refc, 2);
goto off_heap_common;
}
- /* Fall through... */
+ ERTS_FALLTHROUGH();
}
default:
{
@@ -2101,6 +2103,7 @@ move_one_frag(Eterm** hpp, ErlHeapFragment* frag, ErlOffHeap* off_heap, int lite
if (!is_magic_ref_thing(hdr)) {
break;
}
+ ERTS_FALLTHROUGH();
case BIN_REF_SUBTAG:
case EXTERNAL_PID_SUBTAG:
case EXTERNAL_PORT_SUBTAG:
diff --git a/erts/emulator/beam/dist.c b/erts/emulator/beam/dist.c
index 906ea8de59..c1670f8b2f 100644
--- a/erts/emulator/beam/dist.c
+++ b/erts/emulator/beam/dist.c
@@ -383,6 +383,7 @@ con_monitor_link_seq_cleanup(void *vcmlcp)
ASSERT(!cmlcp->yield_state);
cmlcp->state = ERTS_CML_CLEANUP_STATE_MONITORS;
+ ERTS_FALLTHROUGH();
case ERTS_CML_CLEANUP_STATE_MONITORS:
reds = erts_monitor_list_foreach_delete_yielding(&dist->monitors,
monitor_connection_down,
@@ -393,6 +394,7 @@ con_monitor_link_seq_cleanup(void *vcmlcp)
ASSERT(!cmlcp->yield_state);
cmlcp->state = ERTS_CML_CLEANUP_STATE_ONAME_MONITORS;
+ ERTS_FALLTHROUGH();
case ERTS_CML_CLEANUP_STATE_ONAME_MONITORS:
reds = erts_monitor_tree_foreach_delete_yielding(&dist->orig_name_monitors,
monitor_connection_down,
@@ -403,6 +405,7 @@ con_monitor_link_seq_cleanup(void *vcmlcp)
ASSERT(!cmlcp->yield_state);
cmlcp->state = ERTS_CML_CLEANUP_STATE_PEND_SPAWN_EXIT_MONITORS;
+ ERTS_FALLTHROUGH();
case ERTS_CML_CLEANUP_STATE_PEND_SPAWN_EXIT_MONITORS:
reds = erts_monitor_tree_foreach_delete_yielding(&dist->dist_pend_spawn_exit,
dist_pend_spawn_exit_connection_down,
@@ -416,6 +419,7 @@ con_monitor_link_seq_cleanup(void *vcmlcp)
ASSERT(!cmlcp->yield_state);
cmlcp->state = ERTS_CML_CLEANUP_STATE_SEQUENCES;
+ ERTS_FALLTHROUGH();
case ERTS_CML_CLEANUP_STATE_SEQUENCES:
reds = erts_dist_seq_tree_foreach_delete_yielding(&cmlcp->seq,
&cmlcp->yield_state,
@@ -425,6 +429,7 @@ con_monitor_link_seq_cleanup(void *vcmlcp)
ASSERT(!cmlcp->yield_state);
cmlcp->state = ERTS_CML_CLEANUP_STATE_NODE_MONITORS;
+ ERTS_FALLTHROUGH();
case ERTS_CML_CLEANUP_STATE_NODE_MONITORS:
if (cmlcp->trigger_node_monitors) {
Process* waiter;
@@ -2114,6 +2119,7 @@ int erts_net_message(Port *prt,
}
/* fall through, the first fragment in the sequence was the last fragment */
+ ERTS_FALLTHROUGH();
case ERTS_PREP_DIST_EXT_FRAG_CONT: {
DistSeqNode *seq;
erts_de_rlock(dep);
@@ -3274,6 +3280,7 @@ erts_dsig_send(ErtsDSigSendContext *ctx)
}
ctx->phase = ERTS_DSIG_SEND_PHASE_MSG_SIZE;
+ ERTS_FALLTHROUGH();
case ERTS_DSIG_SEND_PHASE_MSG_SIZE: {
Sint reds, *redsp;
if (!ctx->no_trap)
@@ -3311,6 +3318,7 @@ erts_dsig_send(ErtsDSigSendContext *ctx)
}
ctx->phase = ERTS_DSIG_SEND_PHASE_ALLOC;
+ ERTS_FALLTHROUGH();
}
case ERTS_DSIG_SEND_PHASE_ALLOC: {
@@ -3356,6 +3364,7 @@ erts_dsig_send(ErtsDSigSendContext *ctx)
}
ctx->phase = ERTS_DSIG_SEND_PHASE_MSG_ENCODE;
+ ERTS_FALLTHROUGH();
}
case ERTS_DSIG_SEND_PHASE_MSG_ENCODE: {
Sint reds, *redsp;
@@ -3387,6 +3396,7 @@ erts_dsig_send(ErtsDSigSendContext *ctx)
}
ctx->phase = ERTS_DSIG_SEND_PHASE_FIN;
+ ERTS_FALLTHROUGH();
}
case ERTS_DSIG_SEND_PHASE_FIN: {
Uint fid = ctx->fragments;
@@ -3456,6 +3466,7 @@ erts_dsig_send(ErtsDSigSendContext *ctx)
retval = ERTS_DSIG_SEND_CONTINUE;
goto done;
}
+ ERTS_FALLTHROUGH();
}
case ERTS_DSIG_SEND_PHASE_SEND: {
/*
diff --git a/erts/emulator/beam/emu/bs_instrs.tab b/erts/emulator/beam/emu/bs_instrs.tab
index 1c41b5b3cc..7e95d4e790 100644
--- a/erts/emulator/beam/emu/bs_instrs.tab
+++ b/erts/emulator/beam/emu/bs_instrs.tab
@@ -1343,22 +1343,22 @@ i_bs_read_bits.execute() {
#ifdef ARCH_64
case 9:
case 8:
- bitdata = bitdata << 8 | *byte_ptr++;
+ bitdata = bitdata << 8 | *byte_ptr++; ERTS_FALLTHROUGH();
case 7:
- bitdata = bitdata << 8 | *byte_ptr++;
+ bitdata = bitdata << 8 | *byte_ptr++; ERTS_FALLTHROUGH();
case 6:
- bitdata = bitdata << 8 | *byte_ptr++;
+ bitdata = bitdata << 8 | *byte_ptr++; ERTS_FALLTHROUGH();
case 5:
- bitdata = bitdata << 8 | *byte_ptr++;
+ bitdata = bitdata << 8 | *byte_ptr++; ERTS_FALLTHROUGH();
#else
case 5:
#endif
case 4:
- bitdata = bitdata << 8 | *byte_ptr++;
+ bitdata = bitdata << 8 | *byte_ptr++; ERTS_FALLTHROUGH();
case 3:
- bitdata = bitdata << 8 | *byte_ptr++;
+ bitdata = bitdata << 8 | *byte_ptr++; ERTS_FALLTHROUGH();
case 2:
- bitdata = bitdata << 8 | *byte_ptr++;
+ bitdata = bitdata << 8 | *byte_ptr++; ERTS_FALLTHROUGH();
case 1:
bitdata = bitdata << 8 | *byte_ptr++;
}
diff --git a/erts/emulator/beam/erl_arith.c b/erts/emulator/beam/erl_arith.c
index b608df2b4f..e394a3a941 100644
--- a/erts/emulator/beam/erl_arith.c
+++ b/erts/emulator/beam/erl_arith.c
@@ -370,7 +370,7 @@ erts_mixed_plus(Process* p, Eterm arg1, Eterm arg2)
case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):
case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):
switch (arg2 & _TAG_PRIMARY_MASK) {
- case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):
+ case TAG_PRIMARY_IMMED1:
switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {
case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):
if (arg2 == SMALL_ZERO) {
@@ -408,7 +408,9 @@ erts_mixed_plus(Process* p, Eterm arg1, Eterm arg2)
default:
goto badarith;
}
- }
+ default:
+ goto badarith;
+ }
case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):
switch (arg2 & _TAG_PRIMARY_MASK) {
case TAG_PRIMARY_IMMED1:
@@ -576,7 +578,7 @@ erts_mixed_minus(Process* p, Eterm arg1, Eterm arg2)
case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):
case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):
switch (arg2 & _TAG_PRIMARY_MASK) {
- case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):
+ case TAG_PRIMARY_IMMED1:
switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {
case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):
if (arg2 == SMALL_ZERO) {
@@ -615,6 +617,8 @@ erts_mixed_minus(Process* p, Eterm arg1, Eterm arg2)
default:
goto badarith;
}
+ default:
+ goto badarith;
}
case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):
switch (arg2 & _TAG_PRIMARY_MASK) {
@@ -744,17 +748,19 @@ erts_mixed_times(Process* p, Eterm arg1, Eterm arg2)
default:
goto badarith;
}
- }
- default:
+ default:
+ goto badarith;
+ }
+ default:
goto badarith;
- }
+ }
case TAG_PRIMARY_BOXED:
hdr = *boxed_val(arg1);
switch ((hdr & _TAG_HEADER_MASK) >> _TAG_PRIMARY_SIZE) {
case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):
case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):
switch (arg2 & _TAG_PRIMARY_MASK) {
- case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):
+ case TAG_PRIMARY_IMMED1:
switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {
case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):
if (arg2 == SMALL_ZERO)
@@ -810,7 +816,9 @@ erts_mixed_times(Process* p, Eterm arg1, Eterm arg2)
default:
goto badarith;
}
- }
+ default:
+ goto badarith;
+ }
case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):
switch (arg2 & _TAG_PRIMARY_MASK) {
case TAG_PRIMARY_IMMED1:
@@ -998,7 +1006,7 @@ erts_mixed_div(Process* p, Eterm arg1, Eterm arg2)
case (_TAG_HEADER_POS_BIG >> _TAG_PRIMARY_SIZE):
case (_TAG_HEADER_NEG_BIG >> _TAG_PRIMARY_SIZE):
switch (arg2 & _TAG_PRIMARY_MASK) {
- case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):
+ case TAG_PRIMARY_IMMED1:
switch ((arg2 & _TAG_IMMED1_MASK) >> _TAG_PRIMARY_SIZE) {
case (_TAG_IMMED1_SMALL >> _TAG_PRIMARY_SIZE):
if (big_to_double(arg1, &f1.fd) < 0) {
@@ -1028,7 +1036,9 @@ erts_mixed_div(Process* p, Eterm arg1, Eterm arg2)
default:
goto badarith;
}
- }
+ default:
+ goto badarith;
+ }
case (_TAG_HEADER_FLOAT >> _TAG_PRIMARY_SIZE):
switch (arg2 & _TAG_PRIMARY_MASK) {
case TAG_PRIMARY_IMMED1:
diff --git a/erts/emulator/beam/erl_bif_re.c b/erts/emulator/beam/erl_bif_re.c
index 38072f3fcd..88433a2938 100644
--- a/erts/emulator/beam/erl_bif_re.c
+++ b/erts/emulator/beam/erl_bif_re.c
@@ -1361,7 +1361,8 @@ handle_iodata:
case PCRE_ERROR_BADUTF8_OFFSET:
BUMP_ALL_REDS(p); /* Unknown amount of work done... */
/* Fall through for badarg... */
-
+ ERTS_FALLTHROUGH();
+
/* Bad pre-compiled regexp... */
case PCRE_ERROR_BADMAGIC:
case PCRE_ERROR_BADENDIANNESS:
diff --git a/erts/emulator/beam/erl_bif_trace.c b/erts/emulator/beam/erl_bif_trace.c
index a761440315..40b1433c9f 100644
--- a/erts/emulator/beam/erl_bif_trace.c
+++ b/erts/emulator/beam/erl_bif_trace.c
@@ -2666,6 +2666,7 @@ erts_finish_breakpointing(void)
}
/* Nothing to do here. Fall through to next stage. */
finish_bp.current++;
+ ERTS_FALLTHROUGH();
case 1:
/*
* Switch index for the breakpoint data, activating the staged
@@ -2702,6 +2703,7 @@ erts_finish_breakpointing(void)
}
/* Nothing done here. Fall through to next stage. */
finish_bp.current++;
+ ERTS_FALLTHROUGH();
case 3:
/*
* Now all breakpoints have either been inserted or removed.
diff --git a/erts/emulator/beam/erl_bits.c b/erts/emulator/beam/erl_bits.c
index a385884128..ef3640e1c2 100644
--- a/erts/emulator/beam/erl_bits.c
+++ b/erts/emulator/beam/erl_bits.c
@@ -246,13 +246,13 @@ Process *p, Uint num_bits, unsigned flags, ErlSubBits *sb)
*/
switch (BYTE_OFFSET(n)) {
#if defined(ARCH_64)
- case 7: w = (w << 8) | *bp++;
- case 6: w = (w << 8) | *bp++;
- case 5: w = (w << 8) | *bp++;
- case 4: w = (w << 8) | *bp++;
+ case 7: w = (w << 8) | *bp++; ERTS_FALLTHROUGH();
+ case 6: w = (w << 8) | *bp++; ERTS_FALLTHROUGH();
+ case 5: w = (w << 8) | *bp++; ERTS_FALLTHROUGH();
+ case 4: w = (w << 8) | *bp++; ERTS_FALLTHROUGH();
#endif
- case 3: w = (w << 8) | *bp++;
- case 2: w = (w << 8) | *bp++;
+ case 3: w = (w << 8) | *bp++; ERTS_FALLTHROUGH();
+ case 2: w = (w << 8) | *bp++; ERTS_FALLTHROUGH();
case 1: w = (w << 8) | *bp++;
}
n = BIT_OFFSET(n);
diff --git a/erts/emulator/beam/erl_db_tree.c b/erts/emulator/beam/erl_db_tree.c
index 4660837300..9714851ca6 100644
--- a/erts/emulator/beam/erl_db_tree.c
+++ b/erts/emulator/beam/erl_db_tree.c
@@ -3902,6 +3902,7 @@ static Sint do_cmp_partly_bound(Eterm a, Eterm b, int *done)
return 0;
}
/* Drop through */
+ ERTS_FALLTHROUGH();
default:
return CMP(a,b);
}
diff --git a/erts/emulator/beam/erl_gc.c b/erts/emulator/beam/erl_gc.c
index 11e8974f8d..20585d75f7 100644
--- a/erts/emulator/beam/erl_gc.c
+++ b/erts/emulator/beam/erl_gc.c
@@ -2562,6 +2562,7 @@ erts_copy_one_frag(Eterm** hpp, ErlOffHeap* off_heap,
case REF_SUBTAG:
if (!is_magic_ref_thing(fhp - 1))
goto the_default;
+ ERTS_FALLTHROUGH();
case BIN_REF_SUBTAG:
case EXTERNAL_PID_SUBTAG:
case EXTERNAL_PORT_SUBTAG:
@@ -3058,7 +3059,7 @@ sweep_off_heap(Process *p, int fullsweep)
bin_vheap += size / sizeof(Eterm);
else
p->bin_old_vheap += size / sizeof(Eterm); /* for binary gc (words)*/
- /* fall through... */
+ ERTS_FALLTHROUGH();
}
default:
if (is_external_header(ptr->thing_word)) {
@@ -3312,6 +3313,7 @@ offset_heap(Eterm* hp, Uint sz, Sint offs, char* area, Uint area_size)
case REF_SUBTAG:
if (!is_magic_ref_thing(hp))
break;
+ ERTS_FALLTHROUGH();
case BIN_REF_SUBTAG:
case EXTERNAL_PID_SUBTAG:
case EXTERNAL_PORT_SUBTAG:
@@ -4023,7 +4025,7 @@ check_all_heap_terms_in_range(int (*check_eterm)(Eterm),
if (is_magic_ref_thing(rtp)) {
goto off_heap_common;
}
- /* Fall through... */
+ ERTS_FALLTHROUGH();
}
default:
{
diff --git a/erts/emulator/beam/erl_init.c b/erts/emulator/beam/erl_init.c
index d8397d31db..a875fba895 100644
--- a/erts/emulator/beam/erl_init.c
+++ b/erts/emulator/beam/erl_init.c
@@ -528,7 +528,7 @@ load_preloaded(void)
}
/* be helpful (or maybe downright rude:-) */
-void erts_usage(void)
+__decl_noreturn void __noreturn erts_usage(void)
{
int this_rel = this_rel_num();
erts_fprintf(stderr, "Usage: %s [flags] [ -- [init_args] ]\n", progname(program));
@@ -1033,6 +1033,7 @@ early_init(int *argc, char **argv) /*
case 1:
onln = tot < dirty_cpu_scheds_online ?
tot : dirty_cpu_scheds_online;
+ ERTS_FALLTHROUGH();
case 2:
chk_SDcpu:
if (tot > 0)
@@ -1103,6 +1104,7 @@ early_init(int *argc, char **argv) /*
}
case 1:
onln = tot < schdlrs_onln ? tot : schdlrs_onln;
+ ERTS_FALLTHROUGH();
case 2:
chk_S:
if (tot > 0)
diff --git a/erts/emulator/beam/erl_map.c b/erts/emulator/beam/erl_map.c
index bdbd10d222..541d3c1220 100644
--- a/erts/emulator/beam/erl_map.c
+++ b/erts/emulator/beam/erl_map.c
@@ -1656,7 +1656,7 @@ recurse:
sp->abm = 0xffff;
break;
}
- case HAMT_SUBTAG_HEAD_BITMAP: sp->srcA++;
+ case HAMT_SUBTAG_HEAD_BITMAP: sp->srcA++; ERTS_FALLTHROUGH();
case HAMT_SUBTAG_NODE_BITMAP: {
ASSERT(ctx->lvl < HAMT_MAX_LEVEL);
sp->abm = MAP_HEADER_VAL(hdrA);
@@ -1693,7 +1693,7 @@ recurse:
sp->bbm = 0xffff;
break;
}
- case HAMT_SUBTAG_HEAD_BITMAP: sp->srcB++;
+ case HAMT_SUBTAG_HEAD_BITMAP: sp->srcB++; ERTS_FALLTHROUGH();
case HAMT_SUBTAG_NODE_BITMAP: {
ASSERT(ctx->lvl < HAMT_MAX_LEVEL);
sp->bbm = MAP_HEADER_VAL(hdrB);
@@ -2329,6 +2329,7 @@ Uint hashmap_node_size(Eterm hdr, Eterm **nodep)
break;
case HAMT_SUBTAG_HEAD_BITMAP:
if (nodep) ++*nodep;
+ ERTS_FALLTHROUGH();
case HAMT_SUBTAG_NODE_BITMAP:
sz = hashmap_bitcount(MAP_HEADER_VAL(hdr));
ASSERT(sz < 17);
@@ -2711,6 +2712,7 @@ Eterm erts_hashmap_insert_up(Eterm *hp, Eterm key, Eterm value,
/* subnodes, fake it */
fake = node;
node = make_boxed(&fake);
+ ERTS_FALLTHROUGH();
case TAG_PRIMARY_BOXED:
ptr = boxed_val(node);
hdr = *ptr;
@@ -3442,6 +3444,7 @@ BIF_RETTYPE erts_internal_map_hashmap_children_1(BIF_ALIST_1) {
BIF_ERROR(BIF_P, BADARG);
case HAMT_SUBTAG_HEAD_BITMAP:
ptr++;
+ ERTS_FALLTHROUGH();
case HAMT_SUBTAG_NODE_BITMAP:
ptr++;
sz = hashmap_bitcount(MAP_HEADER_VAL(hdr));
diff --git a/erts/emulator/beam/erl_message.c b/erts/emulator/beam/erl_message.c
index bb075be5d1..3cb6b0a3da 100644
--- a/erts/emulator/beam/erl_message.c
+++ b/erts/emulator/beam/erl_message.c
@@ -1509,7 +1509,7 @@ void erts_factory_trim_and_close(ErtsHeapFactory* factory,
/*else we don't trim multi fragmented messages for now (off_heap...) */
break;
}
- /* Fall through... */
+ ERTS_FALLTHROUGH();
}
case FACTORY_HEAP_FRAGS:
bp = factory->heap_frags;
diff --git a/erts/emulator/beam/erl_monitor_link.c b/erts/emulator/beam/erl_monitor_link.c
index 85d880dda3..59506b1051 100644
--- a/erts/emulator/beam/erl_monitor_link.c
+++ b/erts/emulator/beam/erl_monitor_link.c
@@ -894,7 +894,8 @@ erts_monitor_create(Uint16 type, Eterm ref, Eterm orgn, Eterm trgt, Eterm name,
mdp->u.target.type = type;
erts_atomic32_init_nob(&mdp->refc, 2);
break;
- }
+ } /* end of "if (is_nil(name))"" */
+ ERTS_FALLTHROUGH();
case ERTS_MON_TYPE_DIST_PROC:
case ERTS_MON_TYPE_DIST_PORT:
case ERTS_MON_TYPE_RESOURCE:
diff --git a/erts/emulator/beam/erl_nif.c b/erts/emulator/beam/erl_nif.c
index f5600b7dc6..6c40b8290a 100644
--- a/erts/emulator/beam/erl_nif.c
+++ b/erts/emulator/beam/erl_nif.c
@@ -2707,10 +2707,10 @@ ErlNifResourceType* open_resource_type(ErlNifEnv* env,
ort->type = type;
sys_memzero(&ort->new_callbacks, sizeof(ErlNifResourceTypeInit));
switch (init_members) {
- case 4: ort->new_callbacks.dyncall = init->dyncall;
- case 3: ort->new_callbacks.down = init->down;
- case 2: ort->new_callbacks.stop = init->stop;
- case 1: ort->new_callbacks.dtor = init->dtor;
+ case 4: ort->new_callbacks.dyncall = init->dyncall; ERTS_FALLTHROUGH();
+ case 3: ort->new_callbacks.down = init->down; ERTS_FALLTHROUGH();
+ case 2: ort->new_callbacks.stop = init->stop; ERTS_FALLTHROUGH();
+ case 1: ort->new_callbacks.dtor = init->dtor; ERTS_FALLTHROUGH();
case 0:
break;
default:
diff --git a/erts/emulator/beam/erl_process.c b/erts/emulator/beam/erl_process.c
index ee266a47dd..b96a01bc45 100644
--- a/erts/emulator/beam/erl_process.c
+++ b/erts/emulator/beam/erl_process.c
@@ -14161,6 +14161,7 @@ restart:
trap_state->phase = ERTS_CONTINUE_EXIT_BLCKD_MSHED;
if (reds <= 0) goto yield;
+ ERTS_FALLTHROUGH();
case ERTS_CONTINUE_EXIT_BLCKD_MSHED:
if (p->flags & F_HAVE_BLCKD_MSCHED) {
@@ -14181,6 +14182,7 @@ restart:
trap_state->phase = ERTS_CONTINUE_EXIT_BLCKD_NMSHED;
if (reds <= 0) goto yield;
+ ERTS_FALLTHROUGH();
case ERTS_CONTINUE_EXIT_BLCKD_NMSHED:
if (p->flags & F_HAVE_BLCKD_NMSCHED) {
@@ -14202,6 +14204,7 @@ restart:
trap_state->yield_state = NULL;
trap_state->phase = ERTS_CONTINUE_EXIT_USING_DB;
if (reds <= 0) goto yield;
+ ERTS_FALLTHROUGH();
case ERTS_CONTINUE_EXIT_USING_DB:
if (p->flags & F_USING_DB) {
@@ -14211,6 +14214,7 @@ restart:
}
trap_state->phase = ERTS_CONTINUE_EXIT_CLEAN_SYS_TASKS;
+ ERTS_FALLTHROUGH();
case ERTS_CONTINUE_EXIT_CLEAN_SYS_TASKS:
state = erts_atomic32_read_acqb(&p->state);
@@ -14246,6 +14250,7 @@ restart:
}
trap_state->phase = ERTS_CONTINUE_EXIT_FREE;
+ ERTS_FALLTHROUGH();
case ERTS_CONTINUE_EXIT_FREE:
#ifdef DEBUG
@@ -14320,6 +14325,7 @@ restart:
erts_proc_unlock(p, ERTS_PROC_LOCKS_ALL_MINOR);
curr_locks = ERTS_PROC_LOCK_MAIN;
trap_state->phase = ERTS_CONTINUE_EXIT_CLEAN_SYS_TASKS_AFTER;
+ ERTS_FALLTHROUGH();
case ERTS_CONTINUE_EXIT_CLEAN_SYS_TASKS_AFTER:
/*
* It might show up signal prio elevation tasks until we
@@ -14383,6 +14389,7 @@ restart:
trap_state->yield_state = NULL;
trap_state->phase = ERTS_CONTINUE_EXIT_LINKS;
if (reds <= 0) goto yield;
+ ERTS_FALLTHROUGH();
case ERTS_CONTINUE_EXIT_LINKS:
reds = erts_link_tree_foreach_delete_yielding(
@@ -14397,6 +14404,7 @@ restart:
ASSERT(!trap_state->links);
trap_state->yield_state = NULL;
trap_state->phase = ERTS_CONTINUE_EXIT_MONITORS;
+ ERTS_FALLTHROUGH();
case ERTS_CONTINUE_EXIT_MONITORS:
reds = erts_monitor_tree_foreach_delete_yielding(
@@ -14411,6 +14419,7 @@ restart:
ASSERT(!trap_state->monitors);
trap_state->yield_state = NULL;
trap_state->phase = ERTS_CONTINUE_EXIT_LT_MONITORS;
+ ERTS_FALLTHROUGH();
case ERTS_CONTINUE_EXIT_LT_MONITORS:
reds = erts_monitor_list_foreach_delete_yielding(
@@ -14424,6 +14433,7 @@ restart:
ASSERT(!trap_state->lt_monitors);
trap_state->phase = ERTS_CONTINUE_EXIT_HANDLE_PROC_SIG;
+ ERTS_FALLTHROUGH();
case ERTS_CONTINUE_EXIT_HANDLE_PROC_SIG: {
Sint r = reds;
@@ -14434,6 +14444,7 @@ restart:
reds -= r;
trap_state->phase = ERTS_CONTINUE_EXIT_DIST_SEND;
+ ERTS_FALLTHROUGH();
}
case ERTS_CONTINUE_EXIT_DIST_SEND: {
@@ -14472,6 +14483,7 @@ restart:
}
trap_state->phase = ERTS_CONTINUE_EXIT_DIST_LINKS;
+ ERTS_FALLTHROUGH();
}
case ERTS_CONTINUE_EXIT_DIST_LINKS: {
@@ -14488,6 +14500,7 @@ restart:
goto yield;
trap_state->phase = ERTS_CONTINUE_EXIT_DIST_MONITORS;
+ ERTS_FALLTHROUGH();
}
case ERTS_CONTINUE_EXIT_DIST_MONITORS: {
@@ -14504,6 +14517,7 @@ restart:
goto yield;
trap_state->phase = ERTS_CONTINUE_EXIT_DIST_PEND_SPAWN_MONITORS;
+ ERTS_FALLTHROUGH();
}
case ERTS_CONTINUE_EXIT_DIST_PEND_SPAWN_MONITORS: {
@@ -14529,6 +14543,7 @@ restart:
goto yield;
trap_state->phase = ERTS_CONTINUE_EXIT_DONE;
+ ERTS_FALLTHROUGH();
}
case ERTS_CONTINUE_EXIT_DONE: {
erts_aint_t state;
diff --git a/erts/emulator/beam/erl_term_hashing.c b/erts/emulator/beam/erl_term_hashing.c
index a32d47aa91..3ada7f479c 100644
--- a/erts/emulator/beam/erl_term_hashing.c
+++ b/erts/emulator/beam/erl_term_hashing.c
@@ -462,17 +462,17 @@ Uint32 block_hash_final_bytes(byte *buf,
ctx->c += full_length;
switch(len)
{ /* all the case statements fall through */
- case 11: ctx->c+=((Uint32)k[10]<<24);
- case 10: ctx->c+=((Uint32)k[9]<<16);
- case 9 : ctx->c+=((Uint32)k[8]<<8);
+ case 11: ctx->c+=((Uint32)k[10]<<24); ERTS_FALLTHROUGH();
+ case 10: ctx->c+=((Uint32)k[9]<<16); ERTS_FALLTHROUGH();
+ case 9 : ctx->c+=((Uint32)k[8]<<8); ERTS_FALLTHROUGH();
/* the first byte of c is reserved for the length */
- case 8 : ctx->b+=((Uint32)k[7]<<24);
- case 7 : ctx->b+=((Uint32)k[6]<<16);
- case 6 : ctx->b+=((Uint32)k[5]<<8);
- case 5 : ctx->b+=k[4];
- case 4 : ctx->a+=((Uint32)k[3]<<24);
- case 3 : ctx->a+=((Uint32)k[2]<<16);
- case 2 : ctx->a+=((Uint32)k[1]<<8);
+ case 8 : ctx->b+=((Uint32)k[7]<<24); ERTS_FALLTHROUGH();
+ case 7 : ctx->b+=((Uint32)k[6]<<16); ERTS_FALLTHROUGH();
+ case 6 : ctx->b+=((Uint32)k[5]<<8); ERTS_FALLTHROUGH();
+ case 5 : ctx->b+=k[4]; ERTS_FALLTHROUGH();
+ case 4 : ctx->a+=((Uint32)k[3]<<24); ERTS_FALLTHROUGH();
+ case 3 : ctx->a+=((Uint32)k[2]<<16); ERTS_FALLTHROUGH();
+ case 2 : ctx->a+=((Uint32)k[1]<<8); ERTS_FALLTHROUGH();
case 1 : ctx->a+=k[0];
/* case 0: nothing left to add */
}
@@ -1964,12 +1964,12 @@ make_internal_hash(Eterm term, erts_ihash_t salt)
value = 0;
switch(BYTE_SIZE(size) % sizeof(Uint64[2]))
{
- case 15: value ^= ((Uint64)bytes[it + 14]) << 0x30;
- case 14: value ^= ((Uint64)bytes[it + 13]) << 0x28;
- case 13: value ^= ((Uint64)bytes[it + 12]) << 0x20;
- case 12: value ^= ((Uint64)bytes[it + 11]) << 0x18;
- case 11: value ^= ((Uint64)bytes[it + 10]) << 0x10;
- case 10: value ^= ((Uint64)bytes[it + 9]) << 0x08;
+ case 15: value ^= ((Uint64)bytes[it + 14]) << 0x30; ERTS_FALLTHROUGH();
+ case 14: value ^= ((Uint64)bytes[it + 13]) << 0x28; ERTS_FALLTHROUGH();
+ case 13: value ^= ((Uint64)bytes[it + 12]) << 0x20; ERTS_FALLTHROUGH();
+ case 12: value ^= ((Uint64)bytes[it + 11]) << 0x18; ERTS_FALLTHROUGH();
+ case 11: value ^= ((Uint64)bytes[it + 10]) << 0x10; ERTS_FALLTHROUGH();
+ case 10: value ^= ((Uint64)bytes[it + 9]) << 0x08; ERTS_FALLTHROUGH();
case 9: value ^= ((Uint64)bytes[it + 8]) << 0x00;
{
value *= IHASH_C2;
@@ -1977,15 +1977,15 @@ make_internal_hash(Eterm term, erts_ihash_t salt)
value *= IHASH_C1;
hash_beta ^= value;
value = 0;
- /* !! FALL THROUGH !! */
+ ERTS_FALLTHROUGH();
}
- case 8: value ^= ((Uint64)bytes[it + 7]) << 0x38;
- case 7: value ^= ((Uint64)bytes[it + 6]) << 0x30;
- case 6: value ^= ((Uint64)bytes[it + 5]) << 0x28;
- case 5: value ^= ((Uint64)bytes[it + 4]) << 0x20;
- case 4: value ^= ((Uint64)bytes[it + 3]) << 0x18;
- case 3: value ^= ((Uint64)bytes[it + 2]) << 0x10;
- case 2: value ^= ((Uint64)bytes[it + 1]) << 0x08;
+ case 8: value ^= ((Uint64)bytes[it + 7]) << 0x38; ERTS_FALLTHROUGH();
+ case 7: value ^= ((Uint64)bytes[it + 6]) << 0x30; ERTS_FALLTHROUGH();
+ case 6: value ^= ((Uint64)bytes[it + 5]) << 0x28; ERTS_FALLTHROUGH();
+ case 5: value ^= ((Uint64)bytes[it + 4]) << 0x20; ERTS_FALLTHROUGH();
+ case 4: value ^= ((Uint64)bytes[it + 3]) << 0x18; ERTS_FALLTHROUGH();
+ case 3: value ^= ((Uint64)bytes[it + 2]) << 0x10; ERTS_FALLTHROUGH();
+ case 2: value ^= ((Uint64)bytes[it + 1]) << 0x08; ERTS_FALLTHROUGH();
case 1: value ^= ((Uint64)bytes[it + 0]) << 0x00;
{
value *= IHASH_C1;
diff --git a/erts/emulator/beam/erl_trace.c b/erts/emulator/beam/erl_trace.c
index e28d4be00e..c814f81beb 100644
--- a/erts/emulator/beam/erl_trace.c
+++ b/erts/emulator/beam/erl_trace.c
@@ -1226,7 +1226,7 @@ erts_call_trace(Process* p, ErtsCodeInfo *info, Binary *match_spec,
&tnif, TRACE_FUN_ENABLED,
am_trace_status, p->common.id)) {
default:
- case am_remove: *tracer_p = erts_tracer_nil;
+ case am_remove: *tracer_p = erts_tracer_nil; ERTS_FALLTHROUGH();
case am_discard: return 0;
case am_trace:
switch (call_enabled_tracer(tracer,
diff --git a/erts/emulator/beam/erl_unicode.c b/erts/emulator/beam/erl_unicode.c
index 9e2924946d..46f487bec4 100644
--- a/erts/emulator/beam/erl_unicode.c
+++ b/erts/emulator/beam/erl_unicode.c
@@ -2164,6 +2164,7 @@ Eterm erts_convert_native_to_filename(Process *p, size_t size, byte *bytes)
goto noconvert;
case ERL_FILENAME_UTF8_MAC:
mac = 1;
+ ERTS_FALLTHROUGH();
case ERL_FILENAME_UTF8:
if (size == 0)
return NIL;
@@ -2334,6 +2335,7 @@ L_Again: /* Restart with sublist, old listend was pushed on stack */
need += 2;
break;
} /* else fall through to error */
+ ERTS_FALLTHROUGH();
default:
DESTROY_ESTACK(stack);
return ((Sint) -1);
diff --git a/erts/emulator/beam/external.c b/erts/emulator/beam/external.c
index 4c8becb666..4e99d9e3d0 100644
--- a/erts/emulator/beam/external.c
+++ b/erts/emulator/beam/external.c
@@ -633,10 +633,13 @@ Sint erts_encode_ext_dist_header_finalize(ErtsDistOutputBuf* ob,
switch (flgs_bytes) {
case 4:
*--ep = (byte) ((flgs >> 24) & 0xff);
+ ERTS_FALLTHROUGH();
case 3:
*--ep = (byte) ((flgs >> 16) & 0xff);
+ ERTS_FALLTHROUGH();
case 2:
*--ep = (byte) ((flgs >> 8) & 0xff);
+ ERTS_FALLTHROUGH();
case 1:
*--ep = (byte) (flgs & 0xff);
}
@@ -1044,9 +1047,11 @@ erts_prepare_dist_ext(ErtsDistExternal *edep,
case 6:
case 5:
flgs |= (((Uint32) flgsp[2]) << 16);
+ ERTS_FALLTHROUGH();
case 4:
case 3:
flgs |= (((Uint32) flgsp[1]) << 8);
+ ERTS_FALLTHROUGH();
case 2:
case 1:
flgs |= ((Uint32) flgsp[0]);
@@ -3089,11 +3094,11 @@ dec_atom(ErtsDistExternal *edep, const byte* ep, Eterm* objp, int internal_nc)
*objp = make_atom(n);
break;
case NIL_EXT:
- if (internal_nc) {
- *objp = INTERNAL_LOCAL_SYSNAME;
- break;
+ if (!internal_nc) {
+ goto error;
}
- /* else: fail... */
+ *objp = INTERNAL_LOCAL_SYSNAME;
+ break;
default:
error:
*objp = NIL; /* Don't leave a hole in the heap */
diff --git a/erts/emulator/beam/io.c b/erts/emulator/beam/io.c
index 78efccc376..a80b1863ea 100644
--- a/erts/emulator/beam/io.c
+++ b/erts/emulator/beam/io.c
@@ -3198,6 +3198,7 @@ static int flush_linebuf(LineBufContext *bp)
resize_linebuf(bp->b);
LINEBUF_DATA(*bp)[((*bp->b)->ovlen)++] = '\r';
++bp->retlen; /* fall through instead of switching state... */
+ ERTS_FALLTHROUGH();
case LINEBUF_MAIN:
case LINEBUF_FULL:
(*bp->b)->ovlen = 0;
diff --git a/erts/emulator/beam/packet_parser.c b/erts/emulator/beam/packet_parser.c
index a349c3ff84..c4adee9f34 100644
--- a/erts/emulator/beam/packet_parser.c
+++ b/erts/emulator/beam/packet_parser.c
@@ -388,6 +388,7 @@ int packet_get_length(enum PacketParseType htype,
case TCP_PB_HTTPH:
case TCP_PB_HTTPH_BIN:
*statep = !0;
+ ERTS_FALLTHROUGH();
case TCP_PB_HTTP:
case TCP_PB_HTTP_BIN:
/* TCP_PB_HTTP: data \r\n(SP data\r\n)* */
diff --git a/erts/emulator/beam/sys.h b/erts/emulator/beam/sys.h
index 02ab608166..90085e92e1 100644
--- a/erts/emulator/beam/sys.h
+++ b/erts/emulator/beam/sys.h
@@ -309,6 +309,16 @@ __decl_noreturn void __noreturn erl_assert_error(const char* expr, const char *f
} while (0)
#endif
+/* Taken from https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#warn-about-implicit-fallthrough-in-switch-statements */
+#ifdef __has_attribute
+# if __has_attribute(__fallthrough__)
+# define ERTS_FALLTHROUGH() __attribute__((__fallthrough__))
+# endif
+#endif
+#ifndef ERTS_FALLTHROUGH
+# define ERTS_FALLTHROUGH() do {} while (0) /* fallthrough */
+#endif
+
/* C99: bool, true and false */
#include <stdbool.h>
diff --git a/erts/emulator/beam/utils.c b/erts/emulator/beam/utils.c
index d975bcd2f4..57f809f29b 100644
--- a/erts/emulator/beam/utils.c
+++ b/erts/emulator/beam/utils.c
@@ -1450,6 +1450,7 @@ tailrecur_ne:
if (aa[0] != bb[0])
goto not_equal;
aa++; bb++;
+ ERTS_FALLTHROUGH();
case HAMT_SUBTAG_NODE_BITMAP:
sz = hashmap_bitcount(MAP_HEADER_VAL(hdr));
ASSERT(sz > 0 && sz < 17);
@@ -1803,7 +1804,8 @@ tailrecur_ne:
goto mixed_types;
}
}
- }
+ }
+ ERTS_ASSERT(0 && "unreachable");
case TAG_PRIMARY_LIST:
if (is_not_list(b)) {
a_tag = LIST_DEF;
diff --git a/erts/emulator/sys/common/erl_check_io.c b/erts/emulator/sys/common/erl_check_io.c
index f821cca9c8..70986d7a0b 100644
--- a/erts/emulator/sys/common/erl_check_io.c
+++ b/erts/emulator/sys/common/erl_check_io.c
@@ -589,8 +589,8 @@ abort_tasks(ErtsDrvEventState *state, int mode)
return;
default:
ASSERT(state->type == ERTS_EV_TYPE_DRV_SEL);
- /* Fall through */
}
+ ERTS_FALLTHROUGH();
case ERL_DRV_READ|ERL_DRV_WRITE:
case ERL_DRV_WRITE:
ASSERT(state->type == ERTS_EV_TYPE_DRV_SEL);
@@ -599,6 +599,7 @@ abort_tasks(ErtsDrvEventState *state, int mode)
state->type);
if (mode == ERL_DRV_WRITE)
break;
+ ERTS_FALLTHROUGH();
case ERL_DRV_READ:
ASSERT(state->type == ERTS_EV_TYPE_DRV_SEL);
abort_task(state->driver.select->inport,
diff --git a/erts/epmd/src/epmd.c b/erts/epmd/src/epmd.c
index e71a0528dd..a0d5e9ab22 100644
--- a/erts/epmd/src/epmd.c
+++ b/erts/epmd/src/epmd.c
@@ -523,7 +523,9 @@ static void free_all_nodes(EpmdVars *g)
free(tmp);
}
}
-void epmd_cleanup_exit(EpmdVars *g, int exitval)
+
+__decl_noreturn void __noreturn
+epmd_cleanup_exit(EpmdVars *g, int exitval)
{
int i;
diff --git a/erts/epmd/src/epmd_int.h b/erts/epmd/src/epmd_int.h
index ed2ca33074..523a55f3d1 100644
--- a/erts/epmd/src/epmd_int.h
+++ b/erts/epmd/src/epmd_int.h
@@ -97,6 +97,21 @@
#define ASSERT(Cnd)
#endif
+#if __GNUC__
+# define __decl_noreturn
+# ifndef __noreturn
+# define __noreturn __attribute__((noreturn))
+# endif
+#else
+# if defined(__WIN32__) && defined(_MSC_VER)
+# define __noreturn
+# define __decl_noreturn __declspec(noreturn)
+# else
+# define __noreturn
+# define __decl_noreturn
+# endif
+#endif
+
#if defined(HAVE_IN6) && defined(AF_INET6) && defined(HAVE_INET_PTON)
# define EPMD6
#endif
@@ -343,7 +358,7 @@ void dbg_perror(EpmdVars*,const char*,...);
void kill_epmd(EpmdVars*);
void epmd_call(EpmdVars*,int);
void run(EpmdVars*);
-void epmd_cleanup_exit(EpmdVars*, int);
+__decl_noreturn void __noreturn epmd_cleanup_exit(EpmdVars*, int);
int epmd_conn_close(EpmdVars*,Connection*);
void stop_cli(EpmdVars *g, char *name);
diff --git a/erts/include/internal/ethread.h b/erts/include/internal/ethread.h
index e1aa6d4126..d0227a481f 100644
--- a/erts/include/internal/ethread.h
+++ b/erts/include/internal/ethread.h
@@ -105,6 +105,15 @@ ethr_assert_failed(const char *file, int line, const char *func, const char *a);
#define ETHR_ASSERT(A) ((void) 1)
#endif
+/* Taken from https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#warn-about-implicit-fallthrough-in-switch-statements */
+#ifdef __has_attribute
+# if __has_attribute(__fallthrough__)
+# define ETHR_FALLTHROUGH() __attribute__((__fallthrough__))
+# endif
+#endif
+#ifndef ETHR_FALLTHROUGH
+# define ETHR_FALLTHROUGH() do {} while (0) /* fallthrough */
+#endif
#if defined(ETHR_PTHREADS)
/* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * *\
diff --git a/erts/lib_src/common/erl_printf_format.c b/erts/lib_src/common/erl_printf_format.c
index d59a5df2e5..f4a32615b7 100644
--- a/erts/lib_src/common/erl_printf_format.c
+++ b/erts/lib_src/common/erl_printf_format.c
@@ -45,6 +45,17 @@
#include "erl_printf.h"
#include "erl_printf_format.h"
+
+/* Taken from https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#warn-about-implicit-fallthrough-in-switch-statements */
+#ifdef __has_attribute
+# if __has_attribute(__fallthrough__)
+# define FALLTHROUGH() __attribute__((__fallthrough__))
+# endif
+#endif
+#ifndef FALLTHROUGH
+# define FALLTHROUGH() do {} while (0) /* fallthrough */
+#endif
+
#ifdef DEBUG
#include <assert.h>
#define ASSERT(X) assert(X)
@@ -234,6 +245,7 @@ static int fmt_uword(fmtfn_t fn,void* arg,int sign,ErlPfUWord uval,
break;
case FMTC_X:
dc = heX;
+ FALLTHROUGH();
case FMTC_x:
base = 16;
break;
@@ -286,6 +298,7 @@ static int fmt_long_long(fmtfn_t fn,void* arg,int sign,
break;
case FMTC_X:
dc = heX;
+ FALLTHROUGH();
case FMTC_x:
base = 16;
break;
diff --git a/erts/lib_src/common/ethr_mutex.c b/erts/lib_src/common/ethr_mutex.c
index 636adfe397..abfa659649 100644
--- a/erts/lib_src/common/ethr_mutex.c
+++ b/erts/lib_src/common/ethr_mutex.c
@@ -2657,6 +2657,7 @@ ethr_rwmutex_init_opt(ethr_rwmutex *rwmtx, ethr_rwmutex_opt *opt)
rwmtx->type = ETHR_RWMUTEX_TYPE_EXTREMELY_FREQUENT_READ;
}
/* Fall through */
+ ETHR_FALLTHROUGH();
case ETHR_RWMUTEX_TYPE_EXTREMELY_FREQUENT_READ: {
int length;
@@ -2688,6 +2689,7 @@ ethr_rwmutex_init_opt(ethr_rwmutex *rwmtx, ethr_rwmutex_opt *opt)
break;
}
}
+ ETHR_FALLTHROUGH();
case ETHR_RWMUTEX_TYPE_NORMAL:
rwmtx->tdata.rs = 0;
break;
diff --git a/lib/erl_interface/src/misc/ei_format.c b/lib/erl_interface/src/misc/ei_format.c
index 6ae5521357..74846cb50e 100644
--- a/lib/erl_interface/src/misc/ei_format.c
+++ b/lib/erl_interface/src/misc/ei_format.c
@@ -116,6 +116,7 @@ static int eiformat(const char** fmt, union arg** args, ei_x_buff* x)
ei_x_free(&x2);
break;
}
+ EI_FALLTHROUGH();
default:
if (isdigit((int)*p))
res = pdigit(&p, x);
diff --git a/lib/erl_interface/src/misc/eidef.h b/lib/erl_interface/src/misc/eidef.h
index 01479887c8..09d8c8c261 100644
--- a/lib/erl_interface/src/misc/eidef.h
+++ b/lib/erl_interface/src/misc/eidef.h
@@ -58,6 +58,16 @@ typedef int socklen_t;
# define HAVE_ISFINITE
#endif
+/* Taken from https://best.openssf.org/Compiler-Hardening-Guides/Compiler-Options-Hardening-Guide-for-C-and-C++.html#warn-about-implicit-fallthrough-in-switch-statements */
+#ifdef __has_attribute
+# if __has_attribute(__fallthrough__)
+# define EI_FALLTHROUGH() __attribute__((__fallthrough__))
+# endif
+#endif
+#ifndef EI_FALLTHROUGH
+# define EI_FALLTHROUGH() do {} while (0) /* fallthrough */
+#endif
+
typedef unsigned char uint8; /* FIXME use configure */
typedef unsigned short uint16;
typedef unsigned int uint32;
diff --git a/lib/erl_interface/src/misc/get_type.c b/lib/erl_interface/src/misc/get_type.c
index d76119ca62..8ff42fd9d5 100644
--- a/lib/erl_interface/src/misc/get_type.c
+++ b/lib/erl_interface/src/misc/get_type.c
@@ -38,12 +38,14 @@ int ei_get_type(const char *buf, const int *index, int *type, int *len)
case ERL_SMALL_ATOM_EXT:
case ERL_SMALL_ATOM_UTF8_EXT:
*type = ERL_ATOM_EXT;
+ EI_FALLTHROUGH();
case ERL_SMALL_TUPLE_EXT:
*len = get8(s);
break;
case ERL_ATOM_UTF8_EXT:
*type = ERL_ATOM_EXT;
+ EI_FALLTHROUGH();
case ERL_ATOM_EXT:
case ERL_STRING_EXT:
*len = get16be(s);
diff --git a/lib/erl_interface/src/prog/erl_call.c b/lib/erl_interface/src/prog/erl_call.c
index 74750d78de..bcbe11f8d9 100644
--- a/lib/erl_interface/src/prog/erl_call.c
+++ b/lib/erl_interface/src/prog/erl_call.c
@@ -78,6 +78,27 @@
#include <fcntl.h>
#include <signal.h>
+/* In VC++, noreturn is a declspec that has to be before the types,
+ * but in GNUC it is an attribute to be placed between return type
+ * and function name, hence __decl_noreturn <types> __noreturn <function name>
+ *
+ * at some platforms (e.g. Android) __noreturn is defined at sys/cdef.h
+ */
+#if __GNUC__
+# define __decl_noreturn
+# ifndef __noreturn
+# define __noreturn __attribute__((noreturn))
+# endif
+#else
+# if defined(__WIN32__) && defined(_MSC_VER)
+# define __noreturn
+# define __decl_noreturn __declspec(noreturn)
+# else
+# define __noreturn
+# define __decl_noreturn
+# endif
+#endif
+
#include "ei.h"
#include "ei_resolve.h"
@@ -125,9 +146,9 @@ struct call_flags {
/* start an erlang system */
int erl_start_sys(ei_cnode *ec, char *alive, Erl_IpAddr addr, int flags,
char *erl, char *add_args[]);
-static void usage_arg(const char *progname, const char *switchname);
-static void usage_error(const char *progname, const char *switchname);
-static void usage(const char *progname);
+__decl_noreturn static void __noreturn usage_arg(const char *progname, const char *switchname);
+__decl_noreturn static void __noreturn usage_error(const char *progname, const char *switchname);
+__decl_noreturn static void __noreturn usage(const char *progname);
static int get_module(char **mbuf, char **mname);
static int do_connect(ei_cnode *ec, char *nodename, struct call_flags *flags);
static int read_stdin(char **buf);
@@ -140,7 +161,9 @@ static char* ei_chk_strdup(char *s);
static int rpc_print_node_stdout(ei_cnode* ec, int fd, char *mod,
char *fun, const char* inbuf,
int inbuflen, ei_x_buff* x);
-static void exit_free_flags_fields(int exit_status, struct call_flags* flags);
+__decl_noreturn static void __noreturn exit_free_flags_fields(
+ int exit_status,
+ struct call_flags* flags);
/* Converts the given hostname to a shortname, if required. */
static void format_node_hostname(const struct call_flags *flags,
@@ -1032,19 +1055,19 @@ static void usage_noexit(const char *progname) {
fprintf(stderr," -x use specified erl start script, default is erl\n");
}
-static void usage_arg(const char *progname, const char *switchname) {
+__decl_noreturn static void __noreturn usage_arg(const char *progname, const char *switchname) {
fprintf(stderr, "Missing argument(s) for \'%s\'.\n", switchname);
usage_noexit(progname);
exit(1);
}
-static void usage_error(const char *progname, const char *switchname) {
+__decl_noreturn static void __noreturn usage_error(const char *progname, const char *switchname) {
fprintf(stderr, "Illegal argument \'%s\'.\n", switchname);
usage_noexit(progname);
exit(1);
}
-static void usage(const char *progname) {
+void __noreturn usage(const char *progname) {
usage_noexit(progname);
exit(0);
}
@@ -1181,7 +1204,8 @@ ebadmsg:
}
-void exit_free_flags_fields(int exit_status, struct call_flags* flags) {
+__decl_noreturn static void __noreturn
+exit_free_flags_fields(int exit_status, struct call_flags* flags) {
if (flags->script != NULL) {
free(flags->script);
}
--
2.43.0