Disallow x[y] if x has a maybe type
[delight/core.git] / dmd2 / class.c
blob200c9ed0b7db293701da43b7bde5974882271160
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, LINK l)
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 linkage = l;
195 vthis = NULL;
196 inuse = 0;
199 Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
201 ClassDeclaration *cd;
203 //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
204 if (s)
205 cd = (ClassDeclaration *)s;
206 else
207 cd = new ClassDeclaration(loc, ident, NULL, linkage);
209 cd->storage_class |= storage_class;
211 cd->baseclasses.setDim(this->baseclasses.dim);
212 for (int i = 0; i < cd->baseclasses.dim; i++)
214 BaseClass *b = (BaseClass *)this->baseclasses.data[i];
215 BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
216 cd->baseclasses.data[i] = b2;
219 ScopeDsymbol::syntaxCopy(cd);
220 return cd;
223 void ClassDeclaration::semantic(Scope *sc)
224 { int i;
226 //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
227 //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
228 //printf("sc->stc = %x\n", sc->stc);
230 //{ static int n; if (++n == 20) *(char*)0=0; }
232 if (!ident) // if anonymous class
233 { char *id = "__anonclass";
235 ident = Identifier::generateId(id);
238 if (!scope)
240 if (!parent && sc->parent && !sc->parent->isModule())
241 parent = sc->parent;
243 type = type->semantic(loc, sc);
244 handle = handle->semantic(loc, sc);
246 if (!members) // if forward reference
247 { //printf("\tclass '%s' is forward referenced\n", toChars());
248 return;
250 if (symtab)
251 { if (!scope)
252 { //printf("\tsemantic for '%s' is already completed\n", toChars());
253 return; // semantic() already completed
256 else
257 symtab = new DsymbolTable();
259 Scope *scx = NULL;
260 if (scope)
261 { sc = scope;
262 scx = scope; // save so we don't make redundant copies
263 scope = NULL;
265 if (attributes)
266 attributes->append(sc->attributes);
267 else
268 attributes = sc->attributes;
269 #ifdef IN_GCC
270 methods.setDim(0);
271 #endif
273 if (sc->stc & STCdeprecated)
275 isdeprecated = 1;
278 if (sc->linkage == LINKcpp)
279 error("cannot create C++ classes");
281 // Expand any tuples in baseclasses[]
282 for (i = 0; i < baseclasses.dim; )
283 { BaseClass *b = (BaseClass *)baseclasses.data[i];
284 b->type = b->type->semantic(loc, sc);
285 Type *tb = b->type->toBasetype();
287 if (tb->ty == Ttuple)
288 { TypeTuple *tup = (TypeTuple *)tb;
289 enum PROT protection = b->protection;
290 baseclasses.remove(i);
291 size_t dim = Argument::dim(tup->arguments);
292 for (size_t j = 0; j < dim; j++)
293 { Argument *arg = Argument::getNth(tup->arguments, j);
294 b = new BaseClass(arg->type, protection);
295 baseclasses.insert(i + j, b);
298 else
299 i++;
302 // See if there's a base class as first in baseclasses[]
303 if (baseclasses.dim)
304 { TypeClass *tc;
305 BaseClass *b;
306 Type *tb;
308 b = (BaseClass *)baseclasses.data[0];
309 //b->type = b->type->semantic(loc, sc);
310 tb = b->type->toBasetype();
311 if (tb->ty != Tclass)
312 { error("base type must be class or interface, not %s", b->type->toChars());
313 baseclasses.remove(0);
315 else
317 tc = (TypeClass *)(tb);
319 if (tc->sym->isDeprecated())
321 if (!isDeprecated())
323 // Deriving from deprecated class makes this one deprecated too
324 isdeprecated = 1;
326 tc->checkDeprecated(loc, sc);
330 if (tc->sym->isInterfaceDeclaration())
332 else
334 for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
336 if (cdb == this)
338 error("circular inheritance");
339 baseclasses.remove(0);
340 goto L7;
343 if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
345 //error("forward reference of base class %s", baseClass->toChars());
346 // Forward reference of base class, try again later
347 //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
348 scope = scx ? scx : new Scope(*sc);
349 scope->setNoFree();
350 scope->module->addDeferredSemantic(this);
351 return;
353 else
354 { baseClass = tc->sym;
355 b->base = baseClass;
357 L7: ;
362 // Treat the remaining entries in baseclasses as interfaces
363 // Check for errors, handle forward references
364 for (i = (baseClass ? 1 : 0); i < baseclasses.dim; )
365 { TypeClass *tc;
366 BaseClass *b;
367 Type *tb;
369 b = (BaseClass *)baseclasses.data[i];
370 b->type = b->type->semantic(loc, sc);
371 tb = b->type->toBasetype();
372 if (tb->ty == Tclass)
373 tc = (TypeClass *)tb;
374 else
375 tc = NULL;
376 if (!tc || !tc->sym->isInterfaceDeclaration())
378 error("base type must be interface, not %s", b->type->toChars());
379 baseclasses.remove(i);
380 continue;
382 else
384 if (tc->sym->isDeprecated())
386 if (!isDeprecated())
388 // Deriving from deprecated class makes this one deprecated too
389 isdeprecated = 1;
391 tc->checkDeprecated(loc, sc);
395 // Check for duplicate interfaces
396 for (size_t j = (baseClass ? 1 : 0); j < i; j++)
398 BaseClass *b2 = (BaseClass *)baseclasses.data[j];
399 if (b2->base == tc->sym)
400 error("inherits from duplicate interface %s", b2->base->toChars());
403 b->base = tc->sym;
404 if (!b->base->symtab || b->base->scope)
406 //error("forward reference of base class %s", baseClass->toChars());
407 // Forward reference of base, try again later
408 //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
409 scope = scx ? scx : new Scope(*sc);
410 scope->setNoFree();
411 scope->module->addDeferredSemantic(this);
412 return;
415 i++;
419 // If no base class, and this is not an Object, use Object as base class
420 if (!baseClass && ident != Id::Object)
422 // BUG: what if Object is redefined in an inner scope?
423 Type *tbase = new TypeIdentifier(0, Id::Object);
424 BaseClass *b;
425 TypeClass *tc;
426 Type *bt;
428 if (!object)
430 error("missing or corrupt object.d");
431 fatal();
433 bt = tbase->semantic(loc, sc)->toBasetype();
434 b = new BaseClass(bt, PROTpublic);
435 baseclasses.shift(b);
436 assert(b->type->ty == Tclass);
437 tc = (TypeClass *)(b->type);
438 baseClass = tc->sym;
439 assert(!baseClass->isInterfaceDeclaration());
440 b->base = baseClass;
443 interfaces_dim = baseclasses.dim;
444 interfaces = (BaseClass **)baseclasses.data;
447 if (baseClass)
449 if (baseClass->storage_class & STCfinal)
450 error("cannot inherit from final class %s", baseClass->toChars());
452 interfaces_dim--;
453 interfaces++;
455 // Copy vtbl[] from base class
456 vtbl.setDim(baseClass->vtbl.dim);
457 memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim);
459 // Inherit properties from base class
460 com = baseClass->isCOMclass();
461 isauto = baseClass->isauto;
462 vthis = baseClass->vthis;
463 storage_class |= baseClass->storage_class & (STCconst | STCinvariant);
465 else
467 // No base class, so this is the root of the class hierarchy
468 vtbl.setDim(0);
469 vtbl.push(this); // leave room for classinfo as first member
472 protection = sc->protection;
473 storage_class |= sc->stc;
475 if (sizeok == 0)
477 interfaceSemantic(sc);
479 for (i = 0; i < members->dim; i++)
481 Dsymbol *s = (Dsymbol *)members->data[i];
482 s->addMember(sc, this, 1);
485 /* If this is a nested class, add the hidden 'this'
486 * member which is a pointer to the enclosing scope.
488 if (vthis) // if inheriting from nested class
489 { // Use the base class's 'this' member
490 isnested = 1;
491 if (storage_class & STCstatic)
492 error("static class cannot inherit from nested class %s", baseClass->toChars());
493 if (toParent2() != baseClass->toParent2())
494 error("super class %s is nested within %s, not %s",
495 baseClass->toChars(),
496 baseClass->toParent2()->toChars(),
497 toParent2()->toChars());
499 else if (!(storage_class & STCstatic))
500 { Dsymbol *s = toParent2();
501 if (s)
503 ClassDeclaration *cd = s->isClassDeclaration();
504 FuncDeclaration *fd = s->isFuncDeclaration();
507 if (cd || fd)
508 { isnested = 1;
509 Type *t;
510 if (cd)
511 t = cd->type;
512 else if (fd)
513 { AggregateDeclaration *ad = fd->isMember2();
514 if (ad)
515 t = ad->handle;
516 else
518 t = new TypePointer(Type::tvoid);
519 t = t->semantic(0, sc);
522 else
523 assert(0);
524 assert(!vthis);
525 vthis = new ThisDeclaration(t);
526 members->push(vthis);
532 if (storage_class & (STCauto | STCscope))
533 isauto = 1;
534 if (storage_class & STCabstract)
535 isabstract = 1;
536 if (storage_class & STCinvariant)
537 type = type->invariantOf();
538 else if (storage_class & STCconst)
539 type = type->constOf();
541 sc = sc->push(this);
542 sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
543 STCabstract | STCdeprecated | STCconst | STCinvariant | STCtls);
544 sc->stc |= storage_class & (STCconst | STCinvariant);
545 sc->attributes = NULL;
546 sc->parent = this;
547 sc->inunion = 0;
549 if (isCOMclass())
550 sc->linkage = LINKwindows;
551 sc->protection = PROTpublic;
552 sc->explicitProtection = 0;
553 sc->structalign = 8;
554 structalign = sc->structalign;
555 if (baseClass)
556 { sc->offset = baseClass->structsize;
557 alignsize = baseClass->alignsize;
558 // if (isnested)
559 // sc->offset += PTRSIZE; // room for uplevel context pointer
561 else
562 { sc->offset = PTRSIZE * 2; // allow room for vptr[] and monitor
563 alignsize = PTRSIZE;
565 structsize = sc->offset;
566 Scope scsave = *sc;
567 int members_dim = members->dim;
568 sizeok = 0;
569 for (i = 0; i < members_dim; i++)
571 Dsymbol *s = (Dsymbol *)members->data[i];
572 s->semantic(sc);
575 if (sizeok == 2)
576 { // semantic() failed because of forward references.
577 // Unwind what we did, and defer it for later
578 fields.setDim(0);
579 structsize = 0;
580 alignsize = 0;
581 structalign = 0;
583 sc = sc->pop();
585 scope = scx ? scx : new Scope(*sc);
586 scope->setNoFree();
587 scope->module->addDeferredSemantic(this);
589 //printf("\tsemantic('%s') failed due to forward references\n", toChars());
590 return;
593 //printf("\tsemantic('%s') successful\n", toChars());
595 structsize = sc->offset;
596 //members->print();
598 /* Look for special member functions.
599 * They must be in this class, not in a base class.
601 ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
602 if (ctor && ctor->toParent() != this)
603 ctor = NULL;
605 // dtor = (DtorDeclaration *)search(Id::dtor, 0);
606 // if (dtor && dtor->toParent() != this)
607 // dtor = NULL;
609 // inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
610 // if (inv && inv->toParent() != this)
611 // inv = NULL;
613 // Can be in base class
614 aggNew = (NewDeclaration *)search(0, Id::classNew, 0);
615 aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
617 // If this class has no constructor, but base class does, create
618 // a constructor:
620 // this() { }
622 // Also do this if we have some "in" fields on the class, or
623 // if there are non-null fields
624 if (!ctor)
626 bool hasInArgs = false;
627 bool hasNonNull = false;
628 for (int i = 0; i < fields.dim; i++)
630 VarDeclaration *var = (VarDeclaration *) fields.data[i];
632 if (var->storage_class && STCinject) {
633 hasInArgs = true;
634 break;
637 if (var->type->ty == Tclass) {
638 hasNonNull = true;
639 break;
642 if (hasInArgs || hasNonNull || (baseClass && baseClass->ctor))
644 //printf("Creating default this(){} for class %s\n", toChars());
645 ctor = new CtorDeclaration(0, 0, NULL, 0);
646 ctor->fbody = new CompoundStatement(0, new Statements());
647 members->push(ctor);
648 ctor->addMember(sc, this, 1);
649 *sc = scsave; // why? What about sc->nofree?
650 sc->offset = structsize;
651 ctor->semantic(sc);
652 defaultCtor = ctor;
656 #if 0
657 if (baseClass)
658 { if (!aggDelete)
659 aggDelete = baseClass->aggDelete;
660 if (!aggNew)
661 aggNew = baseClass->aggNew;
663 #endif
665 // Allocate instance of each new interface
666 for (i = 0; i < vtblInterfaces->dim; i++)
668 BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
669 unsigned thissize = PTRSIZE;
671 alignmember(structalign, thissize, &sc->offset);
672 assert(b->offset == 0);
673 b->offset = sc->offset;
675 // Take care of single inheritance offsets
676 while (b->baseInterfaces_dim)
678 b = &b->baseInterfaces[0];
679 b->offset = sc->offset;
682 sc->offset += thissize;
683 if (alignsize < thissize)
684 alignsize = thissize;
686 structsize = sc->offset;
687 sizeok = 1;
688 Module::dprogress++;
690 dtor = buildDtor(sc);
692 sc->pop();
694 #if 0 // Do not call until toObjfile() because of forward references
695 // Fill in base class vtbl[]s
696 for (i = 0; i < vtblInterfaces->dim; i++)
698 BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
700 //b->fillVtbl(this, &b->vtbl, 1);
702 #endif
703 //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
706 void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
708 if (!isAnonymous())
710 buf->printf("%s ", kind());
711 buf->writestring(toChars());
712 if (baseclasses.dim)
713 buf->writestring(" : ");
715 for (int i = 0; i < baseclasses.dim; i++)
717 BaseClass *b = (BaseClass *)baseclasses.data[i];
719 if (i)
720 buf->writeByte(',');
721 //buf->writestring(b->base->ident->toChars());
722 b->type->toCBuffer(buf, NULL, hgs);
724 buf->writenl();
725 buf->writeByte('{');
726 buf->writenl();
727 for (int i = 0; i < members->dim; i++)
729 Dsymbol *s = (Dsymbol *)members->data[i];
731 buf->writestring(" ");
732 s->toCBuffer(buf, hgs);
734 buf->writestring("}");
735 buf->writenl();
738 #if 0
739 void ClassDeclaration::defineRef(Dsymbol *s)
741 ClassDeclaration *cd;
743 AggregateDeclaration::defineRef(s);
744 cd = s->isClassDeclaration();
745 baseType = cd->baseType;
746 cd->baseType = NULL;
748 #endif
750 /*********************************************
751 * Determine if 'this' is a base class of cd.
752 * This is used to detect circular inheritance only.
755 int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
757 if (!cd)
758 return 0;
759 //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
760 for (int i = 0; i < cd->baseclasses.dim; i++)
761 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
763 if (b->base == this || isBaseOf2(b->base))
764 return 1;
766 return 0;
769 /*******************************************
770 * Determine if 'this' is a base class of cd.
773 int ClassDeclaration::isBaseOf(ClassDeclaration *cd, target_ptrdiff_t *poffset)
775 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
776 if (poffset)
777 *poffset = 0;
778 while (cd)
780 if (this == cd->baseClass)
781 return 1;
783 /* cd->baseClass might not be set if cd is forward referenced.
785 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
787 cd->error("base class is forward referenced by %s", toChars());
790 cd = cd->baseClass;
792 return 0;
795 Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
797 Dsymbol *s;
799 //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
800 if (scope)
801 semantic(scope);
803 if (!members || !symtab || scope)
804 { error("is forward referenced when looking for '%s'", ident->toChars());
805 //*(char*)0=0;
806 return NULL;
809 s = ScopeDsymbol::search(loc, ident, flags);
810 if (!s)
812 // Search bases classes in depth-first, left to right order
814 int i;
816 for (i = 0; i < baseclasses.dim; i++)
818 BaseClass *b = (BaseClass *)baseclasses.data[i];
820 if (b->base)
822 if (!b->base->symtab)
823 error("base %s is forward referenced", b->base->ident->toChars());
824 else
826 s = b->base->search(loc, ident, flags);
827 if (s == this) // happens if s is nested in this and derives from this
828 s = NULL;
829 else if (s)
830 break;
835 return s;
838 /**********************************************************
839 * fd is in the vtbl[] for this class.
840 * Return 1 if function is hidden (not findable through search).
843 #if V2
844 int isf(void *param, FuncDeclaration *fd)
846 //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
847 return param == fd;
850 int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
852 //printf("ClassDeclaration::isFuncHidden(%s)\n", fd->toChars());
853 Dsymbol *s = search(0, fd->ident, 4|2);
854 if (!s)
855 { //printf("not found\n");
856 /* Because, due to a hack, if there are multiple definitions
857 * of fd->ident, NULL is returned.
859 return 0;
861 s = s->toAlias();
862 OverloadSet *os = s->isOverloadSet();
863 if (os)
865 for (int i = 0; i < os->a.dim; i++)
866 { Dsymbol *s = (Dsymbol *)os->a.data[i];
867 FuncDeclaration *f2 = s->isFuncDeclaration();
868 if (f2 && overloadApply(f2, &isf, fd))
869 return 0;
871 return 1;
873 else
875 FuncDeclaration *fdstart = s->isFuncDeclaration();
876 //printf("%s fdstart = %p\n", s->kind(), fdstart);
877 return !overloadApply(fdstart, &isf, fd);
880 #endif
882 /****************
883 * Find virtual function matching identifier and type.
884 * Used to build virtual function tables for interface implementations.
887 FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
889 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
891 ClassDeclaration *cd = this;
892 Array *vtbl = &cd->vtbl;
893 while (1)
895 for (size_t i = 0; i < vtbl->dim; i++)
897 FuncDeclaration *fd = (FuncDeclaration *)vtbl->data[i];
899 //printf("\t[%d] = %s\n", i, fd->toChars());
900 if (ident == fd->ident &&
901 //tf->equals(fd->type)
902 fd->type->covariant(tf) == 1
904 { //printf("\t\tfound\n");
905 return fd;
907 //else printf("\t\t%d\n", fd->type->covariant(tf));
909 if (!cd)
910 break;
911 vtbl = &cd->vtblFinal;
912 cd = cd->baseClass;
915 return NULL;
918 void ClassDeclaration::interfaceSemantic(Scope *sc)
920 InterfaceDeclaration *id = isInterfaceDeclaration();
922 vtblInterfaces = new BaseClasses();
923 vtblInterfaces->reserve(interfaces_dim);
925 for (size_t i = 0; i < interfaces_dim; i++)
927 BaseClass *b = interfaces[i];
929 // If this is an interface, and it derives from a COM interface,
930 // then this is a COM interface too.
931 if (b->base->isCOMinterface())
932 com = 1;
934 if (b->base->isCPPinterface() && id)
935 id->cpp = 1;
937 vtblInterfaces->push(b);
938 b->copyBaseInterfaces(vtblInterfaces);
942 /****************************************
945 int ClassDeclaration::isCOMclass()
947 return com;
950 int ClassDeclaration::isCOMinterface()
952 return 0;
955 int ClassDeclaration::isCPPinterface()
957 return 0;
961 /****************************************
964 int ClassDeclaration::isAbstract()
966 if (isabstract)
967 return TRUE;
968 for (int i = 1; i < vtbl.dim; i++)
970 FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration();
972 //printf("\tvtbl[%d] = %p\n", i, fd);
973 if (!fd || fd->isAbstract())
975 isabstract |= 1;
976 return TRUE;
979 return FALSE;
983 /****************************************
984 * Returns !=0 if there's an extra member which is the 'this'
985 * pointer to the enclosing context (enclosing class or function)
988 int ClassDeclaration::isNested()
990 return isnested;
993 /****************************************
994 * Determine if slot 0 of the vtbl[] is reserved for something else.
995 * For class objects, yes, this is where the classinfo ptr goes.
996 * For COM interfaces, no.
997 * For non-COM interfaces, yes, this is where the Interface ptr goes.
1000 int ClassDeclaration::vtblOffset()
1002 return 1;
1005 /****************************************
1008 char *ClassDeclaration::kind()
1010 return "class";
1013 /****************************************
1016 void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses)
1018 aclasses->push(this);
1021 /********************************* InterfaceDeclaration ****************************/
1023 InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses, LINK l)
1024 : ClassDeclaration(loc, id, baseclasses, l)
1026 com = 0;
1027 cpp = 0;
1028 if (id == Id::IUnknown) // IUnknown is the root of all COM interfaces
1029 { com = 1;
1030 cpp = 1; // IUnknown is also a C++ interface
1034 Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s)
1036 InterfaceDeclaration *id;
1038 if (s)
1039 id = (InterfaceDeclaration *)s;
1040 else
1041 id = new InterfaceDeclaration(loc, ident, NULL, linkage);
1043 ClassDeclaration::syntaxCopy(id);
1044 return id;
1047 void InterfaceDeclaration::semantic(Scope *sc)
1048 { int i;
1050 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1051 if (inuse)
1052 return;
1053 if (!scope)
1054 { type = type->semantic(loc, sc);
1055 handle = handle->semantic(loc, sc);
1057 if (!members) // if forward reference
1058 { //printf("\tinterface '%s' is forward referenced\n", toChars());
1059 return;
1061 if (symtab) // if already done
1062 { if (!scope)
1063 return;
1065 else
1066 symtab = new DsymbolTable();
1068 Scope *scx = NULL;
1069 if (scope)
1070 { sc = scope;
1071 scx = scope; // save so we don't make redundant copies
1072 scope = NULL;
1075 if (attributes)
1076 attributes->append(sc->attributes);
1077 else
1078 attributes = sc->attributes;
1080 if (sc->stc & STCdeprecated)
1082 isdeprecated = 1;
1085 // Expand any tuples in baseclasses[]
1086 for (i = 0; i < baseclasses.dim; )
1087 { BaseClass *b = (BaseClass *)baseclasses.data[0];
1088 b->type = b->type->semantic(loc, sc);
1089 Type *tb = b->type->toBasetype();
1091 if (tb->ty == Ttuple)
1092 { TypeTuple *tup = (TypeTuple *)tb;
1093 enum PROT protection = b->protection;
1094 baseclasses.remove(i);
1095 size_t dim = Argument::dim(tup->arguments);
1096 for (size_t j = 0; j < dim; j++)
1097 { Argument *arg = Argument::getNth(tup->arguments, j);
1098 b = new BaseClass(arg->type, protection);
1099 baseclasses.insert(i + j, b);
1102 else
1103 i++;
1106 if (!baseclasses.dim && sc->linkage == LINKcpp)
1107 cpp = 1;
1109 // Check for errors, handle forward references
1110 for (i = 0; i < baseclasses.dim; )
1111 { TypeClass *tc;
1112 BaseClass *b;
1113 Type *tb;
1115 b = (BaseClass *)baseclasses.data[i];
1116 b->type = b->type->semantic(loc, sc);
1117 tb = b->type->toBasetype();
1118 if (tb->ty == Tclass)
1119 tc = (TypeClass *)tb;
1120 else
1121 tc = NULL;
1122 if (!tc || !tc->sym->isInterfaceDeclaration())
1124 error("base type must be interface, not %s", b->type->toChars());
1125 baseclasses.remove(i);
1126 continue;
1128 else
1130 // Check for duplicate interfaces
1131 for (size_t j = 0; j < i; j++)
1133 BaseClass *b2 = (BaseClass *)baseclasses.data[j];
1134 if (b2->base == tc->sym)
1135 error("inherits from duplicate interface %s", b2->base->toChars());
1138 b->base = tc->sym;
1139 if (b->base == this || isBaseOf2(b->base))
1141 error("circular inheritance of interface");
1142 baseclasses.remove(i);
1143 continue;
1145 if (!b->base->symtab || b->base->scope || b->base->inuse)
1147 //error("forward reference of base class %s", baseClass->toChars());
1148 // Forward reference of base, try again later
1149 //printf("\ttry later, forward reference of base %s\n", b->base->toChars());
1150 scope = scx ? scx : new Scope(*sc);
1151 scope->setNoFree();
1152 scope->module->addDeferredSemantic(this);
1153 return;
1156 #if 0
1157 // Inherit const/invariant from base class
1158 storage_class |= b->base->storage_class & (STCconst | STCinvariant);
1159 #endif
1160 i++;
1163 interfaces_dim = baseclasses.dim;
1164 interfaces = (BaseClass **)baseclasses.data;
1166 interfaceSemantic(sc);
1168 if (vtblOffset())
1169 vtbl.push(this); // leave room at vtbl[0] for classinfo
1171 // Cat together the vtbl[]'s from base interfaces
1172 for (i = 0; i < interfaces_dim; i++)
1173 { BaseClass *b = interfaces[i];
1175 // Skip if b has already appeared
1176 for (int k = 0; k < i; k++)
1178 if (b == interfaces[i])
1179 goto Lcontinue;
1182 // Copy vtbl[] from base class
1183 if (b->base->vtblOffset())
1184 { int d = b->base->vtbl.dim;
1185 if (d > 1)
1187 vtbl.reserve(d - 1);
1188 for (int j = 1; j < d; j++)
1189 vtbl.push(b->base->vtbl.data[j]);
1192 else
1194 vtbl.append(&b->base->vtbl);
1197 Lcontinue:
1201 protection = sc->protection;
1202 storage_class |= sc->stc & (STCconst | STCinvariant);
1204 for (i = 0; i < members->dim; i++)
1206 Dsymbol *s = (Dsymbol *)members->data[i];
1207 s->addMember(sc, this, 1);
1210 sc = sc->push(this);
1211 sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
1212 STCabstract | STCdeprecated | STCconst | STCinvariant | STCtls);
1213 sc->stc |= storage_class & (STCconst | STCinvariant);
1214 sc->attributes = NULL;
1215 sc->parent = this;
1216 if (isCOMinterface())
1217 sc->linkage = LINKwindows;
1218 else if (isCPPinterface())
1219 sc->linkage = LINKcpp;
1220 sc->structalign = 8;
1221 structalign = sc->structalign;
1222 sc->offset = PTRSIZE * 2;
1223 inuse++;
1224 for (i = 0; i < members->dim; i++)
1226 Dsymbol *s = (Dsymbol *)members->data[i];
1227 s->semantic(sc);
1229 inuse--;
1230 //members->print();
1231 sc->pop();
1232 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1236 /*******************************************
1237 * Determine if 'this' is a base class of cd.
1238 * (Actually, if it is an interface supported by cd)
1239 * Output:
1240 * *poffset offset to start of class
1241 * OFFSET_RUNTIME must determine offset at runtime
1242 * Returns:
1243 * 0 not a base
1244 * 1 is a base
1247 int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, target_ptrdiff_t *poffset)
1249 unsigned j;
1251 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
1252 assert(!baseClass);
1253 for (j = 0; j < cd->interfaces_dim; j++)
1255 BaseClass *b = cd->interfaces[j];
1257 //printf("\tbase %s\n", b->base->toChars());
1258 if (this == b->base)
1260 //printf("\tfound at offset %d\n", b->offset);
1261 if (poffset)
1262 { *poffset = b->offset;
1263 if (j && cd->isInterfaceDeclaration())
1264 *poffset = OFFSET_RUNTIME;
1266 return 1;
1268 if (isBaseOf(b, poffset))
1269 { if (j && poffset && cd->isInterfaceDeclaration())
1270 *poffset = OFFSET_RUNTIME;
1271 return 1;
1275 if (cd->baseClass && isBaseOf(cd->baseClass, poffset))
1276 return 1;
1278 if (poffset)
1279 *poffset = 0;
1280 return 0;
1284 int InterfaceDeclaration::isBaseOf(BaseClass *bc, target_ptrdiff_t *poffset)
1286 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars());
1287 for (unsigned j = 0; j < bc->baseInterfaces_dim; j++)
1289 BaseClass *b = &bc->baseInterfaces[j];
1291 if (this == b->base)
1293 if (poffset)
1294 { *poffset = b->offset;
1296 return 1;
1298 if (isBaseOf(b, poffset))
1300 return 1;
1303 if (poffset)
1304 *poffset = 0;
1305 return 0;
1308 /****************************************
1309 * Determine if slot 0 of the vtbl[] is reserved for something else.
1310 * For class objects, yes, this is where the ClassInfo ptr goes.
1311 * For COM interfaces, no.
1312 * For non-COM interfaces, yes, this is where the Interface ptr goes.
1315 int InterfaceDeclaration::vtblOffset()
1317 if (isCOMinterface() || isCPPinterface())
1318 return 0;
1319 return 1;
1322 int InterfaceDeclaration::isCOMinterface()
1324 return com;
1327 int InterfaceDeclaration::isCPPinterface()
1329 return cpp;
1332 /*******************************************
1335 char *InterfaceDeclaration::kind()
1337 return "interface";
1341 /******************************** BaseClass *****************************/
1343 BaseClass::BaseClass()
1345 memset(this, 0, sizeof(BaseClass));
1348 BaseClass::BaseClass(Type *type, enum PROT protection)
1350 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
1351 this->type = type;
1352 this->protection = protection;
1353 base = NULL;
1354 offset = 0;
1356 baseInterfaces_dim = 0;
1357 baseInterfaces = NULL;
1360 /****************************************
1361 * Fill in vtbl[] for base class based on member functions of class cd.
1362 * Input:
1363 * vtbl if !=NULL, fill it in
1364 * newinstance !=0 means all entries must be filled in by members
1365 * of cd, not members of any base classes of cd.
1366 * Returns:
1367 * !=0 if any entries were filled in by members of cd (not exclusively
1368 * by base classes)
1371 int BaseClass::fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance)
1373 ClassDeclaration *id = base;
1374 int j;
1375 int result = 0;
1377 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars());
1378 if (vtbl)
1379 vtbl->setDim(base->vtbl.dim);
1381 // first entry is ClassInfo reference
1382 for (j = base->vtblOffset(); j < base->vtbl.dim; j++)
1384 FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration();
1385 FuncDeclaration *fd;
1386 TypeFunction *tf;
1388 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
1390 assert(ifd);
1391 // Find corresponding function in this class
1392 tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL;
1393 fd = cd->findFunc(ifd->ident, tf);
1394 if (fd && !fd->isAbstract())
1396 //printf(" found\n");
1397 // Check that calling conventions match
1398 if (fd->linkage != ifd->linkage)
1399 fd->error("linkage doesn't match interface function");
1401 // Check that it is current
1402 if (newinstance &&
1403 fd->toParent() != cd &&
1404 ifd->toParent() == base)
1405 cd->error("interface function %s.%s is not implemented",
1406 id->toChars(), ifd->ident->toChars());
1408 if (fd->toParent() == cd)
1409 result = 1;
1411 else
1413 //printf(" not found\n");
1414 // BUG: should mark this class as abstract?
1415 if (!cd->isAbstract())
1416 cd->error("interface function %s.%s isn't implemented",
1417 id->toChars(), ifd->ident->toChars());
1418 fd = NULL;
1420 if (vtbl)
1421 vtbl->data[j] = fd;
1424 return result;
1427 void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces)
1429 //printf("+copyBaseInterfaces(), %s\n", base->toChars());
1430 // if (baseInterfaces_dim)
1431 // return;
1433 baseInterfaces_dim = base->interfaces_dim;
1434 baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass));
1436 //printf("%s.copyBaseInterfaces()\n", base->toChars());
1437 for (int i = 0; i < baseInterfaces_dim; i++)
1439 BaseClass *b = &baseInterfaces[i];
1440 BaseClass *b2 = base->interfaces[i];
1442 assert(b2->vtbl.dim == 0); // should not be filled yet
1443 memcpy(b, b2, sizeof(BaseClass));
1445 if (i) // single inheritance is i==0
1446 vtblInterfaces->push(b); // only need for M.I.
1447 b->copyBaseInterfaces(vtblInterfaces);
1449 //printf("-copyBaseInterfaces\n");