gh-158942: Use more unique variable names in Py_MIN/MAX/ABS() (#158969)

If Py_MIN/MAX/ABS() macros are called on an existing "_x" or "_y"
variable name, the external variable is used instead of macro local
variable. So use more unique names in the macros to avoid
the issue.

Add test_min_max_abs_macros() to _testlimitedcapi.
diff --git a/Include/pymacro.h b/Include/pymacro.h
index 122d263..41dfd91 100644
--- a/Include/pymacro.h
+++ b/Include/pymacro.h
@@ -118,20 +118,20 @@
    /* Minimum value between x and y */
 #  define Py_MIN(x, y) \
        __extension__ \
-       ({ _Py_TYPEOF (x) _x = (x); \
-          _Py_TYPEOF (y) _y = (y); \
-          _x < _y ? _x : _y; })
+       ({ _Py_TYPEOF (x) _PyMIN_x = (x); \
+          _Py_TYPEOF (y) _PyMIN_y = (y); \
+          _PyMIN_x < _PyMIN_y ? _PyMIN_x : _PyMIN_y; })
    /* Maximum value between x and y */
 #  define Py_MAX(x, y) \
        __extension__ \
-       ({ _Py_TYPEOF (x) _x = (x); \
-          _Py_TYPEOF (y) _y = (y); \
-          _x > _y ? _x : _y; })
+       ({ _Py_TYPEOF (x) _PyMAX_x = (x); \
+          _Py_TYPEOF (y) _PyMAX_y = (y); \
+          _PyMAX_x > _PyMAX_y ? _PyMAX_x : _PyMAX_y; })
    /* Absolute value of the number x */
 #  define Py_ABS(x) \
        __extension__ \
-       ({ _Py_TYPEOF (x) _x = (x); \
-          _x < 0 ? -_x : _x; })
+       ({ _Py_TYPEOF (x) _PyABS_x = (x); \
+          _PyABS_x < 0 ? -_PyABS_x : _PyABS_x; })
 #else
    /* Minimum value between x and y */
 #  define Py_MIN(x, y) (((x) > (y)) ? (y) : (x))
diff --git a/Modules/_testlimitedcapi/object.c b/Modules/_testlimitedcapi/object.c
index 03debb5..5eee2a9 100644
--- a/Modules/_testlimitedcapi/object.c
+++ b/Modules/_testlimitedcapi/object.c
@@ -241,6 +241,63 @@ test_refcount_macros(PyObject *self, PyObject *Py_UNUSED(ignored))
     TEST_REFCOUNT();
 }
 
+
+// Test Py_MIN(), Py_MAX() and Py_ABS() macros.
+// On GCC/clang, they are implemented as a statement expression to only
+// evaluate each argument only once.
+static PyObject*
+test_min_max_abs_macros(PyObject *self, PyObject *Py_UNUSED(ignored))
+{
+    int x = 5, y = 7, z = -11;
+
+    // Simple usage
+    assert(Py_MIN(x, y) == 5);
+    assert(Py_MAX(x, y) == 7);
+    assert(Py_ABS(z) == 11);
+
+    // Combined macros
+    assert(Py_MIN(x, Py_MIN(y, z)) == -11);
+    assert(Py_MAX(x, Py_MAX(y, z)) == 7);
+    assert(Py_MIN(x, Py_MAX(y, z)) == 5);
+    assert(Py_MAX(x, Py_MIN(y, z)) == 5);
+    assert(Py_ABS(Py_ABS(z)) == 11);
+
+    // A few more tests
+    assert(Py_MIN(2, Py_MIN(6, 12)) == 2);
+    assert(Py_MAX(2, Py_MAX(6, 12)) == 12);
+    assert(Py_MIN(2, Py_MAX(6, 12)) == 2);
+    assert(Py_MAX(2, Py_MIN(6, 12)) == 6);
+    assert(Py_MIN(Py_MIN(2, 6), 12) == 2);
+    assert(Py_MAX(Py_MAX(2, 6), 12) == 12);
+    assert(Py_MIN(Py_MAX(2, 6), 12) == 6);
+    assert(Py_MAX(Py_MIN(2, 6), 12) == 12);
+    assert(Py_ABS(Py_ABS(12)) == 12);
+    assert(Py_ABS(Py_ABS(12)) == 12);
+
+    // Integer limits
+    assert(Py_MIN(123, INT_MIN) == INT_MIN);
+    assert(Py_MAX(123, INT_MAX) == INT_MAX);
+    assert(Py_ABS(INT_MAX) == INT_MAX);
+    // Do not tests Py_ABS(INT_MIN), since the behavior is documented.
+    // This limitation is documented in Py_ABS() documentation.
+
+#if ((defined(__GNUC__) || defined(__clang__)) \
+     && defined(_Py_TYPEOF) && !defined(__cplusplus))
+    // Check that arguments are only evaluated once
+    int a = 5, b = 7, c = -11;
+    assert(Py_MIN(++a, ++b) == 6);
+    assert(a == 6);
+    assert(b == 8);
+    assert(Py_MAX(++a, ++b) == 9);
+    assert(a == 7);
+    assert(b == 9);
+    assert(Py_ABS(--c) == 12);
+    assert(c == -12);
+#endif
+
+    Py_RETURN_NONE;
+}
+
 #undef Py_NewRef
 #undef Py_XNewRef
 
@@ -315,6 +372,7 @@ static PyMethodDef test_methods[] = {
     {"test_py_setref", test_py_setref, METH_NOARGS},
     {"test_refcount_macros", test_refcount_macros, METH_NOARGS},
     {"test_refcount_funcs", test_refcount_funcs, METH_NOARGS},
+    {"test_min_max_abs_macros", test_min_max_abs_macros, METH_NOARGS},
     {"test_py_is_macros", test_py_is_macros, METH_NOARGS},
     {"test_py_is_funcs", test_py_is_funcs, METH_NOARGS},
     {NULL},