comparison dmd/class.c @ 1:c53b6e3fe49a trunk

[svn r5] Initial commit. Most things are very rough.
author lindquist
date Sat, 01 Sep 2007 21:43:27 +0200
parents
children 3cfcb944304e
comparison
equal deleted inserted replaced
0:a9e71648e74d 1:c53b6e3fe49a
1
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2006 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.
10
11 #include <stdio.h>
12 #include <stdlib.h>
13 #include <assert.h>
14
15 #include "root.h"
16 #include "mem.h"
17
18 #include "enum.h"
19 #include "init.h"
20 #include "attrib.h"
21 #include "declaration.h"
22 #include "aggregate.h"
23 #include "id.h"
24 #include "mtype.h"
25 #include "scope.h"
26 #include "module.h"
27 #include "expression.h"
28 #include "statement.h"
29
30 /********************************* ClassDeclaration ****************************/
31
32 ClassDeclaration *ClassDeclaration::classinfo;
33 ClassDeclaration *ClassDeclaration::object;
34
35 ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
36 : AggregateDeclaration(loc, id)
37 {
38 static char msg[] = "only object.d can define this reserved class name";
39
40 if (baseclasses)
41 this->baseclasses = *baseclasses;
42 baseClass = NULL;
43
44 interfaces_dim = 0;
45 interfaces = NULL;
46
47 vtblInterfaces = NULL;
48
49 //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses.dim);
50
51 // For forward references
52 type = new TypeClass(this);
53 handle = type;
54
55 ctor = NULL;
56 defaultCtor = NULL;
57 staticCtor = NULL;
58 staticDtor = NULL;
59
60 vtblsym = NULL;
61 vclassinfo = NULL;
62
63 if (id)
64 { // Look for special class names
65
66 if (id == Id::__sizeof || id == Id::alignof || id == Id::mangleof)
67 error("illegal class name");
68
69 // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
70 if (id->toChars()[0] == 'T')
71 {
72 if (id == Id::TypeInfo)
73 { if (Type::typeinfo)
74 Type::typeinfo->error("%s", msg);
75 Type::typeinfo = this;
76 }
77
78 if (id == Id::TypeInfo_Class)
79 { if (Type::typeinfoclass)
80 Type::typeinfoclass->error("%s", msg);
81 Type::typeinfoclass = this;
82 }
83
84 if (id == Id::TypeInfo_Interface)
85 { if (Type::typeinfointerface)
86 Type::typeinfointerface->error("%s", msg);
87 Type::typeinfointerface = this;
88 }
89
90 if (id == Id::TypeInfo_Struct)
91 { if (Type::typeinfostruct)
92 Type::typeinfostruct->error("%s", msg);
93 Type::typeinfostruct = this;
94 }
95
96 if (id == Id::TypeInfo_Typedef)
97 { if (Type::typeinfotypedef)
98 Type::typeinfotypedef->error("%s", msg);
99 Type::typeinfotypedef = this;
100 }
101
102 if (id == Id::TypeInfo_Pointer)
103 { if (Type::typeinfopointer)
104 Type::typeinfopointer->error("%s", msg);
105 Type::typeinfopointer = this;
106 }
107
108 if (id == Id::TypeInfo_Array)
109 { if (Type::typeinfoarray)
110 Type::typeinfoarray->error("%s", msg);
111 Type::typeinfoarray = this;
112 }
113
114 if (id == Id::TypeInfo_StaticArray)
115 { //if (Type::typeinfostaticarray)
116 //Type::typeinfostaticarray->error("%s", msg);
117 Type::typeinfostaticarray = this;
118 }
119
120 if (id == Id::TypeInfo_AssociativeArray)
121 { if (Type::typeinfoassociativearray)
122 Type::typeinfoassociativearray->error("%s", msg);
123 Type::typeinfoassociativearray = this;
124 }
125
126 if (id == Id::TypeInfo_Enum)
127 { if (Type::typeinfoenum)
128 Type::typeinfoenum->error("%s", msg);
129 Type::typeinfoenum = this;
130 }
131
132 if (id == Id::TypeInfo_Function)
133 { if (Type::typeinfofunction)
134 Type::typeinfofunction->error("%s", msg);
135 Type::typeinfofunction = this;
136 }
137
138 if (id == Id::TypeInfo_Delegate)
139 { if (Type::typeinfodelegate)
140 Type::typeinfodelegate->error("%s", msg);
141 Type::typeinfodelegate = this;
142 }
143
144 if (id == Id::TypeInfo_Tuple)
145 { if (Type::typeinfotypelist)
146 Type::typeinfotypelist->error("%s", msg);
147 Type::typeinfotypelist = this;
148 }
149 }
150
151 if (id == Id::Object)
152 { if (object)
153 object->error("%s", msg);
154 object = this;
155 }
156
157 if (id == Id::ClassInfo)
158 { if (classinfo)
159 classinfo->error("%s", msg);
160 classinfo = this;
161 }
162
163 if (id == Id::ModuleInfo)
164 { if (Module::moduleinfo)
165 Module::moduleinfo->error("%s", msg);
166 Module::moduleinfo = this;
167 }
168 }
169
170 com = 0;
171 #if 0
172 if (id == Id::IUnknown) // IUnknown is the root of all COM objects
173 com = 1;
174 #endif
175 isauto = 0;
176 isabstract = 0;
177 isnested = 0;
178 vthis = NULL;
179 }
180
181 Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
182 {
183 ClassDeclaration *cd;
184
185 //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
186 if (s)
187 cd = (ClassDeclaration *)s;
188 else
189 cd = new ClassDeclaration(loc, ident, NULL);
190
191 cd->storage_class |= storage_class;
192
193 cd->baseclasses.setDim(this->baseclasses.dim);
194 for (int i = 0; i < cd->baseclasses.dim; i++)
195 {
196 BaseClass *b = (BaseClass *)this->baseclasses.data[i];
197 BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
198 cd->baseclasses.data[i] = b2;
199 }
200
201 ScopeDsymbol::syntaxCopy(cd);
202 return cd;
203 }
204
205 void ClassDeclaration::semantic(Scope *sc)
206 { int i;
207 unsigned offset;
208
209 //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
210 //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
211 //printf("sc->stc = %x\n", sc->stc);
212
213 //{ static int n; if (++n == 20) *(char*)0=0; }
214
215 if (!ident) // if anonymous class
216 { char *id = "__anonclass";
217
218 ident = Identifier::generateId(id);
219 }
220
221 if (!scope)
222 {
223 if (!parent && sc->parent && !sc->parent->isModule())
224 parent = sc->parent;
225
226 type = type->semantic(loc, sc);
227 handle = handle->semantic(loc, sc);
228 }
229 if (!members) // if forward reference
230 { //printf("\tclass '%s' is forward referenced\n", toChars());
231 return;
232 }
233 if (symtab)
234 { if (!scope)
235 { //printf("\tsemantic for '%s' is already completed\n", toChars());
236 return; // semantic() already completed
237 }
238 }
239 else
240 symtab = new DsymbolTable();
241
242 Scope *scx = NULL;
243 if (scope)
244 { sc = scope;
245 scx = scope; // save so we don't make redundant copies
246 scope = NULL;
247 }
248 #ifdef IN_GCC
249 methods.setDim(0);
250 #endif
251
252 // Expand any tuples in baseclasses[]
253 for (i = 0; i < baseclasses.dim; )
254 { BaseClass *b = (BaseClass *)baseclasses.data[i];
255 b->type = b->type->semantic(loc, sc);
256 Type *tb = b->type->toBasetype();
257
258 if (tb->ty == Ttuple)
259 { TypeTuple *tup = (TypeTuple *)tb;
260 enum PROT protection = b->protection;
261 baseclasses.remove(i);
262 size_t dim = Argument::dim(tup->arguments);
263 for (size_t j = 0; j < dim; j++)
264 { Argument *arg = Argument::getNth(tup->arguments, j);
265 b = new BaseClass(arg->type, protection);
266 baseclasses.insert(i + j, b);
267 }
268 }
269 else
270 i++;
271 }
272
273 // See if there's a base class as first in baseclasses[]
274 if (baseclasses.dim)
275 { TypeClass *tc;
276 BaseClass *b;
277 Type *tb;
278
279 b = (BaseClass *)baseclasses.data[0];
280 //b->type = b->type->semantic(loc, sc);
281 tb = b->type->toBasetype();
282 if (tb->ty != Tclass)
283 { error("base type must be class or interface, not %s", b->type->toChars());
284 baseclasses.remove(0);
285 }
286 else
287 {
288 tc = (TypeClass *)(tb);
289 if (tc->sym->isInterfaceDeclaration())
290 ;
291 else
292 {
293 for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
294 {
295 if (cdb == this)
296 {
297 error("circular inheritance");
298 baseclasses.remove(0);
299 goto L7;
300 }
301 }
302 if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
303 {
304 //error("forward reference of base class %s", baseClass->toChars());
305 // Forward reference of base class, try again later
306 //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
307 scope = scx ? scx : new Scope(*sc);
308 scope->setNoFree();
309 scope->module->addDeferredSemantic(this);
310 return;
311 }
312 else
313 { baseClass = tc->sym;
314 b->base = baseClass;
315 }
316 L7: ;
317 }
318 }
319 }
320
321 // Treat the remaining entries in baseclasses as interfaces
322 // Check for errors, handle forward references
323 for (i = (baseClass ? 1 : 0); i < baseclasses.dim; )
324 { TypeClass *tc;
325 BaseClass *b;
326 Type *tb;
327
328 b = (BaseClass *)baseclasses.data[i];
329 b->type = b->type->semantic(loc, sc);
330 tb = b->type->toBasetype();
331 if (tb->ty == Tclass)
332 tc = (TypeClass *)tb;
333 else
334 tc = NULL;
335 if (!tc || !tc->sym->isInterfaceDeclaration())
336 {
337 error("base type must be interface, not %s", b->type->toChars());
338 baseclasses.remove(i);
339 continue;
340 }
341 else
342 {
343 // Check for duplicate interfaces
344 for (size_t j = (baseClass ? 1 : 0); j < i; j++)
345 {
346 BaseClass *b2 = (BaseClass *)baseclasses.data[j];
347 if (b2->base == tc->sym)
348 error("inherits from duplicate interface %s", b2->base->toChars());
349 }
350
351 b->base = tc->sym;
352 if (!b->base->symtab || b->base->scope)
353 {
354 //error("forward reference of base class %s", baseClass->toChars());
355 // Forward reference of base, try again later
356 //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
357 scope = scx ? scx : new Scope(*sc);
358 scope->setNoFree();
359 scope->module->addDeferredSemantic(this);
360 return;
361 }
362 }
363 i++;
364 }
365
366
367 // If no base class, and this is not an Object, use Object as base class
368 if (!baseClass && ident != Id::Object)
369 {
370 // BUG: what if Object is redefined in an inner scope?
371 Type *tbase = new TypeIdentifier(0, Id::Object);
372 BaseClass *b;
373 TypeClass *tc;
374 Type *bt;
375
376 if (!object)
377 {
378 error("missing or corrupt object.d");
379 fatal();
380 }
381 bt = tbase->semantic(loc, sc)->toBasetype();
382 b = new BaseClass(bt, PROTpublic);
383 baseclasses.shift(b);
384 assert(b->type->ty == Tclass);
385 tc = (TypeClass *)(b->type);
386 baseClass = tc->sym;
387 assert(!baseClass->isInterfaceDeclaration());
388 b->base = baseClass;
389 }
390
391 interfaces_dim = baseclasses.dim;
392 interfaces = (BaseClass **)baseclasses.data;
393
394
395 if (baseClass)
396 {
397 if (baseClass->storage_class & STCfinal)
398 error("cannot inherit from final class %s", baseClass->toChars());
399
400 interfaces_dim--;
401 interfaces++;
402
403 // Copy vtbl[] from base class
404 vtbl.setDim(baseClass->vtbl.dim);
405 memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim);
406
407 // Inherit properties from base class
408 com = baseClass->isCOMclass();
409 isauto = baseClass->isauto;
410 vthis = baseClass->vthis;
411 }
412 else
413 {
414 // No base class, so this is the root of the class hierarchy
415 vtbl.setDim(0);
416 vtbl.push(this); // leave room for classinfo as first member
417 }
418
419 protection = sc->protection;
420 storage_class |= sc->stc;
421
422 if (sizeok == 0)
423 {
424 interfaceSemantic(sc);
425
426 for (i = 0; i < members->dim; i++)
427 {
428 Dsymbol *s = (Dsymbol *)members->data[i];
429 s->addMember(sc, this, 1);
430 }
431
432 /* If this is a nested class, add the hidden 'this'
433 * member which is a pointer to the enclosing scope.
434 */
435 if (vthis) // if inheriting from nested class
436 { // Use the base class's 'this' member
437 isnested = 1;
438 if (storage_class & STCstatic)
439 error("static class cannot inherit from nested class %s", baseClass->toChars());
440 if (toParent2() != baseClass->toParent2())
441 error("super class %s is nested within %s, not %s",
442 baseClass->toChars(),
443 baseClass->toParent2()->toChars(),
444 toParent2()->toChars());
445 }
446 else if (!(storage_class & STCstatic))
447 { Dsymbol *s = toParent2();
448 if (s)
449 {
450 ClassDeclaration *cd = s->isClassDeclaration();
451 FuncDeclaration *fd = s->isFuncDeclaration();
452
453
454 if (cd || fd)
455 { isnested = 1;
456 Type *t;
457 if (cd)
458 t = cd->type;
459 else if (fd)
460 { AggregateDeclaration *ad = fd->isMember2();
461 if (ad)
462 t = ad->handle;
463 else
464 {
465 t = new TypePointer(Type::tvoid);
466 t = t->semantic(0, sc);
467 }
468 }
469 else
470 assert(0);
471 assert(!vthis);
472 vthis = new ThisDeclaration(t);
473 members->push(vthis);
474 }
475 }
476 }
477 }
478
479 if (storage_class & (STCauto | STCscope))
480 isauto = 1;
481 if (storage_class & STCabstract)
482 isabstract = 1;
483 if (storage_class & STCdeprecated)
484 isdeprecated = 1;
485
486 sc = sc->push(this);
487 sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
488 STCabstract | STCdeprecated);
489 sc->parent = this;
490 sc->inunion = 0;
491
492 if (isCOMclass())
493 sc->linkage = LINKwindows;
494 sc->protection = PROTpublic;
495 sc->explicitProtection = 0;
496 sc->structalign = 8;
497 structalign = sc->structalign;
498 if (baseClass)
499 { sc->offset = baseClass->structsize;
500 alignsize = baseClass->alignsize;
501 // if (isnested)
502 // sc->offset += PTRSIZE; // room for uplevel context pointer
503 }
504 else
505 { sc->offset = 8; // allow room for vptr[] and monitor
506 alignsize = 4;
507 }
508 structsize = sc->offset;
509 Scope scsave = *sc;
510 int members_dim = members->dim;
511 sizeok = 0;
512 for (i = 0; i < members_dim; i++)
513 {
514 Dsymbol *s = (Dsymbol *)members->data[i];
515 s->semantic(sc);
516 }
517
518 if (sizeok == 2)
519 { // semantic() failed because of forward references.
520 // Unwind what we did, and defer it for later
521 fields.setDim(0);
522 structsize = 0;
523 alignsize = 0;
524 structalign = 0;
525
526 sc = sc->pop();
527
528 scope = scx ? scx : new Scope(*sc);
529 scope->setNoFree();
530 scope->module->addDeferredSemantic(this);
531
532 //printf("\tsemantic('%s') failed\n", toChars());
533 return;
534 }
535
536 //printf("\tsemantic('%s') successful\n", toChars());
537
538 structsize = sc->offset;
539 //members->print();
540
541 /* Look for special member functions.
542 * They must be in this class, not in a base class.
543 */
544 ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
545 if (ctor && ctor->toParent() != this)
546 ctor = NULL;
547
548 // dtor = (DtorDeclaration *)search(Id::dtor, 0);
549 // if (dtor && dtor->toParent() != this)
550 // dtor = NULL;
551
552 // inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
553 // if (inv && inv->toParent() != this)
554 // inv = NULL;
555
556 // Can be in base class
557 aggNew = (NewDeclaration *)search(0, Id::classNew, 0);
558 aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
559
560 // If this class has no constructor, but base class does, create
561 // a constructor:
562 // this() { }
563 if (!ctor && baseClass && baseClass->ctor)
564 {
565 //printf("Creating default this(){} for class %s\n", toChars());
566 ctor = new CtorDeclaration(0, 0, NULL, 0);
567 ctor->fbody = new CompoundStatement(0, new Statements());
568 members->push(ctor);
569 ctor->addMember(sc, this, 1);
570 *sc = scsave;
571 sc->offset = structsize;
572 ctor->semantic(sc);
573 defaultCtor = ctor;
574 }
575
576 #if 0
577 if (baseClass)
578 { if (!aggDelete)
579 aggDelete = baseClass->aggDelete;
580 if (!aggNew)
581 aggNew = baseClass->aggNew;
582 }
583 #endif
584
585 // Allocate instance of each new interface
586 for (i = 0; i < vtblInterfaces->dim; i++)
587 {
588 BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
589 unsigned thissize = PTRSIZE;
590
591 alignmember(structalign, thissize, &sc->offset);
592 assert(b->offset == 0);
593 b->offset = sc->offset;
594
595 // Take care of single inheritance offsets
596 while (b->baseInterfaces_dim)
597 {
598 b = &b->baseInterfaces[0];
599 b->offset = sc->offset;
600 }
601
602 sc->offset += thissize;
603 if (alignsize < thissize)
604 alignsize = thissize;
605 }
606 structsize = sc->offset;
607 sizeok = 1;
608 Module::dprogress++;
609
610
611 sc->pop();
612
613 #if 0 // Do not call until toObjfile() because of forward references
614 // Fill in base class vtbl[]s
615 for (i = 0; i < vtblInterfaces->dim; i++)
616 {
617 BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
618
619 //b->fillVtbl(this, &b->vtbl, 1);
620 }
621 #endif
622 //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
623 }
624
625 void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
626 {
627 if (!isAnonymous())
628 {
629 buf->printf("%s ", kind());
630 buf->writestring(toChars());
631 if (baseclasses.dim)
632 buf->writestring(" : ");
633 }
634 for (int i = 0; i < baseclasses.dim; i++)
635 {
636 BaseClass *b = (BaseClass *)baseclasses.data[i];
637
638 if (i)
639 buf->writeByte(',');
640 //buf->writestring(b->base->ident->toChars());
641 b->type->toCBuffer(buf, NULL, hgs);
642 }
643 buf->writenl();
644 buf->writeByte('{');
645 buf->writenl();
646 for (int i = 0; i < members->dim; i++)
647 {
648 Dsymbol *s = (Dsymbol *)members->data[i];
649
650 buf->writestring(" ");
651 s->toCBuffer(buf, hgs);
652 }
653 buf->writestring("}");
654 buf->writenl();
655 }
656
657 #if 0
658 void ClassDeclaration::defineRef(Dsymbol *s)
659 {
660 ClassDeclaration *cd;
661
662 AggregateDeclaration::defineRef(s);
663 cd = s->isClassDeclaration();
664 baseType = cd->baseType;
665 cd->baseType = NULL;
666 }
667 #endif
668
669 /*********************************************
670 * Determine if 'this' is a base class of cd.
671 * This is used to detect circular inheritance only.
672 */
673
674 int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
675 {
676 if (!cd)
677 return 0;
678 //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
679 for (int i = 0; i < cd->baseclasses.dim; i++)
680 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
681
682 if (b->base == this || isBaseOf2(b->base))
683 return 1;
684 }
685 return 0;
686 }
687
688 /*******************************************
689 * Determine if 'this' is a base class of cd.
690 */
691
692 int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
693 {
694 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
695 if (poffset)
696 *poffset = 0;
697 while (cd)
698 {
699 if (this == cd->baseClass)
700 return 1;
701
702 /* cd->baseClass might not be set if cd is forward referenced.
703 */
704 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
705 {
706 cd->error("base class is forward referenced by %s", toChars());
707 }
708
709 cd = cd->baseClass;
710 }
711 return 0;
712 }
713
714 Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
715 {
716 Dsymbol *s;
717
718 //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
719 if (scope)
720 semantic(scope);
721
722 if (!members || !symtab || scope)
723 { error("is forward referenced when looking for '%s'", ident->toChars());
724 //*(char*)0=0;
725 return NULL;
726 }
727
728 s = ScopeDsymbol::search(loc, ident, flags);
729 if (!s)
730 {
731 // Search bases classes in depth-first, left to right order
732
733 int i;
734
735 for (i = 0; i < baseclasses.dim; i++)
736 {
737 BaseClass *b = (BaseClass *)baseclasses.data[i];
738
739 if (b->base)
740 {
741 if (!b->base->symtab)
742 error("base %s is forward referenced", b->base->ident->toChars());
743 else
744 {
745 s = b->base->search(loc, ident, flags);
746 if (s == this) // happens if s is nested in this and derives from this
747 s = NULL;
748 else if (s)
749 break;
750 }
751 }
752 }
753 }
754 return s;
755 }
756
757 /****************
758 * Find virtual function matching identifier and type.
759 * Used to build virtual function tables for interface implementations.
760 */
761
762 FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
763 {
764 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
765
766 ClassDeclaration *cd = this;
767 Array *vtbl = &cd->vtbl;
768 while (1)
769 {
770 for (size_t i = 0; i < vtbl->dim; i++)
771 {
772 FuncDeclaration *fd = (FuncDeclaration *)vtbl->data[i];
773
774 //printf("\t[%d] = %s\n", i, fd->toChars());
775 if (ident == fd->ident &&
776 //tf->equals(fd->type)
777 fd->type->covariant(tf) == 1
778 )
779 { //printf("\t\tfound\n");
780 return fd;
781 }
782 //else printf("\t\t%d\n", fd->type->covariant(tf));
783 }
784 if (!cd)
785 break;
786 vtbl = &cd->vtblFinal;
787 cd = cd->baseClass;
788 }
789
790 return NULL;
791 }
792
793 void ClassDeclaration::interfaceSemantic(Scope *sc)
794 { int i;
795
796 vtblInterfaces = new BaseClasses();
797 vtblInterfaces->reserve(interfaces_dim);
798
799 for (i = 0; i < interfaces_dim; i++)
800 {
801 BaseClass *b = interfaces[i];
802
803 // If this is an interface, and it derives from a COM interface,
804 // then this is a COM interface too.
805 if (b->base->isCOMclass())
806 com = 1;
807
808 vtblInterfaces->push(b);
809 b->copyBaseInterfaces(vtblInterfaces);
810 }
811 }
812
813 /****************************************
814 */
815
816 int ClassDeclaration::isCOMclass()
817 {
818 return com;
819 }
820
821
822 /****************************************
823 */
824
825 int ClassDeclaration::isAbstract()
826 {
827 if (isabstract)
828 return TRUE;
829 for (int i = 1; i < vtbl.dim; i++)
830 {
831 FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration();
832
833 //printf("\tvtbl[%d] = %p\n", i, fd);
834 if (!fd || fd->isAbstract())
835 {
836 isabstract |= 1;
837 return TRUE;
838 }
839 }
840 return FALSE;
841 }
842
843 /****************************************
844 * Returns !=0 if there's an extra member which is the 'this'
845 * pointer to the enclosing context (enclosing class or function)
846 */
847
848 int ClassDeclaration::isNested()
849 {
850 return isnested;
851 }
852
853 /****************************************
854 * Determine if slot 0 of the vtbl[] is reserved for something else.
855 * For class objects, yes, this is where the classinfo ptr goes.
856 * For COM interfaces, no.
857 * For non-COM interfaces, yes, this is where the Interface ptr goes.
858 */
859
860 int ClassDeclaration::vtblOffset()
861 {
862 return 1;
863 }
864
865 /****************************************
866 */
867
868 char *ClassDeclaration::kind()
869 {
870 return "class";
871 }
872
873 /****************************************
874 */
875
876 void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses)
877 {
878 aclasses->push(this);
879 }
880
881 /********************************* InterfaceDeclaration ****************************/
882
883 InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
884 : ClassDeclaration(loc, id, baseclasses)
885 {
886 com = 0;
887 if (id == Id::IUnknown) // IUnknown is the root of all COM objects
888 com = 1;
889 }
890
891 Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s)
892 {
893 InterfaceDeclaration *id;
894
895 if (s)
896 id = (InterfaceDeclaration *)s;
897 else
898 id = new InterfaceDeclaration(loc, ident, NULL);
899
900 ClassDeclaration::syntaxCopy(id);
901 return id;
902 }
903
904 void InterfaceDeclaration::semantic(Scope *sc)
905 { int i;
906
907 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
908 if (!scope)
909 { type = type->semantic(loc, sc);
910 handle = handle->semantic(loc, sc);
911 }
912 if (!members) // if forward reference
913 { //printf("\tinterface '%s' is forward referenced\n", toChars());
914 return;
915 }
916 if (symtab) // if already done
917 { if (!scope)
918 return;
919 }
920 else
921 symtab = new DsymbolTable();
922
923 Scope *scx = NULL;
924 if (scope)
925 { sc = scope;
926 scx = scope; // save so we don't make redundant copies
927 scope = NULL;
928 }
929
930 // Expand any tuples in baseclasses[]
931 for (i = 0; i < baseclasses.dim; )
932 { BaseClass *b = (BaseClass *)baseclasses.data[0];
933 b->type = b->type->semantic(loc, sc);
934 Type *tb = b->type->toBasetype();
935
936 if (tb->ty == Ttuple)
937 { TypeTuple *tup = (TypeTuple *)tb;
938 enum PROT protection = b->protection;
939 baseclasses.remove(i);
940 size_t dim = Argument::dim(tup->arguments);
941 for (size_t j = 0; j < dim; j++)
942 { Argument *arg = Argument::getNth(tup->arguments, j);
943 b = new BaseClass(arg->type, protection);
944 baseclasses.insert(i + j, b);
945 }
946 }
947 else
948 i++;
949 }
950
951 // Check for errors, handle forward references
952 for (i = 0; i < baseclasses.dim; )
953 { TypeClass *tc;
954 BaseClass *b;
955 Type *tb;
956
957 b = (BaseClass *)baseclasses.data[i];
958 b->type = b->type->semantic(loc, sc);
959 tb = b->type->toBasetype();
960 if (tb->ty == Tclass)
961 tc = (TypeClass *)tb;
962 else
963 tc = NULL;
964 if (!tc || !tc->sym->isInterfaceDeclaration())
965 {
966 error("base type must be interface, not %s", b->type->toChars());
967 baseclasses.remove(i);
968 continue;
969 }
970 else
971 {
972 // Check for duplicate interfaces
973 for (size_t j = 0; j < i; j++)
974 {
975 BaseClass *b2 = (BaseClass *)baseclasses.data[j];
976 if (b2->base == tc->sym)
977 error("inherits from duplicate interface %s", b2->base->toChars());
978 }
979
980 b->base = tc->sym;
981 if (b->base == this || isBaseOf2(b->base))
982 {
983 error("circular inheritance of interface");
984 baseclasses.remove(i);
985 continue;
986 }
987 if (!b->base->symtab || b->base->scope)
988 {
989 //error("forward reference of base class %s", baseClass->toChars());
990 // Forward reference of base, try again later
991 //printf("\ttry later, forward reference of base %s\n", b->base->toChars());
992 scope = scx ? scx : new Scope(*sc);
993 scope->setNoFree();
994 scope->module->addDeferredSemantic(this);
995 return;
996 }
997 }
998 i++;
999 }
1000
1001 interfaces_dim = baseclasses.dim;
1002 interfaces = (BaseClass **)baseclasses.data;
1003
1004 interfaceSemantic(sc);
1005
1006 if (vtblOffset())
1007 vtbl.push(this); // leave room at vtbl[0] for classinfo
1008
1009 // Cat together the vtbl[]'s from base interfaces
1010 for (i = 0; i < interfaces_dim; i++)
1011 { BaseClass *b = interfaces[i];
1012
1013 // Skip if b has already appeared
1014 for (int k = 0; k < i; k++)
1015 {
1016 if (b == interfaces[i])
1017 goto Lcontinue;
1018 }
1019
1020 // Copy vtbl[] from base class
1021 if (b->base->vtblOffset())
1022 { int d = b->base->vtbl.dim;
1023 if (d > 1)
1024 {
1025 vtbl.reserve(d - 1);
1026 for (int j = 1; j < d; j++)
1027 vtbl.push(b->base->vtbl.data[j]);
1028 }
1029 }
1030 else
1031 {
1032 vtbl.append(&b->base->vtbl);
1033 }
1034
1035 Lcontinue:
1036 ;
1037 }
1038
1039 for (i = 0; i < members->dim; i++)
1040 {
1041 Dsymbol *s = (Dsymbol *)members->data[i];
1042 s->addMember(sc, this, 1);
1043 }
1044
1045 sc = sc->push(this);
1046 sc->parent = this;
1047 if (isCOMclass())
1048 sc->linkage = LINKwindows;
1049 sc->structalign = 8;
1050 structalign = sc->structalign;
1051 sc->offset = 8;
1052 for (i = 0; i < members->dim; i++)
1053 {
1054 Dsymbol *s = (Dsymbol *)members->data[i];
1055 s->semantic(sc);
1056 }
1057 //members->print();
1058 sc->pop();
1059 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1060 }
1061
1062
1063 /*******************************************
1064 * Determine if 'this' is a base class of cd.
1065 * (Actually, if it is an interface supported by cd)
1066 * Output:
1067 * *poffset offset to start of class
1068 * OFFSET_RUNTIME must determine offset at runtime
1069 * Returns:
1070 * 0 not a base
1071 * 1 is a base
1072 */
1073
1074 int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
1075 {
1076 unsigned j;
1077
1078 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
1079 assert(!baseClass);
1080 for (j = 0; j < cd->interfaces_dim; j++)
1081 {
1082 BaseClass *b = cd->interfaces[j];
1083
1084 //printf("\tbase %s\n", b->base->toChars());
1085 if (this == b->base)
1086 {
1087 //printf("\tfound at offset %d\n", b->offset);
1088 if (poffset)
1089 { *poffset = b->offset;
1090 if (j && cd->isInterfaceDeclaration())
1091 *poffset = OFFSET_RUNTIME;
1092 }
1093 return 1;
1094 }
1095 if (isBaseOf(b, poffset))
1096 { if (j && poffset && cd->isInterfaceDeclaration())
1097 *poffset = OFFSET_RUNTIME;
1098 return 1;
1099 }
1100 }
1101
1102 if (cd->baseClass && isBaseOf(cd->baseClass, poffset))
1103 return 1;
1104
1105 if (poffset)
1106 *poffset = 0;
1107 return 0;
1108 }
1109
1110
1111 int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset)
1112 {
1113 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars());
1114 for (unsigned j = 0; j < bc->baseInterfaces_dim; j++)
1115 {
1116 BaseClass *b = &bc->baseInterfaces[j];
1117
1118 if (this == b->base)
1119 {
1120 if (poffset)
1121 { *poffset = b->offset;
1122 }
1123 return 1;
1124 }
1125 if (isBaseOf(b, poffset))
1126 {
1127 return 1;
1128 }
1129 }
1130 if (poffset)
1131 *poffset = 0;
1132 return 0;
1133 }
1134
1135 /****************************************
1136 * Determine if slot 0 of the vtbl[] is reserved for something else.
1137 * For class objects, yes, this is where the classinfo ptr goes.
1138 * For COM interfaces, no.
1139 * For non-COM interfaces, yes, this is where the Interface ptr goes.
1140 */
1141
1142 int InterfaceDeclaration::vtblOffset()
1143 {
1144 if (isCOMclass())
1145 return 0;
1146 return 1;
1147 }
1148
1149 /*******************************************
1150 */
1151
1152 char *InterfaceDeclaration::kind()
1153 {
1154 return "interface";
1155 }
1156
1157
1158 /******************************** BaseClass *****************************/
1159
1160 BaseClass::BaseClass()
1161 {
1162 memset(this, 0, sizeof(BaseClass));
1163 }
1164
1165 BaseClass::BaseClass(Type *type, enum PROT protection)
1166 {
1167 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
1168 this->type = type;
1169 this->protection = protection;
1170 base = NULL;
1171 offset = 0;
1172
1173 baseInterfaces_dim = 0;
1174 baseInterfaces = NULL;
1175 }
1176
1177 /****************************************
1178 * Fill in vtbl[] for base class based on member functions of class cd.
1179 * Input:
1180 * vtbl if !=NULL, fill it in
1181 * newinstance !=0 means all entries must be filled in by members
1182 * of cd, not members of any base classes of cd.
1183 * Returns:
1184 * !=0 if any entries were filled in by members of cd (not exclusively
1185 * by base classes)
1186 */
1187
1188 int BaseClass::fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance)
1189 {
1190 ClassDeclaration *id = base;
1191 int j;
1192 int result = 0;
1193
1194 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars());
1195 if (vtbl)
1196 vtbl->setDim(base->vtbl.dim);
1197
1198 // first entry is ClassInfo reference
1199 for (j = base->vtblOffset(); j < base->vtbl.dim; j++)
1200 {
1201 FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration();
1202 FuncDeclaration *fd;
1203 TypeFunction *tf;
1204
1205 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
1206
1207 assert(ifd);
1208 // Find corresponding function in this class
1209 tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL;
1210 fd = cd->findFunc(ifd->ident, tf);
1211 if (fd && !fd->isAbstract())
1212 {
1213 //printf(" found\n");
1214 // Check that calling conventions match
1215 if (fd->linkage != ifd->linkage)
1216 fd->error("linkage doesn't match interface function");
1217
1218 // Check that it is current
1219 if (newinstance &&
1220 fd->toParent() != cd &&
1221 ifd->toParent() == base)
1222 cd->error("interface function %s.%s is not implemented",
1223 id->toChars(), ifd->ident->toChars());
1224
1225 if (fd->toParent() == cd)
1226 result = 1;
1227 }
1228 else
1229 {
1230 //printf(" not found\n");
1231 // BUG: should mark this class as abstract?
1232 if (!cd->isAbstract())
1233 cd->error("interface function %s.%s isn't implemented",
1234 id->toChars(), ifd->ident->toChars());
1235 fd = NULL;
1236 }
1237 if (vtbl)
1238 vtbl->data[j] = fd;
1239 }
1240
1241 return result;
1242 }
1243
1244 void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces)
1245 {
1246 //printf("+copyBaseInterfaces(), %s\n", base->toChars());
1247 // if (baseInterfaces_dim)
1248 // return;
1249
1250 baseInterfaces_dim = base->interfaces_dim;
1251 baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass));
1252
1253 //printf("%s.copyBaseInterfaces()\n", base->toChars());
1254 for (int i = 0; i < baseInterfaces_dim; i++)
1255 {
1256 BaseClass *b = &baseInterfaces[i];
1257 BaseClass *b2 = base->interfaces[i];
1258
1259 assert(b2->vtbl.dim == 0); // should not be filled yet
1260 memcpy(b, b2, sizeof(BaseClass));
1261
1262 if (i) // single inheritance is i==0
1263 vtblInterfaces->push(b); // only need for M.I.
1264 b->copyBaseInterfaces(vtblInterfaces);
1265 }
1266 //printf("-copyBaseInterfaces\n");
1267 }