https://gcc.gnu.org/bugzilla/show_bug.cgi?id=113124

            Bug ID: 113124
           Summary: g++ should relax designated initialiser rules for
                    trivial classes (read: C structures) and C arrays.
           Product: gcc
           Version: 13.2.1
            Status: UNCONFIRMED
          Severity: normal
          Priority: P3
         Component: c++
          Assignee: unassigned at gcc dot gnu.org
          Reporter: adobriyan at gmail dot com
  Target Milestone: ---

Currently, the rules do not allow reordering member initialisation:

    struct S {
        int a;
        int b;
    };
    S s{.b = 1, .a = 2}; // error

or skipping array element initialisation:

    int a[2] = {[1] = 1}; // error

First, clang++ allows it with warnings which can be silenced.

Second, both restrictions are major problem for converting C projects to C++
if C99 initialisers are used often.

I have bootable Linux compiled with g++ and it became obvious that some changes
are such pain points:
1) implicit casts from void* to T*,
2) "broken" C99 initializers (which Linux uses a lot),
3) pointer arithmetic ("void* + int" and "void* - void*").

(1) and (3) happen _a_lot_ but they aren't a problem, because they aren't a
flag day, casts can be added little by little to any project willing to convert
to C++.

However, (2) is a flag day with g++, suddenly lot of stuff won't compile.
Fixing this requires giving up _nice_ C99 feature which people are used to.
As you all know, reodering struct members doesn't force to change all
initialisers.

But at the moment of doing gcc => g++ flip every single structure becomes
trivial class(?) and restrictions apply.

Linux is _full_ of these misordered initialisations:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/block/fops.c?h=v6.7-rc6#n838
(the order is .llseek, .read_iter, ...)

Arrays can be even more painful:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/drivers/char/mem.c?h=v6.7-rc6#n685

Note, that the last element is undef ifdef, so less space is wasted,
so giving this array size requires constexpr variable and duplicating ifdefs.

Sometimes it is not obvious which elements are reordeded or missing:
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/net/ethtool/common.c?h=v6.7-rc6#n11

Reordered C99 initialisers create problems with maintaining patchset.
Reapplying on top of new version may create some rejects, which are painful for
a human to fix: members can be added/deleted/reorders in main code and then
patch is reordering some members too, so duplicate initializations can appear
if done wrong,
or more importantly, some initializers can be lost (which is null function
pointer dereference somewhere). I've started to redo every initialisers from
scratch just to minimise about of breakage, otherwise it is very easy to miss
stuff.

Reply via email to