Re: Why do we test a build using g++?
Leon Timmermans <[email protected]> Tue, 30 Jun 2026 01:39:37 +0200
| Newsgroups | gmane.comp.lang.perl.perl5.porters |
|---|---|
| Message-ID | <CAHhgV8gBtFs3wcpjA1fUW+qHnwxnZ6EZZGrzBr21P9Z7RdZN7g@mail.gmail.com> |
On Mon, Jun 29, 2026 at 11:42 PM Paul "LeoNerd" Evans < [email protected]> wrote: > TL;DR: We have some CI test builds that use -Dcc='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? Actually, we have one file in Windows that uses C++ (on IMPLICIT_SYS builds at least). > 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 = { > .ver = 2, > .shape = MGv2s_BASE, > .debug_name = "customop_xop", > .free_mg = &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 > ‘MagicFunctions::_v1_vtbl’ [-Wmissing-field-initializers] > 16427 | }; > | ^ > op.c:16427:1: warning: missing initializer for member > ‘MagicFunctions::flags’ [-Wmissing-field-initializers] > op.c:16427:1: warning: missing initializer for member > ‘MagicFunctions::user_size’ [-Wmissing-field-initializers] > op.c:16427:1: warning: missing initializer for member > ‘MagicFunctions::clone_mg’ [-Wmissing-field-initializers] > > 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 ‘MagicFunctions::flags’ > does not match declaration order in ‘const MagicFunctions’ > > 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 = { > ._v1_vtbl = {}, > .ver = 2, > .shape = MGv2s_BASE, > .flags = 0, > .debug_name = "customop_xop", > .user_size = 0, > .free_mg = &customop_xop_free, > .clone_mg = 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 = 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. > Yeah, that is an annoying issue. We also hit it in PR#24390 > 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? > Well volunteered! ;-) Leon