-
Notifications
You must be signed in to change notification settings - Fork 380
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Add VARRAY_FOREACH and VPTRS_ITER macros to iterate over arrays and pointer arrays #4239
base: master
Are you sure you want to change the base?
Conversation
This macro is intended to simplify loops over elements of an array using pointer arithmetic instead of an array index. The usual pattern of iterating over the array index and then accessing the i-th element of the array is replaced with calculating the end pointer and looping over the array elements. The macro basically implements for (pointer = array, end = array + length; pointer < end; pointer++) This pattern is more efficient but less clear to read when written out. The macro is similar to the *_FOREACH pattern which we already use in many other places with trees, lists and queues, but declares the loop variable locally. Remarks on the implementation: - typeof() is now formalized with C23 but has been a GNU extension for long. We use typeof() since e1ac593 as of March 2021. - The construct 'typeof(*(arr)) * var' (using the element type declaring a pointer on it) is used to un-const arr while keeping the constness of the element type: If arr is const, '(typeof arr) var = arr' does not work because var can not be modified. The additional (typeof(var)) cast is to avoid a Flexelint warning (reference to pointer).
The coccinelle patch only catches some cases, makes spatch enter a spinloop and the patch result needs manual polish on top, but at this point the purpose is only to show use cases for the new macro.
Based on VARRAY_FOREACH, this additional macro further simplifies the case of arrays of pointer as, for example, used in struct strands. Here, the loop variable is to be declared outside the macro to support keeping found elements from within the loop.
we add a semantic patch to turn VARRAY_FOREACH cases into VPTRS_ITER cases where applicable.
Bugwash: Overall not sure if this is a net positive (I share this sentiment), but there might be potential with regards to bounds checking.
|
So I pondered the question of better bounds checking and could no come up with anything interesting. An argument could be made that, when iterating with a pointer, out of bounds access might be more obvious than through an array index. struct varray {
unsigned magic;
unsigned length;
TYPE array[] __attribute__((counted_by(length)));
} this could be used for strands and possibly other cases, but it would not be embedable in structs and we would need to take care of the flexarray sizeof issue... |
bugwash discussed, not currently actionable |
These patches add two macros, semantic patches to start using them and the respective changes:
The
VARRAY_FOREACH
macro is intended to simplify loops over elements of an array using pointer arithmetic instead of an array index.The usual pattern of iterating over the array index and then accessing the i-th element of the array is replaced with calculating the end pointer and looping over the array elements.
The macro basically implements
This pattern is more efficient but less clear to read when written out. The macro is similar to the
*_FOREACH
pattern which we already use in many other places with trees, lists and queues, but declares the loop variable locally.The second macro
VPTRS_ITER
further simplifies our "array of pointers" case as, for example, used in struct strands.Here, the loop variable is to be declared outside the macro to support keeping found elements from within the loop.