summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVictor Stinner <vstinner@python.org>2024-04-30 20:29:48 (GMT)
committerGitHub <noreply@github.com>2024-04-30 20:29:48 (GMT)
commit587388ff22dc7cfa4b66722daf0d33cd804af9f2 (patch)
tree1d52a2c1368208c8c8d548ccf183c056135860b5
parent6999d68d2878871493d85dc63599f3d44eada104 (diff)
downloadcpython-587388ff22dc7cfa4b66722daf0d33cd804af9f2.zip
cpython-587388ff22dc7cfa4b66722daf0d33cd804af9f2.tar.gz
cpython-587388ff22dc7cfa4b66722daf0d33cd804af9f2.tar.bz2
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.
-rw-r--r--Include/pymacro.h49
-rw-r--r--Lib/test/test_cext/extension.c5
-rw-r--r--Lib/test/test_cppext/extension.cpp4
-rw-r--r--Misc/NEWS.d/next/C API/2024-04-29-17-44-15.gh-issue-118124.czQQ9G.rst3
4 files changed, 45 insertions, 16 deletions
diff --git a/Include/pymacro.h b/Include/pymacro.h
index cd6fc4e..b388c2a 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 662abd4..eb23dbe 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 a569c22..ab485b6 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 0000000..3deeb51
--- /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.