root/trunk/src/class.c

Revision 873, 43.8 kB (checked in by walter, 1 year ago)

bugzilla 5447 Should be illegal to throw a non-Throwable

  • Property svn:eol-style set to native
Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2009 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <assert.h>
13
14 #include "root.h"
15 #include "rmem.h"
16
17 #include "enum.h"
18 #include "init.h"
19 #include "attrib.h"
20 #include "declaration.h"
21 #include "aggregate.h"
22 #include "id.h"
23 #include "mtype.h"
24 #include "scope.h"
25 #include "module.h"
26 #include "expression.h"
27 #include "statement.h"
28
29 /********************************* ClassDeclaration ****************************/
30
31 ClassDeclaration *ClassDeclaration::classinfo;
32 ClassDeclaration *ClassDeclaration::object;
33 ClassDeclaration *ClassDeclaration::throwable;
34
35 ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
36     : AggregateDeclaration(loc, id)
37 {
38     static char msg[] = "only object.d can define this reserved class name";
39
40     if (baseclasses)
41         // Actually, this is a transfer
42         this->baseclasses = baseclasses;
43     else
44         this->baseclasses = new BaseClasses();
45     baseClass = NULL;
46
47     interfaces_dim = 0;
48     interfaces = NULL;
49
50     vtblInterfaces = NULL;
51
52     //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses->dim);
53
54     // For forward references
55     type = new TypeClass(this);
56     handle = type;
57
58     staticCtor = NULL;
59     staticDtor = NULL;
60
61     vtblsym = NULL;
62     vclassinfo = NULL;
63
64     if (id)
65     {   // Look for special class names
66
67         if (id == Id::__sizeof || id == Id::__xalignof || id == Id::mangleof)
68             error("illegal class name");
69
70         // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
71         if (id->toChars()[0] == 'T')
72         {
73             if (id == Id::TypeInfo)
74             {   if (Type::typeinfo)
75                     Type::typeinfo->error("%s", msg);
76                 Type::typeinfo = this;
77             }
78
79             if (id == Id::TypeInfo_Class)
80             {   if (Type::typeinfoclass)
81                     Type::typeinfoclass->error("%s", msg);
82                 Type::typeinfoclass = this;
83             }
84
85             if (id == Id::TypeInfo_Interface)
86             {   if (Type::typeinfointerface)
87                     Type::typeinfointerface->error("%s", msg);
88                 Type::typeinfointerface = this;
89             }
90
91             if (id == Id::TypeInfo_Struct)
92             {   if (Type::typeinfostruct)
93                     Type::typeinfostruct->error("%s", msg);
94                 Type::typeinfostruct = this;
95             }
96
97             if (id == Id::TypeInfo_Typedef)
98             {   if (Type::typeinfotypedef)
99                     Type::typeinfotypedef->error("%s", msg);
100                 Type::typeinfotypedef = this;
101             }
102
103             if (id == Id::TypeInfo_Pointer)
104             {   if (Type::typeinfopointer)
105                     Type::typeinfopointer->error("%s", msg);
106                 Type::typeinfopointer = this;
107             }
108
109             if (id == Id::TypeInfo_Array)
110             {   if (Type::typeinfoarray)
111                     Type::typeinfoarray->error("%s", msg);
112                 Type::typeinfoarray = this;
113             }
114
115             if (id == Id::TypeInfo_StaticArray)
116             {   //if (Type::typeinfostaticarray)
117                     //Type::typeinfostaticarray->error("%s", msg);
118                 Type::typeinfostaticarray = this;
119             }
120
121             if (id == Id::TypeInfo_AssociativeArray)
122             {   if (Type::typeinfoassociativearray)
123                     Type::typeinfoassociativearray->error("%s", msg);
124                 Type::typeinfoassociativearray = this;
125             }
126
127             if (id == Id::TypeInfo_Enum)
128             {   if (Type::typeinfoenum)
129                     Type::typeinfoenum->error("%s", msg);
130                 Type::typeinfoenum = this;
131             }
132
133             if (id == Id::TypeInfo_Function)
134             {   if (Type::typeinfofunction)
135                     Type::typeinfofunction->error("%s", msg);
136                 Type::typeinfofunction = this;
137             }
138
139             if (id == Id::TypeInfo_Delegate)
140             {   if (Type::typeinfodelegate)
141                     Type::typeinfodelegate->error("%s", msg);
142                 Type::typeinfodelegate = this;
143             }
144
145             if (id == Id::TypeInfo_Tuple)
146             {   if (Type::typeinfotypelist)
147                     Type::typeinfotypelist->error("%s", msg);
148                 Type::typeinfotypelist = this;
149             }
150
151 #if DMDV2
152             if (id == Id::TypeInfo_Const)
153             {   if (Type::typeinfoconst)
154                     Type::typeinfoconst->error("%s", msg);
155                 Type::typeinfoconst = this;
156             }
157
158             if (id == Id::TypeInfo_Invariant)
159             {   if (Type::typeinfoinvariant)
160                     Type::typeinfoinvariant->error("%s", msg);
161                 Type::typeinfoinvariant = this;
162             }
163
164             if (id == Id::TypeInfo_Shared)
165             {   if (Type::typeinfoshared)
166                     Type::typeinfoshared->error("%s", msg);
167                 Type::typeinfoshared = this;
168             }
169
170             if (id == Id::TypeInfo_Wild)
171             {   if (Type::typeinfowild)
172                     Type::typeinfowild->error("%s", msg);
173                 Type::typeinfowild = this;
174             }
175 #endif
176         }
177
178         if (id == Id::Object)
179         {   if (object)
180                 object->error("%s", msg);
181             object = this;
182         }
183
184         if (id == Id::Throwable)
185         {   if (throwable)
186                 throwable->error("%s", msg);
187             throwable = this;
188         }
189
190         //if (id == Id::ClassInfo)
191         if (id == Id::TypeInfo_Class)
192         {   if (classinfo)
193                 classinfo->error("%s", msg);
194             classinfo = this;
195         }
196
197         if (id == Id::ModuleInfo)
198         {   if (Module::moduleinfo)
199                 Module::moduleinfo->error("%s", msg);
200             Module::moduleinfo = this;
201         }
202     }
203
204     com = 0;
205     isscope = 0;
206     isabstract = 0;
207     inuse = 0;
208 }
209
210 Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
211 {
212     ClassDeclaration *cd;
213
214     //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
215     if (s)
216         cd = (ClassDeclaration *)s;
217     else
218         cd = new ClassDeclaration(loc, ident, NULL);
219
220     cd->storage_class |= storage_class;
221
222     cd->baseclasses->setDim(this->baseclasses->dim);
223     for (int i = 0; i < cd->baseclasses->dim; i++)
224     {
225         BaseClass *b = (BaseClass *)this->baseclasses->data[i];
226         BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
227         cd->baseclasses->data[i] = b2;
228     }
229
230     ScopeDsymbol::syntaxCopy(cd);
231     return cd;
232 }
233
234 void ClassDeclaration::semantic(Scope *sc)
235 {   int i;
236     unsigned offset;
237
238     //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
239     //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
240     //printf("sc->stc = %x\n", sc->stc);
241
242     //{ static int n;  if (++n == 20) *(char*)0=0; }
243
244     if (!ident)         // if anonymous class
245     {   const char *id = "__anonclass";
246
247         ident = Identifier::generateId(id);
248     }
249
250     if (!sc)
251         sc = scope;
252     if (!parent && sc->parent && !sc->parent->isModule())
253         parent = sc->parent;
254
255     type = type->semantic(loc, sc);
256     handle = type;
257
258     if (!members)                       // if forward reference
259     {   //printf("\tclass '%s' is forward referenced\n", toChars());
260         return;
261     }
262     if (symtab)
263     {   if (sizeok == 1 || !scope)
264         {   //printf("\tsemantic for '%s' is already completed\n", toChars());
265             return;             // semantic() already completed
266         }
267     }
268     else
269         symtab = new DsymbolTable();
270
271     Scope *scx = NULL;
272     if (scope)
273     {   sc = scope;
274         scx = scope;            // save so we don't make redundant copies
275         scope = NULL;
276     }
277     unsigned dprogress_save = Module::dprogress;
278 #ifdef IN_GCC
279     methods.setDim(0);
280 #endif
281
282     if (sc->stc & STCdeprecated)
283     {
284         isdeprecated = 1;
285     }
286
287     if (sc->linkage == LINKcpp)
288         error("cannot create C++ classes");
289
290     // Expand any tuples in baseclasses[]
291     for (i = 0; i < baseclasses->dim; )
292     {   BaseClass *b = (BaseClass *)baseclasses->data[i];
293 //printf("test1 %s %s\n", toChars(), b->type->toChars());
294         b->type = b->type->semantic(loc, sc);
295 //printf("test2\n");
296         Type *tb = b->type->toBasetype();
297
298         if (tb->ty == Ttuple)
299         {   TypeTuple *tup = (TypeTuple *)tb;
300             enum PROT protection = b->protection;
301             baseclasses->remove(i);
302             size_t dim = Parameter::dim(tup->arguments);
303             for (size_t j = 0; j < dim; j++)
304             {   Parameter *arg = Parameter::getNth(tup->arguments, j);
305                 b = new BaseClass(arg->type, protection);
306                 baseclasses->insert(i + j, b);
307             }
308         }
309         else
310             i++;
311     }
312
313     // See if there's a base class as first in baseclasses[]
314     if (baseclasses->dim)
315     {   TypeClass *tc;
316         BaseClass *b;
317         Type *tb;
318
319         b = (BaseClass *)baseclasses->data[0];
320         //b->type = b->type->semantic(loc, sc);
321         tb = b->type->toBasetype();
322         if (tb->ty != Tclass)
323         {   error("base type must be class or interface, not %s", b->type->toChars());
324             baseclasses->remove(0);
325         }
326         else
327         {
328             tc = (TypeClass *)(tb);
329
330             if (tc->sym->isDeprecated())
331             {
332                 if (!isDeprecated())
333                 {
334                     // Deriving from deprecated class makes this one deprecated too
335                     isdeprecated = 1;
336
337                     tc->checkDeprecated(loc, sc);
338                 }
339             }
340
341             if (tc->sym->isInterfaceDeclaration())
342                 ;
343             else
344             {
345                 for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
346                 {
347                     if (cdb == this)
348                     {
349                         error("circular inheritance");
350                         baseclasses->remove(0);
351                         goto L7;
352                     }
353                 }
354                 if (!tc->sym->symtab || tc->sym->sizeok == 0)
355                 {   // Try to resolve forward reference
356                     if (/*sc->mustsemantic &&*/ tc->sym->scope)
357                         tc->sym->semantic(NULL);
358                 }
359                 if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
360                 {
361                     //printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars());
362                     //error("forward reference of base class %s", baseClass->toChars());
363                     // Forward reference of base class, try again later
364                     //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
365                     scope = scx ? scx : new Scope(*sc);
366                     scope->setNoFree();
367                     if (tc->sym->scope)
368                         tc->sym->scope->module->addDeferredSemantic(tc->sym);
369                     scope->module->addDeferredSemantic(this);
370                     return;
371                 }
372                 else
373                 {   baseClass = tc->sym;
374                     b->base = baseClass;
375                 }
376              L7: ;
377             }
378         }
379     }
380
381     // Treat the remaining entries in baseclasses as interfaces
382     // Check for errors, handle forward references
383     for (i = (baseClass ? 1 : 0); i < baseclasses->dim; )
384     {   TypeClass *tc;
385         BaseClass *b;
386         Type *tb;
387
388         b = (BaseClass *)baseclasses->data[i];
389         b->type = b->type->semantic(loc, sc);
390         tb = b->type->toBasetype();
391         if (tb->ty == Tclass)
392             tc = (TypeClass *)tb;
393         else
394             tc = NULL;
395         if (!tc || !tc->sym->isInterfaceDeclaration())
396         {
397             error("base type must be interface, not %s", b->type->toChars());
398             baseclasses->remove(i);
399             continue;
400         }
401         else
402         {
403             if (tc->sym->isDeprecated())
404             {
405                 if (!isDeprecated())
406                 {
407                     // Deriving from deprecated class makes this one deprecated too
408                     isdeprecated = 1;
409
410                     tc->checkDeprecated(loc, sc);
411                 }
412             }
413
414             // Check for duplicate interfaces
415             for (size_t j = (baseClass ? 1 : 0); j < i; j++)
416             {
417                 BaseClass *b2 = (BaseClass *)baseclasses->data[j];
418                 if (b2->base == tc->sym)
419                     error("inherits from duplicate interface %s", b2->base->toChars());
420             }
421
422             if (!tc->sym->symtab)
423             {   // Try to resolve forward reference
424                 if (/*sc->mustsemantic &&*/ tc->sym->scope)
425                     tc->sym->semantic(NULL);
426             }
427
428             b->base = tc->sym;
429             if (!b->base->symtab || b->base->scope)
430             {
431                 //error("forward reference of base class %s", baseClass->toChars());
432                 // Forward reference of base, try again later
433                 //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
434                 scope = scx ? scx : new Scope(*sc);
435                 scope->setNoFree();
436                 if (tc->sym->scope)
437                     tc->sym->scope->module->addDeferredSemantic(tc->sym);
438                 scope->module->addDeferredSemantic(this);
439                 return;
440             }
441         }
442         i++;
443     }
444
445
446     // If no base class, and this is not an Object, use Object as base class
447     if (!baseClass && ident != Id::Object)
448     {
449         // BUG: what if Object is redefined in an inner scope?
450         Type *tbase = new TypeIdentifier(0, Id::Object);
451         BaseClass *b;
452         TypeClass *tc;
453         Type *bt;
454
455         if (!object)
456         {
457             error("missing or corrupt object.d");
458             fatal();
459         }
460         bt = tbase->semantic(loc, sc)->toBasetype();
461         b = new BaseClass(bt, PROTpublic);
462         baseclasses->shift(b);
463         assert(b->type->ty == Tclass);
464         tc = (TypeClass *)(b->type);
465         baseClass = tc->sym;
466         assert(!baseClass->isInterfaceDeclaration());
467         b->base = baseClass;
468     }
469
470     interfaces_dim = baseclasses->dim;
471     interfaces = (BaseClass **)baseclasses->data;
472
473
474     if (baseClass)
475     {
476         if (baseClass->storage_class & STCfinal)
477             error("cannot inherit from final class %s", baseClass->toChars());
478
479         interfaces_dim--;
480         interfaces++;
481
482         // Copy vtbl[] from base class
483         vtbl.setDim(baseClass->vtbl.dim);
484         memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim);
485
486         // Inherit properties from base class
487         com = baseClass->isCOMclass();
488         isscope = baseClass->isscope;
489         vthis = baseClass->vthis;
490         storage_class |= baseClass->storage_class & STC_TYPECTOR;
491     }
492     else
493     {
494         // No base class, so this is the root of the class hierarchy
495         vtbl.setDim(0);
496         vtbl.push(this);                // leave room for classinfo as first member
497     }
498
499     protection = sc->protection;
500     storage_class |= sc->stc;
501
502     if (sizeok == 0)
503     {
504         interfaceSemantic(sc);
505
506         for (i = 0; i < members->dim; i++)
507         {
508             Dsymbol *s = (Dsymbol *)members->data[i];
509             s->addMember(sc, this, 1);
510         }
511
512         /* If this is a nested class, add the hidden 'this'
513          * member which is a pointer to the enclosing scope.
514          */
515         if (vthis)              // if inheriting from nested class
516         {   // Use the base class's 'this' member
517             isnested = 1;
518             if (storage_class & STCstatic)
519                 error("static class cannot inherit from nested class %s", baseClass->toChars());
520             if (toParent2() != baseClass->toParent2())
521             {
522                 if (toParent2())
523                 {
524                     error("is nested within %s, but super class %s is nested within %s",
525                         toParent2()->toChars(),
526                         baseClass->toChars(),
527                         baseClass->toParent2()->toChars());
528                 }
529                 else
530                 {
531                     error("is not nested, but super class %s is nested within %s",
532                         baseClass->toChars(),
533                         baseClass->toParent2()->toChars());
534                 }
535                 isnested = 0;
536             }
537         }
538         else if (!(storage_class & STCstatic))
539         {   Dsymbol *s = toParent2();
540             if (s)
541             {
542                 AggregateDeclaration *ad = s->isClassDeclaration();
543                 FuncDeclaration *fd = s->isFuncDeclaration();
544
545
546                 if (ad || fd)
547                 {   isnested = 1;
548                     Type *t;
549                     if (ad)
550                         t = ad->handle;
551                     else if (fd)
552                     {   AggregateDeclaration *ad = fd->isMember2();
553                         if (ad)
554                             t = ad->handle;
555                         else
556                         {
557                             t = Type::tvoidptr;
558                         }
559                     }
560                     else
561                         assert(0);
562                     if (t->ty == Tstruct)       // ref to struct
563                         t = Type::tvoidptr;
564                     assert(!vthis);
565                     vthis = new ThisDeclaration(loc, t);
566                     members->push(vthis);
567                 }
568             }
569         }
570     }
571
572     if (storage_class & STCauto)
573         error("storage class 'auto' is invalid when declaring a class, did you mean to use 'scope'?");
574     if (storage_class & STCscope)
575         isscope = 1;
576     if (storage_class & STCabstract)
577         isabstract = 1;
578
579     if (storage_class & STCimmutable)
580         type = type->addMod(MODimmutable);
581     if (storage_class & STCconst)
582         type = type->addMod(MODconst);
583     if (storage_class & STCshared)
584         type = type->addMod(MODshared);
585
586     sc = sc->push(this);
587     //sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared);
588     //sc->stc |= storage_class & STC_TYPECTOR;
589     sc->stc &= STCsafe | STCtrusted | STCsystem;
590     sc->parent = this;
591     sc->inunion = 0;
592
593     if (isCOMclass())
594     {
595 #if _WIN32
596         sc->linkage = LINKwindows;
597 #else
598         /* This enables us to use COM objects under Linux and
599          * work with things like XPCOM
600          */
601         sc->linkage = LINKc;
602 #endif
603     }
604     sc->protection = PROTpublic;
605     sc->explicitProtection = 0;
606     sc->structalign = 8;
607     structalign = sc->structalign;
608     if (baseClass)
609     {   sc->offset = baseClass->structsize;
610         alignsize = baseClass->alignsize;
611 //      if (isnested)
612 //          sc->offset += PTRSIZE;      // room for uplevel context pointer
613     }
614     else
615     {   sc->offset = PTRSIZE * 2;       // allow room for __vptr and __monitor
616         alignsize = PTRSIZE;
617     }
618     structsize = sc->offset;
619     Scope scsave = *sc;
620     int members_dim = members->dim;
621     sizeok = 0;
622
623     /* Set scope so if there are forward references, we still might be able to
624      * resolve individual members like enums.
625      */
626     for (i = 0; i < members_dim; i++)
627     {   Dsymbol *s = (Dsymbol *)members->data[i];
628         /* There are problems doing this in the general case because
629          * Scope keeps track of things like 'offset'
630          */
631         if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident))
632         {
633             //printf("setScope %s %s\n", s->kind(), s->toChars());
634             s->setScope(sc);
635         }
636     }
637
638     for (i = 0; i < members_dim; i++)
639     {   Dsymbol *s = (Dsymbol *)members->data[i];
640         s->semantic(sc);
641     }
642
643     if (sizeok == 2)
644     {   // semantic() failed because of forward references.
645         // Unwind what we did, and defer it for later
646         fields.setDim(0);
647         structsize = 0;
648         alignsize = 0;
649         structalign = 0;
650
651         sc = sc->pop();
652
653         scope = scx ? scx : new Scope(*sc);
654         scope->setNoFree();
655         scope->module->addDeferredSemantic(this);
656
657         Module::dprogress = dprogress_save;
658
659         //printf("\tsemantic('%s') failed due to forward references\n", toChars());
660         return;
661     }
662
663     //printf("\tsemantic('%s') successful\n", toChars());
664
665     structsize = sc->offset;
666     //members->print();
667
668     /* Look for special member functions.
669      * They must be in this class, not in a base class.
670      */
671     ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
672     if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration()))
673         ctor = NULL;
674
675 //    dtor = (DtorDeclaration *)search(Id::dtor, 0);
676 //    if (dtor && dtor->toParent() != this)
677 //      dtor = NULL;
678
679 //    inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
680 //    if (inv && inv->toParent() != this)
681 //      inv = NULL;
682
683     // Can be in base class
684     aggNew    = (NewDeclaration *)search(0, Id::classNew, 0);
685     aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
686
687     // If this class has no constructor, but base class does, create
688     // a constructor:
689     //    this() { }
690     if (!ctor && baseClass && baseClass->ctor)
691     {
692         //printf("Creating default this(){} for class %s\n", toChars());
693         CtorDeclaration *ctor = new CtorDeclaration(loc, 0, NULL, 0, 0);
694         ctor->fbody = new CompoundStatement(0, new Statements());
695         members->push(ctor);
696         ctor->addMember(sc, this, 1);
697         *sc = scsave;   // why? What about sc->nofree?
698         sc->offset = structsize;
699         ctor->semantic(sc);
700         this->ctor = ctor;
701         defaultCtor = ctor;
702     }
703
704 #if 0
705     if (baseClass)
706     {   if (!aggDelete)
707             aggDelete = baseClass->aggDelete;
708         if (!aggNew)
709             aggNew = baseClass->aggNew;
710     }
711 #endif
712
713     // Allocate instance of each new interface
714     for (i = 0; i < vtblInterfaces->dim; i++)
715     {
716         BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
717         unsigned thissize = PTRSIZE;
718
719         alignmember(structalign, thissize, &sc->offset);
720         assert(b->offset == 0);
721         b->offset = sc->offset;
722
723         // Take care of single inheritance offsets
724         while (b->baseInterfaces_dim)
725         {
726             b = &b->baseInterfaces[0];
727             b->offset = sc->offset;
728         }
729
730         sc->offset += thissize;
731         if (alignsize < thissize)
732             alignsize = thissize;
733     }
734     structsize = sc->offset;
735     sizeok = 1;
736     Module::dprogress++;
737
738     dtor = buildDtor(sc);
739
740     sc->pop();
741
742 #if 0 // Do not call until toObjfile() because of forward references
743     // Fill in base class vtbl[]s
744     for (i = 0; i < vtblInterfaces->dim; i++)
745     {
746         BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
747
748         //b->fillVtbl(this, &b->vtbl, 1);
749     }
750 #endif
751     //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
752 }
753
754 void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
755 {
756     if (!isAnonymous())
757     {
758         buf->printf("%s ", kind());
759         buf->writestring(toChars());
760         if (baseclasses->dim)
761             buf->writestring(" : ");
762     }
763     for (int i = 0; i < baseclasses->dim; i++)
764     {
765         BaseClass *b = (BaseClass *)baseclasses->data[i];
766
767         if (i)
768             buf->writeByte(',');
769         //buf->writestring(b->base->ident->toChars());
770         b->type->toCBuffer(buf, NULL, hgs);
771     }
772     if (members)
773     {
774         buf->writenl();
775         buf->writeByte('{');
776         buf->writenl();
777         for (int i = 0; i < members->dim; i++)
778         {
779             Dsymbol *s = (Dsymbol *)members->data[i];
780
781             buf->writestring("    ");
782             s->toCBuffer(buf, hgs);
783         }
784         buf->writestring("}");
785     }
786     else
787         buf->writeByte(';');
788     buf->writenl();
789 }
790
791 #if 0
792 void ClassDeclaration::defineRef(Dsymbol *s)
793 {
794     ClassDeclaration *cd;
795
796     AggregateDeclaration::defineRef(s);
797     cd = s->isClassDeclaration();
798     baseType = cd->baseType;
799     cd->baseType = NULL;
800 }
801 #endif
802
803 /*********************************************
804  * Determine if 'this' is a base class of cd.
805  * This is used to detect circular inheritance only.
806  */
807
808 int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
809 {
810     if (!cd)
811         return 0;
812     //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
813     for (int i = 0; i < cd->baseclasses->dim; i++)
814     {   BaseClass *b = (BaseClass *)cd->baseclasses->data[i];
815
816         if (b->base == this || isBaseOf2(b->base))
817             return 1;
818     }
819     return 0;
820 }
821
822 /*******************************************
823  * Determine if 'this' is a base class of cd.
824  */
825
826 int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
827 {
828     //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
829     if (poffset)
830         *poffset = 0;
831     while (cd)
832     {
833         if (this == cd->baseClass)
834             return 1;
835
836         /* cd->baseClass might not be set if cd is forward referenced.
837          */
838         if (!cd->baseClass && cd->baseclasses->dim && !cd->isInterfaceDeclaration())
839         {
840             cd->error("base class is forward referenced by %s", toChars());
841         }
842
843         cd = cd->baseClass;
844     }
845     return 0;
846 }
847
848 /*********************************************
849  * Determine if 'this' has complete base class information.
850  * This is used to detect forward references in covariant overloads.
851  */
852
853 int ClassDeclaration::isBaseInfoComplete()
854 {
855     if (!baseClass)
856         return ident == Id::Object;
857     for (int i = 0; i < baseclasses->dim; i++)
858     {   BaseClass *b = (BaseClass *)baseclasses->data[i];
859         if (!b->base || !b->base->isBaseInfoComplete())
860             return 0;
861     }
862     return 1;
863 }
864
865 Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
866 {
867     Dsymbol *s;
868     //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
869
870     if (scope)
871     {   Scope *sc = scope;
872         sc->mustsemantic++;
873         semantic(sc);
874         sc->mustsemantic--;
875     }
876
877     if (!members || !symtab || scope)
878     {
879         error("is forward referenced when looking for '%s'", ident->toChars());
880         //*(char*)0=0;
881         return NULL;
882     }
883
884     s = ScopeDsymbol::search(loc, ident, flags);
885     if (!s)
886     {
887         // Search bases classes in depth-first, left to right order
888
889         int i;
890
891         for (i = 0; i < baseclasses->dim; i++)
892         {
893             BaseClass *b = (BaseClass *)baseclasses->data[i];
894
895             if (b->base)
896             {
897                 if (!b->base->symtab)
898                     error("base %s is forward referenced", b->base->ident->toChars());
899                 else
900                 {
901                     s = b->base->search(loc, ident, flags);
902                     if (s == this)      // happens if s is nested in this and derives from this
903                         s = NULL;
904                     else if (s)
905                         break;
906                 }
907             }
908         }
909     }
910     return s;
911 }
912
913 /**********************************************************
914  * fd is in the vtbl[] for this class.
915  * Return 1 if function is hidden (not findable through search).
916  */
917
918 #if DMDV2
919 int isf(void *param, FuncDeclaration *fd)
920 {
921     //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
922     return param == fd;
923 }
924
925 int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
926 {
927     //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toChars());
928     Dsymbol *s = search(0, fd->ident, 4|2);
929     if (!s)
930     {   //printf("not found\n");
931         /* Because, due to a hack, if there are multiple definitions
932          * of fd->ident, NULL is returned.
933          */
934         return 0;
935     }
936     s = s->toAlias();
937     OverloadSet *os = s->isOverloadSet();
938     if (os)
939     {
940         for (int i = 0; i < os->a.dim; i++)
941         {   Dsymbol *s = (Dsymbol *)os->a.data[i];
942             FuncDeclaration *f2 = s->isFuncDeclaration();
943             if (f2 && overloadApply(f2, &isf, fd))
944                 return 0;
945         }
946         return 1;
947     }
948     else
949     {
950         FuncDeclaration *fdstart = s->isFuncDeclaration();
951         //printf("%s fdstart = %p\n", s->kind(), fdstart);
952         return !overloadApply(fdstart, &isf, fd);
953     }
954 }
955 #endif
956
957 /****************
958  * Find virtual function matching identifier and type.
959  * Used to build virtual function tables for interface implementations.
960  */
961
962 FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
963 {
964     //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
965
966     ClassDeclaration *cd = this;
967     Array *vtbl = &cd->vtbl;
968     while (1)
969     {
970         for (size_t i = 0; i < vtbl->dim; i++)
971         {
972             FuncDeclaration *fd = ((Dsymbol*)vtbl->data[i])->isFuncDeclaration();
973             if (!fd)
974                 continue;               // the first entry might be a ClassInfo
975
976             //printf("\t[%d] = %s\n", i, fd->toChars());
977             if (ident == fd->ident &&
978                 //tf->equals(fd->type)
979                 fd->type->covariant(tf) == 1
980                )
981             {   //printf("\t\tfound\n");
982                 return fd;
983             }
984             //else printf("\t\t%d\n", fd->type->covariant(tf));
985         }
986         if (!cd)
987             break;
988         vtbl = &cd->vtblFinal;
989         cd = cd->baseClass;
990     }
991
992     return NULL;
993 }
994
995 void ClassDeclaration::interfaceSemantic(Scope *sc)
996 {
997     InterfaceDeclaration *id = isInterfaceDeclaration();
998
999     vtblInterfaces = new BaseClasses();
1000     vtblInterfaces->reserve(interfaces_dim);
1001
1002     for (size_t i = 0; i < interfaces_dim; i++)
1003     {
1004         BaseClass *b = interfaces[i];
1005
1006         // If this is an interface, and it derives from a COM interface,
1007         // then this is a COM interface too.
1008         if (b->base->isCOMinterface())
1009             com = 1;
1010
1011         if (b->base->isCPPinterface() && id)
1012             id->cpp = 1;
1013
1014         vtblInterfaces->push(b);
1015         b->copyBaseInterfaces(vtblInterfaces);
1016     }
1017 }
1018
1019 /****************************************
1020  */
1021
1022 int ClassDeclaration::isCOMclass()
1023 {
1024     return com;
1025 }
1026
1027 int ClassDeclaration::isCOMinterface()
1028 {
1029     return 0;
1030 }
1031
1032 #if DMDV2
1033 int ClassDeclaration::isCPPinterface()
1034 {
1035     return 0;
1036 }
1037 #endif
1038
1039
1040 /****************************************
1041  */
1042
1043 int ClassDeclaration::isAbstract()
1044 {
1045     if (isabstract)
1046         return TRUE;
1047     for (int i = 1; i < vtbl.dim; i++)
1048     {
1049         FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration();
1050
1051         //printf("\tvtbl[%d] = %p\n", i, fd);
1052         if (!fd || fd->isAbstract())
1053         {
1054             isabstract |= 1;
1055             return TRUE;
1056         }
1057     }
1058     return FALSE;
1059 }
1060
1061
1062 /****************************************
1063  * Determine if slot 0 of the vtbl[] is reserved for something else.
1064  * For class objects, yes, this is where the classinfo ptr goes.
1065  * For COM interfaces, no.
1066  * For non-COM interfaces, yes, this is where the Interface ptr goes.
1067  */
1068
1069 int ClassDeclaration::vtblOffset()
1070 {
1071     return 1;
1072 }
1073
1074 /****************************************
1075  */
1076
1077 const char *ClassDeclaration::kind()
1078 {
1079     return "class";
1080 }
1081
1082 /****************************************
1083  */
1084
1085 void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses)
1086 {
1087     aclasses->push(this);
1088 }
1089
1090 /********************************* InterfaceDeclaration ****************************/
1091
1092 InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
1093     : ClassDeclaration(loc, id, baseclasses)
1094 {
1095     com = 0;
1096     cpp = 0;
1097     if (id == Id::IUnknown)     // IUnknown is the root of all COM interfaces
1098     {   com = 1;
1099         cpp = 1;                // IUnknown is also a C++ interface
1100     }
1101 }
1102
1103 Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s)
1104 {
1105     InterfaceDeclaration *id;
1106
1107     if (s)
1108         id = (InterfaceDeclaration *)s;
1109     else
1110         id = new InterfaceDeclaration(loc, ident, NULL);
1111
1112     ClassDeclaration::syntaxCopy(id);
1113     return id;
1114 }
1115
1116 void InterfaceDeclaration::semantic(Scope *sc)
1117 {   int i;
1118
1119     //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1120     if (inuse)
1121         return;
1122
1123     if (!sc)
1124         sc = scope;
1125     if (!parent && sc->parent && !sc->parent->isModule())
1126         parent = sc->parent;
1127
1128     type = type->semantic(loc, sc);
1129     handle = type;
1130
1131     if (!members)                       // if forward reference
1132     {   //printf("\tinterface '%s' is forward referenced\n", toChars());
1133         return;
1134     }
1135     if (symtab)                 // if already done
1136     {   if (!scope)
1137             return;
1138     }
1139     else
1140         symtab = new DsymbolTable();
1141
1142     Scope *scx = NULL;
1143     if (scope)
1144     {   sc = scope;
1145         scx = scope;            // save so we don't make redundant copies
1146         scope = NULL;
1147     }
1148
1149     if (sc->stc & STCdeprecated)
1150     {
1151         isdeprecated = 1;
1152     }
1153
1154     // Expand any tuples in baseclasses[]
1155     for (i = 0; i < baseclasses->dim; )
1156     {   BaseClass *b = (BaseClass *)baseclasses->data[0];
1157         b->type = b->type->semantic(loc, sc);
1158         Type *tb = b->type->toBasetype();
1159
1160         if (tb->ty == Ttuple)
1161         {   TypeTuple *tup = (TypeTuple *)tb;
1162             enum PROT protection = b->protection;
1163             baseclasses->remove(i);
1164             size_t dim = Parameter::dim(tup->arguments);
1165             for (size_t j = 0; j < dim; j++)
1166             {   Parameter *arg = Parameter::getNth(tup->arguments, j);
1167                 b = new BaseClass(arg->type, protection);
1168                 baseclasses->insert(i + j, b);
1169             }
1170         }
1171         else
1172             i++;
1173     }
1174
1175     if (!baseclasses->dim && sc->linkage == LINKcpp)
1176         cpp = 1;
1177
1178     // Check for errors, handle forward references
1179     for (i = 0; i < baseclasses->dim; )
1180     {   TypeClass *tc;
1181         BaseClass *b;
1182         Type *tb;
1183
1184         b = (BaseClass *)baseclasses->data[i];
1185         b->type = b->type->semantic(loc, sc);
1186         tb = b->type->toBasetype();
1187         if (tb->ty == Tclass)
1188             tc = (TypeClass *)tb;
1189         else
1190             tc = NULL;
1191         if (!tc || !tc->sym->isInterfaceDeclaration())
1192         {
1193             error("base type must be interface, not %s", b->type->toChars());
1194             baseclasses->remove(i);
1195             continue;
1196         }
1197         else
1198         {
1199             // Check for duplicate interfaces
1200             for (size_t j = 0; j < i; j++)
1201             {
1202                 BaseClass *b2 = (BaseClass *)baseclasses->data[j];
1203                 if (b2->base == tc->sym)
1204                     error("inherits from duplicate interface %s", b2->base->toChars());
1205             }
1206
1207             b->base = tc->sym;
1208             if (b->base == this || isBaseOf2(b->base))
1209             {
1210                 error("circular inheritance of interface");
1211                 baseclasses->remove(i);
1212                 continue;
1213             }
1214             if (!b->base->symtab)
1215             {   // Try to resolve forward reference
1216                 if (sc->mustsemantic && b->base->scope)
1217                     b->base->semantic(NULL);
1218             }
1219             if (!b->base->symtab || b->base->scope || b->base->inuse)
1220             {
1221                 //error("forward reference of base class %s", baseClass->toChars());
1222                 // Forward reference of base, try again later
1223                 //printf("\ttry later, forward reference of base %s\n", b->base->toChars());
1224                 scope = scx ? scx : new Scope(*sc);
1225                 scope->setNoFree();
1226                 scope->module->addDeferredSemantic(this);
1227                 return;
1228             }
1229         }
1230 #if 0
1231         // Inherit const/invariant from base class
1232         storage_class |= b->base->storage_class & STC_TYPECTOR;
1233 #endif
1234         i++;
1235     }
1236
1237     interfaces_dim = baseclasses->dim;
1238     interfaces = (BaseClass **)baseclasses->data;
1239
1240     interfaceSemantic(sc);
1241
1242     if (vtblOffset())
1243         vtbl.push(this);                // leave room at vtbl[0] for classinfo
1244
1245     // Cat together the vtbl[]'s from base interfaces
1246     for (i = 0; i < interfaces_dim; i++)
1247     {   BaseClass *b = interfaces[i];
1248
1249         // Skip if b has already appeared
1250         for (int k = 0; k < i; k++)
1251         {
1252             if (b == interfaces[k])
1253                 goto Lcontinue;
1254         }
1255
1256         // Copy vtbl[] from base class
1257         if (b->base->vtblOffset())
1258         {   int d = b->base->vtbl.dim;
1259             if (d > 1)
1260             {
1261                 vtbl.reserve(d - 1);
1262                 for (int j = 1; j < d; j++)
1263                     vtbl.push(b->base->vtbl.data[j]);
1264             }
1265         }
1266         else
1267         {
1268             vtbl.append(&b->base->vtbl);
1269         }
1270
1271       Lcontinue:
1272         ;
1273     }
1274
1275     protection = sc->protection;
1276     storage_class |= sc->stc & STC_TYPECTOR;
1277
1278     for (i = 0; i < members->dim; i++)
1279     {
1280         Dsymbol *s = (Dsymbol *)members->data[i];
1281         s->addMember(sc, this, 1);
1282     }
1283
1284     sc = sc->push(this);
1285     sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
1286                  STCabstract | STCdeprecated | STC_TYPECTOR | STCtls | STCgshared);
1287     sc->stc |= storage_class & STC_TYPECTOR;
1288     sc->parent = this;
1289     if (isCOMinterface())
1290         sc->linkage = LINKwindows;
1291     else if (isCPPinterface())
1292         sc->linkage = LINKcpp;
1293     sc->structalign = 8;
1294     structalign = sc->structalign;
1295     sc->offset = PTRSIZE * 2;
1296     inuse++;
1297     for (i = 0; i < members->dim; i++)
1298     {
1299         Dsymbol *s = (Dsymbol *)members->data[i];
1300         s->semantic(sc);
1301     }
1302     inuse--;
1303     //members->print();
1304     sc->pop();
1305     //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1306 }
1307
1308
1309 /*******************************************
1310  * Determine if 'this' is a base class of cd.
1311  * (Actually, if it is an interface supported by cd)
1312  * Output:
1313  *      *poffset        offset to start of class
1314  *                      OFFSET_RUNTIME  must determine offset at runtime
1315  * Returns:
1316  *      0       not a base
1317  *      1       is a base
1318  */
1319
1320 int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
1321 {
1322     unsigned j;
1323
1324     //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
1325     assert(!baseClass);
1326     for (j = 0; j < cd->interfaces_dim; j++)
1327     {
1328         BaseClass *b = cd->interfaces[j];
1329
1330         //printf("\tbase %s\n", b->base->toChars());
1331         if (this == b->base)
1332         {
1333             //printf("\tfound at offset %d\n", b->offset);
1334             if (poffset)
1335             {   *poffset = b->offset;
1336                 if (j && cd->isInterfaceDeclaration())
1337                     *poffset = OFFSET_RUNTIME;
1338             }
1339             return 1;
1340         }
1341         if (isBaseOf(b, poffset))
1342         {   if (j && poffset && cd->isInterfaceDeclaration())
1343                 *poffset = OFFSET_RUNTIME;
1344             return 1;
1345         }
1346     }
1347
1348     if (cd->baseClass && isBaseOf(cd->baseClass, poffset))
1349         return 1;
1350
1351     if (poffset)
1352         *poffset = 0;
1353     return 0;
1354 }
1355
1356
1357 int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset)
1358 {
1359     //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars());
1360     for (unsigned j = 0; j < bc->baseInterfaces_dim; j++)
1361     {
1362         BaseClass *b = &bc->baseInterfaces[j];
1363
1364         if (this == b->base)
1365         {
1366             if (poffset)
1367             {   *poffset = b->offset;
1368                 if (j && bc->base->isInterfaceDeclaration())
1369                     *poffset = OFFSET_RUNTIME;
1370             }
1371             return 1;
1372         }
1373         if (isBaseOf(b, poffset))
1374         {   if (j && poffset && bc->base->isInterfaceDeclaration())
1375                 *poffset = OFFSET_RUNTIME;
1376             return 1;
1377         }
1378     }
1379     if (poffset)
1380         *poffset = 0;
1381     return 0;
1382 }
1383
1384 /*********************************************
1385  * Determine if 'this' has clomplete base class information.
1386  * This is used to detect forward references in covariant overloads.
1387  */
1388
1389 int InterfaceDeclaration::isBaseInfoComplete()
1390 {
1391     assert(!baseClass);
1392     for (int i = 0; i < baseclasses->dim; i++)
1393     {   BaseClass *b = (BaseClass *)baseclasses->data[i];
1394         if (!b->base || !b->base->isBaseInfoComplete ())
1395             return 0;
1396     }
1397     return 1;
1398 }
1399
1400 /****************************************
1401  * Determine if slot 0 of the vtbl[] is reserved for something else.
1402  * For class objects, yes, this is where the ClassInfo ptr goes.
1403  * For COM interfaces, no.
1404  * For non-COM interfaces, yes, this is where the Interface ptr goes.
1405  */
1406
1407 int InterfaceDeclaration::vtblOffset()
1408 {
1409     if (isCOMinterface() || isCPPinterface())
1410         return 0;
1411     return 1;
1412 }
1413
1414 int InterfaceDeclaration::isCOMinterface()
1415 {
1416     return com;
1417 }
1418
1419 #if DMDV2
1420 int InterfaceDeclaration::isCPPinterface()
1421 {
1422     return cpp;
1423 }
1424 #endif
1425
1426 /*******************************************
1427  */
1428
1429 const char *InterfaceDeclaration::kind()
1430 {
1431     return "interface";
1432 }
1433
1434
1435 /******************************** BaseClass *****************************/
1436
1437 BaseClass::BaseClass()
1438 {
1439     memset(this, 0, sizeof(BaseClass));
1440 }
1441
1442 BaseClass::BaseClass(Type *type, enum PROT protection)
1443 {
1444     //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
1445     this->type = type;
1446     this->protection = protection;
1447     base = NULL;
1448     offset = 0;
1449
1450     baseInterfaces_dim = 0;
1451     baseInterfaces = NULL;
1452 }
1453
1454 /****************************************
1455  * Fill in vtbl[] for base class based on member functions of class cd.
1456  * Input:
1457  *      vtbl            if !=NULL, fill it in
1458  *      newinstance     !=0 means all entries must be filled in by members
1459  *                      of cd, not members of any base classes of cd.
1460  * Returns:
1461  *      !=0 if any entries were filled in by members of cd (not exclusively
1462  *      by base classes)
1463  */
1464
1465 int BaseClass::fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance)
1466 {
1467     ClassDeclaration *id = base;
1468     int j;
1469     int result = 0;
1470
1471     //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars());
1472     if (vtbl)
1473         vtbl->setDim(base->vtbl.dim);
1474
1475     // first entry is ClassInfo reference
1476     for (j = base->vtblOffset(); j < base->vtbl.dim; j++)
1477     {
1478         FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration();
1479         FuncDeclaration *fd;
1480         TypeFunction *tf;
1481
1482         //printf("        vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
1483
1484         assert(ifd);
1485         // Find corresponding function in this class
1486         tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL;
1487         fd = cd->findFunc(ifd->ident, tf);
1488         if (fd && !fd->isAbstract())
1489         {
1490             //printf("            found\n");
1491             // Check that calling conventions match
1492             if (fd->linkage != ifd->linkage)
1493                 fd->error("linkage doesn't match interface function");
1494
1495             // Check that it is current
1496             if (newinstance &&
1497                 fd->toParent() != cd &&
1498                 ifd->toParent() == base)
1499                 cd->error("interface function %s.%s is not implemented",
1500                     id->toChars(), ifd->ident->toChars());
1501
1502             if (fd->toParent() == cd)
1503                 result = 1;
1504         }
1505         else
1506         {
1507             //printf("            not found\n");
1508             // BUG: should mark this class as abstract?
1509             if (!cd->isAbstract())
1510                 cd->error("interface function %s.%s isn't implemented",
1511                     id->toChars(), ifd->ident->toChars());
1512             fd = NULL;
1513         }
1514         if (vtbl)
1515             vtbl->data[j] = fd;
1516     }
1517
1518     return result;
1519 }
1520
1521 void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces)
1522 {
1523     //printf("+copyBaseInterfaces(), %s\n", base->toChars());
1524 //    if (baseInterfaces_dim)
1525 //      return;
1526
1527     baseInterfaces_dim = base->interfaces_dim;
1528     baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass));
1529
1530     //printf("%s.copyBaseInterfaces()\n", base->toChars());
1531     for (int i = 0; i < baseInterfaces_dim; i++)
1532     {
1533         BaseClass *b = &baseInterfaces[i];
1534         BaseClass *b2 = base->interfaces[i];
1535
1536         assert(b2->vtbl.dim == 0);      // should not be filled yet
1537         memcpy(b, b2, sizeof(BaseClass));
1538
1539         if (i)                          // single inheritance is i==0
1540             vtblInterfaces->push(b);    // only need for M.I.
1541         b->copyBaseInterfaces(vtblInterfaces);
1542     }
1543     //printf("-copyBaseInterfaces\n");
1544 }
Note: See TracBrowser for help on using the browser.