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

openSUSE Build Service is sponsored by