Skip to content

Commit 0deef4f

Browse files
vstinnersobolevn
authored andcommitted
pythongh-121040: Use __attribute__((fallthrough)) (python#121044)
Fix warnings when using -Wimplicit-fallthrough compiler flag. Annotate explicitly "fall through" switch cases with a new _Py_FALLTHROUGH macro which uses __attribute__((fallthrough)) if available. Replace "fall through" comments with _Py_FALLTHROUGH. Add _Py__has_attribute() macro. No longer define __has_attribute() macro if it's not defined. Move also _Py__has_builtin() at the top of pyport.h. Co-Authored-By: Nikita Sobolev <[email protected]>
1 parent 772ab16 commit 0deef4f

29 files changed

+131
-104
lines changed

Include/exports.h

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -41,11 +41,8 @@
4141
* we may still need to support gcc >= 4, as some Ubuntu LTS and Centos versions
4242
* have 4 < gcc < 5.
4343
*/
44-
#ifndef __has_attribute
45-
#define __has_attribute(x) 0 // Compatibility with non-clang compilers.
46-
#endif
4744
#if (defined(__GNUC__) && (__GNUC__ >= 4)) ||\
48-
(defined(__clang__) && __has_attribute(visibility))
45+
(defined(__clang__) && _Py__has_attribute(visibility))
4946
#define Py_IMPORTED_SYMBOL __attribute__ ((visibility ("default")))
5047
#define Py_EXPORTED_SYMBOL __attribute__ ((visibility ("default")))
5148
#define Py_LOCAL_SYMBOL __attribute__ ((visibility ("hidden")))

Include/pyport.h

Lines changed: 35 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,24 @@
99
#endif
1010

1111

12+
// Preprocessor check for a builtin preprocessor function. Always return 0
13+
// if __has_builtin() macro is not defined.
14+
//
15+
// __has_builtin() is available on clang and GCC 10.
16+
#ifdef __has_builtin
17+
# define _Py__has_builtin(x) __has_builtin(x)
18+
#else
19+
# define _Py__has_builtin(x) 0
20+
#endif
21+
22+
// Preprocessor check for a compiler __attribute__. Always return 0
23+
// if __has_attribute() macro is not defined.
24+
#ifdef __has_attribute
25+
# define _Py__has_attribute(x) __has_attribute(x)
26+
#else
27+
# define _Py__has_attribute(x) 0
28+
#endif
29+
1230
// Macro to use C++ static_cast<> in the Python C API.
1331
#ifdef __cplusplus
1432
# define _Py_STATIC_CAST(type, expr) static_cast<type>(expr)
@@ -532,16 +550,6 @@ extern "C" {
532550
#endif
533551

534552

535-
// Preprocessor check for a builtin preprocessor function. Always return 0
536-
// if __has_builtin() macro is not defined.
537-
//
538-
// __has_builtin() is available on clang and GCC 10.
539-
#ifdef __has_builtin
540-
# define _Py__has_builtin(x) __has_builtin(x)
541-
#else
542-
# define _Py__has_builtin(x) 0
543-
#endif
544-
545553
// _Py_TYPEOF(expr) gets the type of an expression.
546554
//
547555
// Example: _Py_TYPEOF(x) x_copy = (x);
@@ -607,4 +615,21 @@ extern "C" {
607615
# define _SGI_MP_SOURCE
608616
#endif
609617

618+
// Explicit fallthrough in switch case to avoid warnings
619+
// with compiler flag -Wimplicit-fallthrough.
620+
//
621+
// Usage example:
622+
//
623+
// switch (value) {
624+
// case 1: _Py_FALLTHROUGH;
625+
// case 2: code; break;
626+
// }
627+
//
628+
// __attribute__((fallthrough)) was introduced in GCC 7.
629+
#if _Py__has_attribute(fallthrough)
630+
# define _Py_FALLTHROUGH __attribute__((fallthrough))
631+
#else
632+
# define _Py_FALLTHROUGH do { } while (0)
633+
#endif
634+
610635
#endif /* Py_PYPORT_H */

Modules/_csv.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -731,7 +731,7 @@ parse_process_char(ReaderObj *self, _csvstate *module_state, Py_UCS4 c)
731731
}
732732
/* normal character - handle as START_FIELD */
733733
self->state = START_FIELD;
734-
/* fallthru */
734+
_Py_FALLTHROUGH;
735735
case START_FIELD:
736736
/* expecting field */
737737
self->unquoted_field = true;
@@ -785,7 +785,7 @@ parse_process_char(ReaderObj *self, _csvstate *module_state, Py_UCS4 c)
785785
case AFTER_ESCAPED_CRNL:
786786
if (c == EOL)
787787
break;
788-
/*fallthru*/
788+
_Py_FALLTHROUGH;
789789

790790
case IN_FIELD:
791791
/* in unquoted field */

Modules/_ctypes/_ctypes.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4074,7 +4074,7 @@ _build_callargs(ctypes_state *st, PyCFuncPtrObject *self, PyObject *argtypes,
40744074
case (PARAMFLAG_FIN | PARAMFLAG_FOUT):
40754075
*pinoutmask |= (1 << i); /* mark as inout arg */
40764076
(*pnumretvals)++;
4077-
/* fall through */
4077+
_Py_FALLTHROUGH;
40784078
case 0:
40794079
case PARAMFLAG_FIN:
40804080
/* 'in' parameter. Copy it from inargs. */

Modules/_ctypes/stgdict.c

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -485,10 +485,11 @@ PyCStructUnionType_update_stginfo(PyObject *type, PyObject *fields, int isStruct
485485
case FFI_TYPE_SINT16:
486486
case FFI_TYPE_SINT32:
487487
if (info->getfunc != _ctypes_get_fielddesc("c")->getfunc
488-
&& info->getfunc != _ctypes_get_fielddesc("u")->getfunc
489-
)
488+
&& info->getfunc != _ctypes_get_fielddesc("u")->getfunc)
489+
{
490490
break;
491-
/* else fall through */
491+
}
492+
_Py_FALLTHROUGH; /* else fall through */
492493
default:
493494
PyErr_Format(PyExc_TypeError,
494495
"bit fields not allowed for type %s",

Modules/_interpqueuesmodule.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -363,7 +363,7 @@ handle_queue_error(int err, PyObject *mod, int64_t qid)
363363

364364
module_state *state;
365365
switch (err) {
366-
case ERR_QUEUE_ALLOC: // fall through
366+
case ERR_QUEUE_ALLOC: _Py_FALLTHROUGH;
367367
case ERR_QUEUES_ALLOC:
368368
PyErr_NoMemory();
369369
break;

Modules/_ssl.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3472,8 +3472,8 @@ set_min_max_proto_version(PySSLContext *self, PyObject *arg, int what)
34723472
}
34733473

34743474
switch(self->protocol) {
3475-
case PY_SSL_VERSION_TLS_CLIENT: /* fall through */
3476-
case PY_SSL_VERSION_TLS_SERVER: /* fall through */
3475+
case PY_SSL_VERSION_TLS_CLIENT: _Py_FALLTHROUGH;
3476+
case PY_SSL_VERSION_TLS_SERVER: _Py_FALLTHROUGH;
34773477
case PY_SSL_VERSION_TLS:
34783478
break;
34793479
default:

Modules/_struct.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1373,7 +1373,7 @@ whichtable(const char **pfmt)
13731373
}
13741374
default:
13751375
--*pfmt; /* Back out of pointer increment */
1376-
/* Fall through */
1376+
_Py_FALLTHROUGH;
13771377
case '@':
13781378
return native_table;
13791379
}
@@ -1475,7 +1475,7 @@ prepare_s(PyStructObject *self)
14751475
return -1;
14761476

14771477
switch (c) {
1478-
case 's': /* fall through */
1478+
case 's': _Py_FALLTHROUGH;
14791479
case 'p': len++; ncodes++; break;
14801480
case 'x': break;
14811481
default: len += num; if (num) ncodes++; break;

Modules/_testcapi/exceptions.c

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,11 +34,11 @@ err_restore(PyObject *self, PyObject *args) {
3434
case 3:
3535
traceback = PyTuple_GetItem(args, 2);
3636
Py_INCREF(traceback);
37-
/* fall through */
37+
_Py_FALLTHROUGH;
3838
case 2:
3939
value = PyTuple_GetItem(args, 1);
4040
Py_INCREF(value);
41-
/* fall through */
41+
_Py_FALLTHROUGH;
4242
case 1:
4343
type = PyTuple_GetItem(args, 0);
4444
Py_INCREF(type);

Modules/cjkcodecs/_codecs_iso2022.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -806,7 +806,7 @@ jisx0213_encoder(const MultibyteCodec *codec, const Py_UCS4 *data,
806806
jisx0213_pair_encmap, JISX0213_ENCPAIRS);
807807
if (coded != DBCINV)
808808
return coded;
809-
/* fall through */
809+
_Py_FALLTHROUGH;
810810

811811
case -1: /* flush unterminated */
812812
*length = 1;

0 commit comments

Comments
 (0)