https://github.com/python/cpython/commit/587388ff22dc7cfa4b66722daf0d33cd804af9f2
commit: 587388ff22dc7cfa4b66722daf0d33cd804af9f2
branch: main
author: Victor Stinner <[email protected]>
committer: vstinner <[email protected]>
date: 2024-04-30T22:29:48+02:00
summary:

gh-118124: Use static_assert() in Py_BUILD_ASSERT() on C11 (#118398)

Use static_assert() in Py_BUILD_ASSERT() and Py_BUILD_ASSERT_EXPR()
on C11 and newer and C++11 and newer.

Add tests to test_cext and test_cppext.

files:
A Misc/NEWS.d/next/C API/2024-04-29-17-44-15.gh-issue-118124.czQQ9G.rst
M Include/pymacro.h
M Lib/test/test_cext/extension.c
M Lib/test/test_cppext/extension.cpp

diff --git a/Include/pymacro.h b/Include/pymacro.h
index cd6fc4eba9c2ed..b388c2a4a663ce 100644
--- a/Include/pymacro.h
+++ b/Include/pymacro.h
@@ -46,24 +46,41 @@
 /* Argument must be a char or an int in [-128, 127] or [0, 255]. */
 #define Py_CHARMASK(c) ((unsigned char)((c) & 0xff))
 
-/* Assert a build-time dependency, as an expression.
-
-   Your compile will fail if the condition isn't true, or can't be evaluated
-   by the compiler. This can be used in an expression: its value is 0.
-
-   Example:
-
-   #define foo_to_char(foo)  \
-       ((char *)(foo)        \
-        + Py_BUILD_ASSERT_EXPR(offsetof(struct foo, string) == 0))
-
-   Written by Rusty Russell, public domain, http://ccodearchive.net/ */
-#define Py_BUILD_ASSERT_EXPR(cond) \
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
+#  define Py_BUILD_ASSERT_EXPR(cond) \
+    ((void)sizeof(struct { int dummy; _Static_assert(cond, #cond); }), \
+     0)
+#else
+   /* Assert a build-time dependency, as an expression.
+    *
+    * Your compile will fail if the condition isn't true, or can't be evaluated
+    * by the compiler. This can be used in an expression: its value is 0.
+    *
+    * Example:
+    *
+    * #define foo_to_char(foo)  \
+    *     ((char *)(foo)        \
+    *      + Py_BUILD_ASSERT_EXPR(offsetof(struct foo, string) == 0))
+    *
+    * Written by Rusty Russell, public domain, http://ccodearchive.net/
+    */
+#  define Py_BUILD_ASSERT_EXPR(cond) \
     (sizeof(char [1 - 2*!(cond)]) - 1)
+#endif
 
-#define Py_BUILD_ASSERT(cond)  do {         \
-        (void)Py_BUILD_ASSERT_EXPR(cond);   \
-    } while(0)
+#if ((defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L) \
+     || (defined(__cplusplus) && __cplusplus >= 201103L))
+   // Use static_assert() on C11 and newer
+#  define Py_BUILD_ASSERT(cond) \
+        do { \
+            static_assert((cond), #cond); \
+        } while (0)
+#else
+#  define Py_BUILD_ASSERT(cond)  \
+        do { \
+            (void)Py_BUILD_ASSERT_EXPR(cond); \
+        } while(0)
+#endif
 
 /* Get the number of elements in a visible array
 
diff --git a/Lib/test/test_cext/extension.c b/Lib/test/test_cext/extension.c
index 662abd4005e8d2..eb23dbe20353ba 100644
--- a/Lib/test/test_cext/extension.c
+++ b/Lib/test/test_cext/extension.c
@@ -44,6 +44,11 @@ _testcext_exec(PyObject *module)
         return -1;
     }
 #endif
+
+    // test Py_BUILD_ASSERT() and Py_BUILD_ASSERT_EXPR()
+    Py_BUILD_ASSERT(sizeof(int) == sizeof(unsigned int));
+    assert(Py_BUILD_ASSERT_EXPR(sizeof(int) == sizeof(unsigned int)) == 0);
+
     return 0;
 }
 
diff --git a/Lib/test/test_cppext/extension.cpp 
b/Lib/test/test_cppext/extension.cpp
index a569c2251d1ad7..ab485b629b7788 100644
--- a/Lib/test/test_cppext/extension.cpp
+++ b/Lib/test/test_cppext/extension.cpp
@@ -225,6 +225,10 @@ _testcppext_exec(PyObject *module)
     if (!result) return -1;
     Py_DECREF(result);
 
+    // test Py_BUILD_ASSERT() and Py_BUILD_ASSERT_EXPR()
+    Py_BUILD_ASSERT(sizeof(int) == sizeof(unsigned int));
+    assert(Py_BUILD_ASSERT_EXPR(sizeof(int) == sizeof(unsigned int)) == 0);
+
     return 0;
 }
 
diff --git a/Misc/NEWS.d/next/C 
API/2024-04-29-17-44-15.gh-issue-118124.czQQ9G.rst b/Misc/NEWS.d/next/C 
API/2024-04-29-17-44-15.gh-issue-118124.czQQ9G.rst
new file mode 100644
index 00000000000000..3deeb517eb9fce
--- /dev/null
+++ b/Misc/NEWS.d/next/C API/2024-04-29-17-44-15.gh-issue-118124.czQQ9G.rst     
@@ -0,0 +1,3 @@
+Fix :c:macro:`Py_BUILD_ASSERT` and :c:macro:`Py_BUILD_ASSERT_EXPR` for
+non-constant expressions: use ``static_assert()`` on C11 and newer.
+Patch by Victor Stinner.

_______________________________________________
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