Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 19 additions & 15 deletions Include/pymacro.h
Original file line number Diff line number Diff line change
Expand Up @@ -174,23 +174,27 @@
} while(0)
#endif

/* Get the number of elements in a visible array

This does not work on pointers, or arrays declared as [], or function
parameters. With correct compiler support, such usage will cause a build
error (see Py_BUILD_ASSERT_EXPR).

Written by Rusty Russell, public domain, http://ccodearchive.net/

Requires at GCC 3.1+ */
#if (defined(__GNUC__) && !defined(__STRICT_ANSI__) && \
(((__GNUC__ == 3) && (__GNUC_MINOR__ >= 1)) || (__GNUC__ >= 4)))
/* Two gcc extensions.
&a[0] degrades to a pointer: a different type from an array */
// Get the number of elements in a visible array.
//
// This does not work on pointers, or arrays declared as [], or function
// parameters. With correct compiler support, such usage will cause a build
// error (see Py_BUILD_ASSERT_EXPR).
//
// Written by Rusty Russell, public domain, http://ccodearchive.net/
//
// Require GCC 4 (it works on GCC 3.1).
//
// Two GCC extensions: &a[0] degrades to a pointer, a different type from an
// array.
//
// gh-158810: Do not use __builtin_types_compatible_p() in strict C ANSI mode
// and on C++.
#if (defined(__GNUC__) && __GNUC__ >= 4 && defined(_Py_TYPEOF) \
&& !defined(__STRICT_ANSI__) && !defined(__cplusplus))
#define Py_ARRAY_LENGTH(array) \
(sizeof(array) / sizeof((array)[0]) \
+ Py_BUILD_ASSERT_EXPR(!__builtin_types_compatible_p(typeof(array), \
typeof(&(array)[0]))))
+ Py_BUILD_ASSERT_EXPR(!__builtin_types_compatible_p(_Py_TYPEOF(array), \
_Py_TYPEOF(&(array)[0]))))
#else
#define Py_ARRAY_LENGTH(array) \
(sizeof(array) / sizeof((array)[0]))
Expand Down
22 changes: 21 additions & 1 deletion Lib/test/test_cext/extension.c
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,8 @@ static PyObject *
test_macros(PyObject *Py_UNUSED(module), PyObject *Py_UNUSED(args))
{
PyObject *obj, *dict;
PyObject *slots[1];
int small_array[] = {2, 5, 7};

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

// gh-157649: Test Py_CLEAR() on an array
slots[0] = Py_None;
Py_CLEAR(slots[0]);
assert(slots[0] == _Py_NULL);

#ifndef Py_LIMITED_API
// Test Py_SETREF(): use typeof()/__typeof__() if available, or memcpy()
obj = Py_None;
Py_SETREF(obj, _Py_NULL);
assert(obj == _Py_NULL);

// gh-157649: Test Py_SETREF() on an array
slots[0] = Py_None;
Py_SETREF(slots[0], _Py_NULL);
assert(slots[0] == _Py_NULL);

// Test Py_XSETREF(): use typeof()/__typeof__() if available, or memcpy()
obj = Py_None;
Py_XSETREF(obj, _Py_NULL);
assert(obj == _Py_NULL);
#endif

// gh-157649: Test Py_XSETREF() on an array
slots[0] = Py_None;
Py_XSETREF(slots[0], _Py_NULL);
assert(slots[0] == _Py_NULL);
#endif // !Py_LIMITED_API

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

// Test Py_ARRAY_LENGTH()
assert(Py_ARRAY_LENGTH(small_array) == 3);

Py_RETURN_NONE;
}

Expand Down
2 changes: 1 addition & 1 deletion Lib/test/test_cext/setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -155,7 +155,7 @@ def main():
# option emits a C++ compiler warning. Remove "-std11" option from the
# CC command.
cmd = (sysconfig.get_config_var('CC') or '')
if cmd is not None:
if cmd is not None and 'CC' not in os.environ:
if support.MS_WINDOWS:
std_prefix = '/std'
else:
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
Fix :c:macro:`Py_ARRAY_LENGTH()` macro on C++: do not use
``__builtin_types_compatible_p()`` on C++. Patch by Victor Stinner.
Loading