xref: /netbsd/external/gpl3/gcc.old/dist/gcc/d/dmd/dclass.c (revision 0bfacb9b)
1760c2415Smrg 
2760c2415Smrg /* Compiler implementation of the D programming language
3760c2415Smrg  * Copyright (C) 1999-2019 by The D Language Foundation, All Rights Reserved
4760c2415Smrg  * written by Walter Bright
5760c2415Smrg  * http://www.digitalmars.com
6760c2415Smrg  * Distributed under the Boost Software License, Version 1.0.
7760c2415Smrg  * http://www.boost.org/LICENSE_1_0.txt
8760c2415Smrg  * https://github.com/D-Programming-Language/dmd/blob/master/src/class.c
9760c2415Smrg  */
10760c2415Smrg 
11760c2415Smrg #include "root/dsystem.h"               // mem{cpy|set}()
12760c2415Smrg #include "root/root.h"
13760c2415Smrg #include "root/rmem.h"
14760c2415Smrg 
15760c2415Smrg #include "errors.h"
16760c2415Smrg #include "enum.h"
17760c2415Smrg #include "init.h"
18760c2415Smrg #include "attrib.h"
19760c2415Smrg #include "declaration.h"
20760c2415Smrg #include "aggregate.h"
21760c2415Smrg #include "id.h"
22760c2415Smrg #include "mtype.h"
23760c2415Smrg #include "scope.h"
24760c2415Smrg #include "module.h"
25760c2415Smrg #include "expression.h"
26760c2415Smrg #include "statement.h"
27760c2415Smrg #include "template.h"
28760c2415Smrg #include "target.h"
29760c2415Smrg #include "objc.h"
30760c2415Smrg 
31760c2415Smrg bool symbolIsVisible(Dsymbol *origin, Dsymbol *s);
32760c2415Smrg Objc *objc();
33760c2415Smrg 
34760c2415Smrg 
35760c2415Smrg /********************************* ClassDeclaration ****************************/
36760c2415Smrg 
37760c2415Smrg ClassDeclaration *ClassDeclaration::object;
38760c2415Smrg ClassDeclaration *ClassDeclaration::throwable;
39760c2415Smrg ClassDeclaration *ClassDeclaration::exception;
40760c2415Smrg ClassDeclaration *ClassDeclaration::errorException;
41760c2415Smrg ClassDeclaration *ClassDeclaration::cpp_type_info_ptr;   // Object.__cpp_type_info_ptr
42760c2415Smrg 
ClassDeclaration(Loc loc,Identifier * id,BaseClasses * baseclasses,Dsymbols * members,bool inObject)43760c2415Smrg ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject)
44760c2415Smrg     : AggregateDeclaration(loc, id ? id : Identifier::generateId("__anonclass"))
45760c2415Smrg {
46760c2415Smrg     static const char msg[] = "only object.d can define this reserved class name";
47760c2415Smrg 
48760c2415Smrg     if (baseclasses)
49760c2415Smrg     {
50760c2415Smrg         // Actually, this is a transfer
51760c2415Smrg         this->baseclasses = baseclasses;
52760c2415Smrg     }
53760c2415Smrg     else
54760c2415Smrg         this->baseclasses = new BaseClasses();
55760c2415Smrg 
56760c2415Smrg     this->members = members;
57760c2415Smrg 
58760c2415Smrg     baseClass = NULL;
59760c2415Smrg 
60760c2415Smrg     interfaces.length = 0;
61760c2415Smrg     interfaces.ptr = NULL;
62760c2415Smrg 
63760c2415Smrg     vtblInterfaces = NULL;
64760c2415Smrg 
65760c2415Smrg     //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses->dim);
66760c2415Smrg 
67760c2415Smrg     // For forward references
68760c2415Smrg     type = new TypeClass(this);
69760c2415Smrg 
70760c2415Smrg     staticCtor = NULL;
71760c2415Smrg     staticDtor = NULL;
72760c2415Smrg 
73760c2415Smrg     vtblsym = NULL;
74760c2415Smrg     vclassinfo = NULL;
75760c2415Smrg 
76760c2415Smrg     if (id)
77760c2415Smrg     {
78760c2415Smrg         // Look for special class names
79760c2415Smrg 
80760c2415Smrg         if (id == Id::__sizeof || id == Id::__xalignof || id == Id::_mangleof)
81760c2415Smrg             error("illegal class name");
82760c2415Smrg 
83760c2415Smrg         // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
84760c2415Smrg         if (id->toChars()[0] == 'T')
85760c2415Smrg         {
86760c2415Smrg             if (id == Id::TypeInfo)
87760c2415Smrg             {
88760c2415Smrg                 if (!inObject)
89760c2415Smrg                     error("%s", msg);
90760c2415Smrg                 Type::dtypeinfo = this;
91760c2415Smrg             }
92760c2415Smrg 
93760c2415Smrg             if (id == Id::TypeInfo_Class)
94760c2415Smrg             {
95760c2415Smrg                 if (!inObject)
96760c2415Smrg                     error("%s", msg);
97760c2415Smrg                 Type::typeinfoclass = this;
98760c2415Smrg             }
99760c2415Smrg 
100760c2415Smrg             if (id == Id::TypeInfo_Interface)
101760c2415Smrg             {
102760c2415Smrg                 if (!inObject)
103760c2415Smrg                     error("%s", msg);
104760c2415Smrg                 Type::typeinfointerface = this;
105760c2415Smrg             }
106760c2415Smrg 
107760c2415Smrg             if (id == Id::TypeInfo_Struct)
108760c2415Smrg             {
109760c2415Smrg                 if (!inObject)
110760c2415Smrg                     error("%s", msg);
111760c2415Smrg                 Type::typeinfostruct = this;
112760c2415Smrg             }
113760c2415Smrg 
114760c2415Smrg             if (id == Id::TypeInfo_Pointer)
115760c2415Smrg             {
116760c2415Smrg                 if (!inObject)
117760c2415Smrg                     error("%s", msg);
118760c2415Smrg                 Type::typeinfopointer = this;
119760c2415Smrg             }
120760c2415Smrg 
121760c2415Smrg             if (id == Id::TypeInfo_Array)
122760c2415Smrg             {
123760c2415Smrg                 if (!inObject)
124760c2415Smrg                     error("%s", msg);
125760c2415Smrg                 Type::typeinfoarray = this;
126760c2415Smrg             }
127760c2415Smrg 
128760c2415Smrg             if (id == Id::TypeInfo_StaticArray)
129760c2415Smrg             {
130760c2415Smrg                 //if (!inObject)
131760c2415Smrg                 //    Type::typeinfostaticarray->error("%s", msg);
132760c2415Smrg                 Type::typeinfostaticarray = this;
133760c2415Smrg             }
134760c2415Smrg 
135760c2415Smrg             if (id == Id::TypeInfo_AssociativeArray)
136760c2415Smrg             {
137760c2415Smrg                 if (!inObject)
138760c2415Smrg                     error("%s", msg);
139760c2415Smrg                 Type::typeinfoassociativearray = this;
140760c2415Smrg             }
141760c2415Smrg 
142760c2415Smrg             if (id == Id::TypeInfo_Enum)
143760c2415Smrg             {
144760c2415Smrg                 if (!inObject)
145760c2415Smrg                     error("%s", msg);
146760c2415Smrg                 Type::typeinfoenum = this;
147760c2415Smrg             }
148760c2415Smrg 
149760c2415Smrg             if (id == Id::TypeInfo_Function)
150760c2415Smrg             {
151760c2415Smrg                 if (!inObject)
152760c2415Smrg                     error("%s", msg);
153760c2415Smrg                 Type::typeinfofunction = this;
154760c2415Smrg             }
155760c2415Smrg 
156760c2415Smrg             if (id == Id::TypeInfo_Delegate)
157760c2415Smrg             {
158760c2415Smrg                 if (!inObject)
159760c2415Smrg                     error("%s", msg);
160760c2415Smrg                 Type::typeinfodelegate = this;
161760c2415Smrg             }
162760c2415Smrg 
163760c2415Smrg             if (id == Id::TypeInfo_Tuple)
164760c2415Smrg             {
165760c2415Smrg                 if (!inObject)
166760c2415Smrg                     error("%s", msg);
167760c2415Smrg                 Type::typeinfotypelist = this;
168760c2415Smrg             }
169760c2415Smrg 
170760c2415Smrg             if (id == Id::TypeInfo_Const)
171760c2415Smrg             {
172760c2415Smrg                 if (!inObject)
173760c2415Smrg                     error("%s", msg);
174760c2415Smrg                 Type::typeinfoconst = this;
175760c2415Smrg             }
176760c2415Smrg 
177760c2415Smrg             if (id == Id::TypeInfo_Invariant)
178760c2415Smrg             {
179760c2415Smrg                 if (!inObject)
180760c2415Smrg                     error("%s", msg);
181760c2415Smrg                 Type::typeinfoinvariant = this;
182760c2415Smrg             }
183760c2415Smrg 
184760c2415Smrg             if (id == Id::TypeInfo_Shared)
185760c2415Smrg             {
186760c2415Smrg                 if (!inObject)
187760c2415Smrg                     error("%s", msg);
188760c2415Smrg                 Type::typeinfoshared = this;
189760c2415Smrg             }
190760c2415Smrg 
191760c2415Smrg             if (id == Id::TypeInfo_Wild)
192760c2415Smrg             {
193760c2415Smrg                 if (!inObject)
194760c2415Smrg                     error("%s", msg);
195760c2415Smrg                 Type::typeinfowild = this;
196760c2415Smrg             }
197760c2415Smrg 
198760c2415Smrg             if (id == Id::TypeInfo_Vector)
199760c2415Smrg             {
200760c2415Smrg                 if (!inObject)
201760c2415Smrg                     error("%s", msg);
202760c2415Smrg                 Type::typeinfovector = this;
203760c2415Smrg             }
204760c2415Smrg         }
205760c2415Smrg 
206760c2415Smrg         if (id == Id::Object)
207760c2415Smrg         {
208760c2415Smrg             if (!inObject)
209760c2415Smrg                 error("%s", msg);
210760c2415Smrg             object = this;
211760c2415Smrg         }
212760c2415Smrg 
213760c2415Smrg         if (id == Id::Throwable)
214760c2415Smrg         {
215760c2415Smrg             if (!inObject)
216760c2415Smrg                 error("%s", msg);
217760c2415Smrg             throwable = this;
218760c2415Smrg         }
219760c2415Smrg 
220760c2415Smrg         if (id == Id::Exception)
221760c2415Smrg         {
222760c2415Smrg             if (!inObject)
223760c2415Smrg                 error("%s", msg);
224760c2415Smrg             exception = this;
225760c2415Smrg         }
226760c2415Smrg 
227760c2415Smrg         if (id == Id::Error)
228760c2415Smrg         {
229760c2415Smrg             if (!inObject)
230760c2415Smrg                 error("%s", msg);
231760c2415Smrg             errorException = this;
232760c2415Smrg         }
233760c2415Smrg 
234760c2415Smrg         if (id == Id::cpp_type_info_ptr)
235760c2415Smrg         {
236760c2415Smrg             if (!inObject)
237760c2415Smrg                 error("%s", msg);
238760c2415Smrg             cpp_type_info_ptr = this;
239760c2415Smrg         }
240760c2415Smrg     }
241760c2415Smrg 
242760c2415Smrg     com = false;
243760c2415Smrg     isscope = false;
244760c2415Smrg     isabstract = ABSfwdref;
245760c2415Smrg     inuse = 0;
246760c2415Smrg     baseok = BASEOKnone;
247760c2415Smrg     cpp_type_info_ptr_sym = NULL;
248760c2415Smrg }
249760c2415Smrg 
create(Loc loc,Identifier * id,BaseClasses * baseclasses,Dsymbols * members,bool inObject)250760c2415Smrg ClassDeclaration *ClassDeclaration::create(Loc loc, Identifier *id, BaseClasses *baseclasses, Dsymbols *members, bool inObject)
251760c2415Smrg {
252760c2415Smrg     return new ClassDeclaration(loc, id, baseclasses, members, inObject);
253760c2415Smrg }
254760c2415Smrg 
syntaxCopy(Dsymbol * s)255760c2415Smrg Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
256760c2415Smrg {
257760c2415Smrg     //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
258760c2415Smrg     ClassDeclaration *cd =
259760c2415Smrg         s ? (ClassDeclaration *)s
260760c2415Smrg           : new ClassDeclaration(loc, ident, NULL, NULL, false);
261760c2415Smrg 
262760c2415Smrg     cd->storage_class |= storage_class;
263760c2415Smrg 
264760c2415Smrg     cd->baseclasses->setDim(this->baseclasses->dim);
265760c2415Smrg     for (size_t i = 0; i < cd->baseclasses->dim; i++)
266760c2415Smrg     {
267760c2415Smrg         BaseClass *b = (*this->baseclasses)[i];
268760c2415Smrg         BaseClass *b2 = new BaseClass(b->type->syntaxCopy());
269760c2415Smrg         (*cd->baseclasses)[i] = b2;
270760c2415Smrg     }
271760c2415Smrg 
272760c2415Smrg     return ScopeDsymbol::syntaxCopy(cd);
273760c2415Smrg }
274760c2415Smrg 
newScope(Scope * sc)275760c2415Smrg Scope *ClassDeclaration::newScope(Scope *sc)
276760c2415Smrg {
277760c2415Smrg     Scope *sc2 = AggregateDeclaration::newScope(sc);
278760c2415Smrg     if (isCOMclass())
279760c2415Smrg     {
280760c2415Smrg         if (global.params.isWindows)
281760c2415Smrg             sc2->linkage = LINKwindows;
282760c2415Smrg         else
283760c2415Smrg         {
284760c2415Smrg             /* This enables us to use COM objects under Linux and
285760c2415Smrg              * work with things like XPCOM
286760c2415Smrg              */
287760c2415Smrg             sc2->linkage = LINKc;
288760c2415Smrg         }
289760c2415Smrg     }
290760c2415Smrg     return sc2;
291760c2415Smrg }
292760c2415Smrg 
293760c2415Smrg /* Bugzilla 12078, 12143 and 15733:
294760c2415Smrg  * While resolving base classes and interfaces, a base may refer
295760c2415Smrg  * the member of this derived class. In that time, if all bases of
296760c2415Smrg  * this class can  be determined, we can go forward the semantc process
297760c2415Smrg  * beyond the Lancestorsdone. To do the recursive semantic analysis,
298760c2415Smrg  * temporarily set and unset `_scope` around exp().
299760c2415Smrg  */
resolveBase(ClassDeclaration * cd,Scope * sc,Scope * & scx,Type * type)300760c2415Smrg static Type *resolveBase(ClassDeclaration *cd, Scope *sc, Scope *&scx, Type *type)
301760c2415Smrg {
302760c2415Smrg     if (!scx)
303760c2415Smrg     {
304760c2415Smrg         scx = sc->copy();
305760c2415Smrg         scx->setNoFree();
306760c2415Smrg     }
307760c2415Smrg     cd->_scope = scx;
308760c2415Smrg     Type *t = type->semantic(cd->loc, sc);
309760c2415Smrg     cd->_scope = NULL;
310760c2415Smrg     return t;
311760c2415Smrg }
312760c2415Smrg 
resolveBase(ClassDeclaration * cd,Scope * sc,Scope * & scx,ClassDeclaration * sym)313760c2415Smrg static void resolveBase(ClassDeclaration *cd, Scope *sc, Scope *&scx, ClassDeclaration *sym)
314760c2415Smrg {
315760c2415Smrg     if (!scx)
316760c2415Smrg     {
317760c2415Smrg         scx = sc->copy();
318760c2415Smrg         scx->setNoFree();
319760c2415Smrg     }
320760c2415Smrg     cd->_scope = scx;
321760c2415Smrg     sym->semantic(NULL);
322760c2415Smrg     cd->_scope = NULL;
323760c2415Smrg }
324760c2415Smrg 
badObjectDotD(ClassDeclaration * cd)325760c2415Smrg static void badObjectDotD(ClassDeclaration *cd)
326760c2415Smrg {
327760c2415Smrg     cd->error("missing or corrupt object.d");
328760c2415Smrg     fatal();
329760c2415Smrg }
330760c2415Smrg 
semantic(Scope * sc)331760c2415Smrg void ClassDeclaration::semantic(Scope *sc)
332760c2415Smrg {
333760c2415Smrg     //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
334760c2415Smrg     //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
335760c2415Smrg     //printf("sc->stc = %x\n", sc->stc);
336760c2415Smrg 
337760c2415Smrg     //{ static int n;  if (++n == 20) *(char*)0=0; }
338760c2415Smrg 
339760c2415Smrg     if (semanticRun >= PASSsemanticdone)
340760c2415Smrg         return;
341760c2415Smrg     unsigned errors = global.errors;
342760c2415Smrg 
343760c2415Smrg     //printf("+ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
344760c2415Smrg 
345760c2415Smrg     Scope *scx = NULL;
346760c2415Smrg     if (_scope)
347760c2415Smrg     {
348760c2415Smrg         sc = _scope;
349760c2415Smrg         scx = _scope;            // save so we don't make redundant copies
350760c2415Smrg         _scope = NULL;
351760c2415Smrg     }
352760c2415Smrg 
353760c2415Smrg     if (!parent)
354760c2415Smrg     {
355760c2415Smrg         assert(sc->parent);
356760c2415Smrg         parent = sc->parent;
357760c2415Smrg     }
358760c2415Smrg 
359760c2415Smrg     if (this->errors)
360760c2415Smrg         type = Type::terror;
361760c2415Smrg     type = type->semantic(loc, sc);
362760c2415Smrg 
363760c2415Smrg     if (type->ty == Tclass && ((TypeClass *)type)->sym != this)
364760c2415Smrg     {
365760c2415Smrg         TemplateInstance *ti = ((TypeClass *)type)->sym->isInstantiated();
366760c2415Smrg         if (ti && isError(ti))
367760c2415Smrg             ((TypeClass *)type)->sym = this;
368760c2415Smrg     }
369760c2415Smrg 
370760c2415Smrg     // Ungag errors when not speculative
371760c2415Smrg     Ungag ungag = ungagSpeculative();
372760c2415Smrg 
373760c2415Smrg     if (semanticRun == PASSinit)
374760c2415Smrg     {
375760c2415Smrg         protection = sc->protection;
376760c2415Smrg 
377760c2415Smrg         storage_class |= sc->stc;
378760c2415Smrg         if (storage_class & STCdeprecated)
379760c2415Smrg             isdeprecated = true;
380760c2415Smrg         if (storage_class & STCauto)
381760c2415Smrg             error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?");
382760c2415Smrg         if (storage_class & STCscope)
383760c2415Smrg             isscope = true;
384760c2415Smrg         if (storage_class & STCabstract)
385760c2415Smrg             isabstract = ABSyes;
386760c2415Smrg 
387760c2415Smrg         userAttribDecl = sc->userAttribDecl;
388760c2415Smrg 
389760c2415Smrg         if (sc->linkage == LINKcpp)
390*0bfacb9bSmrg             classKind = ClassKind::cpp;
391760c2415Smrg         if (sc->linkage == LINKobjc)
392760c2415Smrg             objc()->setObjc(this);
393760c2415Smrg     }
394760c2415Smrg     else if (symtab && !scx)
395760c2415Smrg     {
396760c2415Smrg         return;
397760c2415Smrg     }
398760c2415Smrg     semanticRun = PASSsemantic;
399760c2415Smrg 
400760c2415Smrg     if (baseok < BASEOKdone)
401760c2415Smrg     {
402760c2415Smrg         baseok = BASEOKin;
403760c2415Smrg 
404760c2415Smrg         // Expand any tuples in baseclasses[]
405760c2415Smrg         for (size_t i = 0; i < baseclasses->dim; )
406760c2415Smrg         {
407760c2415Smrg             BaseClass *b = (*baseclasses)[i];
408760c2415Smrg             b->type = resolveBase(this, sc, scx, b->type);
409760c2415Smrg 
410760c2415Smrg             Type *tb = b->type->toBasetype();
411760c2415Smrg             if (tb->ty == Ttuple)
412760c2415Smrg             {
413760c2415Smrg                 TypeTuple *tup = (TypeTuple *)tb;
414760c2415Smrg                 baseclasses->remove(i);
415760c2415Smrg                 size_t dim = Parameter::dim(tup->arguments);
416760c2415Smrg                 for (size_t j = 0; j < dim; j++)
417760c2415Smrg                 {
418760c2415Smrg                     Parameter *arg = Parameter::getNth(tup->arguments, j);
419760c2415Smrg                     b = new BaseClass(arg->type);
420760c2415Smrg                     baseclasses->insert(i + j, b);
421760c2415Smrg                 }
422760c2415Smrg             }
423760c2415Smrg             else
424760c2415Smrg                 i++;
425760c2415Smrg         }
426760c2415Smrg 
427760c2415Smrg         if (baseok >= BASEOKdone)
428760c2415Smrg         {
429760c2415Smrg             //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
430760c2415Smrg             if (semanticRun >= PASSsemanticdone)
431760c2415Smrg                 return;
432760c2415Smrg             goto Lancestorsdone;
433760c2415Smrg         }
434760c2415Smrg 
435760c2415Smrg         // See if there's a base class as first in baseclasses[]
436760c2415Smrg         if (baseclasses->dim)
437760c2415Smrg         {
438760c2415Smrg             BaseClass *b = (*baseclasses)[0];
439760c2415Smrg             Type *tb = b->type->toBasetype();
440760c2415Smrg             TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
441760c2415Smrg             if (!tc)
442760c2415Smrg             {
443760c2415Smrg                 if (b->type != Type::terror)
444760c2415Smrg                     error("base type must be class or interface, not %s", b->type->toChars());
445760c2415Smrg                 baseclasses->remove(0);
446760c2415Smrg                 goto L7;
447760c2415Smrg             }
448760c2415Smrg 
449760c2415Smrg             if (tc->sym->isDeprecated())
450760c2415Smrg             {
451760c2415Smrg                 if (!isDeprecated())
452760c2415Smrg                 {
453760c2415Smrg                     // Deriving from deprecated class makes this one deprecated too
454760c2415Smrg                     isdeprecated = true;
455760c2415Smrg 
456760c2415Smrg                     tc->checkDeprecated(loc, sc);
457760c2415Smrg                 }
458760c2415Smrg             }
459760c2415Smrg 
460760c2415Smrg             if (tc->sym->isInterfaceDeclaration())
461760c2415Smrg                 goto L7;
462760c2415Smrg 
463760c2415Smrg             for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
464760c2415Smrg             {
465760c2415Smrg                 if (cdb == this)
466760c2415Smrg                 {
467760c2415Smrg                     error("circular inheritance");
468760c2415Smrg                     baseclasses->remove(0);
469760c2415Smrg                     goto L7;
470760c2415Smrg                 }
471760c2415Smrg             }
472760c2415Smrg 
473760c2415Smrg             /* Bugzilla 11034: Essentially, class inheritance hierarchy
474760c2415Smrg              * and instance size of each classes are orthogonal information.
475760c2415Smrg              * Therefore, even if tc->sym->sizeof == SIZEOKnone,
476760c2415Smrg              * we need to set baseClass field for class covariance check.
477760c2415Smrg              */
478760c2415Smrg             baseClass = tc->sym;
479760c2415Smrg             b->sym = baseClass;
480760c2415Smrg 
481*0bfacb9bSmrg             if (tc->sym->baseok < BASEOKdone)
482760c2415Smrg                 resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
483760c2415Smrg             if (tc->sym->baseok < BASEOKdone)
484760c2415Smrg             {
485760c2415Smrg                 //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
486760c2415Smrg                 if (tc->sym->_scope)
487760c2415Smrg                     tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
488760c2415Smrg                 baseok = BASEOKnone;
489760c2415Smrg             }
490760c2415Smrg          L7: ;
491760c2415Smrg         }
492760c2415Smrg 
493760c2415Smrg         // Treat the remaining entries in baseclasses as interfaces
494760c2415Smrg         // Check for errors, handle forward references
495760c2415Smrg         for (size_t i = (baseClass ? 1 : 0); i < baseclasses->dim; )
496760c2415Smrg         {
497760c2415Smrg             BaseClass *b = (*baseclasses)[i];
498760c2415Smrg             Type *tb = b->type->toBasetype();
499760c2415Smrg             TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
500760c2415Smrg             if (!tc || !tc->sym->isInterfaceDeclaration())
501760c2415Smrg             {
502760c2415Smrg                 if (b->type != Type::terror)
503760c2415Smrg                     error("base type must be interface, not %s", b->type->toChars());
504760c2415Smrg                 baseclasses->remove(i);
505760c2415Smrg                 continue;
506760c2415Smrg             }
507760c2415Smrg 
508760c2415Smrg             // Check for duplicate interfaces
509760c2415Smrg             for (size_t j = (baseClass ? 1 : 0); j < i; j++)
510760c2415Smrg             {
511760c2415Smrg                 BaseClass *b2 = (*baseclasses)[j];
512760c2415Smrg                 if (b2->sym == tc->sym)
513760c2415Smrg                 {
514760c2415Smrg                     error("inherits from duplicate interface %s", b2->sym->toChars());
515760c2415Smrg                     baseclasses->remove(i);
516760c2415Smrg                     continue;
517760c2415Smrg                 }
518760c2415Smrg             }
519760c2415Smrg 
520760c2415Smrg             if (tc->sym->isDeprecated())
521760c2415Smrg             {
522760c2415Smrg                 if (!isDeprecated())
523760c2415Smrg                 {
524760c2415Smrg                     // Deriving from deprecated class makes this one deprecated too
525760c2415Smrg                     isdeprecated = true;
526760c2415Smrg 
527760c2415Smrg                     tc->checkDeprecated(loc, sc);
528760c2415Smrg                 }
529760c2415Smrg             }
530760c2415Smrg 
531760c2415Smrg             b->sym = tc->sym;
532760c2415Smrg 
533*0bfacb9bSmrg             if (tc->sym->baseok < BASEOKdone)
534760c2415Smrg                 resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
535760c2415Smrg             if (tc->sym->baseok < BASEOKdone)
536760c2415Smrg             {
537760c2415Smrg                 //printf("\ttry later, forward reference of base %s\n", tc->sym->toChars());
538760c2415Smrg                 if (tc->sym->_scope)
539760c2415Smrg                     tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
540760c2415Smrg                 baseok = BASEOKnone;
541760c2415Smrg             }
542760c2415Smrg             i++;
543760c2415Smrg         }
544760c2415Smrg         if (baseok == BASEOKnone)
545760c2415Smrg         {
546760c2415Smrg             // Forward referencee of one or more bases, try again later
547760c2415Smrg             _scope = scx ? scx : sc->copy();
548760c2415Smrg             _scope->setNoFree();
549760c2415Smrg             _scope->_module->addDeferredSemantic(this);
550760c2415Smrg             //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
551760c2415Smrg             return;
552760c2415Smrg         }
553760c2415Smrg         baseok = BASEOKdone;
554760c2415Smrg 
555760c2415Smrg         // If no base class, and this is not an Object, use Object as base class
556*0bfacb9bSmrg         if (!baseClass && ident != Id::Object && !isCPPclass())
557760c2415Smrg         {
558760c2415Smrg             if (!object || object->errors)
559760c2415Smrg                 badObjectDotD(this);
560760c2415Smrg 
561760c2415Smrg             Type *t = object->type;
562760c2415Smrg             t = t->semantic(loc, sc)->toBasetype();
563760c2415Smrg             if (t->ty == Terror)
564760c2415Smrg                 badObjectDotD(this);
565760c2415Smrg             assert(t->ty == Tclass);
566760c2415Smrg             TypeClass *tc = (TypeClass *)t;
567760c2415Smrg 
568760c2415Smrg             BaseClass *b = new BaseClass(tc);
569760c2415Smrg             baseclasses->shift(b);
570760c2415Smrg 
571760c2415Smrg             baseClass = tc->sym;
572760c2415Smrg             assert(!baseClass->isInterfaceDeclaration());
573760c2415Smrg             b->sym = baseClass;
574760c2415Smrg         }
575760c2415Smrg         if (baseClass)
576760c2415Smrg         {
577760c2415Smrg             if (baseClass->storage_class & STCfinal)
578760c2415Smrg                 error("cannot inherit from final class %s", baseClass->toChars());
579760c2415Smrg 
580760c2415Smrg             // Inherit properties from base class
581760c2415Smrg             if (baseClass->isCOMclass())
582760c2415Smrg                 com = true;
583760c2415Smrg             if (baseClass->isCPPclass())
584*0bfacb9bSmrg                 classKind = ClassKind::cpp;
585760c2415Smrg             if (baseClass->isscope)
586760c2415Smrg                 isscope = true;
587760c2415Smrg             enclosing = baseClass->enclosing;
588760c2415Smrg             storage_class |= baseClass->storage_class & STC_TYPECTOR;
589760c2415Smrg         }
590760c2415Smrg 
591760c2415Smrg         interfaces.length = baseclasses->dim - (baseClass ? 1 : 0);
592760c2415Smrg         interfaces.ptr = baseclasses->tdata() + (baseClass ? 1 : 0);
593760c2415Smrg 
594760c2415Smrg         for (size_t i = 0; i < interfaces.length; i++)
595760c2415Smrg         {
596760c2415Smrg             BaseClass *b = interfaces.ptr[i];
597760c2415Smrg             // If this is an interface, and it derives from a COM interface,
598760c2415Smrg             // then this is a COM interface too.
599760c2415Smrg             if (b->sym->isCOMinterface())
600760c2415Smrg                 com = true;
601*0bfacb9bSmrg             if (isCPPclass() && !b->sym->isCPPinterface())
602760c2415Smrg             {
603760c2415Smrg                 ::error(loc, "C++ class '%s' cannot implement D interface '%s'",
604760c2415Smrg                     toPrettyChars(), b->sym->toPrettyChars());
605760c2415Smrg             }
606760c2415Smrg         }
607760c2415Smrg 
608760c2415Smrg         interfaceSemantic(sc);
609760c2415Smrg     }
610760c2415Smrg Lancestorsdone:
611760c2415Smrg     //printf("\tClassDeclaration::semantic(%s) baseok = %d\n", toChars(), baseok);
612760c2415Smrg 
613760c2415Smrg     if (!members)               // if opaque declaration
614760c2415Smrg     {
615760c2415Smrg         semanticRun = PASSsemanticdone;
616760c2415Smrg         return;
617760c2415Smrg     }
618760c2415Smrg     if (!symtab)
619760c2415Smrg     {
620760c2415Smrg         symtab = new DsymbolTable();
621760c2415Smrg 
622760c2415Smrg         /* Bugzilla 12152: The semantic analysis of base classes should be finished
623760c2415Smrg          * before the members semantic analysis of this class, in order to determine
624760c2415Smrg          * vtbl in this class. However if a base class refers the member of this class,
625760c2415Smrg          * it can be resolved as a normal forward reference.
626760c2415Smrg          * Call addMember() and setScope() to make this class members visible from the base classes.
627760c2415Smrg          */
628760c2415Smrg         for (size_t i = 0; i < members->dim; i++)
629760c2415Smrg         {
630760c2415Smrg             Dsymbol *s = (*members)[i];
631760c2415Smrg             s->addMember(sc, this);
632760c2415Smrg         }
633760c2415Smrg 
634760c2415Smrg         Scope *sc2 = newScope(sc);
635760c2415Smrg 
636760c2415Smrg         /* Set scope so if there are forward references, we still might be able to
637760c2415Smrg          * resolve individual members like enums.
638760c2415Smrg          */
639760c2415Smrg         for (size_t i = 0; i < members->dim; i++)
640760c2415Smrg         {
641760c2415Smrg             Dsymbol *s = (*members)[i];
642760c2415Smrg             //printf("[%d] setScope %s %s, sc2 = %p\n", i, s->kind(), s->toChars(), sc2);
643760c2415Smrg             s->setScope(sc2);
644760c2415Smrg         }
645760c2415Smrg 
646760c2415Smrg         sc2->pop();
647760c2415Smrg     }
648760c2415Smrg 
649760c2415Smrg     for (size_t i = 0; i < baseclasses->dim; i++)
650760c2415Smrg     {
651760c2415Smrg         BaseClass *b = (*baseclasses)[i];
652760c2415Smrg         Type *tb = b->type->toBasetype();
653760c2415Smrg         assert(tb->ty == Tclass);
654760c2415Smrg         TypeClass *tc = (TypeClass *)tb;
655760c2415Smrg 
656760c2415Smrg         if (tc->sym->semanticRun < PASSsemanticdone)
657760c2415Smrg         {
658760c2415Smrg             // Forward referencee of one or more bases, try again later
659760c2415Smrg             _scope = scx ? scx : sc->copy();
660760c2415Smrg             _scope->setNoFree();
661760c2415Smrg             if (tc->sym->_scope)
662760c2415Smrg                 tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
663760c2415Smrg             _scope->_module->addDeferredSemantic(this);
664760c2415Smrg             //printf("\tL%d semantic('%s') failed due to forward references\n", __LINE__, toChars());
665760c2415Smrg             return;
666760c2415Smrg         }
667760c2415Smrg     }
668760c2415Smrg 
669760c2415Smrg     if (baseok == BASEOKdone)
670760c2415Smrg     {
671760c2415Smrg         baseok = BASEOKsemanticdone;
672760c2415Smrg 
673760c2415Smrg         // initialize vtbl
674760c2415Smrg         if (baseClass)
675760c2415Smrg         {
676*0bfacb9bSmrg             if (isCPPclass() && baseClass->vtbl.dim == 0)
677760c2415Smrg             {
678760c2415Smrg                 error("C++ base class %s needs at least one virtual function", baseClass->toChars());
679760c2415Smrg             }
680760c2415Smrg 
681760c2415Smrg             // Copy vtbl[] from base class
682760c2415Smrg             vtbl.setDim(baseClass->vtbl.dim);
683760c2415Smrg             memcpy(vtbl.tdata(), baseClass->vtbl.tdata(), sizeof(void *) * vtbl.dim);
684760c2415Smrg 
685760c2415Smrg             vthis = baseClass->vthis;
686760c2415Smrg         }
687760c2415Smrg         else
688760c2415Smrg         {
689760c2415Smrg             // No base class, so this is the root of the class hierarchy
690760c2415Smrg             vtbl.setDim(0);
691760c2415Smrg             if (vtblOffset())
692760c2415Smrg                 vtbl.push(this);            // leave room for classinfo as first member
693760c2415Smrg         }
694760c2415Smrg 
695760c2415Smrg         /* If this is a nested class, add the hidden 'this'
696760c2415Smrg          * member which is a pointer to the enclosing scope.
697760c2415Smrg          */
698760c2415Smrg         if (vthis)              // if inheriting from nested class
699760c2415Smrg         {
700760c2415Smrg             // Use the base class's 'this' member
701760c2415Smrg             if (storage_class & STCstatic)
702760c2415Smrg                 error("static class cannot inherit from nested class %s", baseClass->toChars());
703760c2415Smrg             if (toParent2() != baseClass->toParent2() &&
704760c2415Smrg                 (!toParent2() ||
705760c2415Smrg                  !baseClass->toParent2()->getType() ||
706760c2415Smrg                  !baseClass->toParent2()->getType()->isBaseOf(toParent2()->getType(), NULL)))
707760c2415Smrg             {
708760c2415Smrg                 if (toParent2())
709760c2415Smrg                 {
710760c2415Smrg                     error("is nested within %s, but super class %s is nested within %s",
711760c2415Smrg                         toParent2()->toChars(),
712760c2415Smrg                         baseClass->toChars(),
713760c2415Smrg                         baseClass->toParent2()->toChars());
714760c2415Smrg                 }
715760c2415Smrg                 else
716760c2415Smrg                 {
717760c2415Smrg                     error("is not nested, but super class %s is nested within %s",
718760c2415Smrg                         baseClass->toChars(),
719760c2415Smrg                         baseClass->toParent2()->toChars());
720760c2415Smrg                 }
721760c2415Smrg                 enclosing = NULL;
722760c2415Smrg             }
723760c2415Smrg         }
724760c2415Smrg         else
725760c2415Smrg             makeNested();
726760c2415Smrg     }
727760c2415Smrg 
728760c2415Smrg     Scope *sc2 = newScope(sc);
729760c2415Smrg 
730760c2415Smrg     for (size_t i = 0; i < members->dim; i++)
731760c2415Smrg     {
732760c2415Smrg         Dsymbol *s = (*members)[i];
733760c2415Smrg         s->importAll(sc2);
734760c2415Smrg     }
735760c2415Smrg 
736760c2415Smrg     // Note that members.dim can grow due to tuple expansion during semantic()
737760c2415Smrg     for (size_t i = 0; i < members->dim; i++)
738760c2415Smrg     {
739760c2415Smrg         Dsymbol *s = (*members)[i];
740760c2415Smrg         s->semantic(sc2);
741760c2415Smrg     }
742760c2415Smrg 
743760c2415Smrg     if (!determineFields())
744760c2415Smrg     {
745760c2415Smrg         assert(type == Type::terror);
746760c2415Smrg         sc2->pop();
747760c2415Smrg         return;
748760c2415Smrg     }
749760c2415Smrg 
750760c2415Smrg     /* Following special member functions creation needs semantic analysis
751760c2415Smrg      * completion of sub-structs in each field types.
752760c2415Smrg      */
753760c2415Smrg     for (size_t i = 0; i < fields.dim; i++)
754760c2415Smrg     {
755760c2415Smrg         VarDeclaration *v = fields[i];
756760c2415Smrg         Type *tb = v->type->baseElemOf();
757760c2415Smrg         if (tb->ty != Tstruct)
758760c2415Smrg             continue;
759760c2415Smrg         StructDeclaration *sd = ((TypeStruct *)tb)->sym;
760760c2415Smrg         if (sd->semanticRun >= PASSsemanticdone)
761760c2415Smrg             continue;
762760c2415Smrg 
763760c2415Smrg         sc2->pop();
764760c2415Smrg 
765760c2415Smrg         _scope = scx ? scx : sc->copy();
766760c2415Smrg         _scope->setNoFree();
767760c2415Smrg         _scope->_module->addDeferredSemantic(this);
768760c2415Smrg         //printf("\tdeferring %s\n", toChars());
769760c2415Smrg         return;
770760c2415Smrg     }
771760c2415Smrg 
772760c2415Smrg     /* Look for special member functions.
773760c2415Smrg      * They must be in this class, not in a base class.
774760c2415Smrg      */
775760c2415Smrg 
776760c2415Smrg     // Can be in base class
777760c2415Smrg     aggNew    =    (NewDeclaration *)search(Loc(), Id::classNew);
778760c2415Smrg     aggDelete = (DeleteDeclaration *)search(Loc(), Id::classDelete);
779760c2415Smrg 
780760c2415Smrg     // Look for the constructor
781760c2415Smrg     ctor = searchCtor();
782760c2415Smrg 
783760c2415Smrg     if (!ctor && noDefaultCtor)
784760c2415Smrg     {
785760c2415Smrg         // A class object is always created by constructor, so this check is legitimate.
786760c2415Smrg         for (size_t i = 0; i < fields.dim; i++)
787760c2415Smrg         {
788760c2415Smrg             VarDeclaration *v = fields[i];
789760c2415Smrg             if (v->storage_class & STCnodefaultctor)
790760c2415Smrg                 ::error(v->loc, "field %s must be initialized in constructor", v->toChars());
791760c2415Smrg         }
792760c2415Smrg     }
793760c2415Smrg 
794760c2415Smrg     // If this class has no constructor, but base class has a default
795760c2415Smrg     // ctor, create a constructor:
796760c2415Smrg     //    this() { }
797760c2415Smrg     if (!ctor && baseClass && baseClass->ctor)
798760c2415Smrg     {
799760c2415Smrg         FuncDeclaration *fd = resolveFuncCall(loc, sc2, baseClass->ctor, NULL, type, NULL, 1);
800760c2415Smrg         if (!fd) // try shared base ctor instead
801760c2415Smrg             fd = resolveFuncCall(loc, sc2, baseClass->ctor, NULL, type->sharedOf(), NULL, 1);
802760c2415Smrg         if (fd && !fd->errors)
803760c2415Smrg         {
804760c2415Smrg             //printf("Creating default this(){} for class %s\n", toChars());
805760c2415Smrg             TypeFunction *btf = fd->type->toTypeFunction();
806760c2415Smrg             TypeFunction *tf = new TypeFunction(NULL, NULL, 0, LINKd, fd->storage_class);
807760c2415Smrg             tf->mod = btf->mod;
808760c2415Smrg             tf->purity = btf->purity;
809760c2415Smrg             tf->isnothrow = btf->isnothrow;
810760c2415Smrg             tf->isnogc = btf->isnogc;
811760c2415Smrg             tf->trust = btf->trust;
812760c2415Smrg 
813760c2415Smrg             CtorDeclaration *ctor = new CtorDeclaration(loc, Loc(), 0, tf);
814760c2415Smrg             ctor->fbody = new CompoundStatement(Loc(), new Statements());
815760c2415Smrg 
816760c2415Smrg             members->push(ctor);
817760c2415Smrg             ctor->addMember(sc, this);
818760c2415Smrg             ctor->semantic(sc2);
819760c2415Smrg 
820760c2415Smrg             this->ctor = ctor;
821760c2415Smrg             defaultCtor = ctor;
822760c2415Smrg         }
823760c2415Smrg         else
824760c2415Smrg         {
825760c2415Smrg             error("cannot implicitly generate a default ctor when base class %s is missing a default ctor",
826760c2415Smrg                 baseClass->toPrettyChars());
827760c2415Smrg         }
828760c2415Smrg     }
829760c2415Smrg 
830760c2415Smrg     dtor = buildDtor(this, sc2);
831760c2415Smrg 
832760c2415Smrg     if (FuncDeclaration *f = hasIdentityOpAssign(this, sc2))
833760c2415Smrg     {
834760c2415Smrg         if (!(f->storage_class & STCdisable))
835760c2415Smrg             error(f->loc, "identity assignment operator overload is illegal");
836760c2415Smrg     }
837760c2415Smrg 
838760c2415Smrg     inv = buildInv(this, sc2);
839760c2415Smrg 
840760c2415Smrg     Module::dprogress++;
841760c2415Smrg     semanticRun = PASSsemanticdone;
842760c2415Smrg     //printf("-ClassDeclaration.semantic(%s), type = %p\n", toChars(), type);
843760c2415Smrg     //members.print();
844760c2415Smrg 
845760c2415Smrg     sc2->pop();
846760c2415Smrg 
847760c2415Smrg     if (type->ty == Tclass && ((TypeClass *)type)->sym != this)
848760c2415Smrg     {
849760c2415Smrg         // https://issues.dlang.org/show_bug.cgi?id=17492
850760c2415Smrg         ClassDeclaration *cd = ((TypeClass *)type)->sym;
851760c2415Smrg         error("already exists at %s. Perhaps in another function with the same name?", cd->loc.toChars());
852760c2415Smrg     }
853760c2415Smrg 
854760c2415Smrg     if (global.errors != errors)
855760c2415Smrg     {
856760c2415Smrg         // The type is no good.
857760c2415Smrg         type = Type::terror;
858760c2415Smrg         this->errors = true;
859760c2415Smrg         if (deferred)
860760c2415Smrg             deferred->errors = true;
861760c2415Smrg     }
862760c2415Smrg 
863760c2415Smrg     // Verify fields of a synchronized class are not public
864760c2415Smrg     if (storage_class & STCsynchronized)
865760c2415Smrg     {
866760c2415Smrg         for (size_t i = 0; i < fields.dim; i++)
867760c2415Smrg         {
868760c2415Smrg             VarDeclaration *vd = fields[i];
869760c2415Smrg             if (!vd->isThisDeclaration() &&
870760c2415Smrg                 !vd->prot().isMoreRestrictiveThan(Prot(PROTpublic)))
871760c2415Smrg             {
872760c2415Smrg                 vd->error("Field members of a synchronized class cannot be %s",
873760c2415Smrg                     protectionToChars(vd->prot().kind));
874760c2415Smrg             }
875760c2415Smrg         }
876760c2415Smrg     }
877760c2415Smrg 
878760c2415Smrg     if (deferred && !global.gag)
879760c2415Smrg     {
880760c2415Smrg         deferred->semantic2(sc);
881760c2415Smrg         deferred->semantic3(sc);
882760c2415Smrg     }
883760c2415Smrg     //printf("-ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
884760c2415Smrg }
885760c2415Smrg 
886760c2415Smrg /*********************************************
887760c2415Smrg  * Determine if 'this' is a base class of cd.
888760c2415Smrg  * This is used to detect circular inheritance only.
889760c2415Smrg  */
890760c2415Smrg 
isBaseOf2(ClassDeclaration * cd)891760c2415Smrg bool ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
892760c2415Smrg {
893760c2415Smrg     if (!cd)
894760c2415Smrg         return false;
895760c2415Smrg     //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
896760c2415Smrg     for (size_t i = 0; i < cd->baseclasses->dim; i++)
897760c2415Smrg     {
898760c2415Smrg         BaseClass *b = (*cd->baseclasses)[i];
899760c2415Smrg         if (b->sym == this || isBaseOf2(b->sym))
900760c2415Smrg             return true;
901760c2415Smrg     }
902760c2415Smrg     return false;
903760c2415Smrg }
904760c2415Smrg 
905760c2415Smrg /*******************************************
906760c2415Smrg  * Determine if 'this' is a base class of cd.
907760c2415Smrg  */
908760c2415Smrg 
isBaseOf(ClassDeclaration * cd,int * poffset)909760c2415Smrg bool ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
910760c2415Smrg {
911760c2415Smrg     //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
912760c2415Smrg     if (poffset)
913760c2415Smrg         *poffset = 0;
914760c2415Smrg     while (cd)
915760c2415Smrg     {
916760c2415Smrg         /* cd->baseClass might not be set if cd is forward referenced.
917760c2415Smrg          */
918*0bfacb9bSmrg         if (!cd->baseClass && cd->semanticRun < PASSsemanticdone && !cd->isInterfaceDeclaration())
919760c2415Smrg         {
920760c2415Smrg             cd->semantic(NULL);
921*0bfacb9bSmrg             if (!cd->baseClass && cd->semanticRun < PASSsemanticdone)
922760c2415Smrg                 cd->error("base class is forward referenced by %s", toChars());
923760c2415Smrg         }
924760c2415Smrg 
925760c2415Smrg         if (this == cd->baseClass)
926760c2415Smrg             return true;
927760c2415Smrg 
928760c2415Smrg         cd = cd->baseClass;
929760c2415Smrg     }
930760c2415Smrg     return false;
931760c2415Smrg }
932760c2415Smrg 
933760c2415Smrg /*********************************************
934760c2415Smrg  * Determine if 'this' has complete base class information.
935760c2415Smrg  * This is used to detect forward references in covariant overloads.
936760c2415Smrg  */
937760c2415Smrg 
isBaseInfoComplete()938760c2415Smrg bool ClassDeclaration::isBaseInfoComplete()
939760c2415Smrg {
940760c2415Smrg     return baseok >= BASEOKdone;
941760c2415Smrg }
942760c2415Smrg 
search(const Loc & loc,Identifier * ident,int flags)943760c2415Smrg Dsymbol *ClassDeclaration::search(const Loc &loc, Identifier *ident, int flags)
944760c2415Smrg {
945760c2415Smrg     //printf("%s.ClassDeclaration::search('%s', flags=x%x)\n", toChars(), ident->toChars(), flags);
946760c2415Smrg 
947760c2415Smrg     //if (_scope) printf("%s baseok = %d\n", toChars(), baseok);
948760c2415Smrg     if (_scope && baseok < BASEOKdone)
949760c2415Smrg     {
950760c2415Smrg         if (!inuse)
951760c2415Smrg         {
952760c2415Smrg             // must semantic on base class/interfaces
953760c2415Smrg             ++inuse;
954760c2415Smrg             semantic(NULL);
955760c2415Smrg             --inuse;
956760c2415Smrg         }
957760c2415Smrg     }
958760c2415Smrg 
959760c2415Smrg     if (!members || !symtab)    // opaque or addMember is not yet done
960760c2415Smrg     {
961760c2415Smrg         error("is forward referenced when looking for '%s'", ident->toChars());
962760c2415Smrg         //*(char*)0=0;
963760c2415Smrg         return NULL;
964760c2415Smrg     }
965760c2415Smrg 
966760c2415Smrg     Dsymbol *s = ScopeDsymbol::search(loc, ident, flags);
967760c2415Smrg 
968760c2415Smrg     // don't search imports of base classes
969760c2415Smrg     if (flags & SearchImportsOnly)
970760c2415Smrg         return s;
971760c2415Smrg 
972760c2415Smrg     if (!s)
973760c2415Smrg     {
974760c2415Smrg         // Search bases classes in depth-first, left to right order
975760c2415Smrg 
976760c2415Smrg         for (size_t i = 0; i < baseclasses->dim; i++)
977760c2415Smrg         {
978760c2415Smrg             BaseClass *b = (*baseclasses)[i];
979760c2415Smrg 
980760c2415Smrg             if (b->sym)
981760c2415Smrg             {
982760c2415Smrg                 if (!b->sym->symtab)
983760c2415Smrg                     error("base %s is forward referenced", b->sym->ident->toChars());
984760c2415Smrg                 else
985760c2415Smrg                 {
986760c2415Smrg                     s = b->sym->search(loc, ident, flags);
987760c2415Smrg                     if (!s)
988760c2415Smrg                         continue;
989760c2415Smrg                     else if (s == this) // happens if s is nested in this and derives from this
990760c2415Smrg                         s = NULL;
991760c2415Smrg                     else if (!(flags & IgnoreSymbolVisibility) && !(s->prot().kind == PROTprotected) && !symbolIsVisible(this, s))
992760c2415Smrg                         s = NULL;
993760c2415Smrg                     else
994760c2415Smrg                         break;
995760c2415Smrg                 }
996760c2415Smrg             }
997760c2415Smrg         }
998760c2415Smrg     }
999760c2415Smrg     return s;
1000760c2415Smrg }
1001760c2415Smrg 
1002760c2415Smrg /************************************
1003760c2415Smrg  * Search base classes in depth-first, left-to-right order for
1004760c2415Smrg  * a class or interface named 'ident'.
1005760c2415Smrg  * Stops at first found. Does not look for additional matches.
1006760c2415Smrg  * Params:
1007760c2415Smrg  *  ident = identifier to search for
1008760c2415Smrg  * Returns:
1009760c2415Smrg  *  ClassDeclaration if found, null if not
1010760c2415Smrg  */
searchBase(Identifier * ident)1011760c2415Smrg ClassDeclaration *ClassDeclaration::searchBase(Identifier *ident)
1012760c2415Smrg {
1013760c2415Smrg     for (size_t i = 0; i < baseclasses->dim; i++)
1014760c2415Smrg     {
1015760c2415Smrg         BaseClass *b = (*baseclasses)[i];
1016760c2415Smrg         ClassDeclaration *cdb = b->type->isClassHandle();
1017760c2415Smrg         if (!cdb)   // Bugzilla 10616
1018760c2415Smrg             return NULL;
1019760c2415Smrg         if (cdb->ident->equals(ident))
1020760c2415Smrg             return cdb;
1021760c2415Smrg         cdb = cdb->searchBase(ident);
1022760c2415Smrg         if (cdb)
1023760c2415Smrg             return cdb;
1024760c2415Smrg     }
1025760c2415Smrg     return NULL;
1026760c2415Smrg }
1027760c2415Smrg 
1028760c2415Smrg /****
1029760c2415Smrg  * Runs through the inheritance graph to set the BaseClass.offset fields.
1030760c2415Smrg  * Recursive in order to account for the size of the interface classes, if they are
1031760c2415Smrg  * more than just interfaces.
1032760c2415Smrg  * Params:
1033760c2415Smrg  *      cd = interface to look at
1034760c2415Smrg  *      baseOffset = offset of where cd will be placed
1035760c2415Smrg  * Returns:
1036760c2415Smrg  *      subset of instantiated size used by cd for interfaces
1037760c2415Smrg  */
membersPlace(BaseClasses * vtblInterfaces,size_t & bi,ClassDeclaration * cd,unsigned baseOffset)1038760c2415Smrg static unsigned membersPlace(BaseClasses *vtblInterfaces, size_t &bi, ClassDeclaration *cd, unsigned baseOffset)
1039760c2415Smrg {
1040760c2415Smrg     //printf("    membersPlace(%s, %d)\n", cd->toChars(), baseOffset);
1041760c2415Smrg     unsigned offset = baseOffset;
1042760c2415Smrg 
1043760c2415Smrg     for (size_t i = 0; i < cd->interfaces.length; i++)
1044760c2415Smrg     {
1045760c2415Smrg         BaseClass *b = cd->interfaces.ptr[i];
1046760c2415Smrg         if (b->sym->sizeok != SIZEOKdone)
1047760c2415Smrg             b->sym->finalizeSize();
1048760c2415Smrg         assert(b->sym->sizeok == SIZEOKdone);
1049760c2415Smrg 
1050760c2415Smrg         if (!b->sym->alignsize)
1051760c2415Smrg             b->sym->alignsize = Target::ptrsize;
1052760c2415Smrg         cd->alignmember(b->sym->alignsize, b->sym->alignsize, &offset);
1053760c2415Smrg         assert(bi < vtblInterfaces->dim);
1054760c2415Smrg         BaseClass *bv = (*vtblInterfaces)[bi];
1055760c2415Smrg         if (b->sym->interfaces.length == 0)
1056760c2415Smrg         {
1057760c2415Smrg             //printf("\tvtblInterfaces[%d] b=%p b->sym = %s, offset = %d\n", bi, bv, bv->sym->toChars(), offset);
1058760c2415Smrg             bv->offset = offset;
1059760c2415Smrg             ++bi;
1060760c2415Smrg             // All the base interfaces down the left side share the same offset
1061760c2415Smrg             for (BaseClass *b2 = bv; b2->baseInterfaces.length; )
1062760c2415Smrg             {
1063760c2415Smrg                 b2 = &b2->baseInterfaces.ptr[0];
1064760c2415Smrg                 b2->offset = offset;
1065760c2415Smrg                 //printf("\tvtblInterfaces[%d] b=%p   sym = %s, offset = %d\n", bi, b2, b2->sym->toChars(), b2->offset);
1066760c2415Smrg             }
1067760c2415Smrg         }
1068760c2415Smrg         membersPlace(vtblInterfaces, bi, b->sym, offset);
1069760c2415Smrg         //printf(" %s size = %d\n", b->sym->toChars(), b->sym->structsize);
1070760c2415Smrg         offset += b->sym->structsize;
1071760c2415Smrg         if (cd->alignsize < b->sym->alignsize)
1072760c2415Smrg             cd->alignsize = b->sym->alignsize;
1073760c2415Smrg     }
1074760c2415Smrg     return offset - baseOffset;
1075760c2415Smrg }
1076760c2415Smrg 
finalizeSize()1077760c2415Smrg void ClassDeclaration::finalizeSize()
1078760c2415Smrg {
1079760c2415Smrg     assert(sizeok != SIZEOKdone);
1080760c2415Smrg 
1081760c2415Smrg     // Set the offsets of the fields and determine the size of the class
1082760c2415Smrg     if (baseClass)
1083760c2415Smrg     {
1084760c2415Smrg         assert(baseClass->sizeok == SIZEOKdone);
1085760c2415Smrg 
1086760c2415Smrg         alignsize = baseClass->alignsize;
1087760c2415Smrg         structsize = baseClass->structsize;
1088*0bfacb9bSmrg         if (isCPPclass() && global.params.isWindows)
1089760c2415Smrg             structsize = (structsize + alignsize - 1) & ~(alignsize - 1);
1090760c2415Smrg     }
1091760c2415Smrg     else if (isInterfaceDeclaration())
1092760c2415Smrg     {
1093760c2415Smrg         if (interfaces.length == 0)
1094760c2415Smrg         {
1095760c2415Smrg             alignsize = Target::ptrsize;
1096760c2415Smrg             structsize = Target::ptrsize;      // allow room for __vptr
1097760c2415Smrg         }
1098760c2415Smrg     }
1099760c2415Smrg     else
1100760c2415Smrg     {
1101760c2415Smrg         alignsize = Target::ptrsize;
1102760c2415Smrg         structsize = Target::ptrsize;      // allow room for __vptr
1103*0bfacb9bSmrg         if (!isCPPclass())
1104760c2415Smrg             structsize += Target::ptrsize; // allow room for __monitor
1105760c2415Smrg     }
1106760c2415Smrg 
1107760c2415Smrg     //printf("finalizeSize() %s, sizeok = %d\n", toChars(), sizeok);
1108760c2415Smrg     size_t bi = 0;                  // index into vtblInterfaces[]
1109760c2415Smrg 
1110760c2415Smrg     // Add vptr's for any interfaces implemented by this class
1111760c2415Smrg     structsize += membersPlace(vtblInterfaces, bi, this, structsize);
1112760c2415Smrg 
1113760c2415Smrg     if (isInterfaceDeclaration())
1114760c2415Smrg     {
1115760c2415Smrg         sizeok = SIZEOKdone;
1116760c2415Smrg         return;
1117760c2415Smrg     }
1118760c2415Smrg 
1119760c2415Smrg     // FIXME: Currently setFieldOffset functions need to increase fields
1120760c2415Smrg     // to calculate each variable offsets. It can be improved later.
1121760c2415Smrg     fields.setDim(0);
1122760c2415Smrg 
1123760c2415Smrg     unsigned offset = structsize;
1124760c2415Smrg     for (size_t i = 0; i < members->dim; i++)
1125760c2415Smrg     {
1126760c2415Smrg         Dsymbol *s = (*members)[i];
1127760c2415Smrg         s->setFieldOffset(this, &offset, false);
1128760c2415Smrg     }
1129760c2415Smrg 
1130760c2415Smrg     sizeok = SIZEOKdone;
1131760c2415Smrg 
1132760c2415Smrg     // Calculate fields[i]->overlapped
1133760c2415Smrg     checkOverlappedFields();
1134760c2415Smrg }
1135760c2415Smrg 
1136760c2415Smrg /**********************************************************
1137760c2415Smrg  * fd is in the vtbl[] for this class.
1138760c2415Smrg  * Return 1 if function is hidden (not findable through search).
1139760c2415Smrg  */
1140760c2415Smrg 
isf(void * param,Dsymbol * s)1141760c2415Smrg int isf(void *param, Dsymbol *s)
1142760c2415Smrg {
1143760c2415Smrg     FuncDeclaration *fd = s->isFuncDeclaration();
1144760c2415Smrg     if (!fd)
1145760c2415Smrg         return 0;
1146760c2415Smrg     //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
1147760c2415Smrg     return (RootObject *)param == fd;
1148760c2415Smrg }
1149760c2415Smrg 
isFuncHidden(FuncDeclaration * fd)1150760c2415Smrg bool ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
1151760c2415Smrg {
1152760c2415Smrg     //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toPrettyChars());
1153760c2415Smrg     Dsymbol *s = search(Loc(), fd->ident, IgnoreAmbiguous | IgnoreErrors);
1154760c2415Smrg     if (!s)
1155760c2415Smrg     {
1156760c2415Smrg         //printf("not found\n");
1157760c2415Smrg         /* Because, due to a hack, if there are multiple definitions
1158760c2415Smrg          * of fd->ident, NULL is returned.
1159760c2415Smrg          */
1160760c2415Smrg         return false;
1161760c2415Smrg     }
1162760c2415Smrg     s = s->toAlias();
1163760c2415Smrg     OverloadSet *os = s->isOverloadSet();
1164760c2415Smrg     if (os)
1165760c2415Smrg     {
1166760c2415Smrg         for (size_t i = 0; i < os->a.dim; i++)
1167760c2415Smrg         {
1168760c2415Smrg             Dsymbol *s2 = os->a[i];
1169760c2415Smrg             FuncDeclaration *f2 = s2->isFuncDeclaration();
1170760c2415Smrg             if (f2 && overloadApply(f2, (void *)fd, &isf))
1171760c2415Smrg                 return false;
1172760c2415Smrg         }
1173760c2415Smrg         return true;
1174760c2415Smrg     }
1175760c2415Smrg     else
1176760c2415Smrg     {
1177760c2415Smrg         FuncDeclaration *fdstart = s->isFuncDeclaration();
1178760c2415Smrg         //printf("%s fdstart = %p\n", s->kind(), fdstart);
1179760c2415Smrg         if (overloadApply(fdstart, (void *)fd, &isf))
1180760c2415Smrg             return false;
1181760c2415Smrg 
1182760c2415Smrg         return !fd->parent->isTemplateMixin();
1183760c2415Smrg     }
1184760c2415Smrg }
1185760c2415Smrg 
1186760c2415Smrg /****************
1187760c2415Smrg  * Find virtual function matching identifier and type.
1188760c2415Smrg  * Used to build virtual function tables for interface implementations.
1189760c2415Smrg  */
1190760c2415Smrg 
findFunc(Identifier * ident,TypeFunction * tf)1191760c2415Smrg FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
1192760c2415Smrg {
1193760c2415Smrg     //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
1194760c2415Smrg     FuncDeclaration *fdmatch = NULL;
1195760c2415Smrg     FuncDeclaration *fdambig = NULL;
1196760c2415Smrg 
1197760c2415Smrg     ClassDeclaration *cd = this;
1198760c2415Smrg     Dsymbols *vtbl = &cd->vtbl;
1199760c2415Smrg     while (1)
1200760c2415Smrg     {
1201760c2415Smrg         for (size_t i = 0; i < vtbl->dim; i++)
1202760c2415Smrg         {
1203760c2415Smrg             FuncDeclaration *fd = (*vtbl)[i]->isFuncDeclaration();
1204760c2415Smrg             if (!fd)
1205760c2415Smrg                 continue;               // the first entry might be a ClassInfo
1206760c2415Smrg 
1207760c2415Smrg             //printf("\t[%d] = %s\n", i, fd->toChars());
1208760c2415Smrg             if (ident == fd->ident &&
1209760c2415Smrg                 fd->type->covariant(tf) == 1)
1210760c2415Smrg             {
1211760c2415Smrg                 //printf("fd->parent->isClassDeclaration() = %p\n", fd->parent->isClassDeclaration());
1212760c2415Smrg                 if (!fdmatch)
1213760c2415Smrg                     goto Lfd;
1214760c2415Smrg                 if (fd == fdmatch)
1215760c2415Smrg                     goto Lfdmatch;
1216760c2415Smrg 
1217760c2415Smrg                 {
1218760c2415Smrg                 // Function type matcing: exact > covariant
1219760c2415Smrg                 MATCH m1 = tf->equals(fd     ->type) ? MATCHexact : MATCHnomatch;
1220760c2415Smrg                 MATCH m2 = tf->equals(fdmatch->type) ? MATCHexact : MATCHnomatch;
1221760c2415Smrg                 if (m1 > m2)
1222760c2415Smrg                     goto Lfd;
1223760c2415Smrg                 else if (m1 < m2)
1224760c2415Smrg                     goto Lfdmatch;
1225760c2415Smrg                 }
1226760c2415Smrg 
1227760c2415Smrg                 {
1228760c2415Smrg                 MATCH m1 = (tf->mod == fd     ->type->mod) ? MATCHexact : MATCHnomatch;
1229760c2415Smrg                 MATCH m2 = (tf->mod == fdmatch->type->mod) ? MATCHexact : MATCHnomatch;
1230760c2415Smrg                 if (m1 > m2)
1231760c2415Smrg                     goto Lfd;
1232760c2415Smrg                 else if (m1 < m2)
1233760c2415Smrg                     goto Lfdmatch;
1234760c2415Smrg                 }
1235760c2415Smrg 
1236760c2415Smrg                 {
1237760c2415Smrg                 // The way of definition: non-mixin > mixin
1238760c2415Smrg                 MATCH m1 = fd     ->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch;
1239760c2415Smrg                 MATCH m2 = fdmatch->parent->isClassDeclaration() ? MATCHexact : MATCHnomatch;
1240760c2415Smrg                 if (m1 > m2)
1241760c2415Smrg                     goto Lfd;
1242760c2415Smrg                 else if (m1 < m2)
1243760c2415Smrg                     goto Lfdmatch;
1244760c2415Smrg                 }
1245760c2415Smrg 
1246760c2415Smrg                 fdambig = fd;
1247760c2415Smrg                 //printf("Lambig fdambig = %s %s [%s]\n", fdambig->toChars(), fdambig->type->toChars(), fdambig->loc.toChars());
1248760c2415Smrg                 continue;
1249760c2415Smrg 
1250760c2415Smrg             Lfd:
1251760c2415Smrg                 fdmatch = fd;
1252760c2415Smrg                 fdambig = NULL;
1253760c2415Smrg                 //printf("Lfd fdmatch = %s %s [%s]\n", fdmatch->toChars(), fdmatch->type->toChars(), fdmatch->loc.toChars());
1254760c2415Smrg                 continue;
1255760c2415Smrg 
1256760c2415Smrg             Lfdmatch:
1257760c2415Smrg                 continue;
1258760c2415Smrg             }
1259760c2415Smrg             //else printf("\t\t%d\n", fd->type->covariant(tf));
1260760c2415Smrg         }
1261760c2415Smrg         if (!cd)
1262760c2415Smrg             break;
1263760c2415Smrg         vtbl = &cd->vtblFinal;
1264760c2415Smrg         cd = cd->baseClass;
1265760c2415Smrg     }
1266760c2415Smrg 
1267760c2415Smrg     if (fdambig)
1268760c2415Smrg         error("ambiguous virtual function %s", fdambig->toChars());
1269760c2415Smrg     return fdmatch;
1270760c2415Smrg }
1271760c2415Smrg 
interfaceSemantic(Scope *)1272760c2415Smrg void ClassDeclaration::interfaceSemantic(Scope *)
1273760c2415Smrg {
1274760c2415Smrg     vtblInterfaces = new BaseClasses();
1275760c2415Smrg     vtblInterfaces->reserve(interfaces.length);
1276760c2415Smrg 
1277760c2415Smrg     for (size_t i = 0; i < interfaces.length; i++)
1278760c2415Smrg     {
1279760c2415Smrg         BaseClass *b = interfaces.ptr[i];
1280760c2415Smrg         vtblInterfaces->push(b);
1281760c2415Smrg         b->copyBaseInterfaces(vtblInterfaces);
1282760c2415Smrg     }
1283760c2415Smrg }
1284760c2415Smrg 
1285760c2415Smrg /****************************************
1286760c2415Smrg  */
1287760c2415Smrg 
isCOMclass()1288760c2415Smrg bool ClassDeclaration::isCOMclass() const
1289760c2415Smrg {
1290760c2415Smrg     return com;
1291760c2415Smrg }
1292760c2415Smrg 
isCOMinterface()1293760c2415Smrg bool ClassDeclaration::isCOMinterface() const
1294760c2415Smrg {
1295760c2415Smrg     return false;
1296760c2415Smrg }
1297760c2415Smrg 
isCPPclass()1298760c2415Smrg bool ClassDeclaration::isCPPclass() const
1299760c2415Smrg {
1300*0bfacb9bSmrg     return classKind == ClassKind::cpp;
1301760c2415Smrg }
1302760c2415Smrg 
isCPPinterface()1303760c2415Smrg bool ClassDeclaration::isCPPinterface() const
1304760c2415Smrg {
1305760c2415Smrg     return false;
1306760c2415Smrg }
1307760c2415Smrg 
1308760c2415Smrg 
1309760c2415Smrg /****************************************
1310760c2415Smrg  */
1311760c2415Smrg 
isAbstract()1312760c2415Smrg bool ClassDeclaration::isAbstract()
1313760c2415Smrg {
1314760c2415Smrg     if (isabstract != ABSfwdref)
1315760c2415Smrg         return isabstract == ABSyes;
1316760c2415Smrg 
1317760c2415Smrg     /* Bugzilla 11169: Resolve forward references to all class member functions,
1318760c2415Smrg      * and determine whether this class is abstract.
1319760c2415Smrg      */
1320760c2415Smrg     struct SearchAbstract
1321760c2415Smrg     {
1322760c2415Smrg         static int fp(Dsymbol *s, void *)
1323760c2415Smrg         {
1324760c2415Smrg             FuncDeclaration *fd = s->isFuncDeclaration();
1325760c2415Smrg             if (!fd)
1326760c2415Smrg                 return 0;
1327760c2415Smrg             if (fd->storage_class & STCstatic)
1328760c2415Smrg                 return 0;
1329760c2415Smrg 
1330760c2415Smrg             if (fd->_scope)
1331760c2415Smrg                 fd->semantic(NULL);
1332760c2415Smrg 
1333760c2415Smrg             if (fd->isAbstract())
1334760c2415Smrg                 return 1;
1335760c2415Smrg             return 0;
1336760c2415Smrg         }
1337760c2415Smrg     };
1338760c2415Smrg 
1339760c2415Smrg     for (size_t i = 0; i < members->dim; i++)
1340760c2415Smrg     {
1341760c2415Smrg         Dsymbol *s = (*members)[i];
1342760c2415Smrg         if (s->apply(&SearchAbstract::fp, this))
1343760c2415Smrg         {
1344760c2415Smrg             isabstract = ABSyes;
1345760c2415Smrg             return true;
1346760c2415Smrg         }
1347760c2415Smrg     }
1348760c2415Smrg 
1349760c2415Smrg     /* Iterate inherited member functions and check their abstract attribute.
1350760c2415Smrg      */
1351760c2415Smrg     for (size_t i = 1; i < vtbl.dim; i++)
1352760c2415Smrg     {
1353760c2415Smrg         FuncDeclaration *fd = vtbl[i]->isFuncDeclaration();
1354760c2415Smrg         //if (fd) printf("\tvtbl[%d] = [%s] %s\n", i, fd->loc.toChars(), fd->toChars());
1355760c2415Smrg         if (!fd || fd->isAbstract())
1356760c2415Smrg         {
1357760c2415Smrg             isabstract = ABSyes;
1358760c2415Smrg             return true;
1359760c2415Smrg         }
1360760c2415Smrg     }
1361760c2415Smrg 
1362760c2415Smrg     isabstract = ABSno;
1363760c2415Smrg     return false;
1364760c2415Smrg }
1365760c2415Smrg 
1366760c2415Smrg 
1367760c2415Smrg /****************************************
1368760c2415Smrg  * Determine if slot 0 of the vtbl[] is reserved for something else.
1369760c2415Smrg  * For class objects, yes, this is where the classinfo ptr goes.
1370760c2415Smrg  * For COM interfaces, no.
1371760c2415Smrg  * For non-COM interfaces, yes, this is where the Interface ptr goes.
1372760c2415Smrg  * Returns:
1373760c2415Smrg  *      0       vtbl[0] is first virtual function pointer
1374760c2415Smrg  *      1       vtbl[0] is classinfo/interfaceinfo pointer
1375760c2415Smrg  */
1376760c2415Smrg 
vtblOffset()1377760c2415Smrg int ClassDeclaration::vtblOffset() const
1378760c2415Smrg {
1379*0bfacb9bSmrg     return classKind == ClassKind::cpp ? 0 : 1;
1380760c2415Smrg }
1381760c2415Smrg 
1382760c2415Smrg /****************************************
1383760c2415Smrg  */
1384760c2415Smrg 
kind()1385760c2415Smrg const char *ClassDeclaration::kind() const
1386760c2415Smrg {
1387760c2415Smrg     return "class";
1388760c2415Smrg }
1389760c2415Smrg 
1390760c2415Smrg /****************************************
1391760c2415Smrg  */
1392760c2415Smrg 
addLocalClass(ClassDeclarations * aclasses)1393760c2415Smrg void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses)
1394760c2415Smrg {
1395760c2415Smrg     aclasses->push(this);
1396760c2415Smrg }
1397760c2415Smrg 
1398760c2415Smrg /********************************* InterfaceDeclaration ****************************/
1399760c2415Smrg 
InterfaceDeclaration(Loc loc,Identifier * id,BaseClasses * baseclasses)1400760c2415Smrg InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
1401760c2415Smrg     : ClassDeclaration(loc, id, baseclasses, NULL, false)
1402760c2415Smrg {
1403760c2415Smrg     if (id == Id::IUnknown)     // IUnknown is the root of all COM interfaces
1404760c2415Smrg     {
1405760c2415Smrg         com = true;
1406*0bfacb9bSmrg         classKind = ClassKind::cpp; // IUnknown is also a C++ interface
1407760c2415Smrg     }
1408760c2415Smrg }
1409760c2415Smrg 
syntaxCopy(Dsymbol * s)1410760c2415Smrg Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s)
1411760c2415Smrg {
1412760c2415Smrg     InterfaceDeclaration *id =
1413760c2415Smrg         s ? (InterfaceDeclaration *)s
1414760c2415Smrg           : new InterfaceDeclaration(loc, ident, NULL);
1415760c2415Smrg     return ClassDeclaration::syntaxCopy(id);
1416760c2415Smrg }
1417760c2415Smrg 
newScope(Scope * sc)1418760c2415Smrg Scope *InterfaceDeclaration::newScope(Scope *sc)
1419760c2415Smrg {
1420760c2415Smrg     Scope *sc2 = ClassDeclaration::newScope(sc);
1421760c2415Smrg     if (com)
1422760c2415Smrg         sc2->linkage = LINKwindows;
1423*0bfacb9bSmrg     else if (classKind == ClassKind::cpp)
1424760c2415Smrg         sc2->linkage = LINKcpp;
1425*0bfacb9bSmrg     else if (classKind == ClassKind::objc)
1426760c2415Smrg         sc2->linkage = LINKobjc;
1427760c2415Smrg     return sc2;
1428760c2415Smrg }
1429760c2415Smrg 
semantic(Scope * sc)1430760c2415Smrg void InterfaceDeclaration::semantic(Scope *sc)
1431760c2415Smrg {
1432760c2415Smrg     //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1433760c2415Smrg     if (semanticRun >= PASSsemanticdone)
1434760c2415Smrg         return;
1435760c2415Smrg     unsigned errors = global.errors;
1436760c2415Smrg 
1437760c2415Smrg     //printf("+InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type);
1438760c2415Smrg 
1439760c2415Smrg     Scope *scx = NULL;
1440760c2415Smrg     if (_scope)
1441760c2415Smrg     {
1442760c2415Smrg         sc = _scope;
1443760c2415Smrg         scx = _scope;            // save so we don't make redundant copies
1444760c2415Smrg         _scope = NULL;
1445760c2415Smrg     }
1446760c2415Smrg 
1447760c2415Smrg     if (!parent)
1448760c2415Smrg     {
1449760c2415Smrg         assert(sc->parent && sc->func);
1450760c2415Smrg         parent = sc->parent;
1451760c2415Smrg     }
1452760c2415Smrg     assert(parent && !isAnonymous());
1453760c2415Smrg 
1454760c2415Smrg     if (this->errors)
1455760c2415Smrg         type = Type::terror;
1456760c2415Smrg     type = type->semantic(loc, sc);
1457760c2415Smrg 
1458760c2415Smrg     if (type->ty == Tclass && ((TypeClass *)type)->sym != this)
1459760c2415Smrg     {
1460760c2415Smrg         TemplateInstance *ti = ((TypeClass *)type)->sym->isInstantiated();
1461760c2415Smrg         if (ti && isError(ti))
1462760c2415Smrg             ((TypeClass *)type)->sym = this;
1463760c2415Smrg     }
1464760c2415Smrg 
1465760c2415Smrg     // Ungag errors when not speculative
1466760c2415Smrg     Ungag ungag = ungagSpeculative();
1467760c2415Smrg 
1468760c2415Smrg     if (semanticRun == PASSinit)
1469760c2415Smrg     {
1470760c2415Smrg         protection = sc->protection;
1471760c2415Smrg 
1472760c2415Smrg         storage_class |= sc->stc;
1473760c2415Smrg         if (storage_class & STCdeprecated)
1474760c2415Smrg             isdeprecated = true;
1475760c2415Smrg 
1476760c2415Smrg         userAttribDecl = sc->userAttribDecl;
1477760c2415Smrg     }
1478760c2415Smrg     else if (symtab)
1479760c2415Smrg     {
1480760c2415Smrg         if (sizeok == SIZEOKdone || !scx)
1481760c2415Smrg         {
1482760c2415Smrg             semanticRun = PASSsemanticdone;
1483760c2415Smrg             return;
1484760c2415Smrg         }
1485760c2415Smrg     }
1486760c2415Smrg     semanticRun = PASSsemantic;
1487760c2415Smrg 
1488760c2415Smrg     if (baseok < BASEOKdone)
1489760c2415Smrg     {
1490760c2415Smrg         baseok = BASEOKin;
1491760c2415Smrg 
1492760c2415Smrg         // Expand any tuples in baseclasses[]
1493760c2415Smrg         for (size_t i = 0; i < baseclasses->dim; )
1494760c2415Smrg         {
1495760c2415Smrg             BaseClass *b = (*baseclasses)[i];
1496760c2415Smrg             b->type = resolveBase(this, sc, scx, b->type);
1497760c2415Smrg 
1498760c2415Smrg             Type *tb = b->type->toBasetype();
1499760c2415Smrg             if (tb->ty == Ttuple)
1500760c2415Smrg             {
1501760c2415Smrg                 TypeTuple *tup = (TypeTuple *)tb;
1502760c2415Smrg                 baseclasses->remove(i);
1503760c2415Smrg                 size_t dim = Parameter::dim(tup->arguments);
1504760c2415Smrg                 for (size_t j = 0; j < dim; j++)
1505760c2415Smrg                 {
1506760c2415Smrg                     Parameter *arg = Parameter::getNth(tup->arguments, j);
1507760c2415Smrg                     b = new BaseClass(arg->type);
1508760c2415Smrg                     baseclasses->insert(i + j, b);
1509760c2415Smrg                 }
1510760c2415Smrg             }
1511760c2415Smrg             else
1512760c2415Smrg                 i++;
1513760c2415Smrg         }
1514760c2415Smrg 
1515760c2415Smrg         if (baseok >= BASEOKdone)
1516760c2415Smrg         {
1517760c2415Smrg             //printf("%s already semantic analyzed, semanticRun = %d\n", toChars(), semanticRun);
1518760c2415Smrg             if (semanticRun >= PASSsemanticdone)
1519760c2415Smrg                 return;
1520760c2415Smrg             goto Lancestorsdone;
1521760c2415Smrg         }
1522760c2415Smrg 
1523760c2415Smrg         if (!baseclasses->dim && sc->linkage == LINKcpp)
1524*0bfacb9bSmrg             classKind = ClassKind::cpp;
1525760c2415Smrg         if (sc->linkage == LINKobjc)
1526760c2415Smrg             objc()->setObjc(this);
1527760c2415Smrg 
1528760c2415Smrg         // Check for errors, handle forward references
1529760c2415Smrg         for (size_t i = 0; i < baseclasses->dim; )
1530760c2415Smrg         {
1531760c2415Smrg             BaseClass *b = (*baseclasses)[i];
1532760c2415Smrg             Type *tb = b->type->toBasetype();
1533760c2415Smrg             TypeClass *tc = (tb->ty == Tclass) ? (TypeClass *)tb : NULL;
1534760c2415Smrg             if (!tc || !tc->sym->isInterfaceDeclaration())
1535760c2415Smrg             {
1536760c2415Smrg                 if (b->type != Type::terror)
1537760c2415Smrg                     error("base type must be interface, not %s", b->type->toChars());
1538760c2415Smrg                 baseclasses->remove(i);
1539760c2415Smrg                 continue;
1540760c2415Smrg             }
1541760c2415Smrg 
1542760c2415Smrg             // Check for duplicate interfaces
1543760c2415Smrg             for (size_t j = 0; j < i; j++)
1544760c2415Smrg             {
1545760c2415Smrg                 BaseClass *b2 = (*baseclasses)[j];
1546760c2415Smrg                 if (b2->sym == tc->sym)
1547760c2415Smrg                 {
1548760c2415Smrg                     error("inherits from duplicate interface %s", b2->sym->toChars());
1549760c2415Smrg                     baseclasses->remove(i);
1550760c2415Smrg                     continue;
1551760c2415Smrg                 }
1552760c2415Smrg             }
1553760c2415Smrg 
1554760c2415Smrg             if (tc->sym == this || isBaseOf2(tc->sym))
1555760c2415Smrg             {
1556760c2415Smrg                 error("circular inheritance of interface");
1557760c2415Smrg                 baseclasses->remove(i);
1558760c2415Smrg                 continue;
1559760c2415Smrg             }
1560760c2415Smrg 
1561760c2415Smrg             if (tc->sym->isDeprecated())
1562760c2415Smrg             {
1563760c2415Smrg                 if (!isDeprecated())
1564760c2415Smrg                 {
1565760c2415Smrg                     // Deriving from deprecated class makes this one deprecated too
1566760c2415Smrg                     isdeprecated = true;
1567760c2415Smrg 
1568760c2415Smrg                     tc->checkDeprecated(loc, sc);
1569760c2415Smrg                 }
1570760c2415Smrg             }
1571760c2415Smrg 
1572760c2415Smrg             b->sym = tc->sym;
1573760c2415Smrg 
1574*0bfacb9bSmrg             if (tc->sym->baseok < BASEOKdone)
1575760c2415Smrg                 resolveBase(this, sc, scx, tc->sym); // Try to resolve forward reference
1576760c2415Smrg             if (tc->sym->baseok < BASEOKdone)
1577760c2415Smrg             {
1578760c2415Smrg                 //printf("\ttry later, forward reference of base %s\n", tc->sym->toChars());
1579760c2415Smrg                 if (tc->sym->_scope)
1580760c2415Smrg                     tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
1581760c2415Smrg                 baseok = BASEOKnone;
1582760c2415Smrg             }
1583760c2415Smrg             i++;
1584760c2415Smrg         }
1585760c2415Smrg         if (baseok == BASEOKnone)
1586760c2415Smrg         {
1587760c2415Smrg             // Forward referencee of one or more bases, try again later
1588760c2415Smrg             _scope = scx ? scx : sc->copy();
1589760c2415Smrg             _scope->setNoFree();
1590760c2415Smrg             _scope->_module->addDeferredSemantic(this);
1591760c2415Smrg             return;
1592760c2415Smrg         }
1593760c2415Smrg         baseok = BASEOKdone;
1594760c2415Smrg 
1595760c2415Smrg         interfaces.length = baseclasses->dim;
1596760c2415Smrg         interfaces.ptr = baseclasses->tdata();
1597760c2415Smrg 
1598760c2415Smrg         for (size_t i = 0; i < interfaces.length; i++)
1599760c2415Smrg         {
1600760c2415Smrg             BaseClass *b = interfaces.ptr[i];
1601760c2415Smrg             // If this is an interface, and it derives from a COM interface,
1602760c2415Smrg             // then this is a COM interface too.
1603760c2415Smrg             if (b->sym->isCOMinterface())
1604760c2415Smrg                 com = true;
1605760c2415Smrg             if (b->sym->isCPPinterface())
1606*0bfacb9bSmrg                 classKind = ClassKind::cpp;
1607760c2415Smrg         }
1608760c2415Smrg 
1609760c2415Smrg         interfaceSemantic(sc);
1610760c2415Smrg     }
1611760c2415Smrg Lancestorsdone:
1612760c2415Smrg 
1613760c2415Smrg     if (!members)               // if opaque declaration
1614760c2415Smrg     {
1615760c2415Smrg         semanticRun = PASSsemanticdone;
1616760c2415Smrg         return;
1617760c2415Smrg     }
1618760c2415Smrg     if (!symtab)
1619760c2415Smrg         symtab = new DsymbolTable();
1620760c2415Smrg 
1621760c2415Smrg     for (size_t i = 0; i < baseclasses->dim; i++)
1622760c2415Smrg     {
1623760c2415Smrg         BaseClass *b = (*baseclasses)[i];
1624760c2415Smrg         Type *tb = b->type->toBasetype();
1625760c2415Smrg         assert(tb->ty == Tclass);
1626760c2415Smrg         TypeClass *tc = (TypeClass *)tb;
1627760c2415Smrg 
1628760c2415Smrg         if (tc->sym->semanticRun < PASSsemanticdone)
1629760c2415Smrg         {
1630760c2415Smrg             // Forward referencee of one or more bases, try again later
1631760c2415Smrg             _scope = scx ? scx : sc->copy();
1632760c2415Smrg             _scope->setNoFree();
1633760c2415Smrg             if (tc->sym->_scope)
1634760c2415Smrg                 tc->sym->_scope->_module->addDeferredSemantic(tc->sym);
1635760c2415Smrg             _scope->_module->addDeferredSemantic(this);
1636760c2415Smrg             return;
1637760c2415Smrg         }
1638760c2415Smrg     }
1639760c2415Smrg 
1640760c2415Smrg     if (baseok == BASEOKdone)
1641760c2415Smrg     {
1642760c2415Smrg         baseok = BASEOKsemanticdone;
1643760c2415Smrg 
1644760c2415Smrg         // initialize vtbl
1645760c2415Smrg         if (vtblOffset())
1646760c2415Smrg             vtbl.push(this);                // leave room at vtbl[0] for classinfo
1647760c2415Smrg 
1648760c2415Smrg         // Cat together the vtbl[]'s from base interfaces
1649760c2415Smrg         for (size_t i = 0; i < interfaces.length; i++)
1650760c2415Smrg         {
1651760c2415Smrg             BaseClass *b = interfaces.ptr[i];
1652760c2415Smrg 
1653760c2415Smrg             // Skip if b has already appeared
1654760c2415Smrg             for (size_t k = 0; k < i; k++)
1655760c2415Smrg             {
1656760c2415Smrg                 if (b == interfaces.ptr[k])
1657760c2415Smrg                     goto Lcontinue;
1658760c2415Smrg             }
1659760c2415Smrg 
1660760c2415Smrg             // Copy vtbl[] from base class
1661760c2415Smrg             if (b->sym->vtblOffset())
1662760c2415Smrg             {
1663760c2415Smrg                 size_t d = b->sym->vtbl.dim;
1664760c2415Smrg                 if (d > 1)
1665760c2415Smrg                 {
1666760c2415Smrg                     vtbl.reserve(d - 1);
1667760c2415Smrg                     for (size_t j = 1; j < d; j++)
1668760c2415Smrg                         vtbl.push(b->sym->vtbl[j]);
1669760c2415Smrg                 }
1670760c2415Smrg             }
1671760c2415Smrg             else
1672760c2415Smrg             {
1673760c2415Smrg                 vtbl.append(&b->sym->vtbl);
1674760c2415Smrg             }
1675760c2415Smrg 
1676760c2415Smrg           Lcontinue:
1677760c2415Smrg             ;
1678760c2415Smrg         }
1679760c2415Smrg     }
1680760c2415Smrg 
1681760c2415Smrg     for (size_t i = 0; i < members->dim; i++)
1682760c2415Smrg     {
1683760c2415Smrg         Dsymbol *s = (*members)[i];
1684760c2415Smrg         s->addMember(sc, this);
1685760c2415Smrg     }
1686760c2415Smrg 
1687760c2415Smrg     Scope *sc2 = newScope(sc);
1688760c2415Smrg 
1689760c2415Smrg     /* Set scope so if there are forward references, we still might be able to
1690760c2415Smrg      * resolve individual members like enums.
1691760c2415Smrg      */
1692760c2415Smrg     for (size_t i = 0; i < members->dim; i++)
1693760c2415Smrg     {
1694760c2415Smrg         Dsymbol *s = (*members)[i];
1695760c2415Smrg         //printf("setScope %s %s\n", s->kind(), s->toChars());
1696760c2415Smrg         s->setScope(sc2);
1697760c2415Smrg     }
1698760c2415Smrg 
1699760c2415Smrg     for (size_t i = 0; i < members->dim; i++)
1700760c2415Smrg     {
1701760c2415Smrg         Dsymbol *s = (*members)[i];
1702760c2415Smrg         s->importAll(sc2);
1703760c2415Smrg     }
1704760c2415Smrg 
1705760c2415Smrg     for (size_t i = 0; i < members->dim; i++)
1706760c2415Smrg     {
1707760c2415Smrg         Dsymbol *s = (*members)[i];
1708760c2415Smrg         s->semantic(sc2);
1709760c2415Smrg     }
1710760c2415Smrg 
1711760c2415Smrg     Module::dprogress++;
1712760c2415Smrg     semanticRun = PASSsemanticdone;
1713760c2415Smrg     //printf("-InterfaceDeclaration.semantic(%s), type = %p\n", toChars(), type);
1714760c2415Smrg     //members->print();
1715760c2415Smrg 
1716760c2415Smrg     sc2->pop();
1717760c2415Smrg 
1718760c2415Smrg     if (global.errors != errors)
1719760c2415Smrg     {
1720760c2415Smrg         // The type is no good.
1721760c2415Smrg         type = Type::terror;
1722760c2415Smrg     }
1723760c2415Smrg 
1724760c2415Smrg     assert(type->ty != Tclass || ((TypeClass *)type)->sym == this);
1725760c2415Smrg }
1726760c2415Smrg 
1727760c2415Smrg /*******************************************
1728760c2415Smrg  * Determine if 'this' is a base class of cd.
1729760c2415Smrg  * (Actually, if it is an interface supported by cd)
1730760c2415Smrg  * Output:
1731760c2415Smrg  *      *poffset        offset to start of class
1732760c2415Smrg  *                      OFFSET_RUNTIME  must determine offset at runtime
1733760c2415Smrg  * Returns:
1734760c2415Smrg  *      false   not a base
1735760c2415Smrg  *      true    is a base
1736760c2415Smrg  */
1737760c2415Smrg 
isBaseOf(ClassDeclaration * cd,int * poffset)1738760c2415Smrg bool InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
1739760c2415Smrg {
1740760c2415Smrg     //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
1741760c2415Smrg     assert(!baseClass);
1742760c2415Smrg     for (size_t j = 0; j < cd->interfaces.length; j++)
1743760c2415Smrg     {
1744760c2415Smrg         BaseClass *b = cd->interfaces.ptr[j];
1745760c2415Smrg 
1746760c2415Smrg         //printf("\tX base %s\n", b->sym->toChars());
1747760c2415Smrg         if (this == b->sym)
1748760c2415Smrg         {
1749760c2415Smrg             //printf("\tfound at offset %d\n", b->offset);
1750760c2415Smrg             if (poffset)
1751760c2415Smrg             {
1752760c2415Smrg                 // don't return incorrect offsets https://issues.dlang.org/show_bug.cgi?id=16980
1753760c2415Smrg                 *poffset = cd->sizeok == SIZEOKdone ? b->offset : OFFSET_FWDREF;
1754760c2415Smrg             }
1755760c2415Smrg             //printf("\tfound at offset %d\n", b->offset);
1756760c2415Smrg             return true;
1757760c2415Smrg         }
1758760c2415Smrg         if (isBaseOf(b, poffset))
1759760c2415Smrg             return true;
1760760c2415Smrg     }
1761760c2415Smrg 
1762760c2415Smrg     if (cd->baseClass && isBaseOf(cd->baseClass, poffset))
1763760c2415Smrg         return true;
1764760c2415Smrg 
1765760c2415Smrg     if (poffset)
1766760c2415Smrg         *poffset = 0;
1767760c2415Smrg     return false;
1768760c2415Smrg }
1769760c2415Smrg 
isBaseOf(BaseClass * bc,int * poffset)1770760c2415Smrg bool InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset)
1771760c2415Smrg {
1772760c2415Smrg     //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->sym->toChars());
1773760c2415Smrg     for (size_t j = 0; j < bc->baseInterfaces.length; j++)
1774760c2415Smrg     {
1775760c2415Smrg         BaseClass *b = &bc->baseInterfaces.ptr[j];
1776760c2415Smrg 
1777760c2415Smrg         //printf("\tY base %s\n", b->sym->toChars());
1778760c2415Smrg         if (this == b->sym)
1779760c2415Smrg         {
1780760c2415Smrg             //printf("\tfound at offset %d\n", b->offset);
1781760c2415Smrg             if (poffset)
1782760c2415Smrg             {
1783760c2415Smrg                 *poffset = b->offset;
1784760c2415Smrg             }
1785760c2415Smrg             return true;
1786760c2415Smrg         }
1787760c2415Smrg         if (isBaseOf(b, poffset))
1788760c2415Smrg         {
1789760c2415Smrg             return true;
1790760c2415Smrg         }
1791760c2415Smrg     }
1792760c2415Smrg     if (poffset)
1793760c2415Smrg         *poffset = 0;
1794760c2415Smrg     return false;
1795760c2415Smrg }
1796760c2415Smrg 
1797760c2415Smrg /****************************************
1798760c2415Smrg  * Determine if slot 0 of the vtbl[] is reserved for something else.
1799760c2415Smrg  * For class objects, yes, this is where the ClassInfo ptr goes.
1800760c2415Smrg  * For COM interfaces, no.
1801760c2415Smrg  * For non-COM interfaces, yes, this is where the Interface ptr goes.
1802760c2415Smrg  */
1803760c2415Smrg 
vtblOffset()1804760c2415Smrg int InterfaceDeclaration::vtblOffset() const
1805760c2415Smrg {
1806760c2415Smrg     if (isCOMinterface() || isCPPinterface())
1807760c2415Smrg         return 0;
1808760c2415Smrg     return 1;
1809760c2415Smrg }
1810760c2415Smrg 
isCOMinterface()1811760c2415Smrg bool InterfaceDeclaration::isCOMinterface() const
1812760c2415Smrg {
1813760c2415Smrg     return com;
1814760c2415Smrg }
1815760c2415Smrg 
isCPPinterface()1816760c2415Smrg bool InterfaceDeclaration::isCPPinterface() const
1817760c2415Smrg {
1818*0bfacb9bSmrg     return classKind == ClassKind::cpp;
1819760c2415Smrg }
1820760c2415Smrg 
1821760c2415Smrg /*******************************************
1822760c2415Smrg  */
1823760c2415Smrg 
kind()1824760c2415Smrg const char *InterfaceDeclaration::kind() const
1825760c2415Smrg {
1826760c2415Smrg     return "interface";
1827760c2415Smrg }
1828760c2415Smrg 
1829760c2415Smrg 
1830760c2415Smrg /******************************** BaseClass *****************************/
1831760c2415Smrg 
BaseClass()1832760c2415Smrg BaseClass::BaseClass()
1833760c2415Smrg {
1834760c2415Smrg     this->type = NULL;
1835760c2415Smrg     this->sym = NULL;
1836760c2415Smrg     this->offset = 0;
1837760c2415Smrg 
1838760c2415Smrg     this->baseInterfaces.length = 0;
1839760c2415Smrg     this->baseInterfaces.ptr = NULL;
1840760c2415Smrg }
1841760c2415Smrg 
BaseClass(Type * type)1842760c2415Smrg BaseClass::BaseClass(Type *type)
1843760c2415Smrg {
1844760c2415Smrg     //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
1845760c2415Smrg     this->type = type;
1846760c2415Smrg     this->sym = NULL;
1847760c2415Smrg     this->offset = 0;
1848760c2415Smrg 
1849760c2415Smrg     this->baseInterfaces.length = 0;
1850760c2415Smrg     this->baseInterfaces.ptr = NULL;
1851760c2415Smrg }
1852760c2415Smrg 
1853760c2415Smrg /****************************************
1854760c2415Smrg  * Fill in vtbl[] for base class based on member functions of class cd.
1855760c2415Smrg  * Input:
1856760c2415Smrg  *      vtbl            if !=NULL, fill it in
1857760c2415Smrg  *      newinstance     !=0 means all entries must be filled in by members
1858760c2415Smrg  *                      of cd, not members of any base classes of cd.
1859760c2415Smrg  * Returns:
1860760c2415Smrg  *      true if any entries were filled in by members of cd (not exclusively
1861760c2415Smrg  *      by base classes)
1862760c2415Smrg  */
1863760c2415Smrg 
fillVtbl(ClassDeclaration * cd,FuncDeclarations * vtbl,int newinstance)1864760c2415Smrg bool BaseClass::fillVtbl(ClassDeclaration *cd, FuncDeclarations *vtbl, int newinstance)
1865760c2415Smrg {
1866760c2415Smrg     bool result = false;
1867760c2415Smrg 
1868760c2415Smrg     //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", sym->toChars(), cd->toChars());
1869760c2415Smrg     if (vtbl)
1870760c2415Smrg         vtbl->setDim(sym->vtbl.dim);
1871760c2415Smrg 
1872760c2415Smrg     // first entry is ClassInfo reference
1873760c2415Smrg     for (size_t j = sym->vtblOffset(); j < sym->vtbl.dim; j++)
1874760c2415Smrg     {
1875760c2415Smrg         FuncDeclaration *ifd = sym->vtbl[j]->isFuncDeclaration();
1876760c2415Smrg         FuncDeclaration *fd;
1877760c2415Smrg         TypeFunction *tf;
1878760c2415Smrg 
1879760c2415Smrg         //printf("        vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
1880760c2415Smrg 
1881760c2415Smrg         assert(ifd);
1882760c2415Smrg         // Find corresponding function in this class
1883760c2415Smrg         tf = ifd->type->toTypeFunction();
1884760c2415Smrg         fd = cd->findFunc(ifd->ident, tf);
1885760c2415Smrg         if (fd && !fd->isAbstract())
1886760c2415Smrg         {
1887760c2415Smrg             //printf("            found\n");
1888760c2415Smrg             // Check that calling conventions match
1889760c2415Smrg             if (fd->linkage != ifd->linkage)
1890760c2415Smrg                 fd->error("linkage doesn't match interface function");
1891760c2415Smrg 
1892760c2415Smrg             // Check that it is current
1893760c2415Smrg             //printf("newinstance = %d fd->toParent() = %s ifd->toParent() = %s\n",
1894760c2415Smrg                 //newinstance, fd->toParent()->toChars(), ifd->toParent()->toChars());
1895760c2415Smrg             if (newinstance && fd->toParent() != cd && ifd->toParent() == sym)
1896760c2415Smrg                 cd->error("interface function '%s' is not implemented", ifd->toFullSignature());
1897760c2415Smrg 
1898760c2415Smrg             if (fd->toParent() == cd)
1899760c2415Smrg                 result = true;
1900760c2415Smrg         }
1901760c2415Smrg         else
1902760c2415Smrg         {
1903760c2415Smrg             //printf("            not found %p\n", fd);
1904760c2415Smrg             // BUG: should mark this class as abstract?
1905760c2415Smrg             if (!cd->isAbstract())
1906760c2415Smrg                 cd->error("interface function '%s' is not implemented", ifd->toFullSignature());
1907760c2415Smrg 
1908760c2415Smrg             fd = NULL;
1909760c2415Smrg         }
1910760c2415Smrg         if (vtbl)
1911760c2415Smrg             (*vtbl)[j] = fd;
1912760c2415Smrg     }
1913760c2415Smrg 
1914760c2415Smrg     return result;
1915760c2415Smrg }
1916760c2415Smrg 
copyBaseInterfaces(BaseClasses * vtblInterfaces)1917760c2415Smrg void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces)
1918760c2415Smrg {
1919760c2415Smrg     //printf("+copyBaseInterfaces(), %s\n", sym->toChars());
1920760c2415Smrg //    if (baseInterfaces.length)
1921760c2415Smrg //      return;
1922760c2415Smrg 
1923760c2415Smrg     baseInterfaces.length = sym->interfaces.length;
1924760c2415Smrg     baseInterfaces.ptr = (BaseClass *)mem.xcalloc(baseInterfaces.length, sizeof(BaseClass));
1925760c2415Smrg 
1926760c2415Smrg     //printf("%s.copyBaseInterfaces()\n", sym->toChars());
1927760c2415Smrg     for (size_t i = 0; i < baseInterfaces.length; i++)
1928760c2415Smrg     {
1929760c2415Smrg         void *pb = &baseInterfaces.ptr[i];
1930760c2415Smrg         BaseClass *b2 = sym->interfaces.ptr[i];
1931760c2415Smrg 
1932760c2415Smrg         assert(b2->vtbl.dim == 0);      // should not be filled yet
1933760c2415Smrg         BaseClass *b = (BaseClass *)memcpy(pb, b2, sizeof(BaseClass));
1934760c2415Smrg 
1935760c2415Smrg         if (i)                          // single inheritance is i==0
1936760c2415Smrg             vtblInterfaces->push(b);    // only need for M.I.
1937760c2415Smrg         b->copyBaseInterfaces(vtblInterfaces);
1938760c2415Smrg     }
1939760c2415Smrg     //printf("-copyBaseInterfaces\n");
1940760c2415Smrg }
1941