Warn about "assert X,Y"
[delight/core.git] / dmd2 / class.c
blob57c15d882a9208129e16fb75f43a4a82e5c81d95
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_Array)
115 { if (Type::typeinfoarray)
116 Type::typeinfoarray->error("%s", msg);
117 Type::typeinfoarray = this;
120 if (id == Id::TypeInfo_StaticArray)
121 { //if (Type::typeinfostaticarray)
122 //Type::typeinfostaticarray->error("%s", msg);
123 Type::typeinfostaticarray = this;
126 if (id == Id::TypeInfo_AssociativeArray)
127 { if (Type::typeinfoassociativearray)
128 Type::typeinfoassociativearray->error("%s", msg);
129 Type::typeinfoassociativearray = this;
132 if (id == Id::TypeInfo_Enum)
133 { if (Type::typeinfoenum)
134 Type::typeinfoenum->error("%s", msg);
135 Type::typeinfoenum = this;
138 if (id == Id::TypeInfo_Function)
139 { if (Type::typeinfofunction)
140 Type::typeinfofunction->error("%s", msg);
141 Type::typeinfofunction = this;
144 if (id == Id::TypeInfo_Delegate)
145 { if (Type::typeinfodelegate)
146 Type::typeinfodelegate->error("%s", msg);
147 Type::typeinfodelegate = this;
150 if (id == Id::TypeInfo_Tuple)
151 { if (Type::typeinfotypelist)
152 Type::typeinfotypelist->error("%s", msg);
153 Type::typeinfotypelist = this;
156 #if V2
157 if (id == Id::TypeInfo_Const)
158 { if (Type::typeinfoconst)
159 Type::typeinfoconst->error("%s", msg);
160 Type::typeinfoconst = this;
163 if (id == Id::TypeInfo_Invariant)
164 { if (Type::typeinfoinvariant)
165 Type::typeinfoinvariant->error("%s", msg);
166 Type::typeinfoinvariant = this;
168 #endif
171 if (id == Id::Object)
172 { if (object)
173 object->error("%s", msg);
174 object = this;
177 if (id == Id::ClassInfo)
178 { if (classinfo)
179 classinfo->error("%s", msg);
180 classinfo = this;
183 if (id == Id::ModuleInfo)
184 { if (Module::moduleinfo)
185 Module::moduleinfo->error("%s", msg);
186 Module::moduleinfo = this;
190 com = 0;
191 isauto = 0;
192 isabstract = 0;
193 isnested = 0;
194 vthis = NULL;
195 inuse = 0;
198 Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
200 ClassDeclaration *cd;
202 //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
203 if (s)
204 cd = (ClassDeclaration *)s;
205 else
206 cd = new ClassDeclaration(loc, ident, NULL);
208 cd->storage_class |= storage_class;
210 cd->baseclasses.setDim(this->baseclasses.dim);
211 for (int i = 0; i < cd->baseclasses.dim; i++)
213 BaseClass *b = (BaseClass *)this->baseclasses.data[i];
214 BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
215 cd->baseclasses.data[i] = b2;
218 ScopeDsymbol::syntaxCopy(cd);
219 return cd;
222 void ClassDeclaration::semantic(Scope *sc)
223 { int i;
225 //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
226 //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
227 //printf("sc->stc = %x\n", sc->stc);
229 //{ static int n; if (++n == 20) *(char*)0=0; }
231 if (!ident) // if anonymous class
232 { char *id = "__anonclass";
234 ident = Identifier::generateId(id);
237 if (!scope)
239 if (!parent && sc->parent && !sc->parent->isModule())
240 parent = sc->parent;
242 type = type->semantic(loc, sc);
243 handle = handle->semantic(loc, sc);
245 if (!members) // if forward reference
246 { //printf("\tclass '%s' is forward referenced\n", toChars());
247 return;
249 if (symtab)
250 { if (!scope)
251 { //printf("\tsemantic for '%s' is already completed\n", toChars());
252 return; // semantic() already completed
255 else
256 symtab = new DsymbolTable();
258 Scope *scx = NULL;
259 if (scope)
260 { sc = scope;
261 scx = scope; // save so we don't make redundant copies
262 scope = NULL;
264 if (attributes)
265 attributes->append(sc->attributes);
266 else
267 attributes = sc->attributes;
268 #ifdef IN_GCC
269 methods.setDim(0);
270 #endif
272 if (sc->stc & STCdeprecated)
274 isdeprecated = 1;
277 if (sc->linkage == LINKcpp)
278 error("cannot create C++ classes");
280 // Expand any tuples in baseclasses[]
281 for (i = 0; i < baseclasses.dim; )
282 { BaseClass *b = (BaseClass *)baseclasses.data[i];
283 b->type = b->type->semantic(loc, sc);
284 Type *tb = b->type->toBasetype();
286 if (tb->ty == Ttuple)
287 { TypeTuple *tup = (TypeTuple *)tb;
288 enum PROT protection = b->protection;
289 baseclasses.remove(i);
290 size_t dim = Argument::dim(tup->arguments);
291 for (size_t j = 0; j < dim; j++)
292 { Argument *arg = Argument::getNth(tup->arguments, j);
293 b = new BaseClass(arg->type, protection);
294 baseclasses.insert(i + j, b);
297 else
298 i++;
301 // See if there's a base class as first in baseclasses[]
302 if (baseclasses.dim)
303 { TypeClass *tc;
304 BaseClass *b;
305 Type *tb;
307 b = (BaseClass *)baseclasses.data[0];
308 //b->type = b->type->semantic(loc, sc);
309 tb = b->type->toBasetype();
310 if (tb->ty != Tclass)
311 { error("base type must be class or interface, not %s", b->type->toChars());
312 baseclasses.remove(0);
314 else
316 tc = (TypeClass *)(tb);
318 if (tc->sym->isDeprecated())
320 if (!isDeprecated())
322 // Deriving from deprecated class makes this one deprecated too
323 isdeprecated = 1;
325 tc->checkDeprecated(loc, sc);
329 if (tc->sym->isInterfaceDeclaration())
331 else
333 for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
335 if (cdb == this)
337 error("circular inheritance");
338 baseclasses.remove(0);
339 goto L7;
342 if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
344 //error("forward reference of base class %s", baseClass->toChars());
345 // Forward reference of base class, try again later
346 //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
347 scope = scx ? scx : new Scope(*sc);
348 scope->setNoFree();
349 scope->module->addDeferredSemantic(this);
350 return;
352 else
353 { baseClass = tc->sym;
354 b->base = baseClass;
356 L7: ;
361 // Treat the remaining entries in baseclasses as interfaces
362 // Check for errors, handle forward references
363 for (i = (baseClass ? 1 : 0); i < baseclasses.dim; )
364 { TypeClass *tc;
365 BaseClass *b;
366 Type *tb;
368 b = (BaseClass *)baseclasses.data[i];
369 b->type = b->type->semantic(loc, sc);
370 tb = b->type->toBasetype();
371 if (tb->ty == Tclass)
372 tc = (TypeClass *)tb;
373 else
374 tc = NULL;
375 if (!tc || !tc->sym->isInterfaceDeclaration())
377 error("base type must be interface, not %s", b->type->toChars());
378 baseclasses.remove(i);
379 continue;
381 else
383 if (tc->sym->isDeprecated())
385 if (!isDeprecated())
387 // Deriving from deprecated class makes this one deprecated too
388 isdeprecated = 1;
390 tc->checkDeprecated(loc, sc);
394 // Check for duplicate interfaces
395 for (size_t j = (baseClass ? 1 : 0); j < i; j++)
397 BaseClass *b2 = (BaseClass *)baseclasses.data[j];
398 if (b2->base == tc->sym)
399 error("inherits from duplicate interface %s", b2->base->toChars());
402 b->base = tc->sym;
403 if (!b->base->symtab || b->base->scope)
405 //error("forward reference of base class %s", baseClass->toChars());
406 // Forward reference of base, try again later
407 //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
408 scope = scx ? scx : new Scope(*sc);
409 scope->setNoFree();
410 scope->module->addDeferredSemantic(this);
411 return;
414 i++;
418 // If no base class, and this is not an Object, use Object as base class
419 if (!baseClass && ident != Id::Object)
421 // BUG: what if Object is redefined in an inner scope?
422 Type *tbase = new TypeIdentifier(0, Id::Object);
423 BaseClass *b;
424 TypeClass *tc;
425 Type *bt;
427 if (!object)
429 error("missing or corrupt object.d");
430 fatal();
432 bt = tbase->semantic(loc, sc)->toBasetype();
433 b = new BaseClass(bt, PROTpublic);
434 baseclasses.shift(b);
435 assert(b->type->ty == Tclass);
436 tc = (TypeClass *)(b->type);
437 baseClass = tc->sym;
438 assert(!baseClass->isInterfaceDeclaration());
439 b->base = baseClass;
442 interfaces_dim = baseclasses.dim;
443 interfaces = (BaseClass **)baseclasses.data;
446 if (baseClass)
448 if (baseClass->storage_class & STCfinal)
449 error("cannot inherit from final class %s", baseClass->toChars());
451 interfaces_dim--;
452 interfaces++;
454 // Copy vtbl[] from base class
455 vtbl.setDim(baseClass->vtbl.dim);
456 memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim);
458 // Inherit properties from base class
459 com = baseClass->isCOMclass();
460 isauto = baseClass->isauto;
461 vthis = baseClass->vthis;
462 storage_class |= baseClass->storage_class & (STCconst | STCinvariant);
464 else
466 // No base class, so this is the root of the class hierarchy
467 vtbl.setDim(0);
468 vtbl.push(this); // leave room for classinfo as first member
471 protection = sc->protection;
472 storage_class |= sc->stc;
474 if (sizeok == 0)
476 interfaceSemantic(sc);
478 for (i = 0; i < members->dim; i++)
480 Dsymbol *s = (Dsymbol *)members->data[i];
481 s->addMember(sc, this, 1);
484 /* If this is a nested class, add the hidden 'this'
485 * member which is a pointer to the enclosing scope.
487 if (vthis) // if inheriting from nested class
488 { // Use the base class's 'this' member
489 isnested = 1;
490 if (storage_class & STCstatic)
491 error("static class cannot inherit from nested class %s", baseClass->toChars());
492 if (toParent2() != baseClass->toParent2())
493 error("super class %s is nested within %s, not %s",
494 baseClass->toChars(),
495 baseClass->toParent2()->toChars(),
496 toParent2()->toChars());
498 else if (!(storage_class & STCstatic))
499 { Dsymbol *s = toParent2();
500 if (s)
502 ClassDeclaration *cd = s->isClassDeclaration();
503 FuncDeclaration *fd = s->isFuncDeclaration();
506 if (cd || fd)
507 { isnested = 1;
508 Type *t;
509 if (cd)
510 t = cd->type;
511 else if (fd)
512 { AggregateDeclaration *ad = fd->isMember2();
513 if (ad)
514 t = ad->handle;
515 else
517 t = new TypePointer(Type::tvoid);
518 t = t->semantic(0, sc);
521 else
522 assert(0);
523 assert(!vthis);
524 vthis = new ThisDeclaration(t);
525 members->push(vthis);
531 if (storage_class & (STCauto | STCscope))
532 isauto = 1;
533 if (storage_class & STCabstract)
534 isabstract = 1;
535 if (storage_class & STCinvariant)
536 type = type->invariantOf();
537 else if (storage_class & STCconst)
538 type = type->constOf();
540 sc = sc->push(this);
541 sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
542 STCabstract | STCdeprecated | STCconst | STCinvariant | STCtls);
543 sc->stc |= storage_class & (STCconst | STCinvariant);
544 sc->attributes = NULL;
545 sc->parent = this;
546 sc->inunion = 0;
548 if (isCOMclass())
549 sc->linkage = LINKwindows;
550 sc->protection = PROTpublic;
551 sc->explicitProtection = 0;
552 sc->structalign = 8;
553 structalign = sc->structalign;
554 if (baseClass)
555 { sc->offset = baseClass->structsize;
556 alignsize = baseClass->alignsize;
557 // if (isnested)
558 // sc->offset += PTRSIZE; // room for uplevel context pointer
560 else
561 { sc->offset = PTRSIZE * 2; // allow room for vptr[] and monitor
562 alignsize = PTRSIZE;
564 structsize = sc->offset;
565 Scope scsave = *sc;
566 int members_dim = members->dim;
567 sizeok = 0;
568 for (i = 0; i < members_dim; i++)
570 Dsymbol *s = (Dsymbol *)members->data[i];
571 s->semantic(sc);
574 if (sizeok == 2)
575 { // semantic() failed because of forward references.
576 // Unwind what we did, and defer it for later
577 fields.setDim(0);
578 structsize = 0;
579 alignsize = 0;
580 structalign = 0;
582 sc = sc->pop();
584 scope = scx ? scx : new Scope(*sc);
585 scope->setNoFree();
586 scope->module->addDeferredSemantic(this);
588 //printf("\tsemantic('%s') failed due to forward references\n", toChars());
589 return;
592 //printf("\tsemantic('%s') successful\n", toChars());
594 structsize = sc->offset;
595 //members->print();
597 /* Look for special member functions.
598 * They must be in this class, not in a base class.
600 ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
601 if (ctor && ctor->toParent() != this)
602 ctor = NULL;
604 // dtor = (DtorDeclaration *)search(Id::dtor, 0);
605 // if (dtor && dtor->toParent() != this)
606 // dtor = NULL;
608 // inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
609 // if (inv && inv->toParent() != this)
610 // inv = NULL;
612 // Can be in base class
613 aggNew = (NewDeclaration *)search(0, Id::classNew, 0);
614 aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
616 // If this class has no constructor, but base class does, create
617 // a constructor:
618 // this() { }
619 if (!ctor && baseClass && baseClass->ctor)
621 //printf("Creating default this(){} for class %s\n", toChars());
622 ctor = new CtorDeclaration(0, 0, NULL, 0);
623 ctor->fbody = new CompoundStatement(0, new Statements());
624 members->push(ctor);
625 ctor->addMember(sc, this, 1);
626 *sc = scsave; // why? What about sc->nofree?
627 sc->offset = structsize;
628 ctor->semantic(sc);
629 defaultCtor = ctor;
632 #if 0
633 if (baseClass)
634 { if (!aggDelete)
635 aggDelete = baseClass->aggDelete;
636 if (!aggNew)
637 aggNew = baseClass->aggNew;
639 #endif
641 // Allocate instance of each new interface
642 for (i = 0; i < vtblInterfaces->dim; i++)
644 BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
645 unsigned thissize = PTRSIZE;
647 alignmember(structalign, thissize, &sc->offset);
648 assert(b->offset == 0);
649 b->offset = sc->offset;
651 // Take care of single inheritance offsets
652 while (b->baseInterfaces_dim)
654 b = &b->baseInterfaces[0];
655 b->offset = sc->offset;
658 sc->offset += thissize;
659 if (alignsize < thissize)
660 alignsize = thissize;
662 structsize = sc->offset;
663 sizeok = 1;
664 Module::dprogress++;
666 dtor = buildDtor(sc);
668 sc->pop();
670 #if 0 // Do not call until toObjfile() because of forward references
671 // Fill in base class vtbl[]s
672 for (i = 0; i < vtblInterfaces->dim; i++)
674 BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
676 //b->fillVtbl(this, &b->vtbl, 1);
678 #endif
679 //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
682 void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
684 if (!isAnonymous())
686 buf->printf("%s ", kind());
687 buf->writestring(toChars());
688 if (baseclasses.dim)
689 buf->writestring(" : ");
691 for (int i = 0; i < baseclasses.dim; i++)
693 BaseClass *b = (BaseClass *)baseclasses.data[i];
695 if (i)
696 buf->writeByte(',');
697 //buf->writestring(b->base->ident->toChars());
698 b->type->toCBuffer(buf, NULL, hgs);
700 buf->writenl();
701 buf->writeByte('{');
702 buf->writenl();
703 for (int i = 0; i < members->dim; i++)
705 Dsymbol *s = (Dsymbol *)members->data[i];
707 buf->writestring(" ");
708 s->toCBuffer(buf, hgs);
710 buf->writestring("}");
711 buf->writenl();
714 #if 0
715 void ClassDeclaration::defineRef(Dsymbol *s)
717 ClassDeclaration *cd;
719 AggregateDeclaration::defineRef(s);
720 cd = s->isClassDeclaration();
721 baseType = cd->baseType;
722 cd->baseType = NULL;
724 #endif
726 /*********************************************
727 * Determine if 'this' is a base class of cd.
728 * This is used to detect circular inheritance only.
731 int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
733 if (!cd)
734 return 0;
735 //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
736 for (int i = 0; i < cd->baseclasses.dim; i++)
737 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
739 if (b->base == this || isBaseOf2(b->base))
740 return 1;
742 return 0;
745 /*******************************************
746 * Determine if 'this' is a base class of cd.
749 int ClassDeclaration::isBaseOf(ClassDeclaration *cd, target_ptrdiff_t *poffset)
751 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
752 if (poffset)
753 *poffset = 0;
754 while (cd)
756 if (this == cd->baseClass)
757 return 1;
759 /* cd->baseClass might not be set if cd is forward referenced.
761 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
763 cd->error("base class is forward referenced by %s", toChars());
766 cd = cd->baseClass;
768 return 0;
771 Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
773 Dsymbol *s;
775 //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
776 if (scope)
777 semantic(scope);
779 if (!members || !symtab || scope)
780 { error("is forward referenced when looking for '%s'", ident->toChars());
781 //*(char*)0=0;
782 return NULL;
785 s = ScopeDsymbol::search(loc, ident, flags);
786 if (!s)
788 // Search bases classes in depth-first, left to right order
790 int i;
792 for (i = 0; i < baseclasses.dim; i++)
794 BaseClass *b = (BaseClass *)baseclasses.data[i];
796 if (b->base)
798 if (!b->base->symtab)
799 error("base %s is forward referenced", b->base->ident->toChars());
800 else
802 s = b->base->search(loc, ident, flags);
803 if (s == this) // happens if s is nested in this and derives from this
804 s = NULL;
805 else if (s)
806 break;
811 return s;
814 /**********************************************************
815 * fd is in the vtbl[] for this class.
816 * Return 1 if function is hidden (not findable through search).
819 #if V2
820 int isf(void *param, FuncDeclaration *fd)
822 //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
823 return param == fd;
826 int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
828 //printf("ClassDeclaration::isFuncHidden(%s)\n", fd->toChars());
829 Dsymbol *s = search(0, fd->ident, 4|2);
830 if (!s)
831 { //printf("not found\n");
832 /* Because, due to a hack, if there are multiple definitions
833 * of fd->ident, NULL is returned.
835 return 0;
837 s = s->toAlias();
838 OverloadSet *os = s->isOverloadSet();
839 if (os)
841 for (int i = 0; i < os->a.dim; i++)
842 { Dsymbol *s = (Dsymbol *)os->a.data[i];
843 FuncDeclaration *f2 = s->isFuncDeclaration();
844 if (f2 && overloadApply(f2, &isf, fd))
845 return 0;
847 return 1;
849 else
851 FuncDeclaration *fdstart = s->isFuncDeclaration();
852 //printf("%s fdstart = %p\n", s->kind(), fdstart);
853 return !overloadApply(fdstart, &isf, fd);
856 #endif
858 /****************
859 * Find virtual function matching identifier and type.
860 * Used to build virtual function tables for interface implementations.
863 FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
865 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
867 ClassDeclaration *cd = this;
868 Array *vtbl = &cd->vtbl;
869 while (1)
871 for (size_t i = 0; i < vtbl->dim; i++)
873 FuncDeclaration *fd = (FuncDeclaration *)vtbl->data[i];
875 //printf("\t[%d] = %s\n", i, fd->toChars());
876 if (ident == fd->ident &&
877 //tf->equals(fd->type)
878 fd->type->covariant(tf) == 1
880 { //printf("\t\tfound\n");
881 return fd;
883 //else printf("\t\t%d\n", fd->type->covariant(tf));
885 if (!cd)
886 break;
887 vtbl = &cd->vtblFinal;
888 cd = cd->baseClass;
891 return NULL;
894 void ClassDeclaration::interfaceSemantic(Scope *sc)
896 InterfaceDeclaration *id = isInterfaceDeclaration();
898 vtblInterfaces = new BaseClasses();
899 vtblInterfaces->reserve(interfaces_dim);
901 for (size_t i = 0; i < interfaces_dim; i++)
903 BaseClass *b = interfaces[i];
905 // If this is an interface, and it derives from a COM interface,
906 // then this is a COM interface too.
907 if (b->base->isCOMinterface())
908 com = 1;
910 if (b->base->isCPPinterface() && id)
911 id->cpp = 1;
913 vtblInterfaces->push(b);
914 b->copyBaseInterfaces(vtblInterfaces);
918 /****************************************
921 int ClassDeclaration::isCOMclass()
923 return com;
926 int ClassDeclaration::isCOMinterface()
928 return 0;
931 int ClassDeclaration::isCPPinterface()
933 return 0;
937 /****************************************
940 int ClassDeclaration::isAbstract()
942 if (isabstract)
943 return TRUE;
944 for (int i = 1; i < vtbl.dim; i++)
946 FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration();
948 //printf("\tvtbl[%d] = %p\n", i, fd);
949 if (!fd || fd->isAbstract())
951 isabstract |= 1;
952 return TRUE;
955 return FALSE;
959 /****************************************
960 * Returns !=0 if there's an extra member which is the 'this'
961 * pointer to the enclosing context (enclosing class or function)
964 int ClassDeclaration::isNested()
966 return isnested;
969 /****************************************
970 * Determine if slot 0 of the vtbl[] is reserved for something else.
971 * For class objects, yes, this is where the classinfo ptr goes.
972 * For COM interfaces, no.
973 * For non-COM interfaces, yes, this is where the Interface ptr goes.
976 int ClassDeclaration::vtblOffset()
978 return 1;
981 /****************************************
984 char *ClassDeclaration::kind()
986 return "class";
989 /****************************************
992 void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses)
994 aclasses->push(this);
997 /********************************* InterfaceDeclaration ****************************/
999 InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
1000 : ClassDeclaration(loc, id, baseclasses)
1002 com = 0;
1003 cpp = 0;
1004 if (id == Id::IUnknown) // IUnknown is the root of all COM interfaces
1005 { com = 1;
1006 cpp = 1; // IUnknown is also a C++ interface
1010 Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s)
1012 InterfaceDeclaration *id;
1014 if (s)
1015 id = (InterfaceDeclaration *)s;
1016 else
1017 id = new InterfaceDeclaration(loc, ident, NULL);
1019 ClassDeclaration::syntaxCopy(id);
1020 return id;
1023 void InterfaceDeclaration::semantic(Scope *sc)
1024 { int i;
1026 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1027 if (inuse)
1028 return;
1029 if (!scope)
1030 { type = type->semantic(loc, sc);
1031 handle = handle->semantic(loc, sc);
1033 if (!members) // if forward reference
1034 { //printf("\tinterface '%s' is forward referenced\n", toChars());
1035 return;
1037 if (symtab) // if already done
1038 { if (!scope)
1039 return;
1041 else
1042 symtab = new DsymbolTable();
1044 Scope *scx = NULL;
1045 if (scope)
1046 { sc = scope;
1047 scx = scope; // save so we don't make redundant copies
1048 scope = NULL;
1051 if (attributes)
1052 attributes->append(sc->attributes);
1053 else
1054 attributes = sc->attributes;
1056 if (sc->stc & STCdeprecated)
1058 isdeprecated = 1;
1061 // Expand any tuples in baseclasses[]
1062 for (i = 0; i < baseclasses.dim; )
1063 { BaseClass *b = (BaseClass *)baseclasses.data[0];
1064 b->type = b->type->semantic(loc, sc);
1065 Type *tb = b->type->toBasetype();
1067 if (tb->ty == Ttuple)
1068 { TypeTuple *tup = (TypeTuple *)tb;
1069 enum PROT protection = b->protection;
1070 baseclasses.remove(i);
1071 size_t dim = Argument::dim(tup->arguments);
1072 for (size_t j = 0; j < dim; j++)
1073 { Argument *arg = Argument::getNth(tup->arguments, j);
1074 b = new BaseClass(arg->type, protection);
1075 baseclasses.insert(i + j, b);
1078 else
1079 i++;
1082 if (!baseclasses.dim && sc->linkage == LINKcpp)
1083 cpp = 1;
1085 // Check for errors, handle forward references
1086 for (i = 0; i < baseclasses.dim; )
1087 { TypeClass *tc;
1088 BaseClass *b;
1089 Type *tb;
1091 b = (BaseClass *)baseclasses.data[i];
1092 b->type = b->type->semantic(loc, sc);
1093 tb = b->type->toBasetype();
1094 if (tb->ty == Tclass)
1095 tc = (TypeClass *)tb;
1096 else
1097 tc = NULL;
1098 if (!tc || !tc->sym->isInterfaceDeclaration())
1100 error("base type must be interface, not %s", b->type->toChars());
1101 baseclasses.remove(i);
1102 continue;
1104 else
1106 // Check for duplicate interfaces
1107 for (size_t j = 0; j < i; j++)
1109 BaseClass *b2 = (BaseClass *)baseclasses.data[j];
1110 if (b2->base == tc->sym)
1111 error("inherits from duplicate interface %s", b2->base->toChars());
1114 b->base = tc->sym;
1115 if (b->base == this || isBaseOf2(b->base))
1117 error("circular inheritance of interface");
1118 baseclasses.remove(i);
1119 continue;
1121 if (!b->base->symtab || b->base->scope || b->base->inuse)
1123 //error("forward reference of base class %s", baseClass->toChars());
1124 // Forward reference of base, try again later
1125 //printf("\ttry later, forward reference of base %s\n", b->base->toChars());
1126 scope = scx ? scx : new Scope(*sc);
1127 scope->setNoFree();
1128 scope->module->addDeferredSemantic(this);
1129 return;
1132 #if 0
1133 // Inherit const/invariant from base class
1134 storage_class |= b->base->storage_class & (STCconst | STCinvariant);
1135 #endif
1136 i++;
1139 interfaces_dim = baseclasses.dim;
1140 interfaces = (BaseClass **)baseclasses.data;
1142 interfaceSemantic(sc);
1144 if (vtblOffset())
1145 vtbl.push(this); // leave room at vtbl[0] for classinfo
1147 // Cat together the vtbl[]'s from base interfaces
1148 for (i = 0; i < interfaces_dim; i++)
1149 { BaseClass *b = interfaces[i];
1151 // Skip if b has already appeared
1152 for (int k = 0; k < i; k++)
1154 if (b == interfaces[i])
1155 goto Lcontinue;
1158 // Copy vtbl[] from base class
1159 if (b->base->vtblOffset())
1160 { int d = b->base->vtbl.dim;
1161 if (d > 1)
1163 vtbl.reserve(d - 1);
1164 for (int j = 1; j < d; j++)
1165 vtbl.push(b->base->vtbl.data[j]);
1168 else
1170 vtbl.append(&b->base->vtbl);
1173 Lcontinue:
1177 protection = sc->protection;
1178 storage_class |= sc->stc & (STCconst | STCinvariant);
1180 for (i = 0; i < members->dim; i++)
1182 Dsymbol *s = (Dsymbol *)members->data[i];
1183 s->addMember(sc, this, 1);
1186 sc = sc->push(this);
1187 sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
1188 STCabstract | STCdeprecated | STCconst | STCinvariant | STCtls);
1189 sc->stc |= storage_class & (STCconst | STCinvariant);
1190 sc->attributes = NULL;
1191 sc->parent = this;
1192 if (isCOMinterface())
1193 sc->linkage = LINKwindows;
1194 else if (isCPPinterface())
1195 sc->linkage = LINKcpp;
1196 sc->structalign = 8;
1197 structalign = sc->structalign;
1198 sc->offset = PTRSIZE * 2;
1199 inuse++;
1200 for (i = 0; i < members->dim; i++)
1202 Dsymbol *s = (Dsymbol *)members->data[i];
1203 s->semantic(sc);
1205 inuse--;
1206 //members->print();
1207 sc->pop();
1208 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1212 /*******************************************
1213 * Determine if 'this' is a base class of cd.
1214 * (Actually, if it is an interface supported by cd)
1215 * Output:
1216 * *poffset offset to start of class
1217 * OFFSET_RUNTIME must determine offset at runtime
1218 * Returns:
1219 * 0 not a base
1220 * 1 is a base
1223 int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, target_ptrdiff_t *poffset)
1225 unsigned j;
1227 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
1228 assert(!baseClass);
1229 for (j = 0; j < cd->interfaces_dim; j++)
1231 BaseClass *b = cd->interfaces[j];
1233 //printf("\tbase %s\n", b->base->toChars());
1234 if (this == b->base)
1236 //printf("\tfound at offset %d\n", b->offset);
1237 if (poffset)
1238 { *poffset = b->offset;
1239 if (j && cd->isInterfaceDeclaration())
1240 *poffset = OFFSET_RUNTIME;
1242 return 1;
1244 if (isBaseOf(b, poffset))
1245 { if (j && poffset && cd->isInterfaceDeclaration())
1246 *poffset = OFFSET_RUNTIME;
1247 return 1;
1251 if (cd->baseClass && isBaseOf(cd->baseClass, poffset))
1252 return 1;
1254 if (poffset)
1255 *poffset = 0;
1256 return 0;
1260 int InterfaceDeclaration::isBaseOf(BaseClass *bc, target_ptrdiff_t *poffset)
1262 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars());
1263 for (unsigned j = 0; j < bc->baseInterfaces_dim; j++)
1265 BaseClass *b = &bc->baseInterfaces[j];
1267 if (this == b->base)
1269 if (poffset)
1270 { *poffset = b->offset;
1272 return 1;
1274 if (isBaseOf(b, poffset))
1276 return 1;
1279 if (poffset)
1280 *poffset = 0;
1281 return 0;
1284 /****************************************
1285 * Determine if slot 0 of the vtbl[] is reserved for something else.
1286 * For class objects, yes, this is where the ClassInfo ptr goes.
1287 * For COM interfaces, no.
1288 * For non-COM interfaces, yes, this is where the Interface ptr goes.
1291 int InterfaceDeclaration::vtblOffset()
1293 if (isCOMinterface() || isCPPinterface())
1294 return 0;
1295 return 1;
1298 int InterfaceDeclaration::isCOMinterface()
1300 return com;
1303 int InterfaceDeclaration::isCPPinterface()
1305 return cpp;
1308 /*******************************************
1311 char *InterfaceDeclaration::kind()
1313 return "interface";
1317 /******************************** BaseClass *****************************/
1319 BaseClass::BaseClass()
1321 memset(this, 0, sizeof(BaseClass));
1324 BaseClass::BaseClass(Type *type, enum PROT protection)
1326 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
1327 this->type = type;
1328 this->protection = protection;
1329 base = NULL;
1330 offset = 0;
1332 baseInterfaces_dim = 0;
1333 baseInterfaces = NULL;
1336 /****************************************
1337 * Fill in vtbl[] for base class based on member functions of class cd.
1338 * Input:
1339 * vtbl if !=NULL, fill it in
1340 * newinstance !=0 means all entries must be filled in by members
1341 * of cd, not members of any base classes of cd.
1342 * Returns:
1343 * !=0 if any entries were filled in by members of cd (not exclusively
1344 * by base classes)
1347 int BaseClass::fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance)
1349 ClassDeclaration *id = base;
1350 int j;
1351 int result = 0;
1353 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars());
1354 if (vtbl)
1355 vtbl->setDim(base->vtbl.dim);
1357 // first entry is ClassInfo reference
1358 for (j = base->vtblOffset(); j < base->vtbl.dim; j++)
1360 FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration();
1361 FuncDeclaration *fd;
1362 TypeFunction *tf;
1364 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
1366 assert(ifd);
1367 // Find corresponding function in this class
1368 tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL;
1369 fd = cd->findFunc(ifd->ident, tf);
1370 if (fd && !fd->isAbstract())
1372 //printf(" found\n");
1373 // Check that calling conventions match
1374 if (fd->linkage != ifd->linkage)
1375 fd->error("linkage doesn't match interface function");
1377 // Check that it is current
1378 if (newinstance &&
1379 fd->toParent() != cd &&
1380 ifd->toParent() == base)
1381 cd->error("interface function %s.%s is not implemented",
1382 id->toChars(), ifd->ident->toChars());
1384 if (fd->toParent() == cd)
1385 result = 1;
1387 else
1389 //printf(" not found\n");
1390 // BUG: should mark this class as abstract?
1391 if (!cd->isAbstract())
1392 cd->error("interface function %s.%s isn't implemented",
1393 id->toChars(), ifd->ident->toChars());
1394 fd = NULL;
1396 if (vtbl)
1397 vtbl->data[j] = fd;
1400 return result;
1403 void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces)
1405 //printf("+copyBaseInterfaces(), %s\n", base->toChars());
1406 // if (baseInterfaces_dim)
1407 // return;
1409 baseInterfaces_dim = base->interfaces_dim;
1410 baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass));
1412 //printf("%s.copyBaseInterfaces()\n", base->toChars());
1413 for (int i = 0; i < baseInterfaces_dim; i++)
1415 BaseClass *b = &baseInterfaces[i];
1416 BaseClass *b2 = base->interfaces[i];
1418 assert(b2->vtbl.dim == 0); // should not be filled yet
1419 memcpy(b, b2, sizeof(BaseClass));
1421 if (i) // single inheritance is i==0
1422 vtblInterfaces->push(b); // only need for M.I.
1423 b->copyBaseInterfaces(vtblInterfaces);
1425 //printf("-copyBaseInterfaces\n");