Re: Why do we test a build using g++?

[email protected] ("Kurt Starsinic") Mon, 29 Jun 2026 18:28:52 -0400
Newsgroups perl.perl5.porters
Message-ID <[email protected]>
(Note: I have not reviewed gcc's source code for many years. Most of wha=
t I have to say about gcc was certainly mostly true at one point, but mi=
ght not be today.)

IIRC, the main reason for testing with g++ is because it's capable of fi=
nding errors that gcc can't detect (they are, after all, independent com=
piler implementations). g++ is also able to perform *significant* additi=
onal optimizations.

That being said, we can always turn off warnings we're not interested in=
, e.g., -Wno-missing-field-initializers.

I realize I haven't popped my head up here in quite a while. Not looking=
 to start a beef, just provide some context. :)

- Kurt

On Mon, Jun 29, 2026, at 17:41, Paul "LeoNerd" Evans wrote:
> TL;DR: We have some CI test builds that use -Dcc=3D'g++', to test if w=
e can
>   build perl using g++ as the "C" compiler. I wonder - why do we do th=
is?
>   Perl is written in C, not C++, which is a different language. Can we
>   please not?
>
>
> I ask because it's increasingly annoying and getting in the way. Before
> we added C99 (and thus were only using C89 features), this wasn't so
> bad, but we introduced C99 specifically so we could use some features
> that were introduced only 25 years ago, instead of having to stick to
> features that are over 35 years old.
>
> One feature of C99 that I intend to use a lot is the ability to
> initialise structures with named initialisers, and to be able to omit
> fields to imply the compiler-assigned defaults of zero for integers or
> NULL for pointers. This makes it nicely convenient to initialise
> structures that, for example, have optional "flags" or other features
> in them, or pointers that are rarely used, and so most of the time you
> leave them as NULL. Not having to write lots of extra lines in the
> source makes the code clearer.
>
> The default C99-and-not-C++ compiler is perfectly happy for me to write
> code such as:
>
>   static const struct MagicFunctions magicfuncs_customop_xop =3D {
>       .ver   =3D 2,
>       .shape =3D MGv2s_BASE,
>       .debug_name =3D "customop_xop",
>       .free_mg =3D &customop_xop_free,
>   };
>
> This is relatively easy on the human eye, because it draws attention to
> only those fields that we're putting something interesting in, without
> a lot of extra clutter. It's almost as nice as having named parameters
> with optional defaults in them. ;)
>
> But g++ doesn't like this; it complains:
>
>   op.c:16427:1: warning: missing initializer for member
>       =E2=80=98MagicFunctions::_v1_vtbl=E2=80=99 [-Wmissing-field-init=
ializers]
>   16427 | };
>         | ^
>   op.c:16427:1: warning: missing initializer for member
>       =E2=80=98MagicFunctions::flags=E2=80=99 [-Wmissing-field-initial=
izers]
>   op.c:16427:1: warning: missing initializer for member
>       =E2=80=98MagicFunctions::user_size=E2=80=99 [-Wmissing-field-ini=
tializers]
>   op.c:16427:1: warning: missing initializer for member
>       =E2=80=98MagicFunctions::clone_mg=E2=80=99 [-Wmissing-field-init=
ializers]
>
> In order to appease it, I tried just adding a bunch of zero/NULL/{}
> fields at the end of the struct; but then it complains:
>
>   op.c:16432:1: error: designator order for field =E2=80=98MagicFuncti=
ons::flags=E2=80=99
>       does not match declaration order in =E2=80=98const MagicFunction=
s=E2=80=99
>
> It also still gets upset that initialisers that I have in fact written
> aren't there, because it doesn't see them. Or something. I don't know,
> I'm not a C++ programmer. I write in C.
>
> It seems the only way to make it happy is to write a lot more noisy
> structure, that's far worse on the human reader:
>
>   static const struct MagicFunctions magicfuncs_customop_xop =3D {
>       ._v1_vtbl =3D {},
>       .ver   =3D 2,
>       .shape =3D MGv2s_BASE,
>       .flags =3D 0,
>       .debug_name =3D "customop_xop",
>       .user_size =3D 0,
>       .free_mg =3D &customop_xop_free,
>       .clone_mg =3D NULL,
>   };
>
> I find this quite a bit worse to look at, because of all those empty
> junk lines being added. It makes it harder to see what's "interesting"
> about this struct, as even the zeroes and the NULLs are in there. Plus
> that leading ._v1_vtbl is even worse. It's present in the structure
> definition itself in order to make a compatible hole with (version 1)
> MAGIC structure, but shouldn't really be thought about or visible as
> part of the v2 API. So having to add it in *every* struct
> initialisation is very annoying indeed.
>
> Aside from being more cluttered and less clear to look at to the human
> reader, I also find this worse for longterm maintainability. A key
> selling point of C99's ability to imply zeroes/etc.. for fields you
> don't name, is that if you later extend the struct definition by adding
> more fields to it, you don't have to go around all your initialisers
> everywhere to add more ".foo =3D 0" lines. You can just ignore them,
> knowing they will default to zeroes if you don't need them. It makes it
> easier and nicer to extend those data types later without breaking
> existing source code. Plus, an actual C99 compiler doesn't care if the
> named initialisers don't appear in the same order as the fields in the
> struct. The whole point of naming them is that now order doesn't
> matter. You can reorder the elements in the struct without upsetting
> users of that struct, even in initialisers. Yes you'll still have to
> recompile it - but that's fine for all the code within the source tree.
> You just don't have to manually edit all your .c files.
>
>
> I think therefore I have made a reasonable case for wanting to be able
> to use this C99 named initialiser syntax. So now I want to understand
> why we care if we can compile perl source using g++.
>
> I understand that historically we have used this as a test to see that
> perl's *headers* are suitable for use by both a C compiler and a C++
> compiler, for those folks who want to write XS extensions in C++. That
> made sense when we were only using C89, and the C++ compilers were
> basically able to handle a superset of that anyway. But C99 and C++
> diverge a little, so that is no longer really true.
>
> I'm not aware of any direct reason why the source of the perl binary
> itself needs to be compilable by a C++ compiler; especially not since
> it gets in the way of us writing the code we want to write - in C99.
>
> I'd like to propose that (if there isn't another valid reason that is
> stronger than our desire to use C99 features) we find another way to
> test if the perl headers are compatible with C++. For example, could we
> ship a tiny "helloworld.cpp" program that also pulls in <perl.h> and
> <XSUB.h> or somesuch? Or maybe we write a tiny XS extension in C++ and
> compiled with g++, to use for such testing purposes?
>
> Or failing all of those; would we be able to test with g++ in some sort
> of mode where we can ask it to accept things that C99 considers valid.
> I don't know if this one is possible - see above under "I'm not a C++
> programmer", but I can't imagine we're the first and only people to
> ever run into this issue. Perhaps there's some way we can get around i=
t?
>
> --=20
> Paul "LeoNerd" Evans
>
> [email protected]
> http://www.leonerd.org.uk/  |  https://metacpan.org/author/PEVANS