root/branches/tango/rebuild/class.c

Revision 796, 30.4 kB (checked in by Gregor, 1 year ago)

MERGE: trunk r795

Line 
1 // Compiler implementation of the D programming language
2 // Copyright (c) 1999-2006 by Digital Mars
3 // All Rights Reserved
4 // written by Walter Bright
5 // http://www.digitalmars.com
6 // License for redistribution is by either the Artistic License
7 // in artistic.txt, or the GNU General Public License in gnu.txt.
8 // See the included readme.txt for details.
9
10 #include <stdio.h>
11 #include <stdlib.h>
12 #include <assert.h>
13
14 #include "root.h"
15 #include "mem.h"
16
17 #include "enum.h"
18 #include "init.h"
19 #include "attrib.h"
20 #include "declaration.h"
21 #include "aggregate.h"
22 #include "id.h"
23 #include "mtype.h"
24 #include "scope.h"
25 #include "module.h"
26 #include "expression.h"
27 #include "statement.h"
28
29 /********************************* ClassDeclaration ****************************/
30
31 ClassDeclaration *ClassDeclaration::classinfo;
32 ClassDeclaration *ClassDeclaration::object;
33
34 ClassDeclaration::ClassDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses)
35     : AggregateDeclaration(loc, id)
36 {
37     static char msg[] = "only object.d can define this reserved class name";
38
39     if (baseclasses)
40     this->baseclasses = *baseclasses;
41     baseClass = NULL;
42
43     interfaces_dim = 0;
44     interfaces = NULL;
45
46     vtblInterfaces = NULL;
47
48     //printf("ClassDeclaration(%s), dim = %d\n", id->toChars(), this->baseclasses.dim);
49
50     // For forward references
51     type = new TypeClass(this);
52     handle = type;
53
54     ctor = NULL;
55     defaultCtor = NULL;
56     staticCtor = NULL;
57     staticDtor = NULL;
58
59     vtblsym = NULL;
60     vclassinfo = NULL;
61
62     if (id)
63     {   // Look for special class names
64
65     /*if (id == Id::__sizeof || id == Id::alignof || id == Id::mangleof)
66         error("illegal class name");*/
67
68     // BUG: What if this is the wrong TypeInfo, i.e. it is nested?
69     if (id->toChars()[0] == 'T')
70     {
71         if (id == Id::TypeInfo)
72         {   if (Type::typeinfo)
73             Type::typeinfo->error("%s", msg);
74         Type::typeinfo = this;
75         }
76
77         if (id == Id::TypeInfo_Class)
78         {   if (Type::typeinfoclass)
79             Type::typeinfoclass->error("%s", msg);
80         Type::typeinfoclass = this;
81         }
82
83         if (id == Id::TypeInfo_Interface)
84         {   if (Type::typeinfointerface)
85             Type::typeinfointerface->error("%s", msg);
86         Type::typeinfointerface = this;
87         }
88
89         if (id == Id::TypeInfo_Struct)
90         {   if (Type::typeinfostruct)
91             Type::typeinfostruct->error("%s", msg);
92         Type::typeinfostruct = this;
93         }
94
95         if (id == Id::TypeInfo_Typedef)
96         {   if (Type::typeinfotypedef)
97             Type::typeinfotypedef->error("%s", msg);
98         Type::typeinfotypedef = this;
99         }
100
101         if (id == Id::TypeInfo_Pointer)
102         {   if (Type::typeinfopointer)
103             Type::typeinfopointer->error("%s", msg);
104         Type::typeinfopointer = this;
105         }
106
107         if (id == Id::TypeInfo_Array)
108         {   if (Type::typeinfoarray)
109             Type::typeinfoarray->error("%s", msg);
110         Type::typeinfoarray = this;
111         }
112
113         if (id == Id::TypeInfo_StaticArray)
114         {   //if (Type::typeinfostaticarray)
115             //Type::typeinfostaticarray->error("%s", msg);
116         Type::typeinfostaticarray = this;
117         }
118
119         if (id == Id::TypeInfo_AssociativeArray)
120         {   if (Type::typeinfoassociativearray)
121             Type::typeinfoassociativearray->error("%s", msg);
122         Type::typeinfoassociativearray = this;
123         }
124
125         if (id == Id::TypeInfo_Enum)
126         {   if (Type::typeinfoenum)
127             Type::typeinfoenum->error("%s", msg);
128         Type::typeinfoenum = this;
129         }
130
131         if (id == Id::TypeInfo_Function)
132         {   if (Type::typeinfofunction)
133             Type::typeinfofunction->error("%s", msg);
134         Type::typeinfofunction = this;
135         }
136
137         if (id == Id::TypeInfo_Delegate)
138         {   if (Type::typeinfodelegate)
139             Type::typeinfodelegate->error("%s", msg);
140         Type::typeinfodelegate = this;
141         }
142
143         if (id == Id::TypeInfo_Tuple)
144         {   if (Type::typeinfotypelist)
145             Type::typeinfotypelist->error("%s", msg);
146         Type::typeinfotypelist = this;
147         }
148
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     }
161
162     if (id == Id::Object)
163     {   if (object)
164         object->error("%s", msg);
165         object = this;
166     }
167
168     if (id == Id::ClassInfo)
169     {   if (classinfo)
170         classinfo->error("%s", msg);
171         classinfo = this;
172     }
173
174     if (id == Id::ModuleInfo)
175     {   if (Module::moduleinfo)
176         Module::moduleinfo->error("%s", msg);
177         Module::moduleinfo = this;
178     }
179     }
180
181     com = 0;
182 #if 0
183     if (id == Id::IUnknown)     // IUnknown is the root of all COM objects
184     com = 1;
185 #endif
186     isauto = 0;
187     isabstract = 0;
188     isnested = 0;
189     vthis = NULL;
190 }
191
192 Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
193 {
194     ClassDeclaration *cd;
195
196     //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
197     if (s)
198     cd = (ClassDeclaration *)s;
199     else
200     cd = new ClassDeclaration(loc, ident, NULL);
201
202     cd->storage_class |= storage_class;
203
204     cd->baseclasses.setDim(this->baseclasses.dim);
205     for (int i = 0; i < cd->baseclasses.dim; i++)
206     {
207     BaseClass *b = (BaseClass *)this->baseclasses.data[i];
208     BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
209     cd->baseclasses.data[i] = b2;
210     }
211
212     ScopeDsymbol::syntaxCopy(cd);
213     return cd;
214 }
215
216 void ClassDeclaration::semantic(Scope *sc)
217 {   int i;
218     unsigned offset;
219
220     //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
221     //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
222     //printf("sc->stc = %x\n", sc->stc);
223
224     //{ static int n;  if (++n == 20) *(char*)0=0; }
225
226     if (!ident)     // if anonymous class
227     {   char *id = "__anonclass";
228
229     ident = Identifier::generateId(id);
230     }
231
232     if (!scope)
233     {
234     if (!parent && sc->parent && !sc->parent->isModule())
235         parent = sc->parent;
236
237     type = type->semantic(loc, sc);
238     handle = handle->semantic(loc, sc);
239     }
240     if (!members)           // if forward reference
241     {   //printf("\tclass '%s' is forward referenced\n", toChars());
242     return;
243     }
244     if (symtab)
245     {   if (!scope)
246     {   //printf("\tsemantic for '%s' is already completed\n", toChars());
247         return;     // semantic() already completed
248     }
249     }
250     else
251     symtab = new DsymbolTable();
252
253     Scope *scx = NULL;
254     if (scope)
255     {   sc = scope;
256     scx = scope;        // save so we don't make redundant copies
257     scope = NULL;
258     }
259 #ifdef IN_GCC
260     methods.setDim(0);
261 #endif
262
263     // Expand any tuples in baseclasses[]
264     for (i = 0; i < baseclasses.dim; )
265     {   BaseClass *b = (BaseClass *)baseclasses.data[i];
266     b->type = b->type->semantic(loc, sc);
267     Type *tb = b->type->toBasetype();
268
269     if (tb->ty == Ttuple)
270     {   TypeTuple *tup = (TypeTuple *)tb;
271         enum PROT protection = b->protection;
272         baseclasses.remove(i);
273         size_t dim = Argument::dim(tup->arguments);
274         for (size_t j = 0; j < dim; j++)
275         {   Argument *arg = Argument::getNth(tup->arguments, j);
276         b = new BaseClass(arg->type, protection);
277         baseclasses.insert(i + j, b);
278         }
279     }
280     else
281         i++;
282     }
283
284     // See if there's a base class as first in baseclasses[]
285     if (baseclasses.dim)
286     {   TypeClass *tc;
287     BaseClass *b;
288     Type *tb;
289
290     b = (BaseClass *)baseclasses.data[0];
291     //b->type = b->type->semantic(loc, sc);
292     tb = b->type->toBasetype();
293     if (tb->ty != Tclass)
294     {   //error("base type must be class or interface, not %s", b->type->toChars());
295         baseclasses.remove(0);
296     }
297     else
298     {
299         tc = (TypeClass *)(tb);
300         if (tc->sym->isInterfaceDeclaration())
301         ;
302         else
303         {
304         for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
305         {
306             if (cdb == this)
307             {
308             //error("circular inheritance");
309             baseclasses.remove(0);
310             goto L7;
311             }
312         }
313         if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
314         {
315             //error("forward reference of base class %s", baseClass->toChars());
316             // Forward reference of base class, try again later
317             //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
318             scope = scx ? scx : new Scope(*sc);
319             scope->setNoFree();
320             scope->module->addDeferredSemantic(this);
321             return;
322         }
323         else
324         {   baseClass = tc->sym;
325             b->base = baseClass;
326         }
327          L7: ;
328         }
329     }
330     }
331
332     // Treat the remaining entries in baseclasses as interfaces
333     // Check for errors, handle forward references
334     for (i = (baseClass ? 1 : 0); i < baseclasses.dim; )
335     {   TypeClass *tc;
336     BaseClass *b;
337     Type *tb;
338
339     b = (BaseClass *)baseclasses.data[i];
340     b->type = b->type->semantic(loc, sc);
341     tb = b->type->toBasetype();
342     if (tb->ty == Tclass)
343         tc = (TypeClass *)tb;
344     else
345         tc = NULL;
346     if (!tc || !tc->sym->isInterfaceDeclaration())
347     {
348         //error("base type must be interface, not %s", b->type->toChars());
349         baseclasses.remove(i);
350         continue;
351     }
352     else
353     {
354         // Check for duplicate interfaces
355         for (size_t j = (baseClass ? 1 : 0); j < i; j++)
356         {
357         BaseClass *b2 = (BaseClass *)baseclasses.data[j];
358         /*if (b2->base == tc->sym)
359             error("inherits from duplicate interface %s", b2->base->toChars()); */
360         }
361
362         b->base = tc->sym;
363         if (!b->base->symtab || b->base->scope)
364         {
365         //error("forward reference of base class %s", baseClass->toChars());
366         // Forward reference of base, try again later
367         //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
368         scope = scx ? scx : new Scope(*sc);
369         scope->setNoFree();
370         scope->module->addDeferredSemantic(this);
371         return;
372         }
373     }
374     i++;
375     }
376
377
378     // If no base class, and this is not an Object, use Object as base class
379     if (!baseClass && ident != Id::Object)
380     {
381     // BUG: what if Object is redefined in an inner scope?
382     Type *tbase = new TypeIdentifier(0, Id::Object);
383     BaseClass *b;
384     TypeClass *tc;
385     Type *bt;
386
387     if (!object)
388     {
389         //error("missing or corrupt object.d");
390         fatal();
391     }
392     bt = tbase->semantic(loc, sc)->toBasetype();
393     b = new BaseClass(bt, PROTpublic);
394     baseclasses.shift(b);
395     assert(b->type->ty == Tclass);
396     tc = (TypeClass *)(b->type);
397     baseClass = tc->sym;
398     assert(!baseClass->isInterfaceDeclaration());
399     b->base = baseClass;
400     }
401
402     interfaces_dim = baseclasses.dim;
403     interfaces = (BaseClass **)baseclasses.data;
404
405
406     if (baseClass)
407     {
408     /* if (baseClass->storage_class & STCfinal)
409         error("cannot inherit from final class %s", baseClass->toChars()); */
410
411     interfaces_dim--;
412     interfaces++;
413
414     // Copy vtbl[] from base class
415     vtbl.setDim(baseClass->vtbl.dim);
416     memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim);
417
418     // Inherit properties from base class
419     com = baseClass->isCOMclass();
420     isauto = baseClass->isauto;
421     vthis = baseClass->vthis;
422     }
423     else
424     {
425     // No base class, so this is the root of the class hierarchy
426     vtbl.setDim(0);
427     vtbl.push(this);        // leave room for classinfo as first member
428     }
429
430     protection = sc->protection;
431     storage_class |= sc->stc;
432
433     if (sizeok == 0)
434     {
435     interfaceSemantic(sc);
436
437     for (i = 0; i < members->dim; i++)
438     {
439         Dsymbol *s = (Dsymbol *)members->data[i];
440         s->addMember(sc, this, 1);
441     }
442
443     /* If this is a nested class, add the hidden 'this'
444      * member which is a pointer to the enclosing scope.
445      */
446     if (vthis)      // if inheriting from nested class
447     {   // Use the base class's 'this' member
448         isnested = 1;
449         /*if (storage_class & STCstatic)
450         error("static class cannot inherit from nested class %s", baseClass->toChars());
451         if (toParent2() != baseClass->toParent2())
452         error("super class %s is nested within %s, not %s",
453             baseClass->toChars(),
454             baseClass->toParent2()->toChars(),
455             toParent2()->toChars());*/
456     }
457     else if (!(storage_class & STCstatic))
458     {   Dsymbol *s = toParent2();
459         if (s)
460         {
461         ClassDeclaration *cd = s->isClassDeclaration();
462         FuncDeclaration *fd = s->isFuncDeclaration();
463
464
465         if (cd || fd)
466         {   isnested = 1;
467             Type *t;
468             if (cd)
469             t = cd->type;
470             else if (fd)
471             {   AggregateDeclaration *ad = fd->isMember2();
472             if (ad)
473                 t = ad->handle;
474             else
475             {
476                 t = new TypePointer(Type::tvoid);
477                 t = t->semantic(0, sc);
478             }
479             }
480             else
481             assert(0);
482             assert(!vthis);
483             vthis = new ThisDeclaration(t);
484             members->push(vthis);
485         }
486         }
487     }
488     }
489
490     if (storage_class & (STCauto | STCscope))
491     isauto = 1;
492     if (storage_class & STCabstract)
493     isabstract = 1;
494     if (storage_class & STCdeprecated)
495     isdeprecated = 1;
496
497     sc = sc->push(this);
498     sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
499          STCabstract | STCdeprecated);
500     sc->parent = this;
501     sc->inunion = 0;
502
503     if (isCOMclass())
504     sc->linkage = LINKwindows;
505     sc->protection = PROTpublic;
506     sc->explicitProtection = 0;
507     sc->structalign = 8;
508     structalign = sc->structalign;
509     if (baseClass)
510     {   sc->offset = baseClass->structsize;
511     alignsize = baseClass->alignsize;
512 //  if (isnested)
513 //      sc->offset += PTRSIZE;  // room for uplevel context pointer
514     }
515     else
516     {   sc->offset = 8;     // allow room for vptr[] and monitor
517     alignsize = 4;
518     }
519     structsize = sc->offset;
520     Scope scsave = *sc;
521     int members_dim = members->dim;
522     sizeok = 0;
523     for (i = 0; i < members_dim; i++)
524     {
525     Dsymbol *s = (Dsymbol *)members->data[i];
526     s->semantic(sc);
527     }
528
529     if (sizeok == 2)
530     {   // semantic() failed because of forward references.
531     // Unwind what we did, and defer it for later
532     fields.setDim(0);
533     structsize = 0;
534     alignsize = 0;
535     structalign = 0;
536
537     sc = sc->pop();
538
539     scope = scx ? scx : new Scope(*sc);
540     scope->setNoFree();
541     scope->module->addDeferredSemantic(this);
542
543     //printf("\tsemantic('%s') failed\n", toChars());
544     return;
545     }
546
547     //printf("\tsemantic('%s') successful\n", toChars());
548
549     structsize = sc->offset;
550     //members->print();
551
552     /* Look for special member functions.
553      * They must be in this class, not in a base class.
554      */
555     ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
556     if (ctor && ctor->toParent() != this)
557     ctor = NULL;
558
559 //    dtor = (DtorDeclaration *)search(Id::dtor, 0);
560 //    if (dtor && dtor->toParent() != this)
561 //  dtor = NULL;
562
563 //    inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
564 //    if (inv && inv->toParent() != this)
565 //  inv = NULL;
566
567     // Can be in base class
568     aggNew    = (NewDeclaration *)search(0, Id::classNew, 0);
569     aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
570
571     // If this class has no constructor, but base class does, create
572     // a constructor:
573     //    this() { }
574     if (!ctor && baseClass && baseClass->ctor)
575     {
576     //printf("Creating default this(){} for class %s\n", toChars());
577     ctor = new CtorDeclaration(0, 0, NULL, 0);
578     ctor->fbody = new CompoundStatement(0, new Statements());
579     members->push(ctor);
580     ctor->addMember(sc, this, 1);
581     *sc = scsave;   // why? What about sc->nofree?
582     sc->offset = structsize;
583     ctor->semantic(sc);
584     defaultCtor = ctor;
585     }
586
587 #if 0
588     if (baseClass)
589     {   if (!aggDelete)
590         aggDelete = baseClass->aggDelete;
591     if (!aggNew)
592         aggNew = baseClass->aggNew;
593     }
594 #endif
595
596     // Allocate instance of each new interface
597     for (i = 0; i < vtblInterfaces->dim; i++)
598     {
599     BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
600     unsigned thissize = PTRSIZE;
601
602     alignmember(structalign, thissize, &sc->offset);
603     assert(b->offset == 0);
604     b->offset = sc->offset;
605
606     // Take care of single inheritance offsets
607     while (b->baseInterfaces_dim)
608     {
609         b = &b->baseInterfaces[0];
610         b->offset = sc->offset;
611     }
612
613     sc->offset += thissize;
614     if (alignsize < thissize)
615         alignsize = thissize;
616     }
617     structsize = sc->offset;
618     sizeok = 1;
619     Module::dprogress++;
620
621
622     sc->pop();
623
624 #if 0 // Do not call until toObjfile() because of forward references
625     // Fill in base class vtbl[]s
626     for (i = 0; i < vtblInterfaces->dim; i++)
627     {
628     BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
629
630     //b->fillVtbl(this, &b->vtbl, 1);
631     }
632 #endif
633     //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
634 }
635
636 void ClassDeclaration::toCBuffer(OutBuffer *buf