comparison dmd2/class.c @ 758:f04dde6e882c

Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
date Tue, 11 Nov 2008 01:38:48 +0100
parents
children 69a5e4a6fc0f
comparison
equal deleted inserted replaced
757:2c730d530c98 758:f04dde6e882c
1
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.
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 staticCtor = NULL;
56 staticDtor = NULL;
57
58 vtblsym = NULL;
59 vclassinfo = NULL;
60
61 if (id)
62 { // Look for special class names
63
64 if (id == Id::__sizeof || id == Id::alignof || id == Id::mangleof)
65 error("illegal class name");
66
67 // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
68 if (id->toChars()[0] == 'T')
69 {
70 if (id == Id::TypeInfo)
71 { if (Type::typeinfo)
72 Type::typeinfo->error("%s", msg);
73 Type::typeinfo = this;
74 }
75
76 if (id == Id::TypeInfo_Class)
77 { if (Type::typeinfoclass)
78 Type::typeinfoclass->error("%s", msg);
79 Type::typeinfoclass = this;
80 }
81
82 if (id == Id::TypeInfo_Interface)
83 { if (Type::typeinfointerface)
84 Type::typeinfointerface->error("%s", msg);
85 Type::typeinfointerface = this;
86 }
87
88 if (id == Id::TypeInfo_Struct)
89 { if (Type::typeinfostruct)
90 Type::typeinfostruct->error("%s", msg);
91 Type::typeinfostruct = this;
92 }
93
94 if (id == Id::TypeInfo_Typedef)
95 { if (Type::typeinfotypedef)
96 Type::typeinfotypedef->error("%s", msg);
97 Type::typeinfotypedef = this;
98 }
99
100 if (id == Id::TypeInfo_Pointer)
101 { if (Type::typeinfopointer)
102 Type::typeinfopointer->error("%s", msg);
103 Type::typeinfopointer = this;
104 }
105
106 if (id == Id::TypeInfo_Array)
107 { if (Type::typeinfoarray)
108 Type::typeinfoarray->error("%s", msg);
109 Type::typeinfoarray = this;
110 }
111
112 if (id == Id::TypeInfo_StaticArray)
113 { //if (Type::typeinfostaticarray)
114 //Type::typeinfostaticarray->error("%s", msg);
115 Type::typeinfostaticarray = this;
116 }
117
118 if (id == Id::TypeInfo_AssociativeArray)
119 { if (Type::typeinfoassociativearray)
120 Type::typeinfoassociativearray->error("%s", msg);
121 Type::typeinfoassociativearray = this;
122 }
123
124 if (id == Id::TypeInfo_Enum)
125 { if (Type::typeinfoenum)
126 Type::typeinfoenum->error("%s", msg);
127 Type::typeinfoenum = this;
128 }
129
130 if (id == Id::TypeInfo_Function)
131 { if (Type::typeinfofunction)
132 Type::typeinfofunction->error("%s", msg);
133 Type::typeinfofunction = this;
134 }
135
136 if (id == Id::TypeInfo_Delegate)
137 { if (Type::typeinfodelegate)
138 Type::typeinfodelegate->error("%s", msg);
139 Type::typeinfodelegate = this;
140 }
141
142 if (id == Id::TypeInfo_Tuple)
143 { if (Type::typeinfotypelist)
144 Type::typeinfotypelist->error("%s", msg);
145 Type::typeinfotypelist = this;
146 }
147
148 #if DMDV2
149 if (id == Id::TypeInfo_Const)
150 { if (Type::typeinfoconst)
151 Type::typeinfoconst->error("%s", msg);
152 Type::typeinfoconst = this;
153 }
154
155 if (id == Id::TypeInfo_Invariant)
156 { if (Type::typeinfoinvariant)
157 Type::typeinfoinvariant->error("%s", msg);
158 Type::typeinfoinvariant = this;
159 }
160 #endif
161 }
162
163 if (id == Id::Object)
164 { if (object)
165 object->error("%s", msg);
166 object = this;
167 }
168
169 if (id == Id::ClassInfo)
170 { if (classinfo)
171 classinfo->error("%s", msg);
172 classinfo = this;
173 }
174
175 if (id == Id::ModuleInfo)
176 { if (Module::moduleinfo)
177 Module::moduleinfo->error("%s", msg);
178 Module::moduleinfo = this;
179 }
180 }
181
182 com = 0;
183 isauto = 0;
184 isabstract = 0;
185 isnested = 0;
186 vthis = NULL;
187 inuse = 0;
188 }
189
190 Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
191 {
192 ClassDeclaration *cd;
193
194 //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
195 if (s)
196 cd = (ClassDeclaration *)s;
197 else
198 cd = new ClassDeclaration(loc, ident, NULL);
199
200 cd->storage_class |= storage_class;
201
202 cd->baseclasses.setDim(this->baseclasses.dim);
203 for (int i = 0; i < cd->baseclasses.dim; i++)
204 {
205 BaseClass *b = (BaseClass *)this->baseclasses.data[i];
206 BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
207 cd->baseclasses.data[i] = b2;
208 }
209
210 ScopeDsymbol::syntaxCopy(cd);
211 return cd;
212 }
213
214 void ClassDeclaration::semantic(Scope *sc)
215 { int i;
216 unsigned offset;
217
218 //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
219 //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
220 //printf("sc->stc = %x\n", sc->stc);
221
222 //{ static int n; if (++n == 20) *(char*)0=0; }
223
224 if (!ident) // if anonymous class
225 { const char *id = "__anonclass";
226
227 ident = Identifier::generateId(id);
228 }
229
230 if (!scope)
231 {
232 if (!parent && sc->parent && !sc->parent->isModule())
233 parent = sc->parent;
234
235 type = type->semantic(loc, sc);
236 handle = handle->semantic(loc, sc);
237 }
238 if (!members) // if forward reference
239 { //printf("\tclass '%s' is forward referenced\n", toChars());
240 return;
241 }
242 if (symtab)
243 { if (!scope)
244 { //printf("\tsemantic for '%s' is already completed\n", toChars());
245 return; // semantic() already completed
246 }
247 }
248 else
249 symtab = new DsymbolTable();
250
251 Scope *scx = NULL;
252 if (scope)
253 { sc = scope;
254 scx = scope; // save so we don't make redundant copies
255 scope = NULL;
256 }
257 #ifdef IN_GCC
258 methods.setDim(0);
259 #endif
260
261 if (sc->stc & STCdeprecated)
262 {
263 isdeprecated = 1;
264 }
265
266 if (sc->linkage == LINKcpp)
267 error("cannot create C++ classes");
268
269 // Expand any tuples in baseclasses[]
270 for (i = 0; i < baseclasses.dim; )
271 { BaseClass *b = (BaseClass *)baseclasses.data[i];
272 b->type = b->type->semantic(loc, sc);
273 Type *tb = b->type->toBasetype();
274
275 if (tb->ty == Ttuple)
276 { TypeTuple *tup = (TypeTuple *)tb;
277 enum PROT protection = b->protection;
278 baseclasses.remove(i);
279 size_t dim = Argument::dim(tup->arguments);
280 for (size_t j = 0; j < dim; j++)
281 { Argument *arg = Argument::getNth(tup->arguments, j);
282 b = new BaseClass(arg->type, protection);
283 baseclasses.insert(i + j, b);
284 }
285 }
286 else
287 i++;
288 }
289
290 // See if there's a base class as first in baseclasses[]
291 if (baseclasses.dim)
292 { TypeClass *tc;
293 BaseClass *b;
294 Type *tb;
295
296 b = (BaseClass *)baseclasses.data[0];
297 //b->type = b->type->semantic(loc, sc);
298 tb = b->type->toBasetype();
299 if (tb->ty != Tclass)
300 { error("base type must be class or interface, not %s", b->type->toChars());
301 baseclasses.remove(0);
302 }
303 else
304 {
305 tc = (TypeClass *)(tb);
306
307 if (tc->sym->isDeprecated())
308 {
309 if (!isDeprecated())
310 {
311 // Deriving from deprecated class makes this one deprecated too
312 isdeprecated = 1;
313
314 tc->checkDeprecated(loc, sc);
315 }
316 }
317
318 if (tc->sym->isInterfaceDeclaration())
319 ;
320 else
321 {
322 for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
323 {
324 if (cdb == this)
325 {
326 error("circular inheritance");
327 baseclasses.remove(0);
328 goto L7;
329 }
330 }
331 if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
332 {
333 //error("forward reference of base class %s", baseClass->toChars());
334 // Forward reference of base class, try again later
335 //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
336 scope = scx ? scx : new Scope(*sc);
337 scope->setNoFree();
338 scope->module->addDeferredSemantic(this);
339 return;
340 }
341 else
342 { baseClass = tc->sym;
343 b->base = baseClass;
344 }
345 L7: ;
346 }
347 }
348 }
349
350 // Treat the remaining entries in baseclasses as interfaces
351 // Check for errors, handle forward references
352 for (i = (baseClass ? 1 : 0); i < baseclasses.dim; )
353 { TypeClass *tc;
354 BaseClass *b;
355 Type *tb;
356
357 b = (BaseClass *)baseclasses.data[i];
358 b->type = b->type->semantic(loc, sc);
359 tb = b->type->toBasetype();
360 if (tb->ty == Tclass)
361 tc = (TypeClass *)tb;
362 else
363 tc = NULL;
364 if (!tc || !tc->sym->isInterfaceDeclaration())
365 {
366 error("base type must be interface, not %s", b->type->toChars());
367 baseclasses.remove(i);
368 continue;
369 }
370 else
371 {
372 if (tc->sym->isDeprecated())
373 {
374 if (!isDeprecated())
375 {
376 // Deriving from deprecated class makes this one deprecated too
377 isdeprecated = 1;
378
379 tc->checkDeprecated(loc, sc);
380 }
381 }
382
383 // Check for duplicate interfaces
384 for (size_t j = (baseClass ? 1 : 0); j < i; j++)
385 {
386 BaseClass *b2 = (BaseClass *)baseclasses.data[j];
387 if (b2->base == tc->sym)
388 error("inherits from duplicate interface %s", b2->base->toChars());
389 }
390
391 b->base = tc->sym;
392 if (!b->base->symtab || b->base->scope)
393 {
394 //error("forward reference of base class %s", baseClass->toChars());
395 // Forward reference of base, try again later
396 //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
397 scope = scx ? scx : new Scope(*sc);
398 scope->setNoFree();
399 scope->module->addDeferredSemantic(this);
400 return;
401 }
402 }
403 i++;
404 }
405
406
407 // If no base class, and this is not an Object, use Object as base class
408 if (!baseClass && ident != Id::Object)
409 {
410 // BUG: what if Object is redefined in an inner scope?
411 Type *tbase = new TypeIdentifier(0, Id::Object);
412 BaseClass *b;
413 TypeClass *tc;
414 Type *bt;
415
416 if (!object)
417 {
418 error("missing or corrupt object.d");
419 fatal();
420 }
421 bt = tbase->semantic(loc, sc)->toBasetype();
422 b = new BaseClass(bt, PROTpublic);
423 baseclasses.shift(b);
424 assert(b->type->ty == Tclass);
425 tc = (TypeClass *)(b->type);
426 baseClass = tc->sym;
427 assert(!baseClass->isInterfaceDeclaration());
428 b->base = baseClass;
429 }
430
431 interfaces_dim = baseclasses.dim;
432 interfaces = (BaseClass **)baseclasses.data;
433
434
435 if (baseClass)
436 {
437 if (baseClass->storage_class & STCfinal)
438 error("cannot inherit from final class %s", baseClass->toChars());
439
440 interfaces_dim--;
441 interfaces++;
442
443 // Copy vtbl[] from base class
444 vtbl.setDim(baseClass->vtbl.dim);
445 memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim);
446
447 // Inherit properties from base class
448 com = baseClass->isCOMclass();
449 isauto = baseClass->isauto;
450 vthis = baseClass->vthis;
451 storage_class |= baseClass->storage_class & (STCconst | STCinvariant);
452 }
453 else
454 {
455 // No base class, so this is the root of the class hierarchy
456 vtbl.setDim(0);
457 vtbl.push(this); // leave room for classinfo as first member
458 }
459
460 protection = sc->protection;
461 storage_class |= sc->stc;
462
463 if (sizeok == 0)
464 {
465 interfaceSemantic(sc);
466
467 for (i = 0; i < members->dim; i++)
468 {
469 Dsymbol *s = (Dsymbol *)members->data[i];
470 s->addMember(sc, this, 1);
471 }
472
473 /* If this is a nested class, add the hidden 'this'
474 * member which is a pointer to the enclosing scope.
475 */
476 if (vthis) // if inheriting from nested class
477 { // Use the base class's 'this' member
478 isnested = 1;
479 if (storage_class & STCstatic)
480 error("static class cannot inherit from nested class %s", baseClass->toChars());
481 if (toParent2() != baseClass->toParent2())
482 {
483 if (toParent2())
484 {
485 error("is nested within %s, but super class %s is nested within %s",
486 toParent2()->toChars(),
487 baseClass->toChars(),
488 baseClass->toParent2()->toChars());
489 }
490 else
491 {
492 error("is not nested, but super class %s is nested within %s",
493 baseClass->toChars(),
494 baseClass->toParent2()->toChars());
495 }
496 isnested = 0;
497 }
498 }
499 else if (!(storage_class & STCstatic))
500 { Dsymbol *s = toParent2();
501 if (s)
502 {
503 ClassDeclaration *cd = s->isClassDeclaration();
504 FuncDeclaration *fd = s->isFuncDeclaration();
505
506
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
517 {
518 t = new TypePointer(Type::tvoid);
519 t = t->semantic(0, sc);
520 }
521 }
522 else
523 assert(0);
524 assert(!vthis);
525 vthis = new ThisDeclaration(t);
526 members->push(vthis);
527 }
528 }
529 }
530 }
531
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();
540
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->parent = this;
546 sc->inunion = 0;
547
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
559 }
560 else
561 { sc->offset = PTRSIZE * 2; // allow room for __vptr and __monitor
562 alignsize = 4;
563 }
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++)
569 {
570 Dsymbol *s = (Dsymbol *)members->data[i];
571 s->semantic(sc);
572 }
573
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;
581
582 sc = sc->pop();
583
584 scope = scx ? scx : new Scope(*sc);
585 scope->setNoFree();
586 scope->module->addDeferredSemantic(this);
587
588 //printf("\tsemantic('%s') failed due to forward references\n", toChars());
589 return;
590 }
591
592 //printf("\tsemantic('%s') successful\n", toChars());
593
594 structsize = sc->offset;
595 //members->print();
596
597 /* Look for special member functions.
598 * They must be in this class, not in a base class.
599 */
600 ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
601 if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration()))
602 ctor = NULL;
603
604 // dtor = (DtorDeclaration *)search(Id::dtor, 0);
605 // if (dtor && dtor->toParent() != this)
606 // dtor = NULL;
607
608 // inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
609 // if (inv && inv->toParent() != this)
610 // inv = NULL;
611
612 // Can be in base class
613 aggNew = (NewDeclaration *)search(0, Id::classNew, 0);
614 aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
615
616 // If this class has no constructor, but base class does, create
617 // a constructor:
618 // this() { }
619 if (!ctor && baseClass && baseClass->ctor)
620 {
621 //printf("Creating default this(){} for class %s\n", toChars());
622 ctor = new CtorDeclaration(loc, 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;
630 }
631
632 #if 0
633 if (baseClass)
634 { if (!aggDelete)
635 aggDelete = baseClass->aggDelete;
636 if (!aggNew)
637 aggNew = baseClass->aggNew;
638 }
639 #endif
640
641 // Allocate instance of each new interface
642 for (i = 0; i < vtblInterfaces->dim; i++)
643 {
644 BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
645 unsigned thissize = PTRSIZE;
646
647 alignmember(structalign, thissize, &sc->offset);
648 assert(b->offset == 0);
649 b->offset = sc->offset;
650
651 // Take care of single inheritance offsets
652 while (b->baseInterfaces_dim)
653 {
654 b = &b->baseInterfaces[0];
655 b->offset = sc->offset;
656 }
657
658 sc->offset += thissize;
659 if (alignsize < thissize)
660 alignsize = thissize;
661 }
662 structsize = sc->offset;
663 sizeok = 1;
664 Module::dprogress++;
665
666 dtor = buildDtor(sc);
667
668 sc->pop();
669
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++)
673 {
674 BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
675
676 //b->fillVtbl(this, &b->vtbl, 1);
677 }
678 #endif
679 //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
680 }
681
682 void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
683 {
684 if (!isAnonymous())
685 {
686 buf->printf("%s ", kind());
687 buf->writestring(toChars());
688 if (baseclasses.dim)
689 buf->writestring(" : ");
690 }
691 for (int i = 0; i < baseclasses.dim; i++)
692 {
693 BaseClass *b = (BaseClass *)baseclasses.data[i];
694
695 if (i)
696 buf->writeByte(',');
697 //buf->writestring(b->base->ident->toChars());
698 b->type->toCBuffer(buf, NULL, hgs);
699 }
700 buf->writenl();
701 buf->writeByte('{');
702 buf->writenl();
703 for (int i = 0; i < members->dim; i++)
704 {
705 Dsymbol *s = (Dsymbol *)members->data[i];
706
707 buf->writestring(" ");
708 s->toCBuffer(buf, hgs);
709 }
710 buf->writestring("}");
711 buf->writenl();
712 }
713
714 #if 0
715 void ClassDeclaration::defineRef(Dsymbol *s)
716 {
717 ClassDeclaration *cd;
718
719 AggregateDeclaration::defineRef(s);
720 cd = s->isClassDeclaration();
721 baseType = cd->baseType;
722 cd->baseType = NULL;
723 }
724 #endif
725
726 /*********************************************
727 * Determine if 'this' is a base class of cd.
728 * This is used to detect circular inheritance only.
729 */
730
731 int ClassDeclaration::isBaseOf2(ClassDeclaration *cd)
732 {
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];
738
739 if (b->base == this || isBaseOf2(b->base))
740 return 1;
741 }
742 return 0;
743 }
744
745 /*******************************************
746 * Determine if 'this' is a base class of cd.
747 */
748
749 int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
750 {
751 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars());
752 if (poffset)
753 *poffset = 0;
754 while (cd)
755 {
756 if (this == cd->baseClass)
757 return 1;
758
759 /* cd->baseClass might not be set if cd is forward referenced.
760 */
761 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration())
762 {
763 cd->error("base class is forward referenced by %s", toChars());
764 }
765
766 cd = cd->baseClass;
767 }
768 return 0;
769 }
770
771 Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags)
772 {
773 Dsymbol *s;
774
775 //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars());
776 if (scope)
777 semantic(scope);
778
779 if (!members || !symtab || scope)
780 { error("is forward referenced when looking for '%s'", ident->toChars());
781 //*(char*)0=0;
782 return NULL;
783 }
784
785 s = ScopeDsymbol::search(loc, ident, flags);
786 if (!s)
787 {
788 // Search bases classes in depth-first, left to right order
789
790 int i;
791
792 for (i = 0; i < baseclasses.dim; i++)
793 {
794 BaseClass *b = (BaseClass *)baseclasses.data[i];
795
796 if (b->base)
797 {
798 if (!b->base->symtab)
799 error("base %s is forward referenced", b->base->ident->toChars());
800 else
801 {
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;
807 }
808 }
809 }
810 }
811 return s;
812 }
813
814 /**********************************************************
815 * fd is in the vtbl[] for this class.
816 * Return 1 if function is hidden (not findable through search).
817 */
818
819 #if DMDV2
820 int isf(void *param, FuncDeclaration *fd)
821 {
822 //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars());
823 return param == fd;
824 }
825
826 int ClassDeclaration::isFuncHidden(FuncDeclaration *fd)
827 {
828 //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), 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.
834 */
835 return 0;
836 }
837 s = s->toAlias();
838 OverloadSet *os = s->isOverloadSet();
839 if (os)
840 {
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;
846 }
847 return 1;
848 }
849 else
850 {
851 FuncDeclaration *fdstart = s->isFuncDeclaration();
852 //printf("%s fdstart = %p\n", s->kind(), fdstart);
853 return !overloadApply(fdstart, &isf, fd);
854 }
855 }
856 #endif
857
858 /****************
859 * Find virtual function matching identifier and type.
860 * Used to build virtual function tables for interface implementations.
861 */
862
863 FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf)
864 {
865 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars());
866
867 ClassDeclaration *cd = this;
868 Array *vtbl = &cd->vtbl;
869 while (1)
870 {
871 for (size_t i = 0; i < vtbl->dim; i++)
872 {
873 FuncDeclaration *fd = (FuncDeclaration *)vtbl->data[i];
874
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
879 )
880 { //printf("\t\tfound\n");
881 return fd;
882 }
883 //else printf("\t\t%d\n", fd->type->covariant(tf));
884 }
885 if (!cd)
886 break;
887 vtbl = &cd->vtblFinal;
888 cd = cd->baseClass;
889 }
890
891 return NULL;
892 }
893
894 void ClassDeclaration::interfaceSemantic(Scope *sc)
895 {
896 InterfaceDeclaration *id = isInterfaceDeclaration();
897
898 vtblInterfaces = new BaseClasses();
899 vtblInterfaces->reserve(interfaces_dim);
900
901 for (size_t i = 0; i < interfaces_dim; i++)
902 {
903 BaseClass *b = interfaces[i];
904
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;
909
910 if (b->base->isCPPinterface() && id)
911 id->cpp = 1;
912
913 vtblInterfaces->push(b);
914 b->copyBaseInterfaces(vtblInterfaces);
915 }
916 }
917
918 /****************************************
919 */
920
921 int ClassDeclaration::isCOMclass()
922 {
923 return com;
924 }
925
926 int ClassDeclaration::isCOMinterface()
927 {
928 return 0;
929 }
930
931 int ClassDeclaration::isCPPinterface()
932 {
933 return 0;
934 }
935
936
937 /****************************************
938 */
939
940 int ClassDeclaration::isAbstract()
941 {
942 if (isabstract)
943 return TRUE;
944 for (int i = 1; i < vtbl.dim; i++)
945 {
946 FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration();
947
948 //printf("\tvtbl[%d] = %p\n", i, fd);
949 if (!fd || fd->isAbstract())
950 {
951 isabstract |= 1;
952 return TRUE;
953 }
954 }
955 return FALSE;
956 }
957
958
959 /****************************************
960 * Returns !=0 if there's an extra member which is the 'this'
961 * pointer to the enclosing context (enclosing class or function)
962 */
963
964 int ClassDeclaration::isNested()
965 {
966 return isnested;
967 }
968
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.
974 */
975
976 int ClassDeclaration::vtblOffset()
977 {
978 return 1;
979 }
980
981 /****************************************
982 */
983
984 const char *ClassDeclaration::kind()
985 {
986 return "class";
987 }
988
989 /****************************************
990 */
991
992 void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses)
993 {
994 aclasses->push(this);
995 }
996
997 /********************************* InterfaceDeclaration ****************************/
998
999 InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
1000 : ClassDeclaration(loc, id, baseclasses)
1001 {
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
1007 }
1008 }
1009
1010 Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s)
1011 {
1012 InterfaceDeclaration *id;
1013
1014 if (s)
1015 id = (InterfaceDeclaration *)s;
1016 else
1017 id = new InterfaceDeclaration(loc, ident, NULL);
1018
1019 ClassDeclaration::syntaxCopy(id);
1020 return id;
1021 }
1022
1023 void InterfaceDeclaration::semantic(Scope *sc)
1024 { int i;
1025
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);
1032 }
1033 if (!members) // if forward reference
1034 { //printf("\tinterface '%s' is forward referenced\n", toChars());
1035 return;
1036 }
1037 if (symtab) // if already done
1038 { if (!scope)
1039 return;
1040 }
1041 else
1042 symtab = new DsymbolTable();
1043
1044 Scope *scx = NULL;
1045 if (scope)
1046 { sc = scope;
1047 scx = scope; // save so we don't make redundant copies
1048 scope = NULL;
1049 }
1050
1051 if (sc->stc & STCdeprecated)
1052 {
1053 isdeprecated = 1;
1054 }
1055
1056 // Expand any tuples in baseclasses[]
1057 for (i = 0; i < baseclasses.dim; )
1058 { BaseClass *b = (BaseClass *)baseclasses.data[0];
1059 b->type = b->type->semantic(loc, sc);
1060 Type *tb = b->type->toBasetype();
1061
1062 if (tb->ty == Ttuple)
1063 { TypeTuple *tup = (TypeTuple *)tb;
1064 enum PROT protection = b->protection;
1065 baseclasses.remove(i);
1066 size_t dim = Argument::dim(tup->arguments);
1067 for (size_t j = 0; j < dim; j++)
1068 { Argument *arg = Argument::getNth(tup->arguments, j);
1069 b = new BaseClass(arg->type, protection);
1070 baseclasses.insert(i + j, b);
1071 }
1072 }
1073 else
1074 i++;
1075 }
1076
1077 if (!baseclasses.dim && sc->linkage == LINKcpp)
1078 cpp = 1;
1079
1080 // Check for errors, handle forward references
1081 for (i = 0; i < baseclasses.dim; )
1082 { TypeClass *tc;
1083 BaseClass *b;
1084 Type *tb;
1085
1086 b = (BaseClass *)baseclasses.data[i];
1087 b->type = b->type->semantic(loc, sc);
1088 tb = b->type->toBasetype();
1089 if (tb->ty == Tclass)
1090 tc = (TypeClass *)tb;
1091 else
1092 tc = NULL;
1093 if (!tc || !tc->sym->isInterfaceDeclaration())
1094 {
1095 error("base type must be interface, not %s", b->type->toChars());
1096 baseclasses.remove(i);
1097 continue;
1098 }
1099 else
1100 {
1101 // Check for duplicate interfaces
1102 for (size_t j = 0; j < i; j++)
1103 {
1104 BaseClass *b2 = (BaseClass *)baseclasses.data[j];
1105 if (b2->base == tc->sym)
1106 error("inherits from duplicate interface %s", b2->base->toChars());
1107 }
1108
1109 b->base = tc->sym;
1110 if (b->base == this || isBaseOf2(b->base))
1111 {
1112 error("circular inheritance of interface");
1113 baseclasses.remove(i);
1114 continue;
1115 }
1116 if (!b->base->symtab || b->base->scope || b->base->inuse)
1117 {
1118 //error("forward reference of base class %s", baseClass->toChars());
1119 // Forward reference of base, try again later
1120 //printf("\ttry later, forward reference of base %s\n", b->base->toChars());
1121 scope = scx ? scx : new Scope(*sc);
1122 scope->setNoFree();
1123 scope->module->addDeferredSemantic(this);
1124 return;
1125 }
1126 }
1127 #if 0
1128 // Inherit const/invariant from base class
1129 storage_class |= b->base->storage_class & (STCconst | STCinvariant);
1130 #endif
1131 i++;
1132 }
1133
1134 interfaces_dim = baseclasses.dim;
1135 interfaces = (BaseClass **)baseclasses.data;
1136
1137 interfaceSemantic(sc);
1138
1139 if (vtblOffset())
1140 vtbl.push(this); // leave room at vtbl[0] for classinfo
1141
1142 // Cat together the vtbl[]'s from base interfaces
1143 for (i = 0; i < interfaces_dim; i++)
1144 { BaseClass *b = interfaces[i];
1145
1146 // Skip if b has already appeared
1147 for (int k = 0; k < i; k++)
1148 {
1149 if (b == interfaces[i])
1150 goto Lcontinue;
1151 }
1152
1153 // Copy vtbl[] from base class
1154 if (b->base->vtblOffset())
1155 { int d = b->base->vtbl.dim;
1156 if (d > 1)
1157 {
1158 vtbl.reserve(d - 1);
1159 for (int j = 1; j < d; j++)
1160 vtbl.push(b->base->vtbl.data[j]);
1161 }
1162 }
1163 else
1164 {
1165 vtbl.append(&b->base->vtbl);
1166 }
1167
1168 Lcontinue:
1169 ;
1170 }
1171
1172 protection = sc->protection;
1173 storage_class |= sc->stc & (STCconst | STCinvariant);
1174
1175 for (i = 0; i < members->dim; i++)
1176 {
1177 Dsymbol *s = (Dsymbol *)members->data[i];
1178 s->addMember(sc, this, 1);
1179 }
1180
1181 sc = sc->push(this);
1182 sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
1183 STCabstract | STCdeprecated | STCconst | STCinvariant | STCtls);
1184 sc->stc |= storage_class & (STCconst | STCinvariant);
1185 sc->parent = this;
1186 if (isCOMinterface())
1187 sc->linkage = LINKwindows;
1188 else if (isCPPinterface())
1189 sc->linkage = LINKcpp;
1190 sc->structalign = 8;
1191 structalign = sc->structalign;
1192 sc->offset = PTRSIZE * 2;
1193 inuse++;
1194 for (i = 0; i < members->dim; i++)
1195 {
1196 Dsymbol *s = (Dsymbol *)members->data[i];
1197 s->semantic(sc);
1198 }
1199 inuse--;
1200 //members->print();
1201 sc->pop();
1202 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type);
1203 }
1204
1205
1206 /*******************************************
1207 * Determine if 'this' is a base class of cd.
1208 * (Actually, if it is an interface supported by cd)
1209 * Output:
1210 * *poffset offset to start of class
1211 * OFFSET_RUNTIME must determine offset at runtime
1212 * Returns:
1213 * 0 not a base
1214 * 1 is a base
1215 */
1216
1217 int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset)
1218 {
1219 unsigned j;
1220
1221 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars());
1222 assert(!baseClass);
1223 for (j = 0; j < cd->interfaces_dim; j++)
1224 {
1225 BaseClass *b = cd->interfaces[j];
1226
1227 //printf("\tbase %s\n", b->base->toChars());
1228 if (this == b->base)
1229 {
1230 //printf("\tfound at offset %d\n", b->offset);
1231 if (poffset)
1232 { *poffset = b->offset;
1233 if (j && cd->isInterfaceDeclaration())
1234 *poffset = OFFSET_RUNTIME;
1235 }
1236 return 1;
1237 }
1238 if (isBaseOf(b, poffset))
1239 { if (j && poffset && cd->isInterfaceDeclaration())
1240 *poffset = OFFSET_RUNTIME;
1241 return 1;
1242 }
1243 }
1244
1245 if (cd->baseClass && isBaseOf(cd->baseClass, poffset))
1246 return 1;
1247
1248 if (poffset)
1249 *poffset = 0;
1250 return 0;
1251 }
1252
1253
1254 int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset)
1255 {
1256 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars());
1257 for (unsigned j = 0; j < bc->baseInterfaces_dim; j++)
1258 {
1259 BaseClass *b = &bc->baseInterfaces[j];
1260
1261 if (this == b->base)
1262 {
1263 if (poffset)
1264 { *poffset = b->offset;
1265 }
1266 return 1;
1267 }
1268 if (isBaseOf(b, poffset))
1269 {
1270 return 1;
1271 }
1272 }
1273 if (poffset)
1274 *poffset = 0;
1275 return 0;
1276 }
1277
1278 /****************************************
1279 * Determine if slot 0 of the vtbl[] is reserved for something else.
1280 * For class objects, yes, this is where the ClassInfo ptr goes.
1281 * For COM interfaces, no.
1282 * For non-COM interfaces, yes, this is where the Interface ptr goes.
1283 */
1284
1285 int InterfaceDeclaration::vtblOffset()
1286 {
1287 if (isCOMinterface() || isCPPinterface())
1288 return 0;
1289 return 1;
1290 }
1291
1292 int InterfaceDeclaration::isCOMinterface()
1293 {
1294 return com;
1295 }
1296
1297 int InterfaceDeclaration::isCPPinterface()
1298 {
1299 return cpp;
1300 }
1301
1302 /*******************************************
1303 */
1304
1305 const char *InterfaceDeclaration::kind()
1306 {
1307 return "interface";
1308 }
1309
1310
1311 /******************************** BaseClass *****************************/
1312
1313 BaseClass::BaseClass()
1314 {
1315 memset(this, 0, sizeof(BaseClass));
1316 }
1317
1318 BaseClass::BaseClass(Type *type, enum PROT protection)
1319 {
1320 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars());
1321 this->type = type;
1322 this->protection = protection;
1323 base = NULL;
1324 offset = 0;
1325
1326 baseInterfaces_dim = 0;
1327 baseInterfaces = NULL;
1328 }
1329
1330 /****************************************
1331 * Fill in vtbl[] for base class based on member functions of class cd.
1332 * Input:
1333 * vtbl if !=NULL, fill it in
1334 * newinstance !=0 means all entries must be filled in by members
1335 * of cd, not members of any base classes of cd.
1336 * Returns:
1337 * !=0 if any entries were filled in by members of cd (not exclusively
1338 * by base classes)
1339 */
1340
1341 int BaseClass::fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance)
1342 {
1343 ClassDeclaration *id = base;
1344 int j;
1345 int result = 0;
1346
1347 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars());
1348 if (vtbl)
1349 vtbl->setDim(base->vtbl.dim);
1350
1351 // first entry is ClassInfo reference
1352 for (j = base->vtblOffset(); j < base->vtbl.dim; j++)
1353 {
1354 FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration();
1355 FuncDeclaration *fd;
1356 TypeFunction *tf;
1357
1358 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null");
1359
1360 assert(ifd);
1361 // Find corresponding function in this class
1362 tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL;
1363 fd = cd->findFunc(ifd->ident, tf);
1364 if (fd && !fd->isAbstract())
1365 {
1366 //printf(" found\n");
1367 // Check that calling conventions match
1368 if (fd->linkage != ifd->linkage)
1369 fd->error("linkage doesn't match interface function");
1370
1371 // Check that it is current
1372 if (newinstance &&
1373 fd->toParent() != cd &&
1374 ifd->toParent() == base)
1375 cd->error("interface function %s.%s is not implemented",
1376 id->toChars(), ifd->ident->toChars());
1377
1378 if (fd->toParent() == cd)
1379 result = 1;
1380 }
1381 else
1382 {
1383 //printf(" not found\n");
1384 // BUG: should mark this class as abstract?
1385 if (!cd->isAbstract())
1386 cd->error("interface function %s.%s isn't implemented",
1387 id->toChars(), ifd->ident->toChars());
1388 fd = NULL;
1389 }
1390 if (vtbl)
1391 vtbl->data[j] = fd;
1392 }
1393
1394 return result;
1395 }
1396
1397 void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces)
1398 {
1399 //printf("+copyBaseInterfaces(), %s\n", base->toChars());
1400 // if (baseInterfaces_dim)
1401 // return;
1402
1403 baseInterfaces_dim = base->interfaces_dim;
1404 baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass));
1405
1406 //printf("%s.copyBaseInterfaces()\n", base->toChars());
1407 for (int i = 0; i < baseInterfaces_dim; i++)
1408 {
1409 BaseClass *b = &baseInterfaces[i];
1410 BaseClass *b2 = base->interfaces[i];
1411
1412 assert(b2->vtbl.dim == 0); // should not be filled yet
1413 memcpy(b, b2, sizeof(BaseClass));
1414
1415 if (i) // single inheritance is i==0
1416 vtblInterfaces->push(b); // only need for M.I.
1417 b->copyBaseInterfaces(vtblInterfaces);
1418 }
1419 //printf("-copyBaseInterfaces\n");
1420 }