1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2016 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // Distributed under the Boost Software License, Version 1.0.
7 // http://www.boost.org/LICENSE_1_0.txt
8 
9 module ddmd.dstruct;
10 
11 import core.stdc.stdio;
12 import ddmd.aggregate;
13 import ddmd.argtypes;
14 import ddmd.arraytypes;
15 import ddmd.clone;
16 import ddmd.declaration;
17 import ddmd.dmodule;
18 import ddmd.dscope;
19 import ddmd.dsymbol;
20 import ddmd.dtemplate;
21 import ddmd.errors;
22 import ddmd.expression;
23 import ddmd.func;
24 import ddmd.globals;
25 import ddmd.id;
26 import ddmd.identifier;
27 import ddmd.mtype;
28 import ddmd.opover;
29 import ddmd.tokens;
30 import ddmd.typinf;
31 import ddmd.visitor;
32 
33 /***************************************
34  * Search toString member function for TypeInfo_Struct.
35  *      string toString();
36  */
37 extern (C++) FuncDeclaration search_toString(StructDeclaration sd)
38 {
39     Dsymbol s = search_function(sd, Id.tostring);
40     FuncDeclaration fd = s ? s.isFuncDeclaration() : null;
41     if (fd)
42     {
43         static __gshared TypeFunction tftostring;
44         if (!tftostring)
45         {
46             tftostring = new TypeFunction(null, Type.tstring, 0, LINKd);
47             tftostring = cast(TypeFunction)tftostring.merge();
48         }
49         fd = fd.overloadExactMatch(tftostring);
50     }
51     return fd;
52 }
53 
54 /***************************************
55  * Request additonal semantic analysis for TypeInfo generation.
56  */
57 extern (C++) void semanticTypeInfo(Scope* sc, Type t)
58 {
59     extern (C++) final class FullTypeInfoVisitor : Visitor
60     {
61         alias visit = super.visit;
62     public:
63         Scope* sc;
64 
65         override void visit(Type t)
66         {
67             Type tb = t.toBasetype();
68             if (tb != t)
69                 tb.accept(this);
70         }
71 
72         override void visit(TypeNext t)
73         {
74             if (t.next)
75                 t.next.accept(this);
76         }
77 
78         override void visit(TypeBasic t)
79         {
80         }
81 
82         override void visit(TypeVector t)
83         {
84             t.basetype.accept(this);
85         }
86 
87         override void visit(TypeAArray t)
88         {
89             t.index.accept(this);
90             visit(cast(TypeNext)t);
91         }
92 
93         override void visit(TypeFunction t)
94         {
95             visit(cast(TypeNext)t);
96             // Currently TypeInfo_Function doesn't store parameter types.
97         }
98 
99         override void visit(TypeStruct t)
100         {
101             StructDeclaration sd = t.sym;
102 
103             /* Step 1: create TypeInfoDeclaration
104              */
105             if (!sc) // inline may request TypeInfo.
106             {
107                 Scope scx;
108                 scx._module = sd.getModule();
109                 getTypeInfoType(t, &scx);
110                 sd.requestTypeInfo = true;
111             }
112             else if (!sc.minst)
113             {
114                 // don't yet have to generate TypeInfo instance if
115                 // the typeid(T) expression exists in speculative scope.
116             }
117             else
118             {
119                 getTypeInfoType(t, sc);
120                 sd.requestTypeInfo = true;
121 
122                 // Bugzilla 15149, if the typeid operand type comes from a
123                 // result of auto function, it may be yet speculative.
124                 unSpeculative(sc, sd);
125             }
126 
127             /* Step 2: If the TypeInfo generation requires sd.semantic3, run it later.
128              * This should be done even if typeid(T) exists in speculative scope.
129              * Because it may appear later in non-speculative scope.
130              */
131             if (!sd.members)
132                 return; // opaque struct
133             if (!sd.xeq && !sd.xcmp && !sd.postblit && !sd.dtor && !sd.xhash && !search_toString(sd))
134                 return; // none of TypeInfo-specific members
135 
136             // If the struct is in a non-root module, run semantic3 to get
137             // correct symbols for the member function.
138             if (sd.semanticRun >= PASSsemantic3)
139             {
140                 // semantic3 is already done
141             }
142             else if (TemplateInstance ti = sd.isInstantiated())
143             {
144                 if (ti.minst && !ti.minst.isRoot())
145                     Module.addDeferredSemantic3(sd);
146             }
147             else
148             {
149                 if (sd.inNonRoot())
150                 {
151                     //printf("deferred sem3 for TypeInfo - sd = %s, inNonRoot = %d\n", sd->toChars(), sd->inNonRoot());
152                     Module.addDeferredSemantic3(sd);
153                 }
154             }
155         }
156 
157         override void visit(TypeClass t)
158         {
159         }
160 
161         override void visit(TypeTuple t)
162         {
163             if (t.arguments)
164             {
165                 for (size_t i = 0; i < t.arguments.dim; i++)
166                 {
167                     Type tprm = (*t.arguments)[i].type;
168                     if (tprm)
169                         tprm.accept(this);
170                 }
171             }
172         }
173     }
174 
175     if (sc)
176     {
177         if (!sc.func)
178             return;
179         if (sc.intypeof)
180             return;
181         if (sc.flags & (SCOPEctfe | SCOPEcompile))
182             return;
183     }
184 
185     scope FullTypeInfoVisitor v = new FullTypeInfoVisitor();
186     v.sc = sc;
187     t.accept(v);
188 }
189 
190 struct StructFlags
191 {
192     alias Type = uint;
193 
194     enum Enum : int
195     {
196         hasPointers = 0x1, // NB: should use noPointers as in ClassFlags
197     }
198 
199     alias hasPointers = Enum.hasPointers;
200 }
201 
202 enum StructPOD : int
203 {
204     ISPODno,    // struct is not POD
205     ISPODyes,   // struct is POD
206     ISPODfwd,   // POD not yet computed
207 }
208 
209 alias ISPODno = StructPOD.ISPODno;
210 alias ISPODyes = StructPOD.ISPODyes;
211 alias ISPODfwd = StructPOD.ISPODfwd;
212 
213 /***********************************************************
214  */
215 extern (C++) class StructDeclaration : AggregateDeclaration
216 {
217     int zeroInit;               // !=0 if initialize with 0 fill
218     bool hasIdentityAssign;     // true if has identity opAssign
219     bool hasIdentityEquals;     // true if has identity opEquals
220     FuncDeclarations postblits; // Array of postblit functions
221     FuncDeclaration postblit;   // aggregate postblit
222 
223     FuncDeclaration xeq;        // TypeInfo_Struct.xopEquals
224     FuncDeclaration xcmp;       // TypeInfo_Struct.xopCmp
225     FuncDeclaration xhash;      // TypeInfo_Struct.xtoHash
226     extern (C++) static __gshared FuncDeclaration xerreq;   // object.xopEquals
227     extern (C++) static __gshared FuncDeclaration xerrcmp;  // object.xopCmp
228 
229     structalign_t alignment;    // alignment applied outside of the struct
230     StructPOD ispod;            // if struct is POD
231 
232     // For 64 bit Efl function call/return ABI
233     Type arg1type;
234     Type arg2type;
235 
236     // Even if struct is defined as non-root symbol, some built-in operations
237     // (e.g. TypeidExp, NewExp, ArrayLiteralExp, etc) request its TypeInfo.
238     // For those, today TypeInfo_Struct is generated in COMDAT.
239     bool requestTypeInfo;
240 
241     final extern (D) this(Loc loc, Identifier id)
242     {
243         super(loc, id);
244         zeroInit = 0; // assume false until we do semantic processing
245         ispod = ISPODfwd;
246         // For forward references
247         type = new TypeStruct(this);
248         if (id == Id.ModuleInfo && !Module.moduleinfo)
249             Module.moduleinfo = this;
250     }
251 
252     override Dsymbol syntaxCopy(Dsymbol s)
253     {
254         StructDeclaration sd =
255             s ? cast(StructDeclaration)s
256               : new StructDeclaration(loc, ident);
257         return ScopeDsymbol.syntaxCopy(sd);
258     }
259 
260     override final void semantic(Scope* sc)
261     {
262         //printf("StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", this, toPrettyChars(), sizeok);
263 
264         //static int count; if (++count == 20) assert(0);
265 
266         if (semanticRun >= PASSsemanticdone)
267             return;
268         int errors = global.errors;
269 
270         //printf("+StructDeclaration::semantic(this=%p, '%s', sizeok = %d)\n", this, toPrettyChars(), sizeok);
271         Scope* scx = null;
272         if (_scope)
273         {
274             sc = _scope;
275             scx = _scope; // save so we don't make redundant copies
276             _scope = null;
277         }
278 
279         if (!parent)
280         {
281             assert(sc.parent && sc.func);
282             parent = sc.parent;
283         }
284         assert(parent && !isAnonymous());
285 
286         if (this.errors)
287             type = Type.terror;
288         type = type.semantic(loc, sc);
289         if (type.ty == Tstruct && (cast(TypeStruct)type).sym != this)
290         {
291             auto ti = (cast(TypeStruct)type).sym.isInstantiated();
292             if (ti && isError(ti))
293                 (cast(TypeStruct)type).sym = this;
294         }
295 
296         // Ungag errors when not speculative
297         Ungag ungag = ungagSpeculative();
298 
299         if (semanticRun == PASSinit)
300         {
301             protection = sc.protection;
302 
303             alignment = sc.alignment();
304 
305             storage_class |= sc.stc;
306             if (storage_class & STCdeprecated)
307                 isdeprecated = true;
308             if (storage_class & STCabstract)
309                 error("structs, unions cannot be abstract");
310 
311             userAttribDecl = sc.userAttribDecl;
312         }
313         else if (symtab && !scx)
314         {
315             semanticRun = PASSsemanticdone;
316             return;
317         }
318         semanticRun = PASSsemantic;
319 
320         if (!members) // if opaque declaration
321         {
322             semanticRun = PASSsemanticdone;
323             return;
324         }
325         if (!symtab)
326         {
327             symtab = new DsymbolTable();
328 
329             for (size_t i = 0; i < members.dim; i++)
330             {
331                 auto s = (*members)[i];
332                 //printf("adding member '%s' to '%s'\n", s.toChars(), this.toChars());
333                 s.addMember(sc, this);
334             }
335         }
336 
337         auto sc2 = newScope(sc);
338 
339         /* Set scope so if there are forward references, we still might be able to
340          * resolve individual members like enums.
341          */
342         for (size_t i = 0; i < members.dim; i++)
343         {
344             auto s = (*members)[i];
345             //printf("struct: setScope %s %s\n", s.kind(), s.toChars());
346             s.setScope(sc2);
347         }
348 
349         for (size_t i = 0; i < members.dim; i++)
350         {
351             auto s = (*members)[i];
352             s.importAll(sc2);
353         }
354 
355         for (size_t i = 0; i < members.dim; i++)
356         {
357             auto s = (*members)[i];
358             s.semantic(sc2);
359         }
360 
361         if (!determineFields())
362         {
363             assert(type.ty == Terror);
364             sc2.pop();
365             return;
366         }
367         /* Following special member functions creation needs semantic analysis
368          * completion of sub-structs in each field types. For example, buildDtor
369          * needs to check existence of elaborate dtor in type of each fields.
370          * See the case in compilable/test14838.d
371          */
372         foreach (v; fields)
373         {
374             Type tb = v.type.baseElemOf();
375             if (tb.ty != Tstruct)
376                 continue;
377             auto sd = (cast(TypeStruct)tb).sym;
378             if (sd.semanticRun >= PASSsemanticdone)
379                 continue;
380 
381             sc2.pop();
382 
383             _scope = scx ? scx : sc.copy();
384             _scope.setNoFree();
385             _scope._module.addDeferredSemantic(this);
386             //printf("\tdeferring %s\n", toChars());
387             return;
388         }
389 
390         /* Look for special member functions.
391          */
392         aggNew = cast(NewDeclaration)search(Loc(), Id.classNew);
393         aggDelete = cast(DeleteDeclaration)search(Loc(), Id.classDelete);
394 
395         // Look for the constructor
396         ctor = searchCtor();
397 
398         dtor = buildDtor(this, sc2);
399         postblit = buildPostBlit(this, sc2);
400 
401         buildOpAssign(this, sc2);
402         buildOpEquals(this, sc2);
403 
404         xeq = buildXopEquals(this, sc2);
405         xcmp = buildXopCmp(this, sc2);
406         xhash = buildXtoHash(this, sc2);
407 
408         inv = buildInv(this, sc2);
409 
410         Module.dprogress++;
411         semanticRun = PASSsemanticdone;
412         //printf("-StructDeclaration::semantic(this=%p, '%s')\n", this, toChars());
413 
414         sc2.pop();
415 
416         if (ctor)
417         {
418             Dsymbol scall = search(Loc(), Id.call);
419             if (scall)
420             {
421                 uint xerrors = global.startGagging();
422                 sc = sc.push();
423                 sc.tinst = null;
424                 sc.minst = null;
425                 auto fcall = resolveFuncCall(loc, sc, scall, null, null, null, 1);
426                 sc = sc.pop();
427                 global.endGagging(xerrors);
428 
429                 if (fcall && fcall.isStatic())
430                 {
431                     error(fcall.loc, "static opCall is hidden by constructors and can never be called");
432                     errorSupplemental(fcall.loc, "Please use a factory method instead, or replace all constructors with static opCall.");
433                 }
434             }
435         }
436 
437         if (global.errors != errors)
438         {
439             // The type is no good.
440             type = Type.terror;
441             this.errors = true;
442             if (deferred)
443                 deferred.errors = true;
444         }
445 
446         if (deferred && !global.gag)
447         {
448             deferred.semantic2(sc);
449             deferred.semantic3(sc);
450         }
451 
452         version (none)
453         {
454             if (type.ty == Tstruct && (cast(TypeStruct)type).sym != this)
455             {
456                 printf("this = %p %s\n", this, this.toChars());
457                 printf("type = %d sym = %p\n", type.ty, (cast(TypeStruct)type).sym);
458             }
459         }
460         assert(type.ty != Tstruct || (cast(TypeStruct)type).sym == this);
461     }
462 
463     final void semanticTypeInfoMembers()
464     {
465         if (xeq &&
466             xeq._scope &&
467             xeq.semanticRun < PASSsemantic3done)
468         {
469             uint errors = global.startGagging();
470             xeq.semantic3(xeq._scope);
471             if (global.endGagging(errors))
472                 xeq = xerreq;
473         }
474 
475         if (xcmp &&
476             xcmp._scope &&
477             xcmp.semanticRun < PASSsemantic3done)
478         {
479             uint errors = global.startGagging();
480             xcmp.semantic3(xcmp._scope);
481             if (global.endGagging(errors))
482                 xcmp = xerrcmp;
483         }
484 
485         FuncDeclaration ftostr = search_toString(this);
486         if (ftostr &&
487             ftostr._scope &&
488             ftostr.semanticRun < PASSsemantic3done)
489         {
490             ftostr.semantic3(ftostr._scope);
491         }
492 
493         if (xhash &&
494             xhash._scope &&
495             xhash.semanticRun < PASSsemantic3done)
496         {
497             xhash.semantic3(xhash._scope);
498         }
499 
500         if (postblit &&
501             postblit._scope &&
502             postblit.semanticRun < PASSsemantic3done)
503         {
504             postblit.semantic3(postblit._scope);
505         }
506 
507         if (dtor &&
508             dtor._scope &&
509             dtor.semanticRun < PASSsemantic3done)
510         {
511             dtor.semantic3(dtor._scope);
512         }
513     }
514 
515     override final Dsymbol search(Loc loc, Identifier ident, int flags = SearchLocalsOnly)
516     {
517         //printf("%s.StructDeclaration::search('%s', flags = x%x)\n", toChars(), ident.toChars(), flags);
518         if (_scope && !symtab)
519             semantic(_scope);
520 
521         if (!members || !symtab) // opaque or semantic() is not yet called
522         {
523             error("is forward referenced when looking for '%s'", ident.toChars());
524             return null;
525         }
526 
527         return ScopeDsymbol.search(loc, ident, flags);
528     }
529 
530     override const(char)* kind() const
531     {
532         return "struct";
533     }
534 
535     override final void finalizeSize()
536     {
537         //printf("StructDeclaration::finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
538         assert(sizeok != SIZEOKdone);
539 
540         //printf("+StructDeclaration::finalizeSize() %s, fields.dim = %d, sizeok = %d\n", toChars(), fields.dim, sizeok);
541 
542         fields.setDim(0);   // workaround
543 
544         // Set the offsets of the fields and determine the size of the struct
545         uint offset = 0;
546         bool isunion = isUnionDeclaration() !is null;
547         for (size_t i = 0; i < members.dim; i++)
548         {
549             Dsymbol s = (*members)[i];
550             s.setFieldOffset(this, &offset, isunion);
551         }
552         if (type.ty == Terror)
553             return;
554 
555         // 0 sized struct's are set to 1 byte
556         if (structsize == 0)
557         {
558             structsize = 1;
559             alignsize = 1;
560         }
561 
562         // Round struct size up to next alignsize boundary.
563         // This will ensure that arrays of structs will get their internals
564         // aligned properly.
565         if (alignment == STRUCTALIGN_DEFAULT)
566             structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
567         else
568             structsize = (structsize + alignment - 1) & ~(alignment - 1);
569 
570         sizeok = SIZEOKdone;
571 
572         //printf("-StructDeclaration::finalizeSize() %s, fields.dim = %d, structsize = %d\n", toChars(), fields.dim, structsize);
573 
574         // Calculate fields[i].overlapped
575         checkOverlappedFields();
576 
577         // Determine if struct is all zeros or not
578         zeroInit = 1;
579         foreach (vd; fields)
580         {
581             if (vd._init)
582             {
583                 // Should examine init to see if it is really all 0's
584                 zeroInit = 0;
585                 break;
586             }
587             else if (!vd.type.isZeroInit(loc))
588             {
589                 zeroInit = 0;
590                 break;
591             }
592         }
593 
594         auto tt = toArgTypes(type);
595         size_t dim = tt.arguments.dim;
596         if (dim >= 1)
597         {
598             assert(dim <= 2);
599             arg1type = (*tt.arguments)[0].type;
600             if (dim == 2)
601                 arg2type = (*tt.arguments)[1].type;
602         }
603     }
604 
605     /***************************************
606      * Fit elements[] to the corresponding type of field[].
607      * Input:
608      *      loc
609      *      sc
610      *      elements    The explicit arguments that given to construct object.
611      *      stype       The constructed object type.
612      * Returns false if any errors occur.
613      * Otherwise, returns true and elements[] are rewritten for the output.
614      */
615     final bool fit(Loc loc, Scope* sc, Expressions* elements, Type stype)
616     {
617         if (!elements)
618             return true;
619 
620         size_t nfields = fields.dim - isNested();
621         size_t offset = 0;
622         for (size_t i = 0; i < elements.dim; i++)
623         {
624             Expression e = (*elements)[i];
625             if (!e)
626                 continue;
627 
628             e = resolveProperties(sc, e);
629             if (i >= nfields)
630             {
631                 if (i == fields.dim - 1 && isNested() && e.op == TOKnull)
632                 {
633                     // CTFE sometimes creates null as hidden pointer; we'll allow this.
634                     continue;
635                 }
636                 .error(loc, "more initializers than fields (%d) of %s", nfields, toChars());
637                 return false;
638             }
639             VarDeclaration v = fields[i];
640             if (v.offset < offset)
641             {
642                 .error(loc, "overlapping initialization for %s", v.toChars());
643                 return false;
644             }
645             offset = cast(uint)(v.offset + v.type.size());
646 
647             Type t = v.type;
648             if (stype)
649                 t = t.addMod(stype.mod);
650             Type origType = t;
651             Type tb = t.toBasetype();
652 
653             /* Look for case of initializing a static array with a too-short
654              * string literal, such as:
655              *  char[5] foo = "abc";
656              * Allow this by doing an explicit cast, which will lengthen the string
657              * literal.
658              */
659             if (e.op == TOKstring && tb.ty == Tsarray)
660             {
661                 StringExp se = cast(StringExp)e;
662                 Type typeb = se.type.toBasetype();
663                 TY tynto = tb.nextOf().ty;
664                 if (!se.committed &&
665                     (typeb.ty == Tarray || typeb.ty == Tsarray) &&
666                     (tynto == Tchar || tynto == Twchar || tynto == Tdchar) &&
667                     se.numberOfCodeUnits(tynto) < (cast(TypeSArray)tb).dim.toInteger())
668                 {
669                     e = se.castTo(sc, t);
670                     goto L1;
671                 }
672             }
673 
674             while (!e.implicitConvTo(t) && tb.ty == Tsarray)
675             {
676                 /* Static array initialization, as in:
677                  *  T[3][5] = e;
678                  */
679                 t = tb.nextOf();
680                 tb = t.toBasetype();
681             }
682             if (!e.implicitConvTo(t))
683                 t = origType; // restore type for better diagnostic
684 
685             e = e.implicitCastTo(sc, t);
686         L1:
687             if (e.op == TOKerror)
688                 return false;
689 
690             (*elements)[i] = doCopyOrMove(sc, e);
691         }
692         return true;
693     }
694 
695     /***************************************
696      * Return true if struct is POD (Plain Old Data).
697      * This is defined as:
698      *      not nested
699      *      no postblits, destructors, or assignment operators
700      *      no 'ref' fields or fields that are themselves non-POD
701      * The idea being these are compatible with C structs.
702      */
703     final bool isPOD()
704     {
705         // If we've already determined whether this struct is POD.
706         if (ispod != ISPODfwd)
707             return (ispod == ISPODyes);
708 
709         ispod = ISPODyes;
710 
711         if (enclosing || postblit || dtor)
712             ispod = ISPODno;
713 
714         // Recursively check all fields are POD.
715         for (size_t i = 0; i < fields.dim; i++)
716         {
717             VarDeclaration v = fields[i];
718             if (v.storage_class & STCref)
719             {
720                 ispod = ISPODno;
721                 break;
722             }
723 
724             Type tv = v.type.baseElemOf();
725             if (tv.ty == Tstruct)
726             {
727                 TypeStruct ts = cast(TypeStruct)tv;
728                 StructDeclaration sd = ts.sym;
729                 if (!sd.isPOD())
730                 {
731                     ispod = ISPODno;
732                     break;
733                 }
734             }
735         }
736 
737         return (ispod == ISPODyes);
738     }
739 
740     override final inout(StructDeclaration) isStructDeclaration() inout
741     {
742         return this;
743     }
744 
745     override void accept(Visitor v)
746     {
747         v.visit(this);
748     }
749 }
750 
751 /***********************************************************
752  */
753 extern (C++) final class UnionDeclaration : StructDeclaration
754 {
755     extern (D) this(Loc loc, Identifier id)
756     {
757         super(loc, id);
758     }
759 
760     override Dsymbol syntaxCopy(Dsymbol s)
761     {
762         assert(!s);
763         auto ud = new UnionDeclaration(loc, ident);
764         return StructDeclaration.syntaxCopy(ud);
765     }
766 
767     override const(char)* kind() const
768     {
769         return "union";
770     }
771 
772     override inout(UnionDeclaration) isUnionDeclaration() inout
773     {
774         return this;
775     }
776 
777     override void accept(Visitor v)
778     {
779         v.visit(this);
780     }
781 }