1 /**
2  * Compiler implementation of the
3  * $(LINK2 http://www.dlang.org, D programming language).
4  *
5  * Copyright:   Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved
6  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
7  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
8  * Source:      $(DMDSRC _dclass.d)
9  */
10 
11 module ddmd.dclass;
12 
13 import core.stdc.stdio;
14 import core.stdc..string;
15 
16 import ddmd.aggregate;
17 import ddmd.arraytypes;
18 import ddmd.gluelayer;
19 import ddmd.clone;
20 import ddmd.declaration;
21 import ddmd.dmodule;
22 import ddmd.dscope;
23 import ddmd.dsymbol;
24 import ddmd.dtemplate;
25 import ddmd.errors;
26 import ddmd.func;
27 import ddmd.globals;
28 import ddmd.hdrgen;
29 import ddmd.id;
30 import ddmd.identifier;
31 import ddmd.mtype;
32 import ddmd.objc;
33 import ddmd.root.rmem;
34 import ddmd.statement;
35 import ddmd.target;
36 import ddmd.visitor;
37 
38 enum Abstract : int
39 {
40     ABSfwdref = 0,      // whether an abstract class is not yet computed
41     ABSyes,             // is abstract class
42     ABSno,              // is not abstract class
43 }
44 
45 alias ABSfwdref = Abstract.ABSfwdref;
46 alias ABSyes = Abstract.ABSyes;
47 alias ABSno = Abstract.ABSno;
48 
49 /***********************************************************
50  */
51 struct BaseClass
52 {
53     Type type;          // (before semantic processing)
54 
55     ClassDeclaration sym;
56     uint offset;        // 'this' pointer offset
57 
58     // for interfaces: Array of FuncDeclaration's making up the vtbl[]
59     FuncDeclarations vtbl;
60 
61     // if BaseClass is an interface, these
62     // are a copy of the InterfaceDeclaration.interfaces
63     BaseClass[] baseInterfaces;
64 
65     extern (D) this(Type type)
66     {
67         //printf("BaseClass(this = %p, '%s')\n", this, type.toChars());
68         this.type = type;
69     }
70 
71     /****************************************
72      * Fill in vtbl[] for base class based on member functions of class cd.
73      * Input:
74      *      vtbl            if !=NULL, fill it in
75      *      newinstance     !=0 means all entries must be filled in by members
76      *                      of cd, not members of any base classes of cd.
77      * Returns:
78      *      true if any entries were filled in by members of cd (not exclusively
79      *      by base classes)
80      */
81     extern (C++) bool fillVtbl(ClassDeclaration cd, FuncDeclarations* vtbl, int newinstance)
82     {
83         bool result = false;
84 
85         //printf("BaseClass.fillVtbl(this='%s', cd='%s')\n", sym.toChars(), cd.toChars());
86         if (vtbl)
87             vtbl.setDim(sym.vtbl.dim);
88 
89         // first entry is ClassInfo reference
90         for (size_t j = sym.vtblOffset(); j < sym.vtbl.dim; j++)
91         {
92             FuncDeclaration ifd = sym.vtbl[j].isFuncDeclaration();
93             FuncDeclaration fd;
94             TypeFunction tf;
95 
96             //printf("        vtbl[%d] is '%s'\n", j, ifd ? ifd.toChars() : "null");
97             assert(ifd);
98 
99             // Find corresponding function in this class
100             tf = (ifd.type.ty == Tfunction) ? cast(TypeFunction)ifd.type : null;
101             assert(tf); // should always be non-null
102             fd = cd.findFunc(ifd.ident, tf);
103             if (fd && !fd.isAbstract())
104             {
105                 //printf("            found\n");
106                 // Check that calling conventions match
107                 if (fd.linkage != ifd.linkage)
108                     fd.error("linkage doesn't match interface function");
109 
110                 // Check that it is current
111                 //printf("newinstance = %d fd.toParent() = %s ifd.toParent() = %s\n",
112                     //newinstance, fd.toParent().toChars(), ifd.toParent().toChars());
113                 if (newinstance && fd.toParent() != cd && ifd.toParent() == sym)
114                     cd.error("interface function '%s' is not implemented", ifd.toFullSignature());
115 
116                 if (fd.toParent() == cd)
117                     result = true;
118             }
119             else
120             {
121                 //printf("            not found %p\n", fd);
122                 // BUG: should mark this class as abstract?
123                 if (!cd.isAbstract())
124                     cd.error("interface function '%s' is not implemented", ifd.toFullSignature());
125 
126                 fd = null;
127             }
128             if (vtbl)
129                 (*vtbl)[j] = fd;
130         }
131         return result;
132     }
133 
134     extern (C++) void copyBaseInterfaces(BaseClasses* vtblInterfaces)
135     {
136         //printf("+copyBaseInterfaces(), %s\n", sym.toChars());
137         //    if (baseInterfaces_dim)
138         //      return;
139         auto bc = cast(BaseClass*)mem.xcalloc(sym.interfaces.length, BaseClass.sizeof);
140         baseInterfaces = bc[0 .. sym.interfaces.length];
141         //printf("%s.copyBaseInterfaces()\n", sym.toChars());
142         for (size_t i = 0; i < baseInterfaces.length; i++)
143         {
144             BaseClass* b = &baseInterfaces[i];
145             BaseClass* b2 = sym.interfaces[i];
146 
147             assert(b2.vtbl.dim == 0); // should not be filled yet
148             memcpy(b, b2, BaseClass.sizeof);
149 
150             if (i) // single inheritance is i==0
151                 vtblInterfaces.push(b); // only need for M.I.
152             b.copyBaseInterfaces(vtblInterfaces);
153         }
154         //printf("-copyBaseInterfaces\n");
155     }
156 }
157 
158 struct ClassFlags
159 {
160     alias Type = uint;
161 
162     enum Enum : int
163     {
164         isCOMclass = 0x1,
165         noPointers = 0x2,
166         hasOffTi = 0x4,
167         hasCtor = 0x8,
168         hasGetMembers = 0x10,
169         hasTypeInfo = 0x20,
170         isAbstract = 0x40,
171         isCPPclass = 0x80,
172         hasDtor = 0x100,
173     }
174 
175     alias isCOMclass = Enum.isCOMclass;
176     alias noPointers = Enum.noPointers;
177     alias hasOffTi = Enum.hasOffTi;
178     alias hasCtor = Enum.hasCtor;
179     alias hasGetMembers = Enum.hasGetMembers;
180     alias hasTypeInfo = Enum.hasTypeInfo;
181     alias isAbstract = Enum.isAbstract;
182     alias isCPPclass = Enum.isCPPclass;
183     alias hasDtor = Enum.hasDtor;
184 }
185 
186 /***********************************************************
187  */
188 extern (C++) class ClassDeclaration : AggregateDeclaration
189 {
190     extern (C++) __gshared
191     {
192         // Names found by reading object.d in druntime
193         ClassDeclaration object;
194         ClassDeclaration throwable;
195         ClassDeclaration exception;
196         ClassDeclaration errorException;
197         ClassDeclaration cpp_type_info_ptr;   // Object.__cpp_type_info_ptr
198     }
199 
200     ClassDeclaration baseClass; // NULL only if this is Object
201     FuncDeclaration staticCtor;
202     FuncDeclaration staticDtor;
203     Dsymbols vtbl;              // Array of FuncDeclaration's making up the vtbl[]
204     Dsymbols vtblFinal;         // More FuncDeclaration's that aren't in vtbl[]
205 
206     // Array of BaseClass's; first is super, rest are Interface's
207     BaseClasses* baseclasses;
208 
209     /* Slice of baseclasses[] that does not include baseClass
210      */
211     BaseClass*[] interfaces;
212 
213     // array of base interfaces that have their own vtbl[]
214     BaseClasses* vtblInterfaces;
215 
216     // the ClassInfo object for this ClassDeclaration
217     TypeInfoClassDeclaration vclassinfo;
218 
219     bool com;           // true if this is a COM class (meaning it derives from IUnknown)
220     bool cpp;           // true if this is a C++ interface
221     bool isscope;       // true if this is a scope class
222     Abstract isabstract;
223     int inuse;          // to prevent recursive attempts
224     Baseok baseok;      // set the progress of base classes resolving
225 
226     Objc_ClassDeclaration objc;
227 
228     Symbol* cpp_type_info_ptr_sym;      // cached instance of class Id.cpp_type_info_ptr
229 
230     final extern (D) this(Loc loc, Identifier id, BaseClasses* baseclasses, Dsymbols* members, bool inObject)
231     {
232         if (!id)
233             id = Identifier.generateId("__anonclass");
234         assert(id);
235 
236         super(loc, id);
237 
238         static __gshared const(char)* msg = "only object.d can define this reserved class name";
239 
240         if (baseclasses)
241         {
242             // Actually, this is a transfer
243             this.baseclasses = baseclasses;
244         }
245         else
246             this.baseclasses = new BaseClasses();
247 
248         this.members = members;
249 
250         //printf("ClassDeclaration(%s), dim = %d\n", id.toChars(), this.baseclasses.dim);
251 
252         // For forward references
253         type = new TypeClass(this);
254 
255         if (id)
256         {
257             // Look for special class names
258             if (id == Id.__sizeof || id == Id.__xalignof || id == Id._mangleof)
259                 error("illegal class name");
260 
261             // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
262             if (id.toChars()[0] == 'T')
263             {
264                 if (id == Id.TypeInfo)
265                 {
266                     if (!inObject)
267                         error("%s", msg);
268                     Type.dtypeinfo = this;
269                 }
270                 if (id == Id.TypeInfo_Class)
271                 {
272                     if (!inObject)
273                         error("%s", msg);
274                     Type.typeinfoclass = this;
275                 }
276                 if (id == Id.TypeInfo_Interface)
277                 {
278                     if (!inObject)
279                         error("%s", msg);
280                     Type.typeinfointerface = this;
281                 }
282                 if (id == Id.TypeInfo_Struct)
283                 {
284                     if (!inObject)
285                         error("%s", msg);
286                     Type.typeinfostruct = this;
287                 }
288                 if (id == Id.TypeInfo_Pointer)
289                 {
290                     if (!inObject)
291                         error("%s", msg);
292                     Type.typeinfopointer = this;
293                 }
294                 if (id == Id.TypeInfo_Array)
295                 {
296                     if (!inObject)
297                         error("%s", msg);
298                     Type.typeinfoarray = this;
299                 }
300                 if (id == Id.TypeInfo_StaticArray)
301                 {
302                     //if (!inObject)
303                     //    Type.typeinfostaticarray.error("%s", msg);
304                     Type.typeinfostaticarray = this;
305                 }
306                 if (id == Id.TypeInfo_AssociativeArray)
307                 {
308                     if (!inObject)
309                         error("%s", msg);
310                     Type.typeinfoassociativearray = this;
311                 }
312                 if (id == Id.TypeInfo_Enum)
313                 {
314                     if (!inObject)
315                         error("%s", msg);
316                     Type.typeinfoenum = this;
317                 }
318                 if (id == Id.TypeInfo_Function)
319                 {
320                     if (!inObject)
321                         error("%s", msg);
322                     Type.typeinfofunction = this;
323                 }
324                 if (id == Id.TypeInfo_Delegate)
325                 {
326                     if (!inObject)
327                         error("%s", msg);
328                     Type.typeinfodelegate = this;
329                 }
330                 if (id == Id.TypeInfo_Tuple)
331                 {
332                     if (!inObject)
333                         error("%s", msg);
334                     Type.typeinfotypelist = this;
335                 }
336                 if (id == Id.TypeInfo_Const)
337                 {
338                     if (!inObject)
339                         error("%s", msg);
340                     Type.typeinfoconst = this;
341                 }
342                 if (id == Id.TypeInfo_Invariant)
343                 {
344                     if (!inObject)
345                         error("%s", msg);
346                     Type.typeinfoinvariant = this;
347                 }
348                 if (id == Id.TypeInfo_Shared)
349                 {
350                     if (!inObject)
351                         error("%s", msg);
352                     Type.typeinfoshared = this;
353                 }
354                 if (id == Id.TypeInfo_Wild)
355                 {
356                     if (!inObject)
357                         error("%s", msg);
358                     Type.typeinfowild = this;
359                 }
360                 if (id == Id.TypeInfo_Vector)
361                 {
362                     if (!inObject)
363                         error("%s", msg);
364                     Type.typeinfovector = this;
365                 }
366             }
367 
368             if (id == Id.Object)
369             {
370                 if (!inObject)
371                     error("%s", msg);
372                 object = this;
373             }
374 
375             if (id == Id.Throwable)
376             {
377                 if (!inObject)
378                     error("%s", msg);
379                 throwable = this;
380             }
381             if (id == Id.Exception)
382             {
383                 if (!inObject)
384                     error("%s", msg);
385                 exception = this;
386             }
387             if (id == Id.Error)
388             {
389                 if (!inObject)
390                     error("%s", msg);
391                 errorException = this;
392             }
393             if (id == Id.cpp_type_info_ptr)
394             {
395                 if (!inObject)
396                     error("%s", msg);
397                 cpp_type_info_ptr = this;
398             }
399         }
400         baseok = BASEOKnone;
401     }
402 
403     override Dsymbol syntaxCopy(Dsymbol s)
404     {
405         //printf("ClassDeclaration.syntaxCopy('%s')\n", toChars());
406         ClassDeclaration cd =
407             s ? cast(ClassDeclaration)s
408               : new ClassDeclaration(loc, ident, null, null, false);
409 
410         cd.storage_class |= storage_class;
411 
412         cd.baseclasses.setDim(this.baseclasses.dim);
413         for (size_t i = 0; i < cd.baseclasses.dim; i++)
414         {
415             BaseClass* b = (*this.baseclasses)[i];
416             auto b2 = new BaseClass(b.type.syntaxCopy());
417             (*cd.baseclasses)[i] = b2;
418         }
419 
420         return ScopeDsymbol.syntaxCopy(cd);
421     }
422 
423     override Scope* newScope(Scope* sc)
424     {
425         auto sc2 = super.newScope(sc);
426         if (isCOMclass())
427         {
428             if (global.params.isWindows)
429                 sc2.linkage = LINKwindows;
430             else
431             {
432                 /* This enables us to use COM objects under Linux and
433                  * work with things like XPCOM
434                  */
435                 sc2.linkage = LINKc;
436             }
437         }
438         return sc2;
439     }
440 
441     override void semantic(Scope* sc)
442     {
443         //printf("ClassDeclaration.semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
444         //printf("\tparent = %p, '%s'\n", sc.parent, sc.parent ? sc.parent.toChars() : "");
445         //printf("sc.stc = %x\n", sc.stc);
446 
447         //{ static int n;  if (++n == 20) *(char*)0=0; }
448 
449         if (semanticRun >= PASSsemanticdone)
450             return;
451         int errors = global.errors;
452 
453         //printf("+ClassDeclaration.semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
454 
455         Scope* scx = null;
456         if (_scope)
457         {
458             sc = _scope;
459             scx = _scope; // save so we don't make redundant copies
460             _scope = null;
461         }
462 
463         if (!parent)
464         {
465             assert(sc.parent);
466             parent = sc.parent;
467         }
468 
469         if (this.errors)
470             type = Type.terror;
471         type = type.semantic(loc, sc);
472         if (type.ty == Tclass && (cast(TypeClass)type).sym != this)
473         {
474             auto ti = (cast(TypeClass)type).sym.isInstantiated();
475             if (ti && isError(ti))
476                 (cast(TypeClass)type).sym = this;
477         }
478 
479         // Ungag errors when not speculative
480         Ungag ungag = ungagSpeculative();
481 
482         if (semanticRun == PASSinit)
483         {
484             protection = sc.protection;
485 
486             storage_class |= sc.stc;
487             if (storage_class & STCdeprecated)
488                 isdeprecated = true;
489             if (storage_class & STCauto)
490                 error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?");
491             if (storage_class & STCscope)
492                 isscope = true;
493             if (storage_class & STCabstract)
494                 isabstract = ABSyes;
495 
496             userAttribDecl = sc.userAttribDecl;
497 
498             if (sc.linkage == LINKcpp)
499                 cpp = true;
500             if (sc.linkage == LINKobjc)
501                 objc_ClassDeclaration_semantic_PASSinit_LINKobjc(this);
502         }
503         else if (symtab && !scx)
504         {
505             semanticRun = PASSsemanticdone;
506             return;
507         }
508         semanticRun = PASSsemantic;
509 
510         if (baseok < BASEOKdone)
511         {
512             /* Bugzilla 12078, 12143 and 15733:
513              * While resolving base classes and interfaces, a base may refer
514              * the member of this derived class. In that time, if all bases of
515              * this class can  be determined, we can go forward the semantc process
516              * beyond the Lancestorsdone. To do the recursive semantic analysis,
517              * temporarily set and unset `_scope` around exp().
518              */
519             T resolveBase(T)(lazy T exp)
520             {
521                 if (!scx)
522                 {
523                     scx = sc.copy();
524                     scx.setNoFree();
525                 }
526                 static if (!is(T == void))
527                 {
528                     _scope = scx;
529                     auto r = exp();
530                     _scope = null;
531                     return r;
532                 }
533                 else
534                 {
535                     _scope = scx;
536                     exp();
537                     _scope = null;
538                 }
539             }
540 
541             baseok = BASEOKin;
542 
543             // Expand any tuples in baseclasses[]
544             for (size_t i = 0; i < baseclasses.dim;)
545             {
546                 auto b = (*baseclasses)[i];
547                 b.type = resolveBase(b.type.semantic(loc, sc));
548 
549                 Type tb = b.type.toBasetype();
550                 if (tb.ty == Ttuple)
551                 {
552                     TypeTuple tup = cast(TypeTuple)tb;
553                     baseclasses.remove(i);
554                     size_t dim = Parameter.dim(tup.arguments);
555                     for (size_t j = 0; j < dim; j++)
556                     {
557                         Parameter arg = Parameter.getNth(tup.arguments, j);
558                         b = new BaseClass(arg.type);
559                         baseclasses.insert(i + j, b);
560                     }
561                 }
562                 else
563                     i++;
564             }
565 
566             if (baseok >= BASEOKdone)
567             {
568                 //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
569                 if (semanticRun >= PASSsemanticdone)
570                     return;
571                 goto Lancestorsdone;
572             }
573 
574             // See if there's a base class as first in baseclasses[]
575             if (baseclasses.dim)
576             {
577                 BaseClass* b = (*baseclasses)[0];
578                 Type tb = b.type.toBasetype();
579                 TypeClass tc = (tb.ty == Tclass) ? cast(TypeClass)tb : null;
580                 if (!tc)
581                 {
582                     if (b.type != Type.terror)
583                         error("base type must be class or interface, not %s", b.type.toChars());
584                     baseclasses.remove(0);
585                     goto L7;
586                 }
587                 if (tc.sym.isDeprecated())
588                 {
589                     if (!isDeprecated())
590                     {
591                         // Deriving from deprecated class makes this one deprecated too
592                         isdeprecated = true;
593                         tc.checkDeprecated(loc, sc);
594                     }
595                 }
596                 if (tc.sym.isInterfaceDeclaration())
597                     goto L7;
598 
599                 for (ClassDeclaration cdb = tc.sym; cdb; cdb = cdb.baseClass)
600                 {
601                     if (cdb == this)
602                     {
603                         error("circular inheritance");
604                         baseclasses.remove(0);
605                         goto L7;
606                     }
607                 }
608 
609                 /* Bugzilla 11034: Essentially, class inheritance hierarchy
610                  * and instance size of each classes are orthogonal information.
611                  * Therefore, even if tc.sym.sizeof == SIZEOKnone,
612                  * we need to set baseClass field for class covariance check.
613                  */
614                 baseClass = tc.sym;
615                 b.sym = baseClass;
616 
617                 if (tc.sym._scope && tc.sym.baseok < BASEOKdone)
618                     resolveBase(tc.sym.semantic(null)); // Try to resolve forward reference
619                 if (tc.sym.baseok < BASEOKdone)
620                 {
621                     //printf("\ttry later, forward reference of base class %s\n", tc.sym.toChars());
622                     if (tc.sym._scope)
623                         tc.sym._scope._module.addDeferredSemantic(tc.sym);
624                     baseok = BASEOKnone;
625                 }
626             L7:
627             }
628 
629             // Treat the remaining entries in baseclasses as interfaces
630             // Check for errors, handle forward references
631             for (size_t i = (baseClass ? 1 : 0); i < baseclasses.dim;)
632             {
633                 BaseClass* b = (*baseclasses)[i];
634                 Type tb = b.type.toBasetype();
635                 TypeClass tc = (tb.ty == Tclass) ? cast(TypeClass)tb : null;
636                 if (!tc || !tc.sym.isInterfaceDeclaration())
637                 {
638                     if (b.type != Type.terror)
639                         error("base type must be interface, not %s", b.type.toChars());
640                     baseclasses.remove(i);
641                     continue;
642                 }
643 
644                 // Check for duplicate interfaces
645                 for (size_t j = (baseClass ? 1 : 0); j < i; j++)
646                 {
647                     BaseClass* b2 = (*baseclasses)[j];
648                     if (b2.sym == tc.sym)
649                     {
650                         error("inherits from duplicate interface %s", b2.sym.toChars());
651                         baseclasses.remove(i);
652                         continue;
653                     }
654                 }
655                 if (tc.sym.isDeprecated())
656                 {
657                     if (!isDeprecated())
658                     {
659                         // Deriving from deprecated class makes this one deprecated too
660                         isdeprecated = true;
661                         tc.checkDeprecated(loc, sc);
662                     }
663                 }
664 
665                 b.sym = tc.sym;
666 
667                 if (tc.sym._scope && tc.sym.baseok < BASEOKdone)
668                     resolveBase(tc.sym.semantic(null)); // Try to resolve forward reference
669                 if (tc.sym.baseok < BASEOKdone)
670                 {
671                     //printf("\ttry later, forward reference of base %s\n", tc.sym.toChars());
672                     if (tc.sym._scope)
673                         tc.sym._scope._module.addDeferredSemantic(tc.sym);
674                     baseok = BASEOKnone;
675                 }
676                 i++;
677             }
678             if (baseok == BASEOKnone)
679             {
680                 // Forward referencee of one or more bases, try again later
681                 _scope = scx ? scx : sc.copy();
682                 _scope.setNoFree();
683                 _scope._module.addDeferredSemantic(this);
684                 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
685                 return;
686             }
687             baseok = BASEOKdone;
688 
689             // If no base class, and this is not an Object, use Object as base class
690             if (!baseClass && ident != Id.Object && !cpp)
691             {
692                 if (!object)
693                 {
694                     error("missing or corrupt object.d");
695                     fatal();
696                 }
697 
698                 Type t = object.type;
699                 t = t.semantic(loc, sc).toBasetype();
700                 assert(t.ty == Tclass);
701                 TypeClass tc = cast(TypeClass)t;
702 
703                 auto b = new BaseClass(tc);
704                 baseclasses.shift(b);
705 
706                 baseClass = tc.sym;
707                 assert(!baseClass.isInterfaceDeclaration());
708                 b.sym = baseClass;
709             }
710             if (baseClass)
711             {
712                 if (baseClass.storage_class & STCfinal)
713                     error("cannot inherit from final class %s", baseClass.toChars());
714 
715                 // Inherit properties from base class
716                 if (baseClass.isCOMclass())
717                     com = true;
718                 if (baseClass.isCPPclass())
719                     cpp = true;
720                 if (baseClass.isscope)
721                     isscope = true;
722                 enclosing = baseClass.enclosing;
723                 storage_class |= baseClass.storage_class & STC_TYPECTOR;
724             }
725 
726             interfaces = baseclasses.tdata()[(baseClass ? 1 : 0) .. baseclasses.dim];
727             foreach (b; interfaces)
728             {
729                 // If this is an interface, and it derives from a COM interface,
730                 // then this is a COM interface too.
731                 if (b.sym.isCOMinterface())
732                     com = true;
733                 if (cpp && !b.sym.isCPPinterface())
734                 {
735                     .error(loc, "C++ class '%s' cannot implement D interface '%s'",
736                         toPrettyChars(), b.sym.toPrettyChars());
737                 }
738             }
739             interfaceSemantic(sc);
740         }
741     Lancestorsdone:
742         //printf("\tClassDeclaration.semantic(%s) baseok = %d\n", toChars(), baseok);
743 
744         if (!members) // if opaque declaration
745         {
746             semanticRun = PASSsemanticdone;
747             return;
748         }
749         if (!symtab)
750         {
751             symtab = new DsymbolTable();
752 
753             /* Bugzilla 12152: The semantic analysis of base classes should be finished
754              * before the members semantic analysis of this class, in order to determine
755              * vtbl in this class. However if a base class refers the member of this class,
756              * it can be resolved as a normal forward reference.
757              * Call addMember() and setScope() to make this class members visible from the base classes.
758              */
759             for (size_t i = 0; i < members.dim; i++)
760             {
761                 auto s = (*members)[i];
762                 s.addMember(sc, this);
763             }
764 
765             auto sc2 = newScope(sc);
766 
767             /* Set scope so if there are forward references, we still might be able to
768              * resolve individual members like enums.
769              */
770             for (size_t i = 0; i < members.dim; i++)
771             {
772                 auto s = (*members)[i];
773                 //printf("[%d] setScope %s %s, sc2 = %p\n", i, s.kind(), s.toChars(), sc2);
774                 s.setScope(sc2);
775             }
776 
777             sc2.pop();
778         }
779 
780         for (size_t i = 0; i < baseclasses.dim; i++)
781         {
782             BaseClass* b = (*baseclasses)[i];
783             Type tb = b.type.toBasetype();
784             assert(tb.ty == Tclass);
785             TypeClass tc = cast(TypeClass)tb;
786             if (tc.sym.semanticRun < PASSsemanticdone)
787             {
788                 // Forward referencee of one or more bases, try again later
789                 _scope = scx ? scx : sc.copy();
790                 _scope.setNoFree();
791                 if (tc.sym._scope)
792                     tc.sym._scope._module.addDeferredSemantic(tc.sym);
793                 _scope._module.addDeferredSemantic(this);
794                 //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
795                 return;
796             }
797         }
798 
799         if (baseok == BASEOKdone)
800         {
801             baseok = BASEOKsemanticdone;
802 
803             // initialize vtbl
804             if (baseClass)
805             {
806                 if (cpp && baseClass.vtbl.dim == 0)
807                 {
808                     error("C++ base class %s needs at least one virtual function", baseClass.toChars());
809                 }
810 
811                 // Copy vtbl[] from base class
812                 vtbl.setDim(baseClass.vtbl.dim);
813                 memcpy(vtbl.tdata(), baseClass.vtbl.tdata(), (void*).sizeof * vtbl.dim);
814 
815                 vthis = baseClass.vthis;
816             }
817             else
818             {
819                 // No base class, so this is the root of the class hierarchy
820                 vtbl.setDim(0);
821                 if (vtblOffset())
822                     vtbl.push(this); // leave room for classinfo as first member
823             }
824 
825             /* If this is a nested class, add the hidden 'this'
826              * member which is a pointer to the enclosing scope.
827              */
828             if (vthis) // if inheriting from nested class
829             {
830                 // Use the base class's 'this' member
831                 if (storage_class & STCstatic)
832                     error("static class cannot inherit from nested class %s", baseClass.toChars());
833                 if (toParent2() != baseClass.toParent2() &&
834                     (!toParent2() ||
835                      !baseClass.toParent2().getType() ||
836                      !baseClass.toParent2().getType().isBaseOf(toParent2().getType(), null)))
837                 {
838                     if (toParent2())
839                     {
840                         error("is nested within %s, but super class %s is nested within %s",
841                             toParent2().toChars(),
842                             baseClass.toChars(),
843                             baseClass.toParent2().toChars());
844                     }
845                     else
846                     {
847                         error("is not nested, but super class %s is nested within %s",
848                             baseClass.toChars(),
849                             baseClass.toParent2().toChars());
850                     }
851                     enclosing = null;
852                 }
853             }
854             else
855                 makeNested();
856         }
857 
858         auto sc2 = newScope(sc);
859 
860         for (size_t i = 0; i < members.dim; ++i)
861         {
862             auto s = (*members)[i];
863             s.importAll(sc2);
864         }
865 
866         // Note that members.dim can grow due to tuple expansion during semantic()
867         for (size_t i = 0; i < members.dim; ++i)
868         {
869             auto s = (*members)[i];
870             s.semantic(sc2);
871         }
872 
873         if (!determineFields())
874         {
875             assert(type == Type.terror);
876             sc2.pop();
877             return;
878         }
879         /* Following special member functions creation needs semantic analysis
880          * completion of sub-structs in each field types.
881          */
882         foreach (v; fields)
883         {
884             Type tb = v.type.baseElemOf();
885             if (tb.ty != Tstruct)
886                 continue;
887             auto sd = (cast(TypeStruct)tb).sym;
888             if (sd.semanticRun >= PASSsemanticdone)
889                 continue;
890 
891             sc2.pop();
892 
893             _scope = scx ? scx : sc.copy();
894             _scope.setNoFree();
895             _scope._module.addDeferredSemantic(this);
896             //printf("\tdeferring %s\n", toChars());
897             return;
898         }
899 
900         /* Look for special member functions.
901          * They must be in this class, not in a base class.
902          */
903         // Can be in base class
904         aggNew = cast(NewDeclaration)search(Loc(), Id.classNew);
905         aggDelete = cast(DeleteDeclaration)search(Loc(), Id.classDelete);
906 
907         // Look for the constructor
908         ctor = searchCtor();
909 
910         if (!ctor && noDefaultCtor)
911         {
912             // A class object is always created by constructor, so this check is legitimate.
913             foreach (v; fields)
914             {
915                 if (v.storage_class & STCnodefaultctor)
916                     .error(v.loc, "field %s must be initialized in constructor", v.toChars());
917             }
918         }
919 
920         // If this class has no constructor, but base class has a default
921         // ctor, create a constructor:
922         //    this() { }
923         if (!ctor && baseClass && baseClass.ctor)
924         {
925             auto fd = resolveFuncCall(loc, sc2, baseClass.ctor, null, null, null, 1);
926             if (fd && !fd.errors)
927             {
928                 //printf("Creating default this(){} for class %s\n", toChars());
929                 auto btf = cast(TypeFunction)fd.type;
930                 auto tf = new TypeFunction(null, null, 0, LINKd, fd.storage_class);
931                 tf.purity    = btf.purity;
932                 tf.isnothrow = btf.isnothrow;
933                 tf.isnogc    = btf.isnogc;
934                 tf.trust     = btf.trust;
935 
936                 auto ctor = new CtorDeclaration(loc, Loc(), 0, tf);
937                 ctor.fbody = new CompoundStatement(Loc(), new Statements());
938 
939                 members.push(ctor);
940                 ctor.addMember(sc, this);
941                 ctor.semantic(sc2);
942 
943                 this.ctor = ctor;
944                 defaultCtor = ctor;
945             }
946             else
947             {
948                 error("cannot implicitly generate a default ctor when base class %s is missing a default ctor",
949                     baseClass.toPrettyChars());
950             }
951         }
952 
953         dtor = buildDtor(this, sc2);
954 
955         if (auto f = hasIdentityOpAssign(this, sc2))
956         {
957             if (!(f.storage_class & STCdisable))
958                 error(f.loc, "identity assignment operator overload is illegal");
959         }
960 
961         inv = buildInv(this, sc2);
962 
963         Module.dprogress++;
964         semanticRun = PASSsemanticdone;
965         //printf("-ClassDeclaration.semantic(%s), type = %p\n", toChars(), type);
966         //members.print();
967 
968         sc2.pop();
969 
970         if (global.errors != errors)
971         {
972             // The type is no good.
973             type = Type.terror;
974             this.errors = true;
975             if (deferred)
976                 deferred.errors = true;
977         }
978 
979         // Verify fields of a synchronized class are not public
980         if (storage_class & STCsynchronized)
981         {
982             foreach (vd; this.fields)
983             {
984                 if (!vd.isThisDeclaration() &&
985                     !vd.prot().isMoreRestrictiveThan(Prot(PROTpublic)))
986                 {
987                     vd.error("Field members of a synchronized class cannot be %s",
988                         protectionToChars(vd.prot().kind));
989                 }
990             }
991         }
992 
993         if (deferred && !global.gag)
994         {
995             deferred.semantic2(sc);
996             deferred.semantic3(sc);
997         }
998 
999         version (none)
1000         {
1001             if (type.ty == Tclass && (cast(TypeClass)type).sym != this)
1002             {
1003                 printf("this = %p %s\n", this, this.toChars());
1004                 printf("type = %d sym = %p\n", type.ty, (cast(TypeClass)type).sym);
1005             }
1006         }
1007         assert(type.ty != Tclass || (cast(TypeClass)type).sym == this);
1008         //printf("-ClassDeclaration.semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
1009     }
1010 
1011     /*********************************************
1012      * Determine if 'this' is a base class of cd.
1013      * This is used to detect circular inheritance only.
1014      */
1015     final bool isBaseOf2(ClassDeclaration cd)
1016     {
1017         if (!cd)
1018             return false;
1019         //printf("ClassDeclaration.isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
1020         for (size_t i = 0; i < cd.baseclasses.dim; i++)
1021         {
1022             BaseClass* b = (*cd.baseclasses)[i];
1023             if (b.sym == this || isBaseOf2(b.sym))
1024                 return true;
1025         }
1026         return false;
1027     }
1028 
1029     enum OFFSET_RUNTIME = 0x76543210;
1030 
1031     /*******************************************
1032      * Determine if 'this' is a base class of cd.
1033      */
1034     bool isBaseOf(ClassDeclaration cd, int* poffset)
1035     {
1036         //printf("ClassDeclaration.isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd.toChars());
1037         if (poffset)
1038             *poffset = 0;
1039         while (cd)
1040         {
1041             /* cd.baseClass might not be set if cd is forward referenced.
1042              */
1043             if (!cd.baseClass && cd._scope && !cd.isInterfaceDeclaration())
1044             {
1045                 cd.semantic(null);
1046                 if (!cd.baseClass && cd._scope)
1047                     cd.error("base class is forward referenced by %s", toChars());
1048             }
1049 
1050             if (this == cd.baseClass)
1051                 return true;
1052 
1053             cd = cd.baseClass;
1054         }
1055         return false;
1056     }
1057 
1058     /*********************************************
1059      * Determine if 'this' has complete base class information.
1060      * This is used to detect forward references in covariant overloads.
1061      */
1062     final bool isBaseInfoComplete() const
1063     {
1064         return baseok >= BASEOKdone;
1065     }
1066 
1067     override final Dsymbol search(Loc loc, Identifier ident, int flags = SearchLocalsOnly)
1068     {
1069         //printf("%s.ClassDeclaration.search('%s', flags=x%x)\n", toChars(), ident.toChars(), flags);
1070         //if (_scope) printf("%s baseok = %d\n", toChars(), baseok);
1071         if (_scope && baseok < BASEOKdone)
1072         {
1073             if (!inuse)
1074             {
1075                 // must semantic on base class/interfaces
1076                 ++inuse;
1077                 semantic(null);
1078                 --inuse;
1079             }
1080         }
1081 
1082         if (!members || !symtab) // opaque or addMember is not yet done
1083         {
1084             error("is forward referenced when looking for '%s'", ident.toChars());
1085             //*(char*)0=0;
1086             return null;
1087         }
1088 
1089         auto s = ScopeDsymbol.search(loc, ident, flags);
1090 
1091         // don't search imports of base classes
1092         if (flags & SearchImportsOnly)
1093             return s;
1094 
1095         if (!s)
1096         {
1097             // Search bases classes in depth-first, left to right order
1098             for (size_t i = 0; i < baseclasses.dim; i++)
1099             {
1100                 BaseClass* b = (*baseclasses)[i];
1101                 if (b.sym)
1102                 {
1103                     if (!b.sym.symtab)
1104                         error("base %s is forward referenced", b.sym.ident.toChars());
1105                     else
1106                     {
1107                         import ddmd.access : symbolIsVisible;
1108 
1109                         s = b.sym.search(loc, ident, flags);
1110                         if (!s)
1111                             continue;
1112                         else if (s == this) // happens if s is nested in this and derives from this
1113                             s = null;
1114                         else if (!(flags & IgnoreSymbolVisibility) && !(s.prot().kind == PROTprotected) && !symbolIsVisible(this, s))
1115                             s = null;
1116                         else
1117                             break;
1118                     }
1119                 }
1120             }
1121         }
1122         return s;
1123     }
1124 
1125     /************************************
1126      * Search base classes in depth-first, left-to-right order for
1127      * a class or interface named 'ident'.
1128      * Stops at first found. Does not look for additional matches.
1129      * Params:
1130      *  ident = identifier to search for
1131      * Returns:
1132      *  ClassDeclaration if found, null if not
1133      */
1134     final ClassDeclaration searchBase(Identifier ident)
1135     {
1136         foreach (b; *baseclasses)
1137         {
1138             auto cdb = b.type.isClassHandle();
1139             if (!cdb) // Bugzilla 10616
1140                 return null;
1141             if (cdb.ident.equals(ident))
1142                 return cdb;
1143             auto result = cdb.searchBase(ident);
1144             if (result)
1145                 return result;
1146         }
1147         return null;
1148     }
1149 
1150     final override void finalizeSize()
1151     {
1152         assert(sizeok != SIZEOKdone);
1153 
1154         // Set the offsets of the fields and determine the size of the class
1155         if (baseClass)
1156         {
1157             assert(baseClass.sizeok == SIZEOKdone);
1158 
1159             alignsize = baseClass.alignsize;
1160             structsize = baseClass.structsize;
1161             if (cpp && global.params.isWindows)
1162                 structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
1163         }
1164         else if (isInterfaceDeclaration())
1165         {
1166             if (interfaces.length == 0)
1167             {
1168                 alignsize = Target.ptrsize;
1169                 structsize = Target.ptrsize;      // allow room for __vptr
1170             }
1171         }
1172         else
1173         {
1174             alignsize = Target.ptrsize;
1175             structsize = Target.ptrsize;      // allow room for __vptr
1176             if (!cpp)
1177                 structsize += Target.ptrsize; // allow room for __monitor
1178         }
1179 
1180         //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
1181         size_t bi = 0;                  // index into vtblInterfaces[]
1182 
1183         /****
1184          * Runs through the inheritance graph to set the BaseClass.offset fields.
1185          * Recursive in order to account for the size of the interface classes, if they are
1186          * more than just interfaces.
1187          * Params:
1188          *      cd = interface to look at
1189          *      baseOffset = offset of where cd will be placed
1190          * Returns:
1191          *      subset of instantiated size used by cd for interfaces
1192          */
1193         uint membersPlace(ClassDeclaration cd, uint baseOffset)
1194         {
1195             //printf("    membersPlace(%s, %d)\n", cd.toChars(), baseOffset);
1196             uint offset = baseOffset;
1197 
1198             foreach (BaseClass* b; cd.interfaces)
1199             {
1200                 if (b.sym.sizeok != SIZEOKdone)
1201                     b.sym.finalizeSize();
1202                 assert(b.sym.sizeok == SIZEOKdone);
1203 
1204                 if (!b.sym.alignsize)
1205                     b.sym.alignsize = Target.ptrsize;
1206                 alignmember(b.sym.alignsize, b.sym.alignsize, &offset);
1207                 assert(bi < vtblInterfaces.dim);
1208 
1209                 BaseClass* bv = (*vtblInterfaces)[bi];
1210                 if (b.sym.interfaces.length == 0)
1211                 {
1212                     //printf("\tvtblInterfaces[%d] b=%p b.sym = %s, offset = %d\n", bi, bv, bv.sym.toChars(), offset);
1213                     bv.offset = offset;
1214                     ++bi;
1215                     // All the base interfaces down the left side share the same offset
1216                     for (BaseClass* b2 = bv; b2.baseInterfaces.length; )
1217                     {
1218                         b2 = &b2.baseInterfaces[0];
1219                         b2.offset = offset;
1220                         //printf("\tvtblInterfaces[%d] b=%p   sym = %s, offset = %d\n", bi, b2, b2.sym.toChars(), b2.offset);
1221                     }
1222                 }
1223                 membersPlace(b.sym, offset);
1224                 //printf(" %s size = %d\n", b.sym.toChars(), b.sym.structsize);
1225                 offset += b.sym.structsize;
1226                 if (alignsize < b.sym.alignsize)
1227                     alignsize = b.sym.alignsize;
1228             }
1229             return offset - baseOffset;
1230         }
1231 
1232         structsize += membersPlace(this, structsize);
1233 
1234         if (isInterfaceDeclaration())
1235         {
1236             sizeok = SIZEOKdone;
1237             return;
1238         }
1239 
1240         // FIXME: Currently setFieldOffset functions need to increase fields
1241         // to calculate each variable offsets. It can be improved later.
1242         fields.setDim(0);
1243 
1244         uint offset = structsize;
1245         foreach (s; *members)
1246         {
1247             s.setFieldOffset(this, &offset, false);
1248         }
1249 
1250         sizeok = SIZEOKdone;
1251 
1252         // Calculate fields[i].overlapped
1253         checkOverlappedFields();
1254     }
1255 
1256     final bool isFuncHidden(FuncDeclaration fd)
1257     {
1258         //printf("ClassDeclaration.isFuncHidden(class = %s, fd = %s)\n", toChars(), fd.toChars());
1259         Dsymbol s = search(Loc(), fd.ident, IgnoreAmbiguous | IgnoreErrors);
1260         if (!s)
1261         {
1262             //printf("not found\n");
1263             /* Because, due to a hack, if there are multiple definitions
1264              * of fd.ident, NULL is returned.
1265              */
1266             return false;
1267         }
1268         s = s.toAlias();
1269         if (auto os = s.isOverloadSet())
1270         {
1271             foreach (sm; os.a)
1272             {
1273                 auto fm = sm.isFuncDeclaration();
1274                 if (overloadApply(fm, s => fd == s.isFuncDeclaration()))
1275                     return false;
1276             }
1277             return true;
1278         }
1279         else
1280         {
1281             auto f = s.isFuncDeclaration();
1282             //printf("%s fdstart = %p\n", s.kind(), fdstart);
1283             if (overloadApply(f, s => fd == s.isFuncDeclaration()))
1284                 return false;
1285             return !fd.parent.isTemplateMixin();
1286         }
1287     }
1288 
1289     /****************
1290      * Find virtual function matching identifier and type.
1291      * Used to build virtual function tables for interface implementations.
1292      * Params:
1293      *  ident = function's identifier
1294      *  tf = function's type
1295      * Returns:
1296      *  function symbol if found, null if not
1297      * Errors:
1298      *  prints error message if more than one match
1299      */
1300     final FuncDeclaration findFunc(Identifier ident, TypeFunction tf)
1301     {
1302         //printf("ClassDeclaration.findFunc(%s, %s) %s\n", ident.toChars(), tf.toChars(), toChars());
1303         FuncDeclaration fdmatch = null;
1304         FuncDeclaration fdambig = null;
1305 
1306         void searchVtbl(ref Dsymbols vtbl)
1307         {
1308             foreach (s; vtbl)
1309             {
1310                 auto fd = s.isFuncDeclaration();
1311                 if (!fd)
1312                     continue;
1313 
1314                 // the first entry might be a ClassInfo
1315                 //printf("\t[%d] = %s\n", i, fd.toChars());
1316                 if (ident == fd.ident && fd.type.covariant(tf) == 1)
1317                 {
1318                     //printf("fd.parent.isClassDeclaration() = %p\n", fd.parent.isClassDeclaration());
1319                     if (!fdmatch)
1320                         goto Lfd;
1321                     if (fd == fdmatch)
1322                         goto Lfdmatch;
1323 
1324                     {
1325                     // Function type matcing: exact > covariant
1326                     MATCH m1 = tf.equals(fd.type) ? MATCHexact : MATCHnomatch;
1327                     MATCH m2 = tf.equals(fdmatch.type) ? MATCHexact : MATCHnomatch;
1328                     if (m1 > m2)
1329                         goto Lfd;
1330                     else if (m1 < m2)
1331                         goto Lfdmatch;
1332                     }
1333                     {
1334                     MATCH m1 = (tf.mod == fd.type.mod) ? MATCHexact : MATCHnomatch;
1335                     MATCH m2 = (tf.mod == fdmatch.type.mod) ? MATCHexact : MATCHnomatch;
1336                     if (m1 > m2)
1337                         goto Lfd;
1338                     else if (m1 < m2)
1339                         goto Lfdmatch;
1340                     }
1341                     {
1342                     // The way of definition: non-mixin > mixin
1343                     MATCH m1 = fd.parent.isClassDeclaration() ? MATCHexact : MATCHnomatch;
1344                     MATCH m2 = fdmatch.parent.isClassDeclaration() ? MATCHexact : MATCHnomatch;
1345                     if (m1 > m2)
1346                         goto Lfd;
1347                     else if (m1 < m2)
1348                         goto Lfdmatch;
1349                     }
1350 
1351                     fdambig = fd;
1352                     //printf("Lambig fdambig = %s %s [%s]\n", fdambig.toChars(), fdambig.type.toChars(), fdambig.loc.toChars());
1353                     continue;
1354 
1355                 Lfd:
1356                     fdmatch = fd;
1357                     fdambig = null;
1358                     //printf("Lfd fdmatch = %s %s [%s]\n", fdmatch.toChars(), fdmatch.type.toChars(), fdmatch.loc.toChars());
1359                     continue;
1360 
1361                 Lfdmatch:
1362                     continue;
1363                 }
1364                 //else printf("\t\t%d\n", fd.type.covariant(tf));
1365             }
1366         }
1367 
1368         searchVtbl(vtbl);
1369         for (auto cd = this; cd; cd = cd.baseClass)
1370         {
1371             searchVtbl(cd.vtblFinal);
1372         }
1373 
1374         if (fdambig)
1375             error("ambiguous virtual function %s", fdambig.toChars());
1376 
1377         return fdmatch;
1378     }
1379 
1380     final void interfaceSemantic(Scope* sc)
1381     {
1382         vtblInterfaces = new BaseClasses();
1383         vtblInterfaces.reserve(interfaces.length);
1384         foreach (b; interfaces)
1385         {
1386             vtblInterfaces.push(b);
1387             b.copyBaseInterfaces(vtblInterfaces);
1388         }
1389     }
1390 
1391 
1392     /****************************************
1393      */
1394     final bool isCOMclass() const
1395     {
1396         return com;
1397     }
1398 
1399     bool isCOMinterface() const
1400     {
1401         return false;
1402     }
1403 
1404     final bool isCPPclass() const
1405     {
1406         return cpp;
1407     }
1408 
1409     bool isCPPinterface() const
1410     {
1411         return false;
1412     }
1413 
1414     /****************************************
1415      */
1416     final bool isAbstract()
1417     {
1418         if (isabstract != ABSfwdref)
1419             return isabstract == ABSyes;
1420 
1421         /* Bugzilla 11169: Resolve forward references to all class member functions,
1422          * and determine whether this class is abstract.
1423          */
1424         extern (C++) static int func(Dsymbol s, void* param)
1425         {
1426             auto fd = s.isFuncDeclaration();
1427             if (!fd)
1428                 return 0;
1429             if (fd.storage_class & STCstatic)
1430                 return 0;
1431 
1432             if (fd._scope)
1433                 fd.semantic(null);
1434 
1435             if (fd.isAbstract())
1436                 return 1;
1437             return 0;
1438         }
1439 
1440         for (size_t i = 0; i < members.dim; i++)
1441         {
1442             auto s = (*members)[i];
1443             if (s.apply(&func, cast(void*)this))
1444             {
1445                 isabstract = ABSyes;
1446                 return true;
1447             }
1448         }
1449 
1450         /* Iterate inherited member functions and check their abstract attribute.
1451          */
1452         for (size_t i = 1; i < vtbl.dim; i++)
1453         {
1454             auto fd = vtbl[i].isFuncDeclaration();
1455             //if (fd) printf("\tvtbl[%d] = [%s] %s\n", i, fd.loc.toChars(), fd.toChars());
1456             if (!fd || fd.isAbstract())
1457             {
1458                 isabstract = ABSyes;
1459                 return true;
1460             }
1461         }
1462 
1463         isabstract = ABSno;
1464         return false;
1465     }
1466 
1467     /****************************************
1468      * Determine if slot 0 of the vtbl[] is reserved for something else.
1469      * For class objects, yes, this is where the classinfo ptr goes.
1470      * For COM interfaces, no.
1471      * For non-COM interfaces, yes, this is where the Interface ptr goes.
1472      * Returns:
1473      *      0       vtbl[0] is first virtual function pointer
1474      *      1       vtbl[0] is classinfo/interfaceinfo pointer
1475      */
1476     int vtblOffset() const
1477     {
1478         return cpp ? 0 : 1;
1479     }
1480 
1481     /****************************************
1482      */
1483     override const(char)* kind() const
1484     {
1485         return "class";
1486     }
1487 
1488     /****************************************
1489      */
1490     override final void addLocalClass(ClassDeclarations* aclasses)
1491     {
1492         aclasses.push(this);
1493     }
1494 
1495     // Back end
1496     Symbol* vtblsym;
1497 
1498     override final inout(ClassDeclaration) isClassDeclaration() inout
1499     {
1500         return this;
1501     }
1502 
1503     override void accept(Visitor v)
1504     {
1505         v.visit(this);
1506     }
1507 }
1508 
1509 /***********************************************************
1510  */
1511 extern (C++) final class InterfaceDeclaration : ClassDeclaration
1512 {
1513     extern (D) this(Loc loc, Identifier id, BaseClasses* baseclasses)
1514     {
1515         super(loc, id, baseclasses, null, false);
1516         if (id == Id.IUnknown) // IUnknown is the root of all COM interfaces
1517         {
1518             com = true;
1519             cpp = true; // IUnknown is also a C++ interface
1520         }
1521     }
1522 
1523     override Dsymbol syntaxCopy(Dsymbol s)
1524     {
1525         InterfaceDeclaration id =
1526             s ? cast(InterfaceDeclaration)s
1527               : new InterfaceDeclaration(loc, ident, null);
1528         return ClassDeclaration.syntaxCopy(id);
1529     }
1530 
1531 
1532     override Scope* newScope(Scope* sc)
1533     {
1534         auto sc2 = super.newScope(sc);
1535         if (com)
1536             sc2.linkage = LINKwindows;
1537         else if (cpp)
1538             sc2.linkage = LINKcpp;
1539         else if (objc.isInterface())
1540             sc2.linkage = LINKobjc;
1541         return sc2;
1542     }
1543 
1544     override void semantic(Scope* sc)
1545     {
1546         //printf("InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type);
1547         if (semanticRun >= PASSsemanticdone)
1548             return;
1549         int errors = global.errors;
1550 
1551         //printf("+InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type);
1552 
1553         Scope* scx = null;
1554         if (_scope)
1555         {
1556             sc = _scope;
1557             scx = _scope; // save so we don't make redundant copies
1558             _scope = null;
1559         }
1560 
1561         if (!parent)
1562         {
1563             assert(sc.parent && sc.func);
1564             parent = sc.parent;
1565         }
1566         assert(parent && !isAnonymous());
1567 
1568         if (this.errors)
1569             type = Type.terror;
1570         type = type.semantic(loc, sc);
1571         if (type.ty == Tclass && (cast(TypeClass)type).sym != this)
1572         {
1573             auto ti = (cast(TypeClass)type).sym.isInstantiated();
1574             if (ti && isError(ti))
1575                 (cast(TypeClass)type).sym = this;
1576         }
1577 
1578         // Ungag errors when not speculative
1579         Ungag ungag = ungagSpeculative();
1580 
1581         if (semanticRun == PASSinit)
1582         {
1583             protection = sc.protection;
1584 
1585             storage_class |= sc.stc;
1586             if (storage_class & STCdeprecated)
1587                 isdeprecated = true;
1588 
1589             userAttribDecl = sc.userAttribDecl;
1590         }
1591         else if (symtab)
1592         {
1593             if (sizeok == SIZEOKdone || !scx)
1594             {
1595                 semanticRun = PASSsemanticdone;
1596                 return;
1597             }
1598         }
1599         semanticRun = PASSsemantic;
1600 
1601         if (baseok < BASEOKdone)
1602         {
1603             T resolveBase(T)(lazy T exp)
1604             {
1605                 if (!scx)
1606                 {
1607                     scx = sc.copy();
1608                     scx.setNoFree();
1609                 }
1610                 static if (!is(T == void))
1611                 {
1612                     _scope = scx;
1613                     auto r = exp();
1614                     _scope = null;
1615                     return r;
1616                 }
1617                 else
1618                 {
1619                     _scope = scx;
1620                     exp();
1621                     _scope = null;
1622                 }
1623             }
1624 
1625             baseok = BASEOKin;
1626 
1627             // Expand any tuples in baseclasses[]
1628             for (size_t i = 0; i < baseclasses.dim;)
1629             {
1630                 auto b = (*baseclasses)[i];
1631                 b.type = resolveBase(b.type.semantic(loc, sc));
1632 
1633                 Type tb = b.type.toBasetype();
1634                 if (tb.ty == Ttuple)
1635                 {
1636                     TypeTuple tup = cast(TypeTuple)tb;
1637                     baseclasses.remove(i);
1638                     size_t dim = Parameter.dim(tup.arguments);
1639                     for (size_t j = 0; j < dim; j++)
1640                     {
1641                         Parameter arg = Parameter.getNth(tup.arguments, j);
1642                         b = new BaseClass(arg.type);
1643                         baseclasses.insert(i + j, b);
1644                     }
1645                 }
1646                 else
1647                     i++;
1648             }
1649 
1650             if (baseok >= BASEOKdone)
1651             {
1652                 //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
1653                 if (semanticRun >= PASSsemanticdone)
1654                     return;
1655                 goto Lancestorsdone;
1656             }
1657 
1658             if (!baseclasses.dim && sc.linkage == LINKcpp)
1659                 cpp = true;
1660 
1661             objc_InterfaceDeclaration_semantic_objcExtern(this, sc);
1662 
1663             // Check for errors, handle forward references
1664             for (size_t i = 0; i < baseclasses.dim;)
1665             {
1666                 BaseClass* b = (*baseclasses)[i];
1667                 Type tb = b.type.toBasetype();
1668                 TypeClass tc = (tb.ty == Tclass) ? cast(TypeClass)tb : null;
1669                 if (!tc || !tc.sym.isInterfaceDeclaration())
1670                 {
1671                     if (b.type != Type.terror)
1672                         error("base type must be interface, not %s", b.type.toChars());
1673                     baseclasses.remove(i);
1674                     continue;
1675                 }
1676 
1677                 // Check for duplicate interfaces
1678                 for (size_t j = 0; j < i; j++)
1679                 {
1680                     BaseClass* b2 = (*baseclasses)[j];
1681                     if (b2.sym == tc.sym)
1682                     {
1683                         error("inherits from duplicate interface %s", b2.sym.toChars());
1684                         baseclasses.remove(i);
1685                         continue;
1686                     }
1687                 }
1688                 if (tc.sym == this || isBaseOf2(tc.sym))
1689                 {
1690                     error("circular inheritance of interface");
1691                     baseclasses.remove(i);
1692                     continue;
1693                 }
1694                 if (tc.sym.isDeprecated())
1695                 {
1696                     if (!isDeprecated())
1697                     {
1698                         // Deriving from deprecated class makes this one deprecated too
1699                         isdeprecated = true;
1700                         tc.checkDeprecated(loc, sc);
1701                     }
1702                 }
1703 
1704                 b.sym = tc.sym;
1705 
1706                 if (tc.sym._scope && tc.sym.baseok < BASEOKdone)
1707                     resolveBase(tc.sym.semantic(null)); // Try to resolve forward reference
1708                 if (tc.sym.baseok < BASEOKdone)
1709                 {
1710                     //printf("\ttry later, forward reference of base %s\n", tc.sym.toChars());
1711                     if (tc.sym._scope)
1712                         tc.sym._scope._module.addDeferredSemantic(tc.sym);
1713                     baseok = BASEOKnone;
1714                 }
1715                 i++;
1716             }
1717             if (baseok == BASEOKnone)
1718             {
1719                 // Forward referencee of one or more bases, try again later
1720                 _scope = scx ? scx : sc.copy();
1721                 _scope.setNoFree();
1722                 _scope._module.addDeferredSemantic(this);
1723                 return;
1724             }
1725             baseok = BASEOKdone;
1726 
1727             interfaces = baseclasses.tdata()[0 .. baseclasses.dim];
1728             foreach (b; interfaces)
1729             {
1730                 // If this is an interface, and it derives from a COM interface,
1731                 // then this is a COM interface too.
1732                 if (b.sym.isCOMinterface())
1733                     com = true;
1734                 if (b.sym.isCPPinterface())
1735                     cpp = true;
1736             }
1737 
1738             interfaceSemantic(sc);
1739         }
1740     Lancestorsdone:
1741 
1742         if (!members) // if opaque declaration
1743         {
1744             semanticRun = PASSsemanticdone;
1745             return;
1746         }
1747         if (!symtab)
1748             symtab = new DsymbolTable();
1749 
1750         for (size_t i = 0; i < baseclasses.dim; i++)
1751         {
1752             BaseClass* b = (*baseclasses)[i];
1753             Type tb = b.type.toBasetype();
1754             assert(tb.ty == Tclass);
1755             TypeClass tc = cast(TypeClass)tb;
1756             if (tc.sym.semanticRun < PASSsemanticdone)
1757             {
1758                 // Forward referencee of one or more bases, try again later
1759                 _scope = scx ? scx : sc.copy();
1760                 _scope.setNoFree();
1761                 if (tc.sym._scope)
1762                     tc.sym._scope._module.addDeferredSemantic(tc.sym);
1763                 _scope._module.addDeferredSemantic(this);
1764                 return;
1765             }
1766         }
1767 
1768         if (baseok == BASEOKdone)
1769         {
1770             baseok = BASEOKsemanticdone;
1771 
1772             // initialize vtbl
1773             if (vtblOffset())
1774                 vtbl.push(this); // leave room at vtbl[0] for classinfo
1775 
1776             // Cat together the vtbl[]'s from base interfaces
1777             foreach (i, b; interfaces)
1778             {
1779                 // Skip if b has already appeared
1780                 for (size_t k = 0; k < i; k++)
1781                 {
1782                     if (b == interfaces[k])
1783                         goto Lcontinue;
1784                 }
1785 
1786                 // Copy vtbl[] from base class
1787                 if (b.sym.vtblOffset())
1788                 {
1789                     size_t d = b.sym.vtbl.dim;
1790                     if (d > 1)
1791                     {
1792                         vtbl.reserve(d - 1);
1793                         for (size_t j = 1; j < d; j++)
1794                             vtbl.push(b.sym.vtbl[j]);
1795                     }
1796                 }
1797                 else
1798                 {
1799                     vtbl.append(&b.sym.vtbl);
1800                 }
1801 
1802             Lcontinue:
1803             }
1804         }
1805 
1806         for (size_t i = 0; i < members.dim; i++)
1807         {
1808             Dsymbol s = (*members)[i];
1809             s.addMember(sc, this);
1810         }
1811 
1812         auto sc2 = newScope(sc);
1813 
1814         /* Set scope so if there are forward references, we still might be able to
1815          * resolve individual members like enums.
1816          */
1817         for (size_t i = 0; i < members.dim; i++)
1818         {
1819             Dsymbol s = (*members)[i];
1820             //printf("setScope %s %s\n", s.kind(), s.toChars());
1821             s.setScope(sc2);
1822         }
1823 
1824         for (size_t i = 0; i < members.dim; i++)
1825         {
1826             Dsymbol s = (*members)[i];
1827             s.importAll(sc2);
1828         }
1829 
1830         for (size_t i = 0; i < members.dim; i++)
1831         {
1832             Dsymbol s = (*members)[i];
1833             s.semantic(sc2);
1834         }
1835 
1836         Module.dprogress++;
1837         semanticRun = PASSsemanticdone;
1838         //printf("-InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type);
1839         //members.print();
1840 
1841         sc2.pop();
1842 
1843         if (global.errors != errors)
1844         {
1845             // The type is no good.
1846             type = Type.terror;
1847         }
1848 
1849         version (none)
1850         {
1851             if (type.ty == Tclass && (cast(TypeClass)type).sym != this)
1852             {
1853                 printf("this = %p %s\n", this, this.toChars());
1854                 printf("type = %d sym = %p\n", type.ty, (cast(TypeClass)type).sym);
1855             }
1856         }
1857         assert(type.ty != Tclass || (cast(TypeClass)type).sym == this);
1858     }
1859 
1860     /*******************************************
1861      * Determine if 'this' is a base class of cd.
1862      * (Actually, if it is an interface supported by cd)
1863      * Output:
1864      *      *poffset        offset to start of class
1865      *                      OFFSET_RUNTIME  must determine offset at runtime
1866      * Returns:
1867      *      false   not a base
1868      *      true    is a base
1869      */
1870     override bool isBaseOf(ClassDeclaration cd, int* poffset)
1871     {
1872         //printf("%s.InterfaceDeclaration.isBaseOf(cd = '%s')\n", toChars(), cd.toChars());
1873         assert(!baseClass);
1874         foreach (j, b; cd.interfaces)
1875         {
1876             //printf("\tX base %s\n", b.sym.toChars());
1877             if (this == b.sym)
1878             {
1879                 //printf("\tfound at offset %d\n", b.offset);
1880                 if (poffset)
1881                     *poffset = b.offset;
1882                 return true;
1883             }
1884             if (isBaseOf(b, poffset))
1885                 return true;
1886         }
1887         if (cd.baseClass && isBaseOf(cd.baseClass, poffset))
1888             return true;
1889 
1890         if (poffset)
1891             *poffset = 0;
1892         return false;
1893     }
1894 
1895     bool isBaseOf(BaseClass* bc, int* poffset)
1896     {
1897         //printf("%s.InterfaceDeclaration.isBaseOf(bc = '%s')\n", toChars(), bc.sym.toChars());
1898         for (size_t j = 0; j < bc.baseInterfaces.length; j++)
1899         {
1900             BaseClass* b = &bc.baseInterfaces[j];
1901             //printf("\tY base %s\n", b.sym.toChars());
1902             if (this == b.sym)
1903             {
1904                 //printf("\tfound at offset %d\n", b.offset);
1905                 if (poffset)
1906                 {
1907                     *poffset = b.offset;
1908                 }
1909                 return true;
1910             }
1911             if (isBaseOf(b, poffset))
1912             {
1913                 return true;
1914             }
1915         }
1916 
1917         if (poffset)
1918             *poffset = 0;
1919         return false;
1920     }
1921 
1922     /*******************************************
1923      */
1924     override const(char)* kind() const
1925     {
1926         return "interface";
1927     }
1928 
1929     /****************************************
1930      * Determine if slot 0 of the vtbl[] is reserved for something else.
1931      * For class objects, yes, this is where the ClassInfo ptr goes.
1932      * For COM interfaces, no.
1933      * For non-COM interfaces, yes, this is where the Interface ptr goes.
1934      */
1935     override int vtblOffset() const
1936     {
1937         if (isCOMinterface() || isCPPinterface())
1938             return 0;
1939         return 1;
1940     }
1941 
1942     override bool isCPPinterface() const
1943     {
1944         return cpp;
1945     }
1946 
1947     override bool isCOMinterface() const
1948     {
1949         return com;
1950     }
1951 
1952     override inout(InterfaceDeclaration) isInterfaceDeclaration() inout
1953     {
1954         return this;
1955     }
1956 
1957     override void accept(Visitor v)
1958     {
1959         v.visit(this);
1960     }
1961 }