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

[email protected] (Sam James) Tue, 30 Jun 2026 00:52:00 +0100
Newsgroups perl.perl5.porters
Organization Gentoo
Message-ID <[email protected]>
--=-=-=
Content-Type: text/plain; charset=utf-8
Content-Transfer-Encoding: quoted-printable

"Kurt Starsinic" <[email protected]> writes:

> (Note: I have not reviewed gcc's source code for many years. Most of what=
 I have to say about gcc was certainly mostly true at one point, but might =
not be today.)
>
> IIRC, the main reason for testing with g++ is because it's capable of
> finding errors that gcc can't detect (they are, after all, independent
> compiler implementations).

No, they're just distinct frontends, and those frontends have different
rules because they're different languages.

> g++ is also able to perform *significant*
> additional optimizations.

As far as I'm aware, of a close observer and sometime contributor of
GCC, this is not true anymore.

>
> 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 we =
can
>>   build perl using g++ as the "C" compiler. I wonder - why do we do this?
>>   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-initia=
lizers]
>>   16427 | };
>>         | ^
>>   op.c:16427:1: warning: missing initializer for member
>>       =E2=80=98MagicFunctions::flags=E2=80=99 [-Wmissing-field-initializ=
ers]
>>   op.c:16427:1: warning: missing initializer for member
>>       =E2=80=98MagicFunctions::user_size=E2=80=99 [-Wmissing-field-initi=
alizers]
>>   op.c:16427:1: warning: missing initializer for member
>>       =E2=80=98MagicFunctions::clone_mg=E2=80=99 [-Wmissing-field-initia=
lizers]
>>
>> 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=98MagicFunction=
s::flags=E2=80=99
>>       does not match declaration order in =E2=80=98const MagicFunctions=
=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 it?
>>
>> --=20
>> Paul "LeoNerd" Evans
>>
>> [email protected]
>> http://www.leonerd.org.uk/  |  https://metacpan.org/author/PEVANS

--=-=-=
Content-Type: application/pgp-signature; name="signature.asc"

-----BEGIN PGP SIGNATURE-----

iQEBBAEWCgCpFiEEJaa7iN2bdkxrVUHCc4QJ9SDfkZAFAmpDBSEbFIAAAAAABAAO
bWFudTIsMi41KzEuMTIsMiwyXxSAAAAAAC4AKGlzc3Vlci1mcHJAbm90YXRpb25z
Lm9wZW5wZ3AuZmlmdGhob3JzZW1hbi5uZXQyNUE2QkI4OEREOUI3NjRDNkI1NTQx
QzI3Mzg0MDlGNTIwREY5MTkwDxxzYW1AZ2VudG9vLm9yZwAKCRBzhAn1IN+RkE1z
AP97cGNSa5wJqzvrztbjSE2+vSA6dIx9bW3OO2NMl6oN9QD9EIpA5E+tEutInuOF
gv1Lc9UfjDgAtmh8nEwZBvt2Yg0=
=t/xk
-----END PGP SIGNATURE-----
--=-=-=--