Merged Delight changes to D1 into D2
[delight/core.git] / dmd2 / class.c
blobd82be4656e6e69bb2bf26f8faea75efc6aaf7d49
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, December 2006
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <assert.h>
21 #include "root.h"
22 #include "mem.h"
24 #include "enum.h"
25 #include "init.h"
26 #include "attrib.h"
27 #include "declaration.h"
28 #include "aggregate.h"
29 #include "id.h"
30 #include "mtype.h"
31 #include "scope.h"
32 #include "module.h"
33 #include "expression.h"
34 #include "statement.h"
36 /********************************* ClassDeclaration ****************************/
38 ClassDeclaration *ClassDeclaration::classinfo;
39 ClassDeclaration *ClassDeclaration::object;
41 ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
42 : AggregateDeclaration(loc, id)
44 static char msg[] = "only object.d can define this reserved class name";
46 if (baseclasses)
47 this->baseclasses = *baseclasses;
48 baseClass = NULL;
50 interfaces_dim = 0;
51 interfaces = NULL;
53 vtblInterfaces = NULL;
55 //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses.dim);
57 // For forward references
58 type = new TypeClass(this);
59 handle = type;
61 ctor = NULL;
62 defaultCtor = NULL;
63 staticCtor = NULL;
64 staticDtor = NULL;
66 vtblsym = NULL;
67 vclassinfo = NULL;
69 if (id)
70 { // Look for special class names
72 if (id == Id::__sizeof || id == Id::alignof || id == Id::mangleof)
73 error("illegal class name");
75 // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
76 if (id->toChars()[0] == 'T')
78 if (id == Id::TypeInfo)
79 { if (Type::typeinfo)
80 Type::typeinfo->error("%s", msg);
81 Type::typeinfo = this;
84 if (id == Id::TypeInfo_Class)
85 { if (Type::typeinfoclass)
86 Type::typeinfoclass->error("%s", msg);
87 Type::typeinfoclass = this;
90 if (id == Id::TypeInfo_Interface)
91 { if (Type::typeinfointerface)
92 Type::typeinfointerface->error("%s", msg);
93 Type::typeinfointerface = this;
96 if (id == Id::TypeInfo_Struct)
97 { if (Type::typeinfostruct)
98 Type::typeinfostruct->error("%s", msg);
99 Type::typeinfostruct = this;
102 if (id == Id::TypeInfo_Typedef)
103 { if (Type::typeinfotypedef)
104 Type::typeinfotypedef->error("%s", msg);
105 Type::typeinfotypedef = this;
108 if (id == Id::TypeInfo_Pointer)
109 { if (Type::typeinfopointer)
110 Type::typeinfopointer->error("%s", msg);
111 Type::typeinfopointer = this;
114 if (id == Id::TypeInfo_Maybe)
115 { if (Type::typeinfomaybe)
116 Type::typeinfomaybe->error("%s", msg);
117 Type::typeinfomaybe = this;
120 if (id == Id::TypeInfo_Array)
121 { if (Type::typeinfoarray)
122 Type::typeinfoarray->error("%s", msg);
123 Type::typeinfoarray = this;
126 if (id == Id::TypeInfo_StaticArray)
127 { //if (Type::typeinfostaticarray)
128 //Type::typeinfostaticarray->error("%s", msg);
129 Type::typeinfostaticarray = this;
132 if (id == Id::TypeInfo_AssociativeArray)
133 { if (Type::typeinfoassociativearray)
134 Type::typeinfoassociativearray->error("%s", msg);
135 Type::typeinfoassociativearray = this;
138 if (id == Id::TypeInfo_Enum)
139 { if (Type::typeinfoenum)
140 Type::typeinfoenum->error("%s", msg);
141 Type::typeinfoenum = this;
144 if (id == Id::TypeInfo_Function)
145 { if (Type::typeinfofunction)
146 Type::typeinfofunction->error("%s", msg);
147 Type::typeinfofunction = this;
150 if (id == Id::TypeInfo_Delegate)
151 { if (Type::typeinfodelegate)
152 Type::typeinfodelegate->error("%s", msg);
153 Type::typeinfodelegate = this;
156 if (id == Id::TypeInfo_Tuple)
157 { if (Type::typeinfotypelist)
158 Type::typeinfotypelist->error("%s", msg);
159 Type::typeinfotypelist = this;
162 #if V2
163 if (id == Id::TypeInfo_Const)
164 { if (Type::typeinfoconst)
165 Type::typeinfoconst->error("%s", msg);
166 Type::typeinfoconst = this;
169 if (id == Id::TypeInfo_Invariant)
170 { if (Type::typeinfoinvariant)
171 Type::typeinfoinvariant->error("%s", msg);
172 Type::typeinfoinvariant = this;
174 #endif
177 if (id == Id::Object)
178 { if (object)
179 object->error("%s", msg);
180 object = this;
183 if (id == Id::ClassInfo)
184 { if (classinfo)
185 classinfo->error("%s", msg);
186 classinfo = this;
189 if (id == Id::ModuleInfo)
190 { if (Module::moduleinfo)
191 Module::moduleinfo->error("%s", msg);
192 Module::moduleinfo = this;
196 com = 0;
197 isauto = 0;
198 isabstract = 0;
199 isnested = 0;
200 vthis = NULL;
201 inuse = 0;
204 Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
206 ClassDeclaration *cd;
208 //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
209 if (s)
210 cd = (ClassDeclaration *)s;
211 else
212 cd = new ClassDeclaration(loc, ident, NULL);
214 cd->storage_class |= storage_class;
216 cd->baseclasses.setDim(this->baseclasses.dim);
217 for (int i = 0; i < cd->baseclasses.dim; i++)
219 BaseClass *b = (BaseClass *)this->baseclasses.data[i];
220 BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
221 cd->baseclasses.data[i] = b2;
224 ScopeDsymbol::syntaxCopy(cd);
225 return cd;
228 void ClassDeclaration::semantic(Scope *sc)
229 { int i;
231 //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
232 //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
233 //printf("sc->stc = %x\n", sc->stc);
235 //{ static int n; if (++n == 20) *(char*)0=0; }
237 if (!ident) // if anonymous class
238 { char *id = "__anonclass";
240 ident = Identifier::generateId(id);
243 if (!scope)
245 if (!parent && sc->parent && !sc->parent->isModule())
246 parent = sc->parent;
248 type = type->semantic(loc, sc);
249 handle = handle->semantic(loc, sc);
251 if (!members) // if forward reference
252 { //printf("\tclass '%s' is forward referenced\n", toChars());
253 return;
255 if (symtab)
256 { if (!scope)
257 { //printf("\tsemantic for '%s' is already completed\n", toChars());
258 return; // semantic() already completed
261 else
262 symtab = new DsymbolTable();
264 Scope *scx = NULL;
265 if (scope)
266 { sc = scope;
267 scx = scope; // save so we don't make redundant copies
268 scope = NULL;
270 if (attributes)
271 attributes->append(sc->attributes);
272 else
273 attributes = sc->attributes;
274 #ifdef IN_GCC
275 methods.setDim(0);
276 #endif
278 if (sc->stc & STCdeprecated)
280 isdeprecated = 1;
283 if (sc->linkage == LINKcpp)
284 error("cannot create C++ classes");
286 // Expand any tuples in baseclasses[]
287 for (i = 0; i < baseclasses.dim; )
288 { BaseClass *b = (BaseClass *)baseclasses.data[i];
289 b->type = b->type->semantic(loc, sc);
290 Type *tb = b->type->toBasetype();
292 if (tb->ty == Ttuple)
293 { TypeTuple *tup = (TypeTuple *)tb;
294 enum PROT protection = b->protection;
295 baseclasses.remove(i);
296 size_t dim = Argument::dim(tup->arguments);
297 for (size_t j = 0; j < dim; j++)
298 { Argument *arg = Argument::getNth(tup->arguments, j);
299 b = new BaseClass(arg->type, protection);
300 baseclasses.insert(i + j, b);
303 else
304 i++;
307 // See if there's a base class as first in baseclasses[]
308 if (baseclasses.dim)
309 { TypeClass *tc;
310 BaseClass *b;
311 Type *tb;
313 b = (BaseClass *)baseclasses.data[0];
314 //b->type = b->type->semantic(loc, sc);
315 tb = b->type->toBasetype();
316 if (tb->ty != Tclass)
317 { error("base type must be class or interface, not %s", b->type->toChars());
318 baseclasses.remove(0);
320 else
322 tc = (TypeClass *)(tb);
324 if (tc->sym->isDeprecated())
326 if (!isDeprecated())
328 // Deriving from deprecated class makes this one deprecated too
329 isdeprecated = 1;
331 tc->checkDeprecated(loc, sc);
335 if (tc->sym->isInterfaceDeclaration())
337 else
339 for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
341 if (cdb == this)
343 error("circular inheritance");
344 baseclasses.remove(0);
345 goto L7;
348 if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
350 //error("forward reference of base class %s", baseClass->toChars());
351 // Forward reference of base class, try again later
352 //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
353 scope = scx ? scx : new Scope(*sc);
354 scope->setNoFree();
355 scope->module->addDeferredSemantic(this);
356 return;
358 else
359 { baseClass = tc->sym;
360 b->base = baseClass;
362 L7: ;
367 // Treat the remaining entries in baseclasses as interfaces
368 // Check for errors, handle forward references
369 for (i = (baseClass ? 1 : 0); i < baseclasses.dim; )
370 { TypeClass *tc;
371 BaseClass *b;
372 Type *tb;
374 b = (BaseClass *)baseclasses.data[i];
375 b->type = b->type->semantic(loc, sc);
376 tb = b->type->toBasetype();
377 if (tb->ty == Tclass)
378 tc = (TypeClass *)tb;
379 else
380 tc = NULL;
381 if (!tc || !tc->sym->isInterfaceDeclaration())
383 error("base type must be interface, not %s", b->type->toChars());
384 baseclasses.remove(i);
385 continue;
387 else
389 if (tc->sym->isDeprecated())
391 if (!isDeprecated())
393 // Deriving from deprecated class makes this one deprecated too
394 isdeprecated = 1;
396 tc->checkDeprecated(loc, sc);
400 // Check for duplicate interfaces
401 for (size_t j = (baseClass ? 1 : 0); j < i; j++)
403 BaseClass *b2 = (BaseClass *)baseclasses.data[j];
404 if (b2->base == tc->sym)
405 error("inherits from duplicate interface %s", b2->base->toChars());
408 b->base = tc->sym;
409 if (!b->base->symtab || b->base->scope)
411 //error("forward reference of base class %s", baseClass->toChars());
412 // Forward reference of base, try again later
413 //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
414 scope = scx ? scx : new Scope(*sc);
415 scope->setNoFree();
416 scope->module->addDeferredSemantic(this);
417 return;
420 i++;
424 // If no base class, and this is not an Object, use Object as base class
425 if (!baseClass && ident != Id::Object)
427 // BUG: what if Object is redefined in an inner scope?
428 Type *tbase = new TypeIdentifier(0, Id::Object);
429 BaseClass *b;
430 TypeClass *tc;
431 Type *bt;
433 if (!object)
435 error("missing or corrupt object.d");
436 fatal();
438 bt = tbase->semantic(loc, sc)->toBasetype();
439 b = new BaseClass(bt, PROTpublic);
440 baseclasses.shift(b);
441 assert(b->type->ty == Tclass);
442 tc = (TypeClass *)(b->type);
443 baseClass = tc->sym;
444 assert(!baseClass->isInterfaceDeclaration());
445 b->base = baseClass;
448 interfaces_dim = baseclasses.dim;
449 interfaces = (BaseClass **)baseclasses.data;
452 if (baseClass)
454 if (baseClass->storage_class & STCfinal)
455 error("cannot inherit from final class %s", baseClass->toChars());
457 interfaces_dim--;
458 interfaces++;
460 // Copy vtbl[] from base class
461 vtbl.setDim(baseClass->vtbl.dim);
462 memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim);
464 // Inherit properties from base class
465 com = baseClass->isCOMclass();
466 isauto = baseClass->isauto;
467 vthis = baseClass->vthis;
468 storage_class |= baseClass->storage_class & (STCconst | STCinvariant);
470 else
472 // No base class, so this is the root of the class hierarchy
473 vtbl.setDim(0);
474 vtbl.push(this); // leave room for classinfo as first member
477 protection = sc->protection;
478 storage_class |= sc->stc;
480 if (sizeok == 0)
482 interfaceSemantic(sc);
484 for (i = 0; i < members->dim; i++)
486 Dsymbol *s = (Dsymbol *)members->data[i];
487 s->addMember(sc, this, 1);
490 /* If this is a nested class, add the hidden 'this'
491 * member which is a pointer to the enclosing scope.
493 if (vthis) // if inheriting from nested class
494 { // Use the base class's 'this' member
495 isnested = 1;
496 if (storage_class & STCstatic)
497 error("static class cannot inherit from nested class %s", baseClass->toChars());
498 if (toParent2() != baseClass->toParent2())
499 error("super class %s is nested within %s, not %s",
500 baseClass->toChars(),
501 baseClass->toParent2()->toChars(),
502 toParent2()->toChars());
504 else if (!(storage_class & STCstatic))
505 { Dsymbol *s = toParent2();
506 if (s)
508 ClassDeclaration *cd = s->isClassDeclaration();
509 FuncDeclaration *fd = s->isFuncDeclaration();
512 if (cd || fd)
513 { isnested = 1;
514 Type *t;
515 if (cd)
516 t = cd->type;
517 else if (fd)
518 { AggregateDeclaration *ad = fd->isMember2();
519 if (ad)
520 t = ad->handle;
521 else
523 t = new TypePointer(Type::tvoid);
524 t = t->semantic(0, sc);
527 else
528 assert(0);
529 assert(!vthis);
530 vthis = new ThisDeclaration(t);
531 members->push(vthis);
537 if (storage_class & (STCauto | STCscope))
538 isauto = 1;
539 if (storage_class & STCabstract)
540 isabstract = 1;
541 if (storage_class & STCinvariant)
542 type = type->invariantOf();
543 else if (storage_class & STCconst)
544 type = type->constOf();
546 sc = sc->push(this);
547 sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
548 STCabstract | STCdeprecated | STCconst | STCinvariant | STCtls);
549 sc->stc |= storage_class & (STCconst | STCinvariant);
550 sc->attributes = NULL;
551 sc->parent = this;
552 sc->inunion = 0;
554 if (isCOMclass())
555 sc->linkage = LINKwindows;
556 sc->protection = PROTpublic;
557 sc->explicitProtection = 0;
558 sc->structalign = 8;
559 structalign = sc->structalign;
560 if (baseClass)
561 { sc->offset = baseClass->structsize;
562 alignsize = baseClass->alignsize;
563 // if (isnested)
564 // sc->offset += PTRSIZE; // room for uplevel context pointer
566 else
567 { sc->offset = PTRSIZE * 2; // allow room for vptr[] and monitor
568 alignsize = PTRSIZE;
570 structsize = sc->offset;
571 Scope scsave = *sc;
572 int members_dim = members->dim;
573 sizeok = 0;
574 for (i = 0; i < members_dim; i++)
576 Dsymbol *s = (Dsymbol *)members->data[i];
577 s->semantic(sc);
580 if (sizeok == 2)
581 { // semantic() failed because of forward references.
582 // Unwind what we did, and defer it for later
583 fields.setDim(0);
584 structsize = 0;
585 alignsize = 0;
586 structalign = 0;
588 sc = sc->pop();
590 scope = scx ? scx : new Scope(*sc);
591 scope->setNoFree();
592 scope->module->addDeferredSemantic(this);
594 //printf("\tsemantic('%s') failed due to forward references\n", toChars());
595 return;
598 //printf("\tsemantic('%s') successful\n", toChars());
600 structsize = sc->offset;
601 //members->print();
603 /* Look for special member functions.
604 * They must be in this class, not in a base class.
606 ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
607 if (ctor && ctor->toParent() != this)
608 ctor = NULL;
610 // dtor = (DtorDeclaration *)search(Id::dtor, 0);
611 // if (dtor && dtor->toParent() != this)
612 // dtor = NULL;
614 // inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
615 // if (inv && inv->toParent() != this)
616 // inv = NULL;
618 // Can be in base class
619 aggNew = (NewDeclaration *)search(0, Id::classNew, 0);
620 aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
622 // If this class has no constructor, but base class does, create
623 // a constructor:
625 // this() { }
627 // Also do this if we have some "in" fields on the class, or
628 // if there are non-null fields
629 if (!ctor)
631 bool hasInArgs = false;
632 bool hasNonNull = false;
633 for (int i = 0; i < fields.dim; i++)
635 VarDeclaration *var = (VarDeclaration *) fields.data[i];
637 if (var->isIn()) {
638 hasInArgs = true;
639 break;
642 if (var->type->ty == Tclass) {
643 hasNonNull = true;
644 break;
647 if (hasInArgs || hasNonNull || (baseClass && baseClass->ctor))
649 //printf("Creating default this(){} for class %s\n", toChars());
650 ctor = new CtorDeclaration(0, 0, NULL, 0);
651 ctor->fbody = new CompoundStatement(0, new Statements());
652 members->push(ctor);
653 ctor->addMember(sc, this, 1);
654 *sc = scsave; // why? What about sc->nofree?
655 sc->offset = structsize;
656 ctor->semantic(sc);
657 defaultCtor = ctor;
661 #if 0
662 if (baseClass)
663 { if (!aggDelete)
664 aggDelete = baseClass->aggDelete;
665 if (!aggNew)
666 aggNew = baseClass->aggNew;
668 #endif
670 // Allocate instance of each new interface
671 for (i = 0; i < vtblInterfaces->dim; i++)
673 BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
674 unsigned thissize = PTRSIZE;
676 alignmember(structalign, thissize, &sc->offset);
677 assert(b->offset == 0);
678 b->offset = sc->offset;
680 // Take care of single inheritance offsets
681 while (b->baseInterfaces_dim)
683 b = &b->baseInterfaces[0];
684 b->offset = sc->offset;
687 sc->offset += thissize;
688 if (alignsize < thissize)
689 alignsize = thissize;
691 structsize = sc->offset;
692 sizeok = 1;
693 Module::dprogress++;
695 dtor = buildDtor(sc);
697 sc->pop();
699 #if 0 // Do not call until toObjfile() because of forward references
700 // Fill in base class vtbl[]s
701 for (i = 0; i < vtblInterfaces->dim; i++)
703 BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
705 //b->fillVtbl(this, &b->vtbl, 1);
707 #endif
708 //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
711 void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
713 if (!isAnonymous())
715 buf->printf("%s ", kind());
716 buf->writestring(toChars());
717 if (baseclasses.dim)
718 buf->writestring(" : ");
720 for (int i = 0; i < baseclasses.dim; i++)
722 BaseClass *b = (BaseClass *)baseclasses.data[i];
724 if (i)
725 buf->writeByte(',');
726 //buf->writestring(b->base->ident->toChars());
727 b->type->toCBuffer(buf, NULL, hgs);
729 buf->writenl();
730 buf->writeByte('{');
731 buf->writenl();
732 for (int i = 0; i < members->dim; i++)
734 Dsymbol *s = (Dsymbol *)members->data[i];
736 buf->writestring(" ");
737 s->toCBuffer(buf, hgs);
739 buf->writestring("}");
740 buf->writenl();
743 #if 0
744 void ClassDeclaration::defineRef(Dsymbol *s)
746 ClassDeclaration *cd;
748 AggregateDeclaration::defineRef(s);
749 cd = s->isClassDeclaration();
750 baseType = cd->baseType;
751 cd->baseType = NULL;
753 #endif
755 /*********************************************
756 * Determine if 'this' is a base class of cd.
757 * This is used to detect circular inheritance only.
760 int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
762 if (!cd)
763 return 0;
764 //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
765 for (int i = 0; i < cd->baseclasses.dim; i++)
766 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
768 if (b->base == this || isBaseOf2(b->base))
769 return 1;
771 return 0;
774 /*******************************************
775 * Determine if 'this' is a base class of cd.
778 int ClassDeclaration::isBaseOf(ClassDeclaration *cd, target_ptrdiff_t *poffset)
780 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
781 if (poffset)
782 *poffset = 0;
783 while (cd)
785 if (this == cd->baseClass)
786 return 1;
788 /* cd->baseClass might not be set if cd is forward referenced.
790 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
792 cd->error("base class is forward referenced by %s", toChars());
795 cd = cd->baseClass;
797 return 0;
800 Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
802 Dsymbol *s;
804 //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
805 if (scope)
806 semantic(scope);
808 if (!members || !symtab || scope)
809 { error("is forward referenced when looking for '%s'", ident->toChars());
810 //*(char*)0=0;
811 return NULL;
814 s = ScopeDsymbol::search(loc, ident, flags);
815 if (!s)
817 // Search bases classes in depth-first, left to right order
819 int i;
821 for (i = 0; i < baseclasses.dim; i++)
823 BaseClass *b = (BaseClass *)baseclasses.data[i];
825 if (b->base)
827 if (!b->base->symtab)
828 error("base %s is forward referenced", b->base->ident->toChars());
829 else
831 s = b->base->search(loc, ident, flags);
832 if (s == this) // happens if s is nested in this and derives from this
833 s = NULL;
834 else if (s)
835 break;
840 return s;
843 /**********************************************************
844 * fd is in the vtbl[] for this class.
845 * Return 1 if function is hidden (not findable through search).
848 #if V2
849 int isf(void *param, FuncDeclaration *fd)
851 //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
852 return param == fd;
855 int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
857 //printf("ClassDeclaration::isFuncHidden(%s)\n", fd->toChars());
858 Dsymbol *s = search(0, fd->ident, 4|2);
859 if (!s)
860 { //printf("not found\n");
861 /* Because, due to a hack, if there are multiple definitions
862 * of fd->ident, NULL is returned.
864 return 0;
866 s = s->toAlias();
867 OverloadSet *os = s->isOverloadSet();
868 if (os)
870 for (int i = 0; i < os->a.dim; i++)
871 { Dsymbol *s = (Dsymbol *)os->a.data[i];
872 FuncDeclaration *f2 = s->isFuncDeclaration();
873 if (f2 && overloadApply(f2, &isf, fd))
874 return 0;
876 return 1;
878 else
880 FuncDeclaration *fdstart = s->isFuncDeclaration();
881 //printf("%s fdstart = %p\n", s->kind(), fdstart);
882 return !overloadApply(fdstart, &isf, fd);
885 #endif
887 /****************
888 * Find virtual function matching identifier and type.
889 * Used to build virtual function tables for interface implementations.
892 FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
894 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
896 ClassDeclaration *cd = this;
897 Array *vtbl = &cd->vtbl;
898 while (1)
900 for (size_t i = 0; i < vtbl->dim; i++)
902 FuncDeclaration *fd = (FuncDeclaration *)vtbl->data[i];
904 //printf("\t[%d] = %s\n", i, fd->toChars());
905 if (ident == fd->ident &&
906 //tf->equals(fd->type)
907 fd->type->covariant(tf) == 1
909 { //printf("\t\tfound\n");
910 return fd;
912 //else printf("\t\t%d\n", fd->type->covariant(tf));
914 if (!cd)
915 break;
916 vtbl = &cd->vtblFinal;
917 cd = cd->baseClass;
920 return NULL;
923 void ClassDeclaration::interfaceSemantic(Scope *sc)
925 InterfaceDeclaration *id = isInterfaceDeclaration();
927 vtblInterfaces = new BaseClasses();
928 vtblInterfaces->reserve(interfaces_dim);
930 for (size_t i = 0; i < interfaces_dim; i++)
932 BaseClass *b = interfaces[i];
934 // If this is an interface, and it derives from a COM interface,
935 // then this is a COM interface too.
936 if (b->base->isCOMinterface())
937 com = 1;
939 if (b->base->isCPPinterface() && id)
940 id->cpp = 1;
942 vtblInterfaces->push(b);
943 b->copyBaseInterfaces(vtblInterfaces);
947 /****************************************
950 int ClassDeclaration::isCOMclass()
952 return com;
955 int ClassDeclaration::isCOMinterface()
957 return 0;
960 int ClassDeclaration::isCPPinterface()
962 return 0;
966 /****************************************
969 int ClassDeclaration::isAbstract()
971 if (isabstract)
972 return TRUE;
973 for (int i = 1; i < vtbl.dim; i++)
975 FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration();
977 //printf("\tvtbl[%d] = %p\n", i, fd);
978 if (!fd || fd->isAbstract())
980 isabstract |= 1;
981 return TRUE;
984 return FALSE;
988 /****************************************
989 * Returns !=0 if there's an extra member which is the 'this'
990 * pointer to the enclosing context (enclosing class or function)
993 int ClassDeclaration::isNested()
995 return isnested;
998 /****************************************
999 * Determine if slot 0 of the vtbl[] is reserved for something else.
1000 * For class objects, yes, this is where the classinfo ptr goes.
1001 * For COM interfaces, no.
1002 * For non-COM interfaces, yes, this is where the Interface ptr goes.
1005 int ClassDeclaration::vtblOffset()
1007 return 1;
1010 /****************************************
1013 char *ClassDeclaration::kind()
1015 return "class";
1018 /****************************************
1021 void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses)
1023 aclasses->push(this);
1026 /********************************* InterfaceDeclaration ****************************/
1028 InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
1029 : ClassDeclaration(loc, id, baseclasses)
1031 com = 0;
1032 cpp = 0;
1033 if (id == Id::IUnknown) // IUnknown is the root of all COM interfaces
1034 { com = 1;
1035 cpp = 1; // IUnknown is also a C++ interface
1039 Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s)
1041 InterfaceDeclaration *id;
1043 if (s)
1044 id = (InterfaceDeclaration *)s;
1045 else
1046 id = new InterfaceDeclaration(loc, ident, NULL);
1048 ClassDeclaration::syntaxCopy(id);
1049 return id;
1052 void InterfaceDeclaration::semantic(Scope *sc)
1053 { int i;
1055 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1056 if (inuse)
1057 return;
1058 if (!scope)
1059 { type = type->semantic(loc, sc);
1060 handle = handle->semantic(loc, sc);
1062 if (!members) // if forward reference
1063 { //printf("\tinterface '%s' is forward referenced\n", toChars());
1064 return;
1066 if (symtab) // if already done
1067 { if (!scope)
1068 return;
1070 else
1071 symtab = new DsymbolTable();
1073 Scope *scx = NULL;
1074 if (scope)
1075 { sc = scope;
1076 scx = scope; // save so we don't make redundant copies
1077 scope = NULL;
1080 if (attributes)
1081 attributes->append(sc->attributes);
1082 else
1083 attributes = sc->attributes;
1085 if (sc->stc & STCdeprecated)
1087 isdeprecated = 1;
1090 // Expand any tuples in baseclasses[]
1091 for (i = 0; i < baseclasses.dim; )
1092 { BaseClass *b = (BaseClass *)baseclasses.data[0];
1093 b->type = b->type->semantic(loc, sc);
1094 Type *tb = b->type->toBasetype();
1096 if (tb->ty == Ttuple)
1097 { TypeTuple *tup = (TypeTuple *)tb;
1098 enum PROT protection = b->protection;
1099 baseclasses.remove(i);
1100 size_t dim = Argument::dim(tup->arguments);
1101 for (size_t j = 0; j < dim; j++)
1102 { Argument *arg = Argument::getNth(tup->arguments, j);
1103 b = new BaseClass(arg->type, protection);
1104 baseclasses.insert(i + j, b);
1107 else
1108 i++;
1111 if (!baseclasses.dim && sc->linkage == LINKcpp)
1112 cpp = 1;
1114 // Check for errors, handle forward references
1115 for (i = 0; i < baseclasses.dim; )
1116 { TypeClass *tc;
1117 BaseClass *b;
1118 Type *tb;
1120 b = (BaseClass *)baseclasses.data[i];
1121 b->type = b->type->semantic(loc, sc);
1122 tb = b->type->toBasetype();
1123 if (tb->ty == Tclass)
1124 tc = (TypeClass *)tb;
1125 else
1126 tc = NULL;
1127 if (!tc || !tc->sym->isInterfaceDeclaration())
1129 error("base type must be interface, not %s", b->type->toChars());
1130 baseclasses.remove(i);
1131 continue;
1133 else
1135 // Check for duplicate interfaces
1136 for (size_t j = 0; j < i; j++)
1138 BaseClass *b2 = (BaseClass *)baseclasses.data[j];
1139 if (b2->base == tc->sym)
1140 error("inherits from duplicate interface %s", b2->base->toChars());
1143 b->base = tc->sym;
1144 if (b->base == this || isBaseOf2(b->base))
1146 error("circular inheritance of interface");
1147 baseclasses.remove(i);
1148 continue;
1150 if (!b->base->symtab || b->base->scope || b->base->inuse)
1152 //error("forward reference of base class %s", baseClass->toChars());
1153 // Forward reference of base, try again later
1154 //printf("\ttry later, forward reference of base %s\n", b->base->toChars());
1155 scope = scx ? scx : new Scope(*sc);
1156 scope->setNoFree();
1157 scope->module->addDeferredSemantic(this);
1158 return;
1161 #if 0
1162 // Inherit const/invariant from base class
1163 storage_class |= b->base->storage_class & (STCconst | STCinvariant);
1164 #endif
1165 i++;
1168 interfaces_dim = baseclasses.dim;
1169 interfaces = (BaseClass **)baseclasses.data;
1171 interfaceSemantic(sc);
1173 if (vtblOffset())
1174 vtbl.push(this); // leave room at vtbl[0] for classinfo
1176 // Cat together the vtbl[]'s from base interfaces
1177 for (i = 0; i < interfaces_dim; i++)
1178 { BaseClass *b = interfaces[i];
1180 // Skip if b has already appeared
1181 for (int k = 0; k < i; k++)
1183 if (b == interfaces[i])
1184 goto Lcontinue;
1187 // Copy vtbl[] from base class
1188 if (b->base->vtblOffset())
1189 { int d = b->base->vtbl.dim;
1190 if (d > 1)
1192 vtbl.reserve(d - 1);
1193 for (int j = 1; j < d; j++)
1194 vtbl.push(b->base->vtbl.data[j]);
1197 else
1199 vtbl.append(&b->base->vtbl);
1202 Lcontinue:
1206 protection = sc->protection;
1207 storage_class |= sc->stc & (STCconst | STCinvariant);
1209 for (i = 0; i < members->dim; i++)
1211 Dsymbol *s = (Dsymbol *)members->data[i];
1212 s->addMember(sc, this, 1);
1215 sc = sc->push(this);
1216 sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
1217 STCabstract | STCdeprecated | STCconst | STCinvariant | STCtls);
1218 sc->stc |= storage_class & (STCconst | STCinvariant);
1219 sc->attributes = NULL;
1220 sc->parent = this;
1221 if (isCOMinterface())
1222 sc->linkage = LINKwindows;
1223 else if (isCPPinterface())
1224 sc->linkage = LINKcpp;
1225 sc->structalign = 8;
1226 structalign = sc->structalign;
1227 sc->offset = PTRSIZE * 2;
1228 inuse++;
1229 for (i = 0; i < members->dim; i++)
1231 Dsymbol *s = (Dsymbol *)members->data[i];
1232 s->semantic(sc);
1234 inuse--;
1235 //members->print();
1236 sc->pop();
1237 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1241 /*******************************************
1242 * Determine if 'this' is a base class of cd.
1243 * (Actually, if it is an interface supported by cd)
1244 * Output:
1245 * *poffset offset to start of class
1246 * OFFSET_RUNTIME must determine offset at runtime
1247 * Returns:
1248 * 0 not a base
1249 * 1 is a base
1252 int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, target_ptrdiff_t *poffset)
1254 unsigned j;
1256 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
1257 assert(!baseClass);
1258 for (j = 0; j < cd->interfaces_dim; j++)
1260 BaseClass *b = cd->interfaces[j];
1262 //printf("\tbase %s\n", b->base->toChars());
1263 if (this == b->base)
1265 //printf("\tfound at offset %d\n", b->offset);
1266 if (poffset)
1267 { *poffset = b->offset;
1268 if (j && cd->isInterfaceDeclaration())
1269 *poffset = OFFSET_RUNTIME;
1271 return 1;
1273 if (isBaseOf(b, poffset))
1274 { if (j && poffset && cd->isInterfaceDeclaration())
1275 *poffset = OFFSET_RUNTIME;
1276 return 1;
1280 if (cd->baseClass && isBaseOf(cd->baseClass, poffset))
1281 return 1;
1283 if (poffset)
1284 *poffset = 0;
1285 return 0;
1289 int InterfaceDeclaration::isBaseOf(BaseClass *bc, target_ptrdiff_t *poffset)
1291 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars());
1292 for (unsigned j = 0; j < bc->baseInterfaces_dim; j++)
1294 BaseClass *b = &bc->baseInterfaces[j];
1296 if (this == b->base)
1298 if (poffset)
1299 { *poffset = b->offset;
1301 return 1;
1303 if (isBaseOf(b, poffset))
1305 return 1;
1308 if (poffset)
1309 *poffset = 0;
1310 return 0;
1313 /****************************************
1314 * Determine if slot 0 of the vtbl[] is reserved for something else.
1315 * For class objects, yes, this is where the ClassInfo ptr goes.
1316 * For COM interfaces, no.
1317 * For non-COM interfaces, yes, this is where the Interface ptr goes.
1320 int InterfaceDeclaration::vtblOffset()
1322 if (isCOMinterface() || isCPPinterface())
1323 return 0;
1324 return 1;
1327 int InterfaceDeclaration::isCOMinterface()
1329 return com;
1332 int InterfaceDeclaration::isCPPinterface()
1334 return cpp;
1337 /*******************************************
1340 char *InterfaceDeclaration::kind()
1342 return "interface";
1346 /******************************** BaseClass *****************************/
1348 BaseClass::BaseClass()
1350 memset(this, 0, sizeof(BaseClass));
1353 BaseClass::BaseClass(Type *type, enum PROT protection)
1355 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
1356 this->type = type;
1357 this->protection = protection;
1358 base = NULL;
1359 offset = 0;
1361 baseInterfaces_dim = 0;
1362 baseInterfaces = NULL;
1365 /****************************************
1366 * Fill in vtbl[] for base class based on member functions of class cd.
1367 * Input:
1368 * vtbl if !=NULL, fill it in
1369 * newinstance !=0 means all entries must be filled in by members
1370 * of cd, not members of any base classes of cd.
1371 * Returns:
1372 * !=0 if any entries were filled in by members of cd (not exclusively
1373 * by base classes)
1376 int BaseClass::fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance)
1378 ClassDeclaration *id = base;
1379 int j;
1380 int result = 0;
1382 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars());
1383 if (vtbl)
1384 vtbl->setDim(base->vtbl.dim);
1386 // first entry is ClassInfo reference
1387 for (j = base->vtblOffset(); j < base->vtbl.dim; j++)
1389 FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration();
1390 FuncDeclaration *fd;
1391 TypeFunction *tf;
1393 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
1395 assert(ifd);
1396 // Find corresponding function in this class
1397 tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL;
1398 fd = cd->findFunc(ifd->ident, tf);
1399 if (fd && !fd->isAbstract())
1401 //printf(" found\n");
1402 // Check that calling conventions match
1403 if (fd->linkage != ifd->linkage)
1404 fd->error("linkage doesn't match interface function");
1406 // Check that it is current
1407 if (newinstance &&
1408 fd->toParent() != cd &&
1409 ifd->toParent() == base)
1410 cd->error("interface function %s.%s is not implemented",
1411 id->toChars(), ifd->ident->toChars());
1413 if (fd->toParent() == cd)
1414 result = 1;
1416 else
1418 //printf(" not found\n");
1419 // BUG: should mark this class as abstract?
1420 if (!cd->isAbstract())
1421 cd->error("interface function %s.%s isn't implemented",
1422 id->toChars(), ifd->ident->toChars());
1423 fd = NULL;
1425 if (vtbl)
1426 vtbl->data[j] = fd;
1429 return result;
1432 void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces)
1434 //printf("+copyBaseInterfaces(), %s\n", base->toChars());
1435 // if (baseInterfaces_dim)
1436 // return;
1438 baseInterfaces_dim = base->interfaces_dim;
1439 baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass));
1441 //printf("%s.copyBaseInterfaces()\n", base->toChars());
1442 for (int i = 0; i < baseInterfaces_dim; i++)
1444 BaseClass *b = &baseInterfaces[i];
1445 BaseClass *b2 = base->interfaces[i];
1447 assert(b2->vtbl.dim == 0); // should not be filled yet
1448 memcpy(b, b2, sizeof(BaseClass));
1450 if (i) // single inheritance is i==0
1451 vtblInterfaces->push(b); // only need for M.I.
1452 b->copyBaseInterfaces(vtblInterfaces);
1454 //printf("-copyBaseInterfaces\n");