include/nuttx/macro.h: Add FOREACH_IDX_ARG() and fix REVERSE_ARG() - #20015
Open
JorgeGzm wants to merge 1 commit into
Open
include/nuttx/macro.h: Add FOREACH_IDX_ARG() and fix REVERSE_ARG()#20015JorgeGzm wants to merge 1 commit into
JorgeGzm wants to merge 1 commit into
Conversation
JorgeGzm
force-pushed
the
macro_foreach_idx
branch
from
August 31, 2026 01:45
dc86bd2 to
f32afdb
Compare
JorgeGzm
force-pushed
the
macro_foreach_idx
branch
from
August 31, 2026 01:51
f32afdb to
dc86bd2
Compare
JorgeGzm
force-pushed
the
macro_foreach_idx
branch
from
August 31, 2026 03:15
dc86bd2 to
658f693
Compare
FOREACH_ARG() handed the position of each argument as the expression "count - N", which can be used as a value but cannot be pasted into an identifier. Hand it out as a literal instead, so that an action macro can build a symbol name out of it, which is what a subsystem needs when the link order of its objects has to follow the declaration order. The per arity chain the expression form required is dropped and the one reached through REVERSE_ARG() is kept, so the file carries a single foreach engine. Reversing the list is what makes the position a literal, and each step emits the recursion before its own action, so the actions still come out in the order the arguments were given. This is how the same problem is solved upstream in Zephyr, whose FOR_EACH() family also reverses the list before walking a per arity chain. The index values are unchanged, so the arithmetic use keeps working: NOTE_PRINTF_TYPES(), the only user in tree, produces the same tags. It now supplies the leading zero itself, because FOREACH_ARG() no longer expands to "0" when the list is empty. Counting the arguments after they are expanded also fixes the empty list: a macro that expands to nothing used to produce one action on an empty argument, and now produces none. REVERSE_ARG() had a "##" right after the opening parenthesis and failed to expand whenever it was given arguments. It is used now. Assisted-by: Claude Code Signed-off-by: Jorge Guzman <jorge.gzm@gmail.com>
JorgeGzm
force-pushed
the
macro_foreach_idx
branch
from
August 31, 2026 21:04
658f693 to
4670bb5
Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
FOREACH_ARG()hands the action the position of the argument as anexpression (
count - N), which cannot be pasted into an identifier. Thisadds a companion that passes it as a two digit literal (
00,01, ...),so the position can become part of a symbol name and, through
SORT_BY_NAME(), part of the order the linker gives to the objects asubsystem registers with the link time iterable sections.
The dispatch uses
CONCATENATE()andGET_ARG_COUNT(), each arity emitsits own literal, and the list is reversed first with
REVERSE_ARG(), sono increment tables are needed. An empty list expands to nothing.
Using
REVERSE_ARG()required fixing it first:REVERSE_ARG()expanded toREVERSE_ARG_(##__VA_ARGS__). The tokenbefore the
##is an opening parenthesis, not a comma, so the GNUextension that swallows an empty variable argument list does not apply:
the preprocessor pastes
(with the first argument and the build failswith
The macro therefore only ever worked with an empty argument list, which
is why the problem went unnoticed since the file was added in
3271142. Dropping the
##makes the arguments expand; the empty caseis unaffected.
And fix
REVERSE_ARG(), which it needsImpact
Nothing existing is affected.
FOREACH_IDX_ARG()is entirely new, andREVERSE_ARG()has no user in either repository: with arguments it didnot compile, so no code could depend on it, and with an empty list it
expands exactly as before. No macro already in the header changes
behaviour.
The documentation of the iterable sections already said that an instance
may encode its order in its name but not how; it now points at the new
macro (four lines in
Documentation/components/iterable_sections.rst).The first user of the new macro is the zbus port
(apache/nuttx-apps#3743), which names one object per channel/observer
pair after the position of the observer in the channel definition.
Testing
Host: Ubuntu 24.04.4 x86_64, arm-none-eabi-gcc 13.2.1.
Expansion checked for 0, 1, 3, 8 and 32 arguments with
and the 32 argument case yields
[a1:00] ... [d8:31]. Without theREVERSE_ARG()fix the same expansions fail with the pasting errorquoted above.
Built and run on linum-stm32h753bi together with apache/nuttx-apps#3743:
the observations of every channel come out of the linker grouped per
channel and ordered by the position in the definition, and the zbus test
suite passes 17/17 twice in the same boot, including a test that asserts
the notification order.
tools/checkpatch.sh -c -u -m -gon the commit: all checks pass, andsphinx-build -Wbuilds the documentation clean.