Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions Doc/c-api/intro.rst
Original file line number Diff line number Diff line change
Expand Up @@ -227,6 +227,10 @@ The following macros are for common tasks not specific to Python.
Use this for unused arguments in a function definition to silence compiler
warnings. Example: ``int func(int a, int Py_UNUSED(b)) { return a; }``.

The macro mangles *name* so that it cannot be used, and when possible,
applies the C23/C++17 attribute ``[[maybe_unused]]`` or a compiler-specific
equivalent.

.. versionadded:: 3.4

.. c:macro:: Py_GCC_ATTRIBUTE(name)
Expand Down
4 changes: 3 additions & 1 deletion Include/pymacro.h
Original file line number Diff line number Diff line change
Expand Up @@ -254,7 +254,9 @@
*
* int func(int a, int Py_UNUSED(b)) { return a; }
*/
#if defined(__GNUC__) || defined(__clang__)
#if _Py__has_c_cpp_attribute(maybe_unused)
# define Py_UNUSED(name) _unused_ ## name _Py_C_ATTRIBUTE(maybe_unused)
#elif defined(__GNUC__) || defined(__clang__)
# define Py_UNUSED(name) _unused_ ## name __attribute__((unused))
#elif defined(_MSC_VER)
// Disable warning C4100: unreferenced formal parameter,
Expand Down
46 changes: 46 additions & 0 deletions Include/pyport.h
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,52 @@
# define _Py__has_attribute(x) 0
#endif

// Same check for C23 [[attribute]].
#ifdef __has_c_attribute
# define _Py__has_c_attribute(X) __has_c_attribute(X)
#else
# define _Py__has_c_attribute(X) 0
#endif

// Same check for C++17 [[attribute]].
#if defined(__cpp_attributes) && defined(__has_cpp_attribute)
# define _Py__has_cpp_attribute(X) __has_cpp_attribute(X)
#else
# define _Py__has_cpp_attribute(X) 0
#endif

// Combined check for C & C++ [[attribute]]. Only use if attribute works
// the same way in both languages.
#ifdef __cplusplus
# define _Py__has_c_cpp_attribute(X) _Py__has_cpp_attribute(X)
#else
# define _Py__has_c_cpp_attribute(X) _Py__has_c_attribute(X)
#endif

// _Py_C_ATTRIBUTE(attribute): wrapper for [[attribute]]
#if defined(__GNUC__) && !defined(__clang__) && defined(__STDC_VERSION__) && __STDC_VERSION__ < 202311L
// In GCC pedantic mode before C23, `__has_c_attribute` is defined but using
// C attributes emits warnings. Suppress them.
# define _Py_C_ATTRIBUTE(ATTR) [[__extension__ ATTR]]
#elif defined(__clang__) && defined(__STDC_VERSION__) && __STDC_VERSION__ < 202311L
// Similar for clang and C23. It's not clear how to suppress this,
// so pretend the feature is missing.
# undef _Py__has_cpp_attribute
# undef _Py__has_c_cpp_attribute
# define _Py__has_cpp_attribute(X) 0
# define _Py__has_c_cpp_attribute(X) 0
# define _Py_C_ATTRIBUTE(ATTR)
#elif defined(__clang__) && defined(__cplusplus) && __cplusplus < 201703L
// Same for clang and C++17.
# undef _Py__has_c_attribute
# undef _Py__has_c_cpp_attribute
# define _Py__has_c_attribute(X) 0
# define _Py__has_c_cpp_attribute(X) 0
# define _Py_C_ATTRIBUTE(ATTR)
#else
# define _Py_C_ATTRIBUTE(ATTR) [[ATTR]]
#endif

// Macro to use C++ static_cast<> in the Python C API.
#ifdef __cplusplus
# define _Py_STATIC_CAST(type, expr) static_cast<type>(expr)
Expand Down
Loading