diff options
author | Victor Stinner <vstinner@python.org> | 2024-04-30 20:29:48 (GMT) |
---|---|---|
committer | GitHub <noreply@github.com> | 2024-04-30 20:29:48 (GMT) |
commit | 587388ff22dc7cfa4b66722daf0d33cd804af9f2 (patch) | |
tree | 1d52a2c1368208c8c8d548ccf183c056135860b5 | |
parent | 6999d68d2878871493d85dc63599f3d44eada104 (diff) | |
download | cpython-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.h | 49 | ||||
-rw-r--r-- | Lib/test/test_cext/extension.c | 5 | ||||
-rw-r--r-- | Lib/test/test_cppext/extension.cpp | 4 | ||||
-rw-r--r-- | Misc/NEWS.d/next/C API/2024-04-29-17-44-15.gh-issue-118124.czQQ9G.rst | 3 |
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. |