https://github.com/python/cpython/commit/ce1a877a3882acf50f1162e4a823ce0abf2d8525
commit: ce1a877a3882acf50f1162e4a823ce0abf2d8525
branch: main
author: Petr Viktorin <[email protected]>
committer: encukou <[email protected]>
date: 2025-08-26T11:14:35+02:00
summary:

gh-138143: Allow anonymous unions in public headers, using `_Py_ANONYMOUS` 
(GH-137283)

We already use an anonymous union for PyObject. This makes the workarounds 
available in all public headers:

- MSVC: `__pragma(warning(disable: 4201))` (with push/pop). Warning 4201 is 
specifically for anonymous unions, so let's disable for all of `<Python.h>`
- GCC/clang, pedantic old C standards: define `_Py_ANONYMOUS` as `__extension__`
- otherwise, define `_Py_ANONYMOUS` as nothing 

(Note that this is only for public headers -- CPython internals use C11, which 
has anonymous structs/unions.)

C API WG vote: https://github.com/capi-workgroup/decisions/issues/74

files:
M Include/Python.h
M Include/object.h
M Include/pymacro.h

diff --git a/Include/Python.h b/Include/Python.h
index b6ee500aada791..261b4d316bdf85 100644
--- a/Include/Python.h
+++ b/Include/Python.h
@@ -60,6 +60,15 @@
 #  endif
 #endif // Py_GIL_DISABLED
 
+#ifdef _MSC_VER
+// Ignore MSC warning C4201: "nonstandard extension used: nameless
+// struct/union".  (Only generated for C standard versions less than C11, which
+// we don't *officially* support.)
+__pragma(warning(push))
+__pragma(warning(disable: 4201))
+#endif
+
+
 // Include Python header files
 #include "pyport.h"
 #include "pymacro.h"
@@ -139,4 +148,8 @@
 #include "cpython/pyfpe.h"
 #include "cpython/tracemalloc.h"
 
+#ifdef _MSC_VER
+__pragma(warning(pop))  // warning(disable: 4201)
+#endif
+
 #endif /* !Py_PYTHON_H */
diff --git a/Include/object.h b/Include/object.h
index 8979ac7dd095a4..064904b733d192 100644
--- a/Include/object.h
+++ b/Include/object.h
@@ -123,18 +123,7 @@ whose size is determined when the object is allocated.
   /* PyObject is opaque */
 #elif !defined(Py_GIL_DISABLED)
 struct _object {
-#if (defined(__GNUC__) || defined(__clang__)) \
-        && !(defined __STDC_VERSION__ && __STDC_VERSION__ >= 201112L)
-    // On C99 and older, anonymous union is a GCC and clang extension
-    __extension__
-#endif
-#ifdef _MSC_VER
-    // Ignore MSC warning C4201: "nonstandard extension used:
-    // nameless struct/union"
-    __pragma(warning(push))
-    __pragma(warning(disable: 4201))
-#endif
-    union {
+    _Py_ANONYMOUS union {
 #if SIZEOF_VOID_P > 4
         PY_INT64_T ob_refcnt_full; /* This field is needed for efficient 
initialization with Clang on ARM */
         struct {
@@ -153,9 +142,6 @@ struct _object {
 #endif
         _Py_ALIGNED_DEF(_PyObject_MIN_ALIGNMENT, char) _aligner;
     };
-#ifdef _MSC_VER
-    __pragma(warning(pop))
-#endif
 
     PyTypeObject *ob_type;
 };
diff --git a/Include/pymacro.h b/Include/pymacro.h
index b2886ddac5d17e..857cdf12db9bf2 100644
--- a/Include/pymacro.h
+++ b/Include/pymacro.h
@@ -86,6 +86,28 @@
 #    endif
 #endif
 
+
+// _Py_ANONYMOUS: modifier for declaring an anonymous union.
+// Usage: _Py_ANONYMOUS union { ... };
+// Standards/compiler support:
+// - C++ allows anonymous unions, but not structs
+// - C11 and above allows anonymous unions and structs
+// - MSVC has warning(disable: 4201) "nonstandard extension used : nameless
+//   struct/union". This is specific enough that we disable it for all of
+//   Python.h.
+// - GCC & clang needs __extension__ before C11
+// To allow unsupported platforms which need other spellings, we use a
+// predefined value of _Py_ANONYMOUS if it exists.
+#ifndef _Py_ANONYMOUS
+#   if (defined(__GNUC__) || defined(__clang__)) \
+          && !(defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L)
+#       define _Py_ANONYMOUS __extension__
+#   else
+#       define _Py_ANONYMOUS
+#   endif
+#endif
+
+
 /* Minimum value between x and y */
 #define Py_MIN(x, y) (((x) > (y)) ? (y) : (x))
 

_______________________________________________
Python-checkins mailing list -- [email protected]
To unsubscribe send an email to [email protected]
https://mail.python.org/mailman3//lists/python-checkins.python.org
Member address: [email protected]

Reply via email to