Skip to content

Commit

Permalink
pythongh-121040: Use __attribute__((fallthrough))
Browse files Browse the repository at this point in the history
Annotate explicitly "fall through" switch cases with a new
_Py_FALLTHROUGH macro which uses __attribute__((fallthrough)) if
available.

Fix warnings when using -Wimplicit-fallthrough compiler flag.
  • Loading branch information
vstinner committed Jun 26, 2024
1 parent 9e4a81f commit bb2eb56
Show file tree
Hide file tree
Showing 27 changed files with 108 additions and 88 deletions.
15 changes: 15 additions & 0 deletions Include/pyport.h
Original file line number Diff line number Diff line change
Expand Up @@ -607,4 +607,19 @@ extern "C" {
# define _SGI_MP_SOURCE
#endif

// Explicit fallthrough in switch case.
// Example:
//
// switch(value)
// case 1: _Py_FALLTHROUGH;
// case 2: code; break;
// }
//
// __attribute__((fallthrough)) was introduced in GCC 7.
#if defined(__has_attribute) && __has_attribute(fallthrough)
# define _Py_FALLTHROUGH __attribute__((fallthrough))
#else
# define _Py_FALLTHROUGH do { } while (0)
#endif

#endif /* Py_PYPORT_H */
4 changes: 2 additions & 2 deletions Modules/_csv.c
Original file line number Diff line number Diff line change
Expand Up @@ -731,7 +731,7 @@ parse_process_char(ReaderObj *self, _csvstate *module_state, Py_UCS4 c)
}
/* normal character - handle as START_FIELD */
self->state = START_FIELD;
/* fallthru */
_Py_FALLTHROUGH;
case START_FIELD:
/* expecting field */
self->unquoted_field = true;
Expand Down Expand Up @@ -785,7 +785,7 @@ parse_process_char(ReaderObj *self, _csvstate *module_state, Py_UCS4 c)
case AFTER_ESCAPED_CRNL:
if (c == EOL)
break;
/*fallthru*/
_Py_FALLTHROUGH;

case IN_FIELD:
/* in unquoted field */
Expand Down
2 changes: 1 addition & 1 deletion Modules/_ctypes/_ctypes.c
Original file line number Diff line number Diff line change
Expand Up @@ -4074,7 +4074,7 @@ _build_callargs(ctypes_state *st, PyCFuncPtrObject *self, PyObject *argtypes,
case (PARAMFLAG_FIN | PARAMFLAG_FOUT):
*pinoutmask |= (1 << i); /* mark as inout arg */
(*pnumretvals)++;
/* fall through */
_Py_FALLTHROUGH;
case 0:
case PARAMFLAG_FIN:
/* 'in' parameter. Copy it from inargs. */
Expand Down
7 changes: 4 additions & 3 deletions Modules/_ctypes/stgdict.c
Original file line number Diff line number Diff line change
Expand Up @@ -485,10 +485,11 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct
case FFI_TYPE_SINT16:
case FFI_TYPE_SINT32:
if (info->getfunc != _ctypes_get_fielddesc("c")->getfunc
&& info->getfunc != _ctypes_get_fielddesc("u")->getfunc
)
&& info->getfunc != _ctypes_get_fielddesc("u")->getfunc)
{
break;
/* else fall through */
}
_Py_FALLTHROUGH; /* else fall through */
default:
PyErr_Format(PyExc_TypeError,
"bit fields not allowed for type %s",
Expand Down
2 changes: 1 addition & 1 deletion Modules/_interpqueuesmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -363,7 +363,7 @@ handle_queue_error(int err, PyObject *mod, int64_t qid)

module_state *state;
switch (err) {
case ERR_QUEUE_ALLOC: // fall through
case ERR_QUEUE_ALLOC: _Py_FALLTHROUGH;
case ERR_QUEUES_ALLOC:
PyErr_NoMemory();
break;
Expand Down
4 changes: 2 additions & 2 deletions Modules/_ssl.c
Original file line number Diff line number Diff line change
Expand Up @@ -3472,8 +3472,8 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what)
}

switch(self->protocol) {
case PY_SSL_VERSION_TLS_CLIENT: /* fall through */
case PY_SSL_VERSION_TLS_SERVER: /* fall through */
case PY_SSL_VERSION_TLS_CLIENT: _Py_FALLTHROUGH;
case PY_SSL_VERSION_TLS_SERVER: _Py_FALLTHROUGH;
case PY_SSL_VERSION_TLS:
break;
default:
Expand Down
4 changes: 2 additions & 2 deletions Modules/_struct.c
Original file line number Diff line number Diff line change
Expand Up @@ -1373,7 +1373,7 @@ whichtable(const char **pfmt)
}
default:
--*pfmt; /* Back out of pointer increment */
/* Fall through */
_Py_FALLTHROUGH;
case '@':
return native_table;
}
Expand Down Expand Up @@ -1475,7 +1475,7 @@ prepare_s(PyStructObject *self)
return -1;

switch (c) {
case 's': /* fall through */
case 's': _Py_FALLTHROUGH;
case 'p': len++; ncodes++; break;
case 'x': break;
default: len += num; if (num) ncodes++; break;
Expand Down
4 changes: 2 additions & 2 deletions Modules/_testcapi/exceptions.c
Original file line number Diff line number Diff line change
Expand Up @@ -34,11 +34,11 @@ err_restore(PyObject *self, PyObject *args) {
case 3:
traceback = PyTuple_GetItem(args, 2);
Py_INCREF(traceback);
/* fall through */
_Py_FALLTHROUGH;
case 2:
value = PyTuple_GetItem(args, 1);
Py_INCREF(value);
/* fall through */
_Py_FALLTHROUGH;
case 1:
type = PyTuple_GetItem(args, 0);
Py_INCREF(type);
Expand Down
2 changes: 1 addition & 1 deletion Modules/cjkcodecs/_codecs_iso2022.c
Original file line number Diff line number Diff line change
Expand Up @@ -806,7 +806,7 @@ jisx0213_encoder(const MultibyteCodec *codec, const Py_UCS4 *data,
jisx0213_pair_encmap, JISX0213_ENCPAIRS);
if (coded != DBCINV)
return coded;
/* fall through */
_Py_FALLTHROUGH;

case -1: /* flush unterminated */
*length = 1;
Expand Down
2 changes: 1 addition & 1 deletion Modules/overlapped.c
Original file line number Diff line number Diff line change
Expand Up @@ -923,7 +923,7 @@ _overlapped_Overlapped_getresult_impl(OverlappedObject *self, BOOL wait)
{
break;
}
/* fall through */
_Py_FALLTHROUGH;
default:
return SetFromWindowsErr(err);
}
Expand Down
11 changes: 7 additions & 4 deletions Modules/socketmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -1887,12 +1887,14 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,

#ifdef AF_RDS
case AF_RDS:
/* RDS sockets use sockaddr_in: fall-through */
/* RDS sockets use sockaddr_in */
_Py_FALLTHROUGH;
#endif /* AF_RDS */

#ifdef AF_DIVERT
case AF_DIVERT:
/* FreeBSD divert(4) sockets use sockaddr_in: fall-through */
/* FreeBSD divert(4) sockets use sockaddr_in */
_Py_FALLTHROUGH;
#endif /* AF_DIVERT */

case AF_INET:
Expand Down Expand Up @@ -2214,7 +2216,7 @@ getsockaddrarg(PySocketSockObject *s, PyObject *args,
switch (s->sock_proto) {
#ifdef CAN_RAW
case CAN_RAW:
/* fall-through */
_Py_FALLTHROUGH;
#endif
#ifdef CAN_BCM
case CAN_BCM:
Expand Down Expand Up @@ -2590,7 +2592,8 @@ getsockaddrlen(PySocketSockObject *s, socklen_t *len_ret)

#ifdef AF_RDS
case AF_RDS:
/* RDS sockets use sockaddr_in: fall-through */
/* RDS sockets use sockaddr_in */
_Py_FALLTHROUGH;
#endif /* AF_RDS */

case AF_INET:
Expand Down
16 changes: 8 additions & 8 deletions Modules/zlibmodule.c
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,8 @@ zlib_decompress_impl(PyObject *module, Py_buffer *data, int wbits,
Py_END_ALLOW_THREADS

switch (err) {
case Z_OK: /* fall through */
case Z_BUF_ERROR: /* fall through */
case Z_OK: _Py_FALLTHROUGH;
case Z_BUF_ERROR: _Py_FALLTHROUGH;
case Z_STREAM_END:
break;
case Z_MEM_ERROR:
Expand Down Expand Up @@ -915,8 +915,8 @@ zlib_Decompress_decompress_impl(compobject *self, PyTypeObject *cls,
Py_END_ALLOW_THREADS

switch (err) {
case Z_OK: /* fall through */
case Z_BUF_ERROR: /* fall through */
case Z_OK: _Py_FALLTHROUGH;
case Z_BUF_ERROR: _Py_FALLTHROUGH;
case Z_STREAM_END:
break;
default:
Expand Down Expand Up @@ -1293,8 +1293,8 @@ zlib_Decompress_flush_impl(compobject *self, PyTypeObject *cls,
Py_END_ALLOW_THREADS

switch (err) {
case Z_OK: /* fall through */
case Z_BUF_ERROR: /* fall through */
case Z_OK: _Py_FALLTHROUGH;
case Z_BUF_ERROR: _Py_FALLTHROUGH;
case Z_STREAM_END:
break;
default:
Expand Down Expand Up @@ -1495,8 +1495,8 @@ decompress_buf(ZlibDecompressor *self, Py_ssize_t max_length)
err = inflate(&self->zst, Z_SYNC_FLUSH);
Py_END_ALLOW_THREADS
switch (err) {
case Z_OK: /* fall through */
case Z_BUF_ERROR: /* fall through */
case Z_OK: _Py_FALLTHROUGH;
case Z_BUF_ERROR: _Py_FALLTHROUGH;
case Z_STREAM_END:
break;
default:
Expand Down
2 changes: 1 addition & 1 deletion Objects/rangeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -83,7 +83,7 @@ range_from_array(PyTypeObject *type, PyObject *const *args, Py_ssize_t num_args)
switch (num_args) {
case 3:
step = args[2];
/* fallthrough */
_Py_FALLTHROUGH;
case 2:
/* Convert borrowed refs to owned refs */
start = PyNumber_Index(args[0]);
Expand Down
4 changes: 2 additions & 2 deletions Objects/stringlib/codecs.h
Original file line number Diff line number Diff line change
Expand Up @@ -331,7 +331,7 @@ STRINGLIB(utf8_encoder)(_PyBytesWriter *writer,
case _Py_ERROR_REPLACE:
memset(p, '?', endpos - startpos);
p += (endpos - startpos);
/* fall through */
_Py_FALLTHROUGH;
case _Py_ERROR_IGNORE:
i += (endpos - startpos - 1);
break;
Expand Down Expand Up @@ -379,7 +379,7 @@ STRINGLIB(utf8_encoder)(_PyBytesWriter *writer,
}
startpos = k;
assert(startpos < endpos);
/* fall through */
_Py_FALLTHROUGH;
default:
rep = unicode_encode_call_errorhandler(
errors, &error_handler_obj, "utf-8", "surrogates not allowed",
Expand Down
10 changes: 5 additions & 5 deletions Objects/unicodeobject.c
Original file line number Diff line number Diff line change
Expand Up @@ -5073,7 +5073,7 @@ unicode_decode_utf8_impl(_PyUnicodeWriter *writer,
/* Truncated surrogate code in range D800-DFFF */
goto End;
}
/* fall through */
_Py_FALLTHROUGH;
case 3:
case 4:
errmsg = "invalid continuation byte";
Expand Down Expand Up @@ -7108,7 +7108,7 @@ unicode_encode_ucs1(PyObject *unicode,
case _Py_ERROR_REPLACE:
memset(str, '?', collend - collstart);
str += (collend - collstart);
/* fall through */
_Py_FALLTHROUGH;
case _Py_ERROR_IGNORE:
pos = collend;
break;
Expand Down Expand Up @@ -7147,7 +7147,7 @@ unicode_encode_ucs1(PyObject *unicode,
break;
collstart = pos;
assert(collstart != collend);
/* fall through */
_Py_FALLTHROUGH;

default:
rep = unicode_encode_call_errorhandler(errors, &error_handler_obj,
Expand Down Expand Up @@ -8699,7 +8699,7 @@ charmap_encoding_error(
return -1;
}
}
/* fall through */
_Py_FALLTHROUGH;
case _Py_ERROR_IGNORE:
*inpos = collendpos;
break;
Expand Down Expand Up @@ -15673,7 +15673,7 @@ _PyUnicode_ClearInterned(PyInterpreterState *interp)
#endif
break;
case SSTATE_NOT_INTERNED:
/* fall through */
_Py_FALLTHROUGH;
default:
Py_UNREACHABLE();
}
Expand Down
6 changes: 3 additions & 3 deletions Python/assemble.c
Original file line number Diff line number Diff line change
Expand Up @@ -369,17 +369,17 @@ write_instr(_Py_CODEUNIT *codestr, instruction *instr, int ilen)
codestr->op.code = EXTENDED_ARG;
codestr->op.arg = (oparg >> 24) & 0xFF;
codestr++;
/* fall through */
_Py_FALLTHROUGH;
case 3:
codestr->op.code = EXTENDED_ARG;
codestr->op.arg = (oparg >> 16) & 0xFF;
codestr++;
/* fall through */
_Py_FALLTHROUGH;
case 2:
codestr->op.code = EXTENDED_ARG;
codestr->op.arg = (oparg >> 8) & 0xFF;
codestr++;
/* fall through */
_Py_FALLTHROUGH;
case 1:
codestr->op.code = opcode;
codestr->op.arg = oparg & 0xFF;
Expand Down
4 changes: 2 additions & 2 deletions Python/bytecodes.c
Original file line number Diff line number Diff line change
Expand Up @@ -794,10 +794,10 @@ dummy_func(
switch (oparg) {
case 2:
cause = args[1];
/* fall through */
_Py_FALLTHROUGH;
case 1:
exc = args[0];
/* fall through */
_Py_FALLTHROUGH;
case 0:
if (do_raise(tstate, exc, cause)) {
assert(oparg == 0);
Expand Down
4 changes: 2 additions & 2 deletions Python/compile.c
Original file line number Diff line number Diff line change
Expand Up @@ -4681,7 +4681,7 @@ check_subscripter(struct compiler *c, expr_ty e)
{
return SUCCESS;
}
/* fall through */
_Py_FALLTHROUGH;
case Set_kind:
case SetComp_kind:
case GeneratorExp_kind:
Expand Down Expand Up @@ -4714,7 +4714,7 @@ check_index(struct compiler *c, expr_ty e, expr_ty s)
if (!(PyUnicode_Check(v) || PyBytes_Check(v) || PyTuple_Check(v))) {
return SUCCESS;
}
/* fall through */
_Py_FALLTHROUGH;
case Tuple_kind:
case List_kind:
case ListComp_kind:
Expand Down
2 changes: 1 addition & 1 deletion Python/crossinterp.c
Original file line number Diff line number Diff line change
Expand Up @@ -969,7 +969,7 @@ _PyXI_ApplyErrorCode(_PyXI_errcode code, PyInterpreterState *interp)
{
assert(!PyErr_Occurred());
switch (code) {
case _PyXI_ERR_NO_ERROR: // fall through
case _PyXI_ERR_NO_ERROR: _Py_FALLTHROUGH;
case _PyXI_ERR_UNCAUGHT_EXCEPTION:
// There is nothing to apply.
#ifdef Py_DEBUG
Expand Down
8 changes: 4 additions & 4 deletions Python/dtoa.c
Original file line number Diff line number Diff line change
Expand Up @@ -1405,7 +1405,7 @@ _Py_dg_strtod(const char *s00, char **se)
switch (c) {
case '-':
sign = 1;
/* fall through */
_Py_FALLTHROUGH;
case '+':
c = *++s;
}
Expand Down Expand Up @@ -1474,7 +1474,7 @@ _Py_dg_strtod(const char *s00, char **se)
switch (c) {
case '-':
esign = 1;
/* fall through */
_Py_FALLTHROUGH;
case '+':
c = *++s;
}
Expand Down Expand Up @@ -2362,15 +2362,15 @@ _Py_dg_dtoa(double dd, int mode, int ndigits,
break;
case 2:
leftright = 0;
/* fall through */
_Py_FALLTHROUGH;
case 4:
if (ndigits <= 0)
ndigits = 1;
ilim = ilim1 = i = ndigits;
break;
case 3:
leftright = 0;
/* fall through */
_Py_FALLTHROUGH;
case 5:
i = ndigits + k + 1;
ilim = i;
Expand Down
2 changes: 1 addition & 1 deletion Python/formatter_unicode.c
Original file line number Diff line number Diff line change
Expand Up @@ -320,7 +320,7 @@ parse_internal_render_format_spec(PyObject *obj,
format->thousands_separators = LT_UNDER_FOUR_LOCALE;
break;
}
/* fall through */
_Py_FALLTHROUGH;
default:
invalid_thousands_separator_type(format->thousands_separators, format->type);
return 0;
Expand Down
2 changes: 1 addition & 1 deletion Python/getargs.c
Original file line number Diff line number Diff line change
Expand Up @@ -2676,7 +2676,7 @@ skipitem(const char **p_format, va_list *p_va, int flags)
goto err;
format++;
}
/* fall through */
_Py_FALLTHROUGH;

case 's': /* string */
case 'z': /* string or None */
Expand Down
Loading

0 comments on commit bb2eb56

Please sign in to comment.