diff --git a/Include/cpython/object.h b/Include/cpython/object.h index e2f87524c218b6..c3c772feb5c0ad 100644 --- a/Include/cpython/object.h +++ b/Include/cpython/object.h @@ -380,55 +380,6 @@ PyAPI_FUNC(PyObject *) _PyObject_FunctionStr(PyObject *); #endif -/* Define a pair of assertion macros: - _PyObject_ASSERT_FROM(), _PyObject_ASSERT_WITH_MSG() and _PyObject_ASSERT(). - - These work like the regular C assert(), in that they will abort the - process with a message on stderr if the given condition fails to hold, - but compile away to nothing if NDEBUG is defined. - - However, before aborting, Python will also try to call _PyObject_Dump() on - the given object. This may be of use when investigating bugs in which a - particular object is corrupt (e.g. buggy a tp_visit method in an extension - module breaking the garbage collector), to help locate the broken objects. - - The WITH_MSG variant allows you to supply an additional message that Python - will attempt to print to stderr, after the object dump. */ -#ifdef NDEBUG - /* No debugging: compile away the assertions: */ -# define _PyObject_ASSERT_FROM(obj, expr, msg, filename, lineno, func) \ - ((void)0) -#else - /* With debugging: generate checks: */ -# define _PyObject_ASSERT_FROM(obj, expr, msg, filename, lineno, func) \ - ((expr) \ - ? (void)(0) \ - : _PyObject_AssertFailed((obj), Py_STRINGIFY(expr), \ - (msg), (filename), (lineno), (func))) -#endif - -#define _PyObject_ASSERT_WITH_MSG(obj, expr, msg) \ - _PyObject_ASSERT_FROM((obj), expr, (msg), __FILE__, __LINE__, __func__) -#define _PyObject_ASSERT(obj, expr) \ - _PyObject_ASSERT_WITH_MSG((obj), expr, NULL) - -#define _PyObject_ASSERT_FAILED_MSG(obj, msg) \ - _PyObject_AssertFailed((obj), NULL, (msg), __FILE__, __LINE__, __func__) - -/* Declare and define _PyObject_AssertFailed() even when NDEBUG is defined, - to avoid causing compiler/linker errors when building extensions without - NDEBUG against a Python built with NDEBUG defined. - - msg, expr and function can be NULL. */ -PyAPI_FUNC(void) _Py_NO_RETURN _PyObject_AssertFailed( - PyObject *obj, - const char *expr, - const char *msg, - const char *file, - int line, - const char *function); - - PyAPI_FUNC(void) _PyTrash_thread_deposit_object(PyThreadState *tstate, PyObject *op); PyAPI_FUNC(void) _PyTrash_thread_destroy_chain(PyThreadState *tstate); diff --git a/Include/internal/pycore_gc.h b/Include/internal/pycore_gc.h index a6519aa086309d..8de8344637a1c6 100644 --- a/Include/internal/pycore_gc.h +++ b/Include/internal/pycore_gc.h @@ -11,6 +11,7 @@ extern "C" { #include "pycore_interp_structs.h" // PyGC_Head #include "pycore_pystate.h" // _PyInterpreterState_GET() #include "pycore_typedefs.h" // _PyInterpreterFrame +#include "pycore_utils.h" // _PyObject_ASSERT_FROM() /* Get an object's GC head */ diff --git a/Include/internal/pycore_utils.h b/Include/internal/pycore_utils.h new file mode 100644 index 00000000000000..3b12d26b20ca80 --- /dev/null +++ b/Include/internal/pycore_utils.h @@ -0,0 +1,62 @@ +#ifndef Py_INTERNAL_UTILS_H +#define Py_INTERNAL_UTILS_H +#ifdef __cplusplus +extern "C" { +#endif + +#ifndef Py_BUILD_CORE +# error "this header requires Py_BUILD_CORE define" +#endif + +/* Define a pair of assertion macros: + * _PyObject_ASSERT_FROM(), _PyObject_ASSERT_WITH_MSG() and _PyObject_ASSERT(). + * + * These work like the regular C assert(), in that they will abort the + * process with a message on stderr if the given condition fails to hold, + * but compile away to nothing if NDEBUG is defined. + * + * However, before aborting, Python will also try to call _PyObject_Dump() on + * the given object. This may be of use when investigating bugs in which a + * particular object is corrupt (e.g. buggy a tp_visit method in an extension + * module breaking the garbage collector), to help locate the broken objects. + * + * The WITH_MSG variant allows you to supply an additional message that Python + * will attempt to print to stderr, after the object dump. */ +#ifdef NDEBUG + /* No debugging: compile away the assertions: */ +# define _PyObject_ASSERT_FROM(obj, expr, msg, filename, lineno, func) \ + ((void)0) +#else + /* With debugging: generate checks: */ +# define _PyObject_ASSERT_FROM(obj, expr, msg, filename, lineno, func) \ + ((expr) \ + ? (void)(0) \ + : _PyObject_AssertFailed((obj), Py_STRINGIFY(expr), \ + (msg), (filename), (lineno), (func))) +#endif + +#define _PyObject_ASSERT_WITH_MSG(obj, expr, msg) \ + _PyObject_ASSERT_FROM((obj), expr, (msg), __FILE__, __LINE__, __func__) +#define _PyObject_ASSERT(obj, expr) \ + _PyObject_ASSERT_WITH_MSG((obj), expr, NULL) + +#define _PyObject_ASSERT_FAILED_MSG(obj, msg) \ + _PyObject_AssertFailed((obj), NULL, (msg), __FILE__, __LINE__, __func__) + +/* Declare and define _PyObject_AssertFailed() even when NDEBUG is defined, + to avoid causing compiler/linker errors when building extensions without + NDEBUG against a Python built with NDEBUG defined. + + msg, expr and function can be NULL. */ +PyAPI_FUNC(void) _Py_NO_RETURN _PyObject_AssertFailed( + PyObject *obj, + const char *expr, + const char *msg, + const char *file, + int line, + const char *function); + +#ifdef __cplusplus +} +#endif +#endif /* !Py_INTERNAL_UTILS_H */ diff --git a/Makefile.pre.in b/Makefile.pre.in index a5223246845dcf..0d93e8903bf9a2 100644 --- a/Makefile.pre.in +++ b/Makefile.pre.in @@ -1439,6 +1439,7 @@ PYTHON_HEADERS= \ $(srcdir)/Include/internal/pycore_uop.h \ $(srcdir)/Include/internal/pycore_uop_ids.h \ $(srcdir)/Include/internal/pycore_uop_metadata.h \ + $(srcdir)/Include/internal/pycore_utils.h \ $(srcdir)/Include/internal/pycore_warnings.h \ $(srcdir)/Include/internal/pycore_weakref.h \ $(DTRACE_HEADERS) \ diff --git a/PCbuild/pythoncore.vcxproj b/PCbuild/pythoncore.vcxproj index e2e1e415827e6f..f1ff3de3383e36 100644 --- a/PCbuild/pythoncore.vcxproj +++ b/PCbuild/pythoncore.vcxproj @@ -331,6 +331,7 @@ + diff --git a/PCbuild/pythoncore.vcxproj.filters b/PCbuild/pythoncore.vcxproj.filters index 7e7ed9c2ae6c43..6ac35c01b08fa6 100644 --- a/PCbuild/pythoncore.vcxproj.filters +++ b/PCbuild/pythoncore.vcxproj.filters @@ -534,6 +534,9 @@ Include\internal + + Include\internal + Include\internal