Skip to content

Commit d1507a0

Browse files
committed
gh-53509: Move _PyObject_ASSERT() to the internal C API
Add pycore_utils.h internal header file. Move the following APIs to pycore_utils.h: * _PyObject_ASSERT() macro * _PyObject_ASSERT_FAILED_MSG() macro * _PyObject_ASSERT_FROM() macro * _PyObject_ASSERT_WITH_MSG() macro * _PyObject_AssertFailed() function
1 parent d2deb8f commit d1507a0

File tree

6 files changed

+68
-49
lines changed

6 files changed

+68
-49
lines changed

Include/cpython/object.h

Lines changed: 0 additions & 49 deletions
Original file line numberDiff line numberDiff line change
@@ -380,55 +380,6 @@ PyAPI_FUNC(PyObject *) _PyObject_FunctionStr(PyObject *);
380380
#endif
381381

382382

383-
/* Define a pair of assertion macros:
384-
_PyObject_ASSERT_FROM(), _PyObject_ASSERT_WITH_MSG() and _PyObject_ASSERT().
385-
386-
These work like the regular C assert(), in that they will abort the
387-
process with a message on stderr if the given condition fails to hold,
388-
but compile away to nothing if NDEBUG is defined.
389-
390-
However, before aborting, Python will also try to call _PyObject_Dump() on
391-
the given object. This may be of use when investigating bugs in which a
392-
particular object is corrupt (e.g. buggy a tp_visit method in an extension
393-
module breaking the garbage collector), to help locate the broken objects.
394-
395-
The WITH_MSG variant allows you to supply an additional message that Python
396-
will attempt to print to stderr, after the object dump. */
397-
#ifdef NDEBUG
398-
/* No debugging: compile away the assertions: */
399-
# define _PyObject_ASSERT_FROM(obj, expr, msg, filename, lineno, func) \
400-
((void)0)
401-
#else
402-
/* With debugging: generate checks: */
403-
# define _PyObject_ASSERT_FROM(obj, expr, msg, filename, lineno, func) \
404-
((expr) \
405-
? (void)(0) \
406-
: _PyObject_AssertFailed((obj), Py_STRINGIFY(expr), \
407-
(msg), (filename), (lineno), (func)))
408-
#endif
409-
410-
#define _PyObject_ASSERT_WITH_MSG(obj, expr, msg) \
411-
_PyObject_ASSERT_FROM((obj), expr, (msg), __FILE__, __LINE__, __func__)
412-
#define _PyObject_ASSERT(obj, expr) \
413-
_PyObject_ASSERT_WITH_MSG((obj), expr, NULL)
414-
415-
#define _PyObject_ASSERT_FAILED_MSG(obj, msg) \
416-
_PyObject_AssertFailed((obj), NULL, (msg), __FILE__, __LINE__, __func__)
417-
418-
/* Declare and define _PyObject_AssertFailed() even when NDEBUG is defined,
419-
to avoid causing compiler/linker errors when building extensions without
420-
NDEBUG against a Python built with NDEBUG defined.
421-
422-
msg, expr and function can be NULL. */
423-
PyAPI_FUNC(void) _Py_NO_RETURN _PyObject_AssertFailed(
424-
PyObject *obj,
425-
const char *expr,
426-
const char *msg,
427-
const char *file,
428-
int line,
429-
const char *function);
430-
431-
432383
PyAPI_FUNC(void) _PyTrash_thread_deposit_object(PyThreadState *tstate, PyObject *op);
433384
PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(PyThreadState *tstate);
434385

Include/internal/pycore_gc.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ extern "C" {
1111
#include "pycore_interp_structs.h" // PyGC_Head
1212
#include "pycore_pystate.h" // _PyInterpreterState_GET()
1313
#include "pycore_typedefs.h" // _PyInterpreterFrame
14+
#include "pycore_utils.h" // _PyObject_ASSERT_FROM()
1415

1516

1617
/* Get an object's GC head */

Include/internal/pycore_utils.h

Lines changed: 62 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
#ifndef Py_INTERNAL_UTILS_H
2+
#define Py_INTERNAL_UTILS_H
3+
#ifdef __cplusplus
4+
extern "C" {
5+
#endif
6+
7+
#ifndef Py_BUILD_CORE
8+
# error "this header requires Py_BUILD_CORE define"
9+
#endif
10+
11+
/* Define a pair of assertion macros:
12+
* _PyObject_ASSERT_FROM(), _PyObject_ASSERT_WITH_MSG() and _PyObject_ASSERT().
13+
*
14+
* These work like the regular C assert(), in that they will abort the
15+
* process with a message on stderr if the given condition fails to hold,
16+
* but compile away to nothing if NDEBUG is defined.
17+
*
18+
* However, before aborting, Python will also try to call _PyObject_Dump() on
19+
* the given object. This may be of use when investigating bugs in which a
20+
* particular object is corrupt (e.g. buggy a tp_visit method in an extension
21+
* module breaking the garbage collector), to help locate the broken objects.
22+
*
23+
* The WITH_MSG variant allows you to supply an additional message that Python
24+
* will attempt to print to stderr, after the object dump. */
25+
#ifdef NDEBUG
26+
/* No debugging: compile away the assertions: */
27+
# define _PyObject_ASSERT_FROM(obj, expr, msg, filename, lineno, func) \
28+
((void)0)
29+
#else
30+
/* With debugging: generate checks: */
31+
# define _PyObject_ASSERT_FROM(obj, expr, msg, filename, lineno, func) \
32+
((expr) \
33+
? (void)(0) \
34+
: _PyObject_AssertFailed((obj), Py_STRINGIFY(expr), \
35+
(msg), (filename), (lineno), (func)))
36+
#endif
37+
38+
#define _PyObject_ASSERT_WITH_MSG(obj, expr, msg) \
39+
_PyObject_ASSERT_FROM((obj), expr, (msg), __FILE__, __LINE__, __func__)
40+
#define _PyObject_ASSERT(obj, expr) \
41+
_PyObject_ASSERT_WITH_MSG((obj), expr, NULL)
42+
43+
#define _PyObject_ASSERT_FAILED_MSG(obj, msg) \
44+
_PyObject_AssertFailed((obj), NULL, (msg), __FILE__, __LINE__, __func__)
45+
46+
/* Declare and define _PyObject_AssertFailed() even when NDEBUG is defined,
47+
to avoid causing compiler/linker errors when building extensions without
48+
NDEBUG against a Python built with NDEBUG defined.
49+
50+
msg, expr and function can be NULL. */
51+
PyAPI_FUNC(void) _Py_NO_RETURN _PyObject_AssertFailed(
52+
PyObject *obj,
53+
const char *expr,
54+
const char *msg,
55+
const char *file,
56+
int line,
57+
const char *function);
58+
59+
#ifdef __cplusplus
60+
}
61+
#endif
62+
#endif /* !Py_INTERNAL_UTILS_H */

Makefile.pre.in

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1439,6 +1439,7 @@ PYTHON_HEADERS= \
14391439
$(srcdir)/Include/internal/pycore_uop.h \
14401440
$(srcdir)/Include/internal/pycore_uop_ids.h \
14411441
$(srcdir)/Include/internal/pycore_uop_metadata.h \
1442+
$(srcdir)/Include/internal/pycore_utils.h \
14421443
$(srcdir)/Include/internal/pycore_warnings.h \
14431444
$(srcdir)/Include/internal/pycore_weakref.h \
14441445
$(DTRACE_HEADERS) \

PCbuild/pythoncore.vcxproj

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -331,6 +331,7 @@
331331
<ClInclude Include="..\Include\internal\pycore_unicodeobject.h" />
332332
<ClInclude Include="..\Include\internal\pycore_unicodeobject_generated.h" />
333333
<ClInclude Include="..\Include\internal\pycore_uniqueid.h" />
334+
<ClInclude Include="..\Include\internal\pycore_utils.h" />
334335
<ClInclude Include="..\Include\internal\pycore_warnings.h" />
335336
<ClInclude Include="..\Include\internal\pycore_weakref.h" />
336337
<ClInclude Include="..\Include\intrcheck.h" />

PCbuild/pythoncore.vcxproj.filters

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -534,6 +534,9 @@
534534
<ClInclude Include="..\Include\internal\pycore_unicodeobject_generated.h">
535535
<Filter>Include\internal</Filter>
536536
</ClInclude>
537+
<ClInclude Include="..\Include\internal\pycore_utils.h">
538+
<Filter>Include\internal</Filter>
539+
</ClInclude>
537540
<ClInclude Include="..\Include\internal\pycore_warnings.h">
538541
<Filter>Include\internal</Filter>
539542
</ClInclude>

0 commit comments

Comments
 (0)