Skip to content

Commit 2a64544

Browse files
xiaoxiang781216GUIDINGLI
authored andcommitted
include/macro.h: fix REVERSE_ARG/FOREACH_ARG for empty args in C++
C++ strict mode drops the GNU ", ##__VA_ARGS__" comma elision, so GET_ARG_COUNT() and REVERSE_ARG() misselect their dispatch entry with zero varargs. Centralize the empty-argument handling in GET_ARG_COUNT (via __VA_OPT__ for C++) and make REVERSE_ARG and FOREACH_ARG dispatch through CONCATENATE(prefix, GET_ARG_COUNT(...)), removing the two duplicated 33-entry selector lists. Signed-off-by: Xiang Xiao <xiaoxiang@xiaomi.com>
1 parent f5df0fc commit 2a64544

1 file changed

Lines changed: 47 additions & 42 deletions

File tree

include/nuttx/macro.h

Lines changed: 47 additions & 42 deletions
Original file line numberDiff line numberDiff line change
@@ -41,13 +41,28 @@
4141
_24, _25, _26, _27, _28, _29, _30, _31, \
4242
_32, name, ...) name
4343

44-
/* Get the number of arguments (up to 32) */
45-
46-
#define GET_ARG_COUNT(...) \
44+
/* Get the number of arguments (up to 32)
45+
*
46+
* C++ strict mode drops the GNU ", ##__VA_ARGS__" comma elision, which
47+
* would shift the selector off by one for the zero-argument case; use the
48+
* standard __VA_OPT__ there instead. This is the only place where the
49+
* empty-argument case needs special handling: every higher-level macro
50+
* (REVERSE_ARG, FOREACH_ARG, ...) dispatches on top of GET_ARG_COUNT.
51+
*/
52+
53+
#if defined(__cplusplus)
54+
# define GET_ARG_COUNT(...) \
55+
GET_ARG_VALUE(_0 __VA_OPT__(,) __VA_ARGS__, 32, 31, 30, \
56+
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
57+
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
58+
9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
59+
#else
60+
# define GET_ARG_COUNT(...) \
4761
GET_ARG_VALUE(_0, ##__VA_ARGS__, 32, 31, 30, \
4862
29, 28, 27, 26, 25, 24, 23, 22, 21, 20, \
4963
19, 18, 17, 16, 15, 14, 13, 12, 11, 10, \
5064
9, 8, 7, 6, 5, 4, 3, 2, 1, 0)
65+
#endif
5166

5267
/* Expand the arguments */
5368

@@ -56,17 +71,17 @@
5671

5772
/* Reverse the arguments */
5873

59-
#define REVERSE_00()
60-
#define REVERSE_01(a) a
61-
#define REVERSE_02(a,b) b,a
62-
#define REVERSE_03(a,...) EXPAND(REVERSE_02(__VA_ARGS__)),a
63-
#define REVERSE_04(a,...) EXPAND(REVERSE_03(__VA_ARGS__)),a
64-
#define REVERSE_05(a,...) EXPAND(REVERSE_04(__VA_ARGS__)),a
65-
#define REVERSE_06(a,...) EXPAND(REVERSE_05(__VA_ARGS__)),a
66-
#define REVERSE_07(a,...) EXPAND(REVERSE_06(__VA_ARGS__)),a
67-
#define REVERSE_08(a,...) EXPAND(REVERSE_07(__VA_ARGS__)),a
68-
#define REVERSE_09(a,...) EXPAND(REVERSE_08(__VA_ARGS__)),a
69-
#define REVERSE_10(a,...) EXPAND(REVERSE_09(__VA_ARGS__)),a
74+
#define REVERSE_0()
75+
#define REVERSE_1(a) a
76+
#define REVERSE_2(a,b) b,a
77+
#define REVERSE_3(a,...) EXPAND(REVERSE_2(__VA_ARGS__)),a
78+
#define REVERSE_4(a,...) EXPAND(REVERSE_3(__VA_ARGS__)),a
79+
#define REVERSE_5(a,...) EXPAND(REVERSE_4(__VA_ARGS__)),a
80+
#define REVERSE_6(a,...) EXPAND(REVERSE_5(__VA_ARGS__)),a
81+
#define REVERSE_7(a,...) EXPAND(REVERSE_6(__VA_ARGS__)),a
82+
#define REVERSE_8(a,...) EXPAND(REVERSE_7(__VA_ARGS__)),a
83+
#define REVERSE_9(a,...) EXPAND(REVERSE_8(__VA_ARGS__)),a
84+
#define REVERSE_10(a,...) EXPAND(REVERSE_9(__VA_ARGS__)),a
7085
#define REVERSE_11(a,...) EXPAND(REVERSE_10(__VA_ARGS__)),a
7186
#define REVERSE_12(a,...) EXPAND(REVERSE_11(__VA_ARGS__)),a
7287
#define REVERSE_13(a,...) EXPAND(REVERSE_12(__VA_ARGS__)),a
@@ -90,30 +105,26 @@
90105
#define REVERSE_31(a,...) EXPAND(REVERSE_30(__VA_ARGS__)),a
91106
#define REVERSE_32(a,...) EXPAND(REVERSE_31(__VA_ARGS__)),a
92107

93-
#define REVERSE_ARG_(...) \
94-
GET_ARG_VALUE(0, ##__VA_ARGS__, \
95-
REVERSE_32, REVERSE_31, REVERSE_30, REVERSE_29, REVERSE_28, REVERSE_27, \
96-
REVERSE_26, REVERSE_25, REVERSE_24, REVERSE_23, REVERSE_22, REVERSE_21, \
97-
REVERSE_20, REVERSE_19, REVERSE_18, REVERSE_17, REVERSE_16, REVERSE_15, \
98-
REVERSE_14, REVERSE_13, REVERSE_12, REVERSE_11, REVERSE_10, REVERSE_09, \
99-
REVERSE_08, REVERSE_07, REVERSE_06, REVERSE_05, REVERSE_04, REVERSE_03, \
100-
REVERSE_02, REVERSE_01, REVERSE_00)(__VA_ARGS__)
108+
/* Select the worker through GET_ARG_COUNT so the zero-argument case
109+
* expands correctly in both C and C++ (see GET_ARG_COUNT).
110+
*/
101111

102-
#define REVERSE_ARG(...) REVERSE_ARG_(##__VA_ARGS__)
112+
#define REVERSE_ARG(...) \
113+
CONCATENATE(REVERSE_, GET_ARG_COUNT(__VA_ARGS__))(__VA_ARGS__)
103114

104115
/* Apply the macro to each argument */
105116

106-
#define FOREACH_00(action, count, param, ...) 0
107-
#define FOREACH_01(action, count, param, arg, ...) action(param, arg, count - 1 )
108-
#define FOREACH_02(action, count, param, arg, ...) action(param, arg, count - 2 ) FOREACH_01(action, count, param, __VA_ARGS__)
109-
#define FOREACH_03(action, count, param, arg, ...) action(param, arg, count - 3 ) FOREACH_02(action, count, param, __VA_ARGS__)
110-
#define FOREACH_04(action, count, param, arg, ...) action(param, arg, count - 4 ) FOREACH_03(action, count, param, __VA_ARGS__)
111-
#define FOREACH_05(action, count, param, arg, ...) action(param, arg, count - 5 ) FOREACH_04(action, count, param, __VA_ARGS__)
112-
#define FOREACH_06(action, count, param, arg, ...) action(param, arg, count - 6 ) FOREACH_05(action, count, param, __VA_ARGS__)
113-
#define FOREACH_07(action, count, param, arg, ...) action(param, arg, count - 7 ) FOREACH_06(action, count, param, __VA_ARGS__)
114-
#define FOREACH_08(action, count, param, arg, ...) action(param, arg, count - 8 ) FOREACH_07(action, count, param, __VA_ARGS__)
115-
#define FOREACH_09(action, count, param, arg, ...) action(param, arg, count - 9 ) FOREACH_08(action, count, param, __VA_ARGS__)
116-
#define FOREACH_10(action, count, param, arg, ...) action(param, arg, count - 10) FOREACH_09(action, count, param, __VA_ARGS__)
117+
#define FOREACH_0(action, count, param, ...) 0
118+
#define FOREACH_1(action, count, param, arg, ...) action(param, arg, count - 1 )
119+
#define FOREACH_2(action, count, param, arg, ...) action(param, arg, count - 2 ) FOREACH_1(action, count, param, __VA_ARGS__)
120+
#define FOREACH_3(action, count, param, arg, ...) action(param, arg, count - 3 ) FOREACH_2(action, count, param, __VA_ARGS__)
121+
#define FOREACH_4(action, count, param, arg, ...) action(param, arg, count - 4 ) FOREACH_3(action, count, param, __VA_ARGS__)
122+
#define FOREACH_5(action, count, param, arg, ...) action(param, arg, count - 5 ) FOREACH_4(action, count, param, __VA_ARGS__)
123+
#define FOREACH_6(action, count, param, arg, ...) action(param, arg, count - 6 ) FOREACH_5(action, count, param, __VA_ARGS__)
124+
#define FOREACH_7(action, count, param, arg, ...) action(param, arg, count - 7 ) FOREACH_6(action, count, param, __VA_ARGS__)
125+
#define FOREACH_8(action, count, param, arg, ...) action(param, arg, count - 8 ) FOREACH_7(action, count, param, __VA_ARGS__)
126+
#define FOREACH_9(action, count, param, arg, ...) action(param, arg, count - 9 ) FOREACH_8(action, count, param, __VA_ARGS__)
127+
#define FOREACH_10(action, count, param, arg, ...) action(param, arg, count - 10) FOREACH_9(action, count, param, __VA_ARGS__)
117128
#define FOREACH_11(action, count, param, arg, ...) action(param, arg, count - 11) FOREACH_10(action, count, param, __VA_ARGS__)
118129
#define FOREACH_12(action, count, param, arg, ...) action(param, arg, count - 12) FOREACH_11(action, count, param, __VA_ARGS__)
119130
#define FOREACH_13(action, count, param, arg, ...) action(param, arg, count - 13) FOREACH_12(action, count, param, __VA_ARGS__)
@@ -138,15 +149,9 @@
138149
#define FOREACH_32(action, count, param, arg, ...) action(param, arg, count - 32) FOREACH_31(action, count, param, __VA_ARGS__)
139150

140151
#define FOREACH_ARG_(action, count, param, ...) \
141-
GET_ARG_VALUE(0, ##__VA_ARGS__, \
142-
FOREACH_32, FOREACH_31, FOREACH_30, FOREACH_29, FOREACH_28, FOREACH_27, \
143-
FOREACH_26, FOREACH_25, FOREACH_24, FOREACH_23, FOREACH_22, FOREACH_21, \
144-
FOREACH_20, FOREACH_19, FOREACH_18, FOREACH_17, FOREACH_16, FOREACH_15, \
145-
FOREACH_14, FOREACH_13, FOREACH_12, FOREACH_11, FOREACH_10, FOREACH_09, \
146-
FOREACH_08, FOREACH_07, FOREACH_06, FOREACH_05, FOREACH_04, FOREACH_03, \
147-
FOREACH_02, FOREACH_01, FOREACH_00)(action, count, param, ##__VA_ARGS__)
152+
CONCATENATE(FOREACH_, count)(action, count, param, __VA_ARGS__)
148153

149154
#define FOREACH_ARG(action, param, ...) \
150-
FOREACH_ARG_(action, GET_ARG_COUNT(__VA_ARGS__), param, ##__VA_ARGS__)
155+
FOREACH_ARG_(action, GET_ARG_COUNT(__VA_ARGS__), param, __VA_ARGS__)
151156

152157
#endif /* __INCLUDE_NUTTX_MACRO_H */

0 commit comments

Comments
 (0)