root/branches/dmdfe/class.c

Revision 659, 30.0 kB (checked in by Gregor, 1 year ago)

MERGE: DMD 1.018

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
150     if (id == Id::Object)
151     {   if (object)
152         object->error("%s", msg);
153         object = this;
154     }
155
156     if (id == Id::ClassInfo)
157     {   if (classinfo)
158         classinfo->error("%s", msg);
159         classinfo = this;
160     }
161
162     if (id == Id::ModuleInfo)
163     {   if (Module::moduleinfo)
164         Module::moduleinfo->error("%s", msg);
165         Module::moduleinfo = this;
166     }
167     }
168
169     com = 0;
170 #if 0
171     if (id == Id::IUnknown)     // IUnknown is the root of all COM objects
172     com = 1;
173 #endif
174     isauto = 0;
175     isabstract = 0;
176     isnested = 0;
177     vthis = NULL;
178 }
179
180 Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s)
181 {
182     ClassDeclaration *cd;
183
184     //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars());
185     if (s)
186     cd = (ClassDeclaration *)s;
187     else
188     cd = new ClassDeclaration(loc, ident, NULL);
189
190     cd->storage_class |= storage_class;
191
192     cd->baseclasses.setDim(this->baseclasses.dim);
193     for (int i = 0; i < cd->baseclasses.dim; i++)
194     {
195     BaseClass *b = (BaseClass *)this->baseclasses.data[i];
196     BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection);
197     cd->baseclasses.data[i] = b2;
198     }
199
200     ScopeDsymbol::syntaxCopy(cd);
201     return cd;
202 }
203
204 void ClassDeclaration::semantic(Scope *sc)
205 {   int i;
206     unsigned offset;
207
208     //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this);
209     //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : "");
210     //printf("sc->stc = %x\n", sc->stc);
211
212     //{ static int n;  if (++n == 20) *(char*)0=0; }
213
214     if (!ident)     // if anonymous class
215     {   char *id = "__anonclass";
216
217     ident = Identifier::generateId(id);
218     }
219
220     if (!scope)
221     {
222     if (!parent && sc->parent && !sc->parent->isModule())
223         parent = sc->parent;
224
225     type = type->semantic(loc, sc);
226     handle = handle->semantic(loc, sc);
227     }
228     if (!members)           // if forward reference
229     {   //printf("\tclass '%s' is forward referenced\n", toChars());
230     return;
231     }
232     if (symtab)
233     {   if (!scope)
234     {   //printf("\tsemantic for '%s' is already completed\n", toChars());
235         return;     // semantic() already completed
236     }
237     }
238     else
239     symtab = new DsymbolTable();
240
241     Scope *scx = NULL;
242     if (scope)
243     {   sc = scope;
244     scx = scope;        // save so we don't make redundant copies
245     scope = NULL;
246     }
247 #ifdef IN_GCC
248     methods.setDim(0);
249 #endif
250
251     // Expand any tuples in baseclasses[]
252     for (i = 0; i < baseclasses.dim; )
253     {   BaseClass *b = (BaseClass *)baseclasses.data[i];
254     b->type = b->type->semantic(loc, sc);
255     Type *tb = b->type->toBasetype();
256
257     if (tb->ty == Ttuple)
258     {   TypeTuple *tup = (TypeTuple *)tb;
259         enum PROT protection = b->protection;
260         baseclasses.remove(i);
261         size_t dim = Argument::dim(tup->arguments);
262         for (size_t j = 0; j < dim; j++)
263         {   Argument *arg = Argument::getNth(tup->arguments, j);
264         b = new BaseClass(arg->type, protection);
265         baseclasses.insert(i + j, b);
266         }
267     }
268     else
269         i++;
270     }
271
272     // See if there's a base class as first in baseclasses[]
273     if (baseclasses.dim)
274     {   TypeClass *tc;
275     BaseClass *b;
276     Type *tb;
277
278     b = (BaseClass *)baseclasses.data[0];
279     //b->type = b->type->semantic(loc, sc);
280     tb = b->type->toBasetype();
281     if (tb->ty != Tclass)
282     {   error("base type must be class or interface, not %s", b->type->toChars());
283         baseclasses.remove(0);
284     }
285     else
286     {
287         tc = (TypeClass *)(tb);
288         if (tc->sym->isInterfaceDeclaration())
289         ;
290         else
291         {
292         for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass)
293         {
294             if (cdb == this)
295             {
296             error("circular inheritance");
297             baseclasses.remove(0);
298             goto L7;
299             }
300         }
301         if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0)
302         {
303             //error("forward reference of base class %s", baseClass->toChars());
304             // Forward reference of base class, try again later
305             //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars());
306             scope = scx ? scx : new Scope(*sc);
307             scope->setNoFree();
308             scope->module->addDeferredSemantic(this);
309             return;
310         }
311         else
312         {   baseClass = tc->sym;
313             b->base = baseClass;
314         }
315          L7: ;
316         }
317     }
318     }
319
320     // Treat the remaining entries in baseclasses as interfaces
321     // Check for errors, handle forward references
322     for (i = (baseClass ? 1 : 0); i < baseclasses.dim; )
323     {   TypeClass *tc;
324     BaseClass *b;
325     Type *tb;
326
327     b = (BaseClass *)baseclasses.data[i];
328     b->type = b->type->semantic(loc, sc);
329     tb = b->type->toBasetype();
330     if (tb->ty == Tclass)
331         tc = (TypeClass *)tb;
332     else
333         tc = NULL;
334     if (!tc || !tc->sym->isInterfaceDeclaration())
335     {
336         error("base type must be interface, not %s", b->type->toChars());
337         baseclasses.remove(i);
338         continue;
339     }
340     else
341     {
342         // Check for duplicate interfaces
343         for (size_t j = (baseClass ? 1 : 0); j < i; j++)
344         {
345         BaseClass *b2 = (BaseClass *)baseclasses.data[j];
346         if (b2->base == tc->sym)
347             error("inherits from duplicate interface %s", b2->base->toChars());
348         }
349
350         b->base = tc->sym;
351         if (!b->base->symtab || b->base->scope)
352         {
353         //error("forward reference of base class %s", baseClass->toChars());
354         // Forward reference of base, try again later
355         //printf("\ttry later, forward reference of base %s\n", baseClass->toChars());
356         scope = scx ? scx : new Scope(*sc);
357         scope->setNoFree();
358         scope->module->addDeferredSemantic(this);
359         return;
360         }
361     }
362     i++;
363     }
364
365
366     // If no base class, and this is not an Object, use Object as base class
367     if (!baseClass && ident != Id::Object)
368     {
369     // BUG: what if Object is redefined in an inner scope?
370     Type *tbase = new TypeIdentifier(0, Id::Object);
371     BaseClass *b;
372     TypeClass *tc;
373     Type *bt;
374
375     if (!object)
376     {
377         error("missing or corrupt object.d");
378         fatal();
379     }
380     bt = tbase->semantic(loc, sc)->toBasetype();
381     b = new BaseClass(bt, PROTpublic);
382     baseclasses.shift(b);
383     assert(b->type->ty == Tclass);
384     tc = (TypeClass *)(b->type);
385     baseClass = tc->sym;
386     assert(!baseClass->isInterfaceDeclaration());
387     b->base = baseClass;
388     }
389
390     interfaces_dim = baseclasses.dim;
391     interfaces = (BaseClass **)baseclasses.data;
392
393
394     if (baseClass)
395     {
396     if (baseClass->storage_class & STCfinal)
397         error("cannot inherit from final class %s", baseClass->toChars());
398
399     interfaces_dim--;
400     interfaces++;
401
402     // Copy vtbl[] from base class
403     vtbl.setDim(baseClass->vtbl.dim);
404     memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim);
405
406     // Inherit properties from base class
407     com = baseClass->isCOMclass();
408     isauto = baseClass->isauto;
409     vthis = baseClass->vthis;
410     }
411     else
412     {
413     // No base class, so this is the root of the class hierarchy
414     vtbl.setDim(0);
415     vtbl.push(this);        // leave room for classinfo as first member
416     }
417
418     protection = sc->protection;
419     storage_class |= sc->stc;
420
421     if (sizeok == 0)
422     {
423     interfaceSemantic(sc);
424
425     for (i = 0; i < members->dim; i++)
426     {
427         Dsymbol *s = (Dsymbol *)members->data[i];
428         s->addMember(sc, this, 1);
429     }
430
431     /* If this is a nested class, add the hidden 'this'
432      * member which is a pointer to the enclosing scope.
433      */
434     if (vthis)      // if inheriting from nested class
435     {   // Use the base class's 'this' member
436         isnested = 1;
437         if (storage_class & STCstatic)
438         error("static class cannot inherit from nested class %s", baseClass->toChars());
439         if (toParent2() != baseClass->toParent2())
440         error("super class %s is nested within %s, not %s",
441             baseClass->toChars(),
442             baseClass->toParent2()->toChars(),
443             toParent2()->toChars());
444     }
445     else if (!(storage_class & STCstatic))
446     {   Dsymbol *s = toParent2();
447         if (s)
448         {
449         ClassDeclaration *cd = s->isClassDeclaration();
450         FuncDeclaration *fd = s->isFuncDeclaration();
451
452
453         if (cd || fd)
454         {   isnested = 1;
455             Type *t;
456             if (cd)
457             t = cd->type;
458             else if (fd)
459             {   AggregateDeclaration *ad = fd->isMember2();
460             if (ad)
461                 t = ad->handle;
462             else
463             {
464                 t = new TypePointer(Type::tvoid);
465                 t = t->semantic(0, sc);
466             }
467             }
468             else
469             assert(0);
470             assert(!vthis);
471             vthis = new ThisDeclaration(t);
472             members->push(vthis);
473         }
474         }
475     }
476     }
477
478     if (storage_class & (STCauto | STCscope))
479     isauto = 1;
480     if (storage_class & STCabstract)
481     isabstract = 1;
482     if (storage_class & STCdeprecated)
483     isdeprecated = 1;
484
485     sc = sc->push(this);
486     sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic |
487          STCabstract | STCdeprecated);
488     sc->parent = this;
489     sc->inunion = 0;
490
491     if (isCOMclass())
492     sc->linkage = LINKwindows;
493     sc->protection = PROTpublic;
494     sc->explicitProtection = 0;
495     sc->structalign = 8;
496     structalign = sc->structalign;
497     if (baseClass)
498     {   sc->offset = baseClass->structsize;
499     alignsize = baseClass->alignsize;
500 //  if (isnested)
501 //      sc->offset += PTRSIZE;  // room for uplevel context pointer
502     }
503     else
504     {   sc->offset = 8;     // allow room for vptr[] and monitor
505     alignsize = 4;
506     }
507     structsize = sc->offset;
508     Scope scsave = *sc;
509     int members_dim = members->dim;
510     sizeok = 0;
511     for (i = 0; i < members_dim; i++)
512     {
513     Dsymbol *s = (Dsymbol *)members->data[i];
514     s->semantic(sc);
515     }
516
517     if (sizeok == 2)
518     {   // semantic() failed because of forward references.
519     // Unwind what we did, and defer it for later
520     fields.setDim(0);
521     structsize = 0;
522     alignsize = 0;
523     structalign = 0;
524
525     sc = sc->pop();
526
527     scope = scx ? scx : new Scope(*sc);
528     scope->setNoFree();
529     scope->module->addDeferredSemantic(this);
530
531     //printf("\tsemantic('%s') failed\n", toChars());
532     return;
533     }
534
535     //printf("\tsemantic('%s') successful\n", toChars());
536
537     structsize = sc->offset;
538     //members->print();
539
540     /* Look for special member functions.
541      * They must be in this class, not in a base class.
542      */
543     ctor = (CtorDeclaration *)search(0, Id::ctor, 0);
544     if (ctor && ctor->toParent() != this)
545     ctor = NULL;
546
547 //    dtor = (DtorDeclaration *)search(Id::dtor, 0);
548 //    if (dtor && dtor->toParent() != this)
549 //  dtor = NULL;
550
551 //    inv = (InvariantDeclaration *)search(Id::classInvariant, 0);
552 //    if (inv && inv->toParent() != this)
553 //  inv = NULL;
554
555     // Can be in base class
556     aggNew    = (NewDeclaration *)search(0, Id::classNew, 0);
557     aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0);
558
559     // If this class has no constructor, but base class does, create
560     // a constructor:
561     //    this() { }
562     if (!ctor && baseClass && baseClass->ctor)
563     {
564     //printf("Creating default this(){} for class %s\n", toChars());
565     ctor = new CtorDeclaration(0, 0, NULL, 0);
566     ctor->fbody = new CompoundStatement(0, new Statements());
567     members->push(ctor);
568     ctor->addMember(sc, this, 1);
569     *sc = scsave;
570     sc->offset = structsize;
571     ctor->semantic(sc);
572     defaultCtor = ctor;
573     }
574
575 #if 0
576     if (baseClass)
577     {   if (!aggDelete)
578         aggDelete = baseClass->aggDelete;
579     if (!aggNew)
580         aggNew = baseClass->aggNew;
581     }
582 #endif
583
584     // Allocate instance of each new interface
585     for (i = 0; i < vtblInterfaces->dim; i++)
586     {
587     BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
588     unsigned thissize = PTRSIZE;
589
590     alignmember(structalign, thissize, &sc->offset);
591     assert(b->offset == 0);
592     b->offset = sc->offset;
593
594     // Take care of single inheritance offsets
595     while (b->baseInterfaces_dim)
596     {
597         b = &b->baseInterfaces[0];
598         b->offset = sc->offset;
599     }
600
601     sc->offset += thissize;
602     if (alignsize < thissize)
603         alignsize = thissize;
604     }
605     structsize = sc->offset;
606     sizeok = 1;
607     Module::dprogress++;
608
609
610     sc->pop();
611
612 #if 0 // Do not call until toObjfile() because of forward references
613     // Fill in base class vtbl[]s
614     for (i = 0; i < vtblInterfaces->dim; i++)
615     {
616     BaseClass *b = (BaseClass *)vtblInterfaces->data[i];
617
618     //b->fillVtbl(this, &b->vtbl, 1);
619     }
620 #endif
621     //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type);
622 }
623
624 void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
625 {
626     if (!isAnonymous())
627     {
628     buf