Skip to content

Commit 152185f

Browse files
authored
[3.15] gh-158810: Fix Py_ARRAY_LENGTH() macro on C++ (#159315)
* gh-158810: Fix Py_ARRAY_LENGTH() macro on C++ (#158812) (cherry picked from commit b2bfbce) * gh-158810: Use _Py_TYPEOF in Py_ARRAY_LENGTH() (#158838) Fix the compiler warning "extension used" when building test_cext with clang. * test_cext no longer overrides the CC environment variable if it's already defined. * test_cext now also logs __STRICT_ANSI__ macro. (cherry picked from commit 85c03d4) * Add Py_SETREF/XSETREF tests to test_cext
1 parent 8514386 commit 152185f

4 files changed

Lines changed: 43 additions & 17 deletions

File tree

‎Include/pymacro.h‎

Lines changed: 19 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -174,23 +174,27 @@
174174
} while(0)
175175
#endif
176176

177-
/* Get the number of elements in a visible array
178-
179-
This does not work on pointers, or arrays declared as [], or function
180-
parameters. With correct compiler support, such usage will cause a build
181-
error (see Py_BUILD_ASSERT_EXPR).
182-
183-
Written by Rusty Russell, public domain, http://ccodearchive.net/
184-
185-
Requires at GCC 3.1+ */
186-
#if (defined(__GNUC__) && !defined(__STRICT_ANSI__) && \
187-
(((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ >= 4)))
188-
/* Two gcc extensions.
189-
&a[0] degrades to a pointer: a different type from an array */
177+
// Get the number of elements in a visible array.
178+
//
179+
// This does not work on pointers, or arrays declared as [], or function
180+
// parameters. With correct compiler support, such usage will cause a build
181+
// error (see Py_BUILD_ASSERT_EXPR).
182+
//
183+
// Written by Rusty Russell, public domain, http://ccodearchive.net/
184+
//
185+
// Require GCC 4 (it works on GCC 3.1).
186+
//
187+
// Two GCC extensions: &a[0] degrades to a pointer, a different type from an
188+
// array.
189+
//
190+
// gh-158810: Do not use __builtin_types_compatible_p() in strict C ANSI mode
191+
// and on C++.
192+
#if (defined(__GNUC__) && __GNUC__ >= 4 && defined(_Py_TYPEOF) \
193+
&& !defined(__STRICT_ANSI__) && !defined(__cplusplus))
190194
#define Py_ARRAY_LENGTH(array) \
191195
(sizeof(array) / sizeof((array)[0]) \
192-
+ Py_BUILD_ASSERT_EXPR(!__builtin_types_compatible_p(typeof(array), \
193-
typeof(&(array)[0]))))
196+
+ Py_BUILD_ASSERT_EXPR(!__builtin_types_compatible_p(_Py_TYPEOF(array), \
197+
_Py_TYPEOF(&(array)[0]))))
194198
#else
195199
#define Py_ARRAY_LENGTH(array) \
196200
(sizeof(array) / sizeof((array)[0]))

‎Lib/test/test_cext/extension.c‎

Lines changed: 21 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -82,6 +82,8 @@ static PyObject *
8282
test_macros(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
8383
{
8484
PyObject *obj, *dict;
85+
PyObject *slots[1];
86+
int small_array[] = {2, 5, 7};
8587

8688
// test Py_BUILD_ASSERT() and Py_BUILD_ASSERT_EXPR()
8789
Py_BUILD_ASSERT(sizeof(int) == sizeof(unsigned int));
@@ -97,17 +99,32 @@ test_macros(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
9799
Py_CLEAR(obj);
98100
assert(obj == _Py_NULL);
99101

102+
// gh-157649: Test Py_CLEAR() on an array
103+
slots[0] = Py_None;
104+
Py_CLEAR(slots[0]);
105+
assert(slots[0] == _Py_NULL);
106+
100107
#ifndef Py_LIMITED_API
101108
// Test Py_SETREF(): use typeof()/__typeof__() if available, or memcpy()
102109
obj = Py_None;
103110
Py_SETREF(obj, _Py_NULL);
104111
assert(obj == _Py_NULL);
105112

113+
// gh-157649: Test Py_SETREF() on an array
114+
slots[0] = Py_None;
115+
Py_SETREF(slots[0], _Py_NULL);
116+
assert(slots[0] == _Py_NULL);
117+
106118
// Test Py_XSETREF(): use typeof()/__typeof__() if available, or memcpy()
107119
obj = Py_None;
108120
Py_XSETREF(obj, _Py_NULL);
109121
assert(obj == _Py_NULL);
110-
#endif
122+
123+
// gh-157649: Test Py_XSETREF() on an array
124+
slots[0] = Py_None;
125+
Py_XSETREF(slots[0], _Py_NULL);
126+
assert(slots[0] == _Py_NULL);
127+
#endif // !Py_LIMITED_API
111128

112129
// Test that Py_BEGIN_CRITICAL_SECTION is available
113130
dict = PyDict_New();
@@ -118,6 +135,9 @@ test_macros(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
118135
Py_END_CRITICAL_SECTION();
119136
Py_DECREF(dict);
120137

138+
// Test Py_ARRAY_LENGTH()
139+
assert(Py_ARRAY_LENGTH(small_array) == 3);
140+
121141
Py_RETURN_NONE;
122142
}
123143

‎Lib/test/test_cext/setup.py‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ def main():
155155
# option emits a C++ compiler warning. Remove "-std11" option from the
156156
# CC command.
157157
cmd = (sysconfig.get_config_var('CC') or '')
158-
if cmd is not None:
158+
if cmd is not None and 'CC' not in os.environ:
159159
if support.MS_WINDOWS:
160160
std_prefix = '/std'
161161
else:
Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,2 @@
1+
Fix :c:macro:`Py_ARRAY_LENGTH()` macro on C++: do not use
2+
``__builtin_types_compatible_p()`` on C++. Patch by Victor Stinner.

0 commit comments

Comments
 (0)