In that case, an even bigger +1 from me. That's a lot of useless
boilerplate we can get rid of!

On Tue, Oct 27, 2026 at 8:18 AM Marco C. <[email protected]> wrote:

> Hello,
>
> A correction to my numbers: I counted only include/.  The headers in
> arch/*/include and in the boards' include/ directories follow the same
> template, and the public headers include some of them (arch/irq.h,
> arch/arch.h, arch/syscall.h, arch/setjmp.h), so they also undefine a
> program's EXTERN.
>
> With them, on master:
>
> - 1344 headers define EXTERN (540 in include/, 280 in arch/, 524 in
>   boards/).
> - 38 use it, for about 70 declarations (20 in include/, 16 in arch/,
>   mostly irq.h, and 2 in boards/).
> - The other 1306 never use it.
>
> The proposal is the same: step 1 removes the unused definitions from
> all 1306 headers, step 2 changes the 38 that use the macro.  As before,
> all their declarations are inside the extern "C" block of their header.
>
> Regards,
> Marco Casaroli
>
> On Tue, Oct 27, 2026 at 11:41 AM Marco C. <[email protected]>
> wrote:
> >
> > Hello,
> >
> > I would like to propose a change to the coding standard for global data
> > declarations in header files.
> >
> > Today Documentation/contributing/coding_style.rst asks every header to
> > define EXTERN at the start of its "Public Data" section:
> >
> >   #ifdef __cplusplus
> >   #define EXTERN extern "C"
> >   extern "C"
> >   {
> >   #else
> >   #define EXTERN extern
> >   #endif
> >
> > and to "#undef EXTERN" at its end.  Global data is then declared with
> > "EXTERN int g_foo;".
> >
> > Some numbers from include/ on master:
> >
> > - 540 headers define EXTERN.
> > - Only 20 of them use it, for about 50 declarations.
> > - The other 520 define and undefine it and never use it.
> >
> > Until 2013 the headers also declared their functions with EXTERN; the
> > 2014 coding standard then said that functions do not use it.  The
> > definition stayed in the template, so most headers still define a macro
> > that nothing in them uses.
> >
> > There are two problems with the macro:
> >
> > 1. In our headers it adds nothing.  All the declarations with EXTERN are
> >    inside the extern "C" block of the same header (I checked the 20
> >    headers), so for C++ "extern int g_foo;" has C linkage too, and plain
> >    "extern" gives the same result in C and C++.  EXTERN is defined only
> as
> >    extern or extern "C", and no file uses it for another purpose.  Its
> one
> >    use is as a safety net: a declaration put outside the extern "C" block
> >    by mistake would still get C linkage.
> >
> > 2. EXTERN is not a reserved name.  A program can define its own EXTERN,
> >    and every system header that it includes after that removes the
> >    program's definition with "#undef EXTERN".  For example, Tcl's tcl.h
> >    defines EXTERN, then tclInt.h includes system headers, and Tcl's own
> >    "EXTERN void TclAllocateFreeObjects(void);" no longer compiles.
> >
> > I propose two steps.
> >
> > 1. Remove the unused definitions from the 520 headers that never use
> >    EXTERN: the "#undef EXTERN", the two "#define EXTERN" lines and the
> >    "#else" that holds one of them.  The extern "C" block for C++ stays,
> >    so the code that the compiler sees does not change.  I have this
> >    change ready (517 headers; three are left out because their SPDX
> >    copyright lines do not pass nxstyle) and can send it as a PR.
> >
> > 2. Change the rule for the 20 headers that declare data and for new code.
> >    These include common headers: unistd.h (optarg, ...), time.h (tzname),
> >    netdb.h (h_errno), netinet/in.h (in6addr_any, ...).  Two options:
> >
> >    A. Plain "extern" inside the extern "C" block, as glibc, musl and the
> >       BSD headers do.  The coding standard drops the EXTERN definition
> >       from the template.
> >
> >    B. Keep the macro, under a reserved name: __EXTERN.  Names that start
> >       with two underscores belong to the implementation, so no program
> >       can use them.  The template keeps its form.
> >
> > Both work with every compiler that NuttX supports (GCC, clang, SDCC,
> > ZDS-II, IAR, Green Hills, TASKING, MSVC): they are plain C and do not
> > need #pragma push_macro.  A is simpler; B is a smaller change of habits.
> > In both cases I can make the change of the 20 headers and of
> > coding_style.rst.
> >
> > Is step 1 welcome as a PR, and which option do you prefer for step 2?
> >
> > Regards,
> > Marco Casaroli
>

Reply via email to