> From: Stephen Hemminger [mailto:step...@networkplumber.org] > Sent: Monday, 22 April 2024 17.14 > > On Sat, 20 Apr 2024 09:48:24 +0200 > Morten Brørup <m...@smartsharesystems.com> wrote: > > > > From: Stephen Hemminger [mailto:step...@networkplumber.org] > > > Sent: Saturday, 20 April 2024 02.08 > > > > > > The macro RTE_LOG_REGISTER_DEFAULT emits code for an initialization > > > function. If a driver (and most do) adds a semicolon after the macro. > > > > > > RTE_LOG_REGISTER_DEFAULT(logtype_foo, INFO); > > > > > > Is equivalent to: > > > > > > int logtype_foo; > > > static void __logtype_foo(void) { > > > logtype_foo = rte_log_register_type_and_pick_level(name, > > > RTE_LOG_INFO); > > > if (type < 0) > > > logtype_foo = RTE_LOGTYPE_EAL; > > > }; > > > The problem is that extra semi-colon after the function. > > > > > > If code is built with highest level of warnings (pedantic), > > > then it will generate a warning. > > > warning: ISO C does not allow extra ‘;’ outside of a function > > > > > > This is a treewide fix for this. > > > > It seems weird omitting the semicolon when using this macro. > > > > How about using the same trick as RTE_INIT_PRIO(): > > > > #define RTE_INIT_PRIO(name, priority) \ > > static void name(void); \ > > static int __cdecl name ## _thunk(void) { name(); return 0; } \ > > __pragma(const_seg(CTOR_PRIORITY_TO_SECTION(priority))) \ > > __declspec(allocate(CTOR_PRIORITY_TO_SECTION(priority))) \ > > _PIFV name ## _pointer = &name ## _thunk; \ > > __pragma(const_seg()) \ > > static void name(void) > > > RTE_INIT_PRIO is what is causing the problem. My example comes from: > RTE_LOG_REGISTER_DEFAULT() -> RTE_LOG_REGISTER_IMPL() -> RTE_INIT -> > RTE_INIT_PRIO > > The last line is used as prefix before RTE_LOG_REGISTER_IMPL that defines > the init function full expansion is: > > // from RTE_LOG_REGISTER_IMPL > int logtype_foo; > // from RTE_INIT_PRIO > static void __logtype_foo(void); > static int __cdecl __logtype_foo_thunk(void) { __logtype_foo(); return 0; } > __pragma(const_seg(CTOR_PRIORITY_TO_SECTION(priority))) > __declspec(allocate(CTOR_PRIORITY_TO_SECTION(priority))) > _PIFV __logtype_foo ## _pointer = &__logtype_foo_thunk; > __pragma(const_seg()) > static void __logtype_foo(void) > // from RTE_LOG_REGISTER_IMPL > logtype_foo = rte_log_register_logtype_foo_and_pick_level(__logtype_foo, > RTE_LOG_##level); > if (logtype_foo < 0) > logtype_foo = RTE_LOGLOGTYPE_FOO_EAL; > } // no ; here is allowed > >
OK. Perhaps adding a dummy afterwards or moving the global "type" variable down would work: #define RTE_LOG_REGISTER_IMPL(type, name, level) \ int type; \ RTE_INIT(__##type) \ { \ type = rte_log_register_type_and_pick_level(name, RTE_LOG_##level); \ if (type < 0) \ type = RTE_LOGTYPE_EAL; \ } \ + int __dummy_##type Or: #define RTE_LOG_REGISTER_IMPL(type, name, level) \ - int type; \ + extern int type; \ RTE_INIT(__##type) \ { \ type = rte_log_register_type_and_pick_level(name, RTE_LOG_##level); \ if (type < 0) \ type = RTE_LOGTYPE_EAL; \ } \ + int type