@@ -820,20 +820,105 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
820820 {
821821 DesigInit di = ci.initializerList[index];
822822 Designators* dlist = di.designatorList;
823+ VarDeclaration field;
823824 if (dlist)
824825 {
825826 const length = (* dlist).length;
827+ auto id = (* dlist)[0 ].ident;
826828 if (length == 0 || ! (* dlist)[0 ].ident)
827829 {
828830 error(ci.loc, " `.identifier` expected for C struct field initializer `%s`" , toChars(ci));
829831 return err ();
830832 }
833+
831834 if (length > 1 )
832835 {
833- error(ci.loc, " only 1 designator currently allowed for C struct field initializer `%s`" , toChars(ci));
834- return err ();
836+ StructDeclaration nstsd = sd; // use this for member structs we wish to traverse
837+ auto subsi = si;
838+ /*
839+ * run this for each designator in the chain until you hit the last
840+ * then perform semantic analysis on the last field in the chain using the previous struct initializer
841+ */
842+ for (size_t i = 0 ; i < length; i++ )
843+ {
844+ int found;
845+ id = (* dlist)[i].ident;
846+ foreach (f; nstsd.fields[])
847+ {
848+ if (f.ident == id)
849+ {
850+ field = f;
851+ ++ found;
852+ break ;
853+ }
854+ }
855+ if (! found)
856+ {
857+ error(ci.loc, " `.%s` is not a field of `%s`\n " , id.toChars(), nstsd.toChars());
858+ return err ();
859+ }
860+
861+ auto base = field.type.toBasetype();
862+
863+ if (i >= length - 1 )
864+ {
865+ subsi.addInit(id, di.initializer);
866+ ++ index;
867+ continue Loop1;
868+ }
869+
870+ auto tstr = base.isTypeStruct();
871+ auto tarr = base.isTypeSArray();
872+
873+ if (tstr)
874+ {
875+ if (! overlaps(field, nstsd.fields[], subsi))
876+ {
877+ auto innersi = new StructInitializer(ci.loc);
878+ subsi.addInit(id, innersi);
879+ subsi = innersi;
880+ }
881+ else {
882+ foreach (k, ident; subsi.field[])
883+ {
884+ if (ident == id && subsi.value[k])
885+ subsi = subsi.value[k].isStructInitializer();
886+ }
887+ }
888+ nstsd = tstr.sym;
889+ }
890+ /*
891+ * once we hit an array, check & attach the array initializer to the struct initializer
892+ * move to the next initializer id and run initializer semantics on it
893+ */
894+ else if (tarr)
895+ {
896+ /*
897+ * so tempting to check for null cases for field._init.
898+ * but if your object is set to null on decl, you can't use designators anymore
899+ * and D does well to default initialize for us
900+ */
901+ auto ai = field._init.isArrayInitializer();
902+
903+ if (ai is null )
904+ {
905+ ai = new ArrayInitializer(ci.loc);
906+ subsi.addInit(id, ai);
907+ field._init = ai;
908+ }
909+
910+ auto ndx = (* dlist)[i+ 1 ].exp;
911+ ai.addInit(ndx, di.initializer);
912+ ++ index;
913+ continue Loop1;
914+ }
915+ else
916+ {
917+ error(ci.loc, " only 1 designated initializer allowed for C struct field of type `%s`" , toChars(base));
918+ return err ();
919+ }
920+ }
835921 }
836- auto id = (* dlist)[0 ].ident;
837922 foreach (k, f; sd.fields[]) // linear search for now
838923 {
839924 if (f.ident == id)
@@ -909,7 +994,6 @@ Initializer initializerSemantic(Initializer init, Scope* sc, ref Type tx, NeedIn
909994 continue Loop1;
910995 }
911996
912- VarDeclaration field;
913997 while (1 ) // skip field if it overlaps with previously seen fields
914998 {
915999 field = sd.fields[fieldi];
0 commit comments