Mercurial > projects > ldc
annotate dmd/class.c @ 837:331a176c1f4f
Removed error on naked, not fully complete, but I'll be doing more work on it during this Christmas, and some things do work.
Fixed taking delegate of final class method. see mini/delegate3.d.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 09 Dec 2008 14:07:30 +0100 |
parents | 69a5e4a6fc0f |
children | 330f999ade44 |
rev | line source |
---|---|
159 | 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 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 | |
336 | 150 #if DMDV2 |
159 | 151 if (id == Id::TypeInfo_Const) |
152 { if (Type::typeinfoconst) | |
153 Type::typeinfoconst->error("%s", msg); | |
154 Type::typeinfoconst = this; | |
155 } | |
156 | |
157 if (id == Id::TypeInfo_Invariant) | |
158 { if (Type::typeinfoinvariant) | |
159 Type::typeinfoinvariant->error("%s", msg); | |
160 Type::typeinfoinvariant = this; | |
161 } | |
162 #endif | |
163 } | |
164 | |
165 if (id == Id::Object) | |
166 { if (object) | |
167 object->error("%s", msg); | |
168 object = this; | |
169 } | |
170 | |
171 if (id == Id::ClassInfo) | |
172 { if (classinfo) | |
173 classinfo->error("%s", msg); | |
174 classinfo = this; | |
175 } | |
176 | |
177 if (id == Id::ModuleInfo) | |
178 { if (Module::moduleinfo) | |
179 Module::moduleinfo->error("%s", msg); | |
180 Module::moduleinfo = this; | |
181 } | |
182 } | |
183 | |
184 com = 0; | |
185 isauto = 0; | |
186 isabstract = 0; | |
187 isnested = 0; | |
188 vthis = NULL; | |
189 inuse = 0; | |
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 if (sc->stc & STCdeprecated) | |
336 | 264 { |
159 | 265 isdeprecated = 1; |
266 } | |
267 | |
268 // Expand any tuples in baseclasses[] | |
269 for (i = 0; i < baseclasses.dim; ) | |
270 { BaseClass *b = (BaseClass *)baseclasses.data[i]; | |
271 b->type = b->type->semantic(loc, sc); | |
272 Type *tb = b->type->toBasetype(); | |
273 | |
274 if (tb->ty == Ttuple) | |
275 { TypeTuple *tup = (TypeTuple *)tb; | |
276 enum PROT protection = b->protection; | |
277 baseclasses.remove(i); | |
278 size_t dim = Argument::dim(tup->arguments); | |
279 for (size_t j = 0; j < dim; j++) | |
280 { Argument *arg = Argument::getNth(tup->arguments, j); | |
281 b = new BaseClass(arg->type, protection); | |
282 baseclasses.insert(i + j, b); | |
283 } | |
284 } | |
285 else | |
286 i++; | |
287 } | |
288 | |
289 // See if there's a base class as first in baseclasses[] | |
290 if (baseclasses.dim) | |
291 { TypeClass *tc; | |
292 BaseClass *b; | |
293 Type *tb; | |
294 | |
295 b = (BaseClass *)baseclasses.data[0]; | |
296 //b->type = b->type->semantic(loc, sc); | |
297 tb = b->type->toBasetype(); | |
298 if (tb->ty != Tclass) | |
299 { error("base type must be class or interface, not %s", b->type->toChars()); | |
300 baseclasses.remove(0); | |
301 } | |
302 else | |
303 { | |
304 tc = (TypeClass *)(tb); | |
336 | 305 |
159 | 306 if (tc->sym->isDeprecated()) |
307 { | |
308 if (!isDeprecated()) | |
309 { | |
310 // Deriving from deprecated class makes this one deprecated too | |
311 isdeprecated = 1; | |
312 | |
313 tc->checkDeprecated(loc, sc); | |
314 } | |
315 } | |
316 | |
317 if (tc->sym->isInterfaceDeclaration()) | |
318 ; | |
319 else | |
320 { | |
321 for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass) | |
322 { | |
323 if (cdb == this) | |
324 { | |
325 error("circular inheritance"); | |
326 baseclasses.remove(0); | |
327 goto L7; | |
328 } | |
329 } | |
330 if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0) | |
331 { | |
332 //error("forward reference of base class %s", baseClass->toChars()); | |
333 // Forward reference of base class, try again later | |
334 //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars()); | |
335 scope = scx ? scx : new Scope(*sc); | |
336 scope->setNoFree(); | |
337 scope->module->addDeferredSemantic(this); | |
338 return; | |
339 } | |
340 else | |
341 { baseClass = tc->sym; | |
342 b->base = baseClass; | |
343 } | |
344 L7: ; | |
345 } | |
346 } | |
347 } | |
348 | |
349 // Treat the remaining entries in baseclasses as interfaces | |
350 // Check for errors, handle forward references | |
351 for (i = (baseClass ? 1 : 0); i < baseclasses.dim; ) | |
352 { TypeClass *tc; | |
353 BaseClass *b; | |
354 Type *tb; | |
355 | |
356 b = (BaseClass *)baseclasses.data[i]; | |
357 b->type = b->type->semantic(loc, sc); | |
358 tb = b->type->toBasetype(); | |
359 if (tb->ty == Tclass) | |
360 tc = (TypeClass *)tb; | |
361 else | |
362 tc = NULL; | |
363 if (!tc || !tc->sym->isInterfaceDeclaration()) | |
364 { | |
365 error("base type must be interface, not %s", b->type->toChars()); | |
366 baseclasses.remove(i); | |
367 continue; | |
368 } | |
369 else | |
370 { | |
371 if (tc->sym->isDeprecated()) | |
372 { | |
373 if (!isDeprecated()) | |
374 { | |
375 // Deriving from deprecated class makes this one deprecated too | |
376 isdeprecated = 1; | |
377 | |
378 tc->checkDeprecated(loc, sc); | |
379 } | |
380 } | |
381 | |
382 // Check for duplicate interfaces | |
383 for (size_t j = (baseClass ? 1 : 0); j < i; j++) | |
384 { | |
385 BaseClass *b2 = (BaseClass *)baseclasses.data[j]; | |
386 if (b2->base == tc->sym) | |
387 error("inherits from duplicate interface %s", b2->base->toChars()); | |
388 } | |
389 | |
390 b->base = tc->sym; | |
391 if (!b->base->symtab || b->base->scope) | |
392 { | |
393 //error("forward reference of base class %s", baseClass->toChars()); | |
394 // Forward reference of base, try again later | |
395 //printf("\ttry later, forward reference of base %s\n", baseClass->toChars()); | |
396 scope = scx ? scx : new Scope(*sc); | |
397 scope->setNoFree(); | |
398 scope->module->addDeferredSemantic(this); | |
399 return; | |
400 } | |
401 } | |
402 i++; | |
403 } | |
404 | |
405 | |
406 // If no base class, and this is not an Object, use Object as base class | |
407 if (!baseClass && ident != Id::Object) | |
408 { | |
409 // BUG: what if Object is redefined in an inner scope? | |
410 Type *tbase = new TypeIdentifier(0, Id::Object); | |
411 BaseClass *b; | |
412 TypeClass *tc; | |
413 Type *bt; | |
414 | |
415 if (!object) | |
416 { | |
417 error("missing or corrupt object.d"); | |
418 fatal(); | |
419 } | |
420 bt = tbase->semantic(loc, sc)->toBasetype(); | |
421 b = new BaseClass(bt, PROTpublic); | |
422 baseclasses.shift(b); | |
423 assert(b->type->ty == Tclass); | |
424 tc = (TypeClass *)(b->type); | |
425 baseClass = tc->sym; | |
426 assert(!baseClass->isInterfaceDeclaration()); | |
427 b->base = baseClass; | |
428 } | |
429 | |
430 interfaces_dim = baseclasses.dim; | |
431 interfaces = (BaseClass **)baseclasses.data; | |
432 | |
433 | |
434 if (baseClass) | |
435 { | |
436 if (baseClass->storage_class & STCfinal) | |
437 error("cannot inherit from final class %s", baseClass->toChars()); | |
438 | |
439 interfaces_dim--; | |
440 interfaces++; | |
441 | |
442 // Copy vtbl[] from base class | |
443 vtbl.setDim(baseClass->vtbl.dim); | |
444 memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim); | |
445 | |
446 // Inherit properties from base class | |
447 com = baseClass->isCOMclass(); | |
448 isauto = baseClass->isauto; | |
449 vthis = baseClass->vthis; | |
450 } | |
451 else | |
452 { | |
453 // No base class, so this is the root of the class hierarchy | |
454 vtbl.setDim(0); | |
455 vtbl.push(this); // leave room for classinfo as first member | |
456 } | |
457 | |
458 protection = sc->protection; | |
459 storage_class |= sc->stc; | |
460 | |
461 if (sizeok == 0) | |
462 { | |
463 interfaceSemantic(sc); | |
464 | |
465 for (i = 0; i < members->dim; i++) | |
466 { | |
467 Dsymbol *s = (Dsymbol *)members->data[i]; | |
468 s->addMember(sc, this, 1); | |
469 } | |
470 | |
471 /* If this is a nested class, add the hidden 'this' | |
472 * member which is a pointer to the enclosing scope. | |
473 */ | |
474 if (vthis) // if inheriting from nested class | |
475 { // Use the base class's 'this' member | |
476 isnested = 1; | |
477 if (storage_class & STCstatic) | |
478 error("static class cannot inherit from nested class %s", baseClass->toChars()); | |
479 if (toParent2() != baseClass->toParent2()) | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
480 { |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
481 if (toParent2()) |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
482 { |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
483 error("is nested within %s, but super class %s is nested within %s", |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
484 toParent2()->toChars(), |
159 | 485 baseClass->toChars(), |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
486 baseClass->toParent2()->toChars()); |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
487 } |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
488 else |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
489 { |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
490 error("is not nested, but super class %s is nested within %s", |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
491 baseClass->toChars(), |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
492 baseClass->toParent2()->toChars()); |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
493 } |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
494 isnested = 0; |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
495 } |
159 | 496 } |
497 else if (!(storage_class & STCstatic)) | |
498 { Dsymbol *s = toParent2(); | |
499 if (s) | |
500 { | |
501 ClassDeclaration *cd = s->isClassDeclaration(); | |
502 FuncDeclaration *fd = s->isFuncDeclaration(); | |
503 | |
504 | |
505 if (cd || fd) | |
506 { isnested = 1; | |
507 Type *t; | |
508 if (cd) | |
509 t = cd->type; | |
510 else if (fd) | |
511 { AggregateDeclaration *ad = fd->isMember2(); | |
512 if (ad) | |
513 t = ad->handle; | |
514 else | |
515 { | |
516 t = new TypePointer(Type::tvoid); | |
517 t = t->semantic(0, sc); | |
518 } | |
519 } | |
520 else | |
521 assert(0); | |
522 assert(!vthis); | |
523 vthis = new ThisDeclaration(t); | |
524 members->push(vthis); | |
525 } | |
526 } | |
527 } | |
528 } | |
529 | |
530 if (storage_class & (STCauto | STCscope)) | |
531 isauto = 1; | |
532 if (storage_class & STCabstract) | |
533 isabstract = 1; | |
534 | |
535 sc = sc->push(this); | |
536 sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | | |
537 STCabstract | STCdeprecated); | |
538 sc->parent = this; | |
539 sc->inunion = 0; | |
540 | |
541 if (isCOMclass()) | |
542 sc->linkage = LINKwindows; | |
543 sc->protection = PROTpublic; | |
544 sc->explicitProtection = 0; | |
545 sc->structalign = 8; | |
546 structalign = sc->structalign; | |
547 if (baseClass) | |
548 { sc->offset = baseClass->structsize; | |
549 alignsize = baseClass->alignsize; | |
550 // if (isnested) | |
551 // sc->offset += PTRSIZE; // room for uplevel context pointer | |
552 } | |
553 else | |
809
69a5e4a6fc0f
Changed some hardcoded offset/alignment for classes in DMD, broke offsets for 64bits.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
554 { sc->offset = 2*PTRSIZE; // allow room for vptr[] and monitor |
69a5e4a6fc0f
Changed some hardcoded offset/alignment for classes in DMD, broke offsets for 64bits.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
555 alignsize = PTRSIZE; |
159 | 556 } |
557 structsize = sc->offset; | |
558 Scope scsave = *sc; | |
559 int members_dim = members->dim; | |
560 sizeok = 0; | |
561 for (i = 0; i < members_dim; i++) | |
562 { | |
563 Dsymbol *s = (Dsymbol *)members->data[i]; | |
564 s->semantic(sc); | |
565 } | |
566 | |
567 if (sizeok == 2) | |
568 { // semantic() failed because of forward references. | |
569 // Unwind what we did, and defer it for later | |
570 fields.setDim(0); | |
571 structsize = 0; | |
572 alignsize = 0; | |
573 structalign = 0; | |
574 | |
575 sc = sc->pop(); | |
576 | |
577 scope = scx ? scx : new Scope(*sc); | |
578 scope->setNoFree(); | |
579 scope->module->addDeferredSemantic(this); | |
580 | |
336 | 581 //printf("\tsemantic('%s') failed due to forward references\n", toChars()); |
159 | 582 return; |
583 } | |
584 | |
585 //printf("\tsemantic('%s') successful\n", toChars()); | |
586 | |
587 structsize = sc->offset; | |
588 //members->print(); | |
589 | |
590 /* Look for special member functions. | |
591 * They must be in this class, not in a base class. | |
592 */ | |
593 ctor = (CtorDeclaration *)search(0, Id::ctor, 0); | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
594 if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration())) |
159 | 595 ctor = NULL; |
596 | |
597 // dtor = (DtorDeclaration *)search(Id::dtor, 0); | |
598 // if (dtor && dtor->toParent() != this) | |
599 // dtor = NULL; | |
600 | |
601 // inv = (InvariantDeclaration *)search(Id::classInvariant, 0); | |
602 // if (inv && inv->toParent() != this) | |
603 // inv = NULL; | |
604 | |
605 // Can be in base class | |
606 aggNew = (NewDeclaration *)search(0, Id::classNew, 0); | |
607 aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0); | |
608 | |
609 // If this class has no constructor, but base class does, create | |
610 // a constructor: | |
611 // this() { } | |
612 if (!ctor && baseClass && baseClass->ctor) | |
613 { | |
614 //printf("Creating default this(){} for class %s\n", toChars()); | |
336 | 615 ctor = new CtorDeclaration(loc, 0, NULL, 0); |
159 | 616 ctor->fbody = new CompoundStatement(0, new Statements()); |
617 members->push(ctor); | |
618 ctor->addMember(sc, this, 1); | |
619 *sc = scsave; // why? What about sc->nofree? | |
620 sc->offset = structsize; | |
621 ctor->semantic(sc); | |
622 defaultCtor = ctor; | |
623 } | |
624 | |
625 #if 0 | |
626 if (baseClass) | |
627 { if (!aggDelete) | |
628 aggDelete = baseClass->aggDelete; | |
629 if (!aggNew) | |
630 aggNew = baseClass->aggNew; | |
631 } | |
632 #endif | |
633 | |
634 // Allocate instance of each new interface | |
635 for (i = 0; i < vtblInterfaces->dim; i++) | |
636 { | |
637 BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; | |
638 unsigned thissize = PTRSIZE; | |
639 | |
640 alignmember(structalign, thissize, &sc->offset); | |
641 assert(b->offset == 0); | |
642 b->offset = sc->offset; | |
643 | |
644 // Take care of single inheritance offsets | |
645 while (b->baseInterfaces_dim) | |
646 { | |
647 b = &b->baseInterfaces[0]; | |
648 b->offset = sc->offset; | |
649 } | |
650 | |
651 sc->offset += thissize; | |
652 if (alignsize < thissize) | |
653 alignsize = thissize; | |
654 } | |
655 structsize = sc->offset; | |
656 sizeok = 1; | |
657 Module::dprogress++; | |
658 | |
659 dtor = buildDtor(sc); | |
660 | |
661 sc->pop(); | |
662 | |
663 #if 0 // Do not call until toObjfile() because of forward references | |
664 // Fill in base class vtbl[]s | |
665 for (i = 0; i < vtblInterfaces->dim; i++) | |
666 { | |
667 BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; | |
668 | |
669 //b->fillVtbl(this, &b->vtbl, 1); | |
670 } | |
671 #endif | |
672 //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type); | |
673 } | |
674 | |
675 void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
676 { | |
677 if (!isAnonymous()) | |
678 { | |
679 buf->printf("%s ", kind()); | |
680 buf->writestring(toChars()); | |
681 if (baseclasses.dim) | |
682 buf->writestring(" : "); | |
683 } | |
684 for (int i = 0; i < baseclasses.dim; i++) | |
685 { | |
686 BaseClass *b = (BaseClass *)baseclasses.data[i]; | |
687 | |
688 if (i) | |
689 buf->writeByte(','); | |
690 //buf->writestring(b->base->ident->toChars()); | |
691 b->type->toCBuffer(buf, NULL, hgs); | |
692 } | |
693 buf->writenl(); | |
694 buf->writeByte('{'); | |
695 buf->writenl(); | |
696 for (int i = 0; i < members->dim; i++) | |
697 { | |
698 Dsymbol *s = (Dsymbol *)members->data[i]; | |
699 | |
700 buf->writestring(" "); | |
701 s->toCBuffer(buf, hgs); | |
702 } | |
703 buf->writestring("}"); | |
704 buf->writenl(); | |
705 } | |
706 | |
707 #if 0 | |
708 void ClassDeclaration::defineRef(Dsymbol *s) | |
709 { | |
710 ClassDeclaration *cd; | |
711 | |
712 AggregateDeclaration::defineRef(s); | |
713 cd = s->isClassDeclaration(); | |
714 baseType = cd->baseType; | |
715 cd->baseType = NULL; | |
716 } | |
717 #endif | |
718 | |
719 /********************************************* | |
720 * Determine if 'this' is a base class of cd. | |
721 * This is used to detect circular inheritance only. | |
722 */ | |
723 | |
724 int ClassDeclaration::isBaseOf2(ClassDeclaration *cd) | |
725 { | |
726 if (!cd) | |
727 return 0; | |
728 //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); | |
729 for (int i = 0; i < cd->baseclasses.dim; i++) | |
730 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i]; | |
731 | |
732 if (b->base == this || isBaseOf2(b->base)) | |
733 return 1; | |
734 } | |
735 return 0; | |
736 } | |
737 | |
738 /******************************************* | |
739 * Determine if 'this' is a base class of cd. | |
740 */ | |
741 | |
742 int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) | |
743 { | |
744 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); | |
745 if (poffset) | |
746 *poffset = 0; | |
747 while (cd) | |
748 { | |
749 if (this == cd->baseClass) | |
750 return 1; | |
751 | |
752 /* cd->baseClass might not be set if cd is forward referenced. | |
753 */ | |
754 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration()) | |
755 { | |
756 cd->error("base class is forward referenced by %s", toChars()); | |
757 } | |
758 | |
759 cd = cd->baseClass; | |
760 } | |
761 return 0; | |
762 } | |
763 | |
764 Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) | |
765 { | |
766 Dsymbol *s; | |
767 | |
768 //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); | |
769 if (scope) | |
770 semantic(scope); | |
771 | |
772 if (!members || !symtab || scope) | |
773 { error("is forward referenced when looking for '%s'", ident->toChars()); | |
774 //*(char*)0=0; | |
775 return NULL; | |
776 } | |
777 | |
778 s = ScopeDsymbol::search(loc, ident, flags); | |
779 if (!s) | |
780 { | |
781 // Search bases classes in depth-first, left to right order | |
782 | |
783 int i; | |
784 | |
785 for (i = 0; i < baseclasses.dim; i++) | |
786 { | |
787 BaseClass *b = (BaseClass *)baseclasses.data[i]; | |
788 | |
789 if (b->base) | |
790 { | |
791 if (!b->base->symtab) | |
792 error("base %s is forward referenced", b->base->ident->toChars()); | |
793 else | |
794 { | |
795 s = b->base->search(loc, ident, flags); | |
796 if (s == this) // happens if s is nested in this and derives from this | |
797 s = NULL; | |
798 else if (s) | |
799 break; | |
800 } | |
801 } | |
802 } | |
803 } | |
804 return s; | |
805 } | |
806 | |
807 /********************************************************** | |
808 * fd is in the vtbl[] for this class. | |
809 * Return 1 if function is hidden (not findable through search). | |
810 */ | |
811 | |
336 | 812 #if DMDV2 |
159 | 813 int isf(void *param, FuncDeclaration *fd) |
814 { | |
815 //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars()); | |
816 return param == fd; | |
817 } | |
818 | |
819 int ClassDeclaration::isFuncHidden(FuncDeclaration *fd) | |
820 { | |
821 //printf("ClassDeclaration::isFuncHidden(%s)\n", fd->toChars()); | |
822 Dsymbol *s = search(0, fd->ident, 4|2); | |
823 if (!s) | |
824 { //printf("not found\n"); | |
825 /* Because, due to a hack, if there are multiple definitions | |
826 * of fd->ident, NULL is returned. | |
827 */ | |
828 return 0; | |
829 } | |
830 FuncDeclaration *fdstart = s->toAlias()->isFuncDeclaration(); | |
831 //printf("%s fdstart = %p\n", s->kind(), fdstart); | |
832 return !overloadApply(fdstart, &isf, fd); | |
833 } | |
834 #endif | |
835 | |
836 /**************** | |
837 * Find virtual function matching identifier and type. | |
838 * Used to build virtual function tables for interface implementations. | |
839 */ | |
840 | |
841 FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) | |
842 { | |
843 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars()); | |
844 | |
845 ClassDeclaration *cd = this; | |
846 Array *vtbl = &cd->vtbl; | |
847 while (1) | |
848 { | |
849 for (size_t i = 0; i < vtbl->dim; i++) | |
850 { | |
851 FuncDeclaration *fd = (FuncDeclaration *)vtbl->data[i]; | |
852 | |
853 //printf("\t[%d] = %s\n", i, fd->toChars()); | |
854 if (ident == fd->ident && | |
855 //tf->equals(fd->type) | |
856 fd->type->covariant(tf) == 1 | |
857 ) | |
858 { //printf("\t\tfound\n"); | |
859 return fd; | |
860 } | |
861 //else printf("\t\t%d\n", fd->type->covariant(tf)); | |
862 } | |
863 if (!cd) | |
864 break; | |
865 vtbl = &cd->vtblFinal; | |
866 cd = cd->baseClass; | |
867 } | |
868 | |
869 return NULL; | |
870 } | |
871 | |
872 void ClassDeclaration::interfaceSemantic(Scope *sc) | |
336 | 873 { |
159 | 874 vtblInterfaces = new BaseClasses(); |
875 vtblInterfaces->reserve(interfaces_dim); | |
876 | |
336 | 877 for (size_t i = 0; i < interfaces_dim; i++) |
159 | 878 { |
879 BaseClass *b = interfaces[i]; | |
880 | |
881 // If this is an interface, and it derives from a COM interface, | |
882 // then this is a COM interface too. | |
883 if (b->base->isCOMinterface()) | |
884 com = 1; | |
885 | |
886 vtblInterfaces->push(b); | |
887 b->copyBaseInterfaces(vtblInterfaces); | |
888 } | |
889 } | |
890 | |
891 /**************************************** | |
892 */ | |
893 | |
894 int ClassDeclaration::isCOMclass() | |
895 { | |
896 return com; | |
897 } | |
898 | |
899 int ClassDeclaration::isCOMinterface() | |
900 { | |
901 return 0; | |
902 } | |
903 | |
904 | |
905 /**************************************** | |
906 */ | |
907 | |
908 int ClassDeclaration::isAbstract() | |
909 { | |
910 if (isabstract) | |
911 return TRUE; | |
912 for (int i = 1; i < vtbl.dim; i++) | |
913 { | |
914 FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration(); | |
915 | |
916 //printf("\tvtbl[%d] = %p\n", i, fd); | |
917 if (!fd || fd->isAbstract()) | |
918 { | |
919 isabstract |= 1; | |
920 return TRUE; | |
921 } | |
922 } | |
923 return FALSE; | |
924 } | |
925 | |
336 | 926 |
159 | 927 /**************************************** |
928 * Returns !=0 if there's an extra member which is the 'this' | |
929 * pointer to the enclosing context (enclosing class or function) | |
930 */ | |
931 | |
932 int ClassDeclaration::isNested() | |
933 { | |
934 return isnested; | |
935 } | |
936 | |
937 /**************************************** | |
938 * Determine if slot 0 of the vtbl[] is reserved for something else. | |
939 * For class objects, yes, this is where the classinfo ptr goes. | |
940 * For COM interfaces, no. | |
941 * For non-COM interfaces, yes, this is where the Interface ptr goes. | |
942 */ | |
943 | |
944 int ClassDeclaration::vtblOffset() | |
945 { | |
946 return 1; | |
947 } | |
948 | |
949 /**************************************** | |
950 */ | |
951 | |
336 | 952 const char *ClassDeclaration::kind() |
159 | 953 { |
954 return "class"; | |
955 } | |
956 | |
957 /**************************************** | |
958 */ | |
959 | |
960 void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses) | |
961 { | |
962 aclasses->push(this); | |
963 } | |
964 | |
965 /********************************* InterfaceDeclaration ****************************/ | |
966 | |
967 InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses) | |
968 : ClassDeclaration(loc, id, baseclasses) | |
969 { | |
970 com = 0; | |
971 if (id == Id::IUnknown) // IUnknown is the root of all COM objects | |
972 com = 1; | |
973 } | |
974 | |
975 Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s) | |
976 { | |
977 InterfaceDeclaration *id; | |
978 | |
979 if (s) | |
980 id = (InterfaceDeclaration *)s; | |
981 else | |
982 id = new InterfaceDeclaration(loc, ident, NULL); | |
983 | |
984 ClassDeclaration::syntaxCopy(id); | |
985 return id; | |
986 } | |
987 | |
988 void InterfaceDeclaration::semantic(Scope *sc) | |
989 { int i; | |
990 | |
991 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); | |
992 if (inuse) | |
993 return; | |
994 if (!scope) | |
995 { type = type->semantic(loc, sc); | |
996 handle = handle->semantic(loc, sc); | |
997 } | |
998 if (!members) // if forward reference | |
999 { //printf("\tinterface '%s' is forward referenced\n", toChars()); | |
1000 return; | |
1001 } | |
1002 if (symtab) // if already done | |
1003 { if (!scope) | |
1004 return; | |
1005 } | |
1006 else | |
1007 symtab = new DsymbolTable(); | |
1008 | |
1009 Scope *scx = NULL; | |
1010 if (scope) | |
1011 { sc = scope; | |
1012 scx = scope; // save so we don't make redundant copies | |
1013 scope = NULL; | |
1014 } | |
1015 | |
1016 if (sc->stc & STCdeprecated) | |
1017 { | |
1018 isdeprecated = 1; | |
1019 } | |
1020 | |
1021 // Expand any tuples in baseclasses[] | |
1022 for (i = 0; i < baseclasses.dim; ) | |
1023 { BaseClass *b = (BaseClass *)baseclasses.data[0]; | |
1024 b->type = b->type->semantic(loc, sc); | |
1025 Type *tb = b->type->toBasetype(); | |
1026 | |
1027 if (tb->ty == Ttuple) | |
1028 { TypeTuple *tup = (TypeTuple *)tb; | |
1029 enum PROT protection = b->protection; | |
1030 baseclasses.remove(i); | |
1031 size_t dim = Argument::dim(tup->arguments); | |
1032 for (size_t j = 0; j < dim; j++) | |
1033 { Argument *arg = Argument::getNth(tup->arguments, j); | |
1034 b = new BaseClass(arg->type, protection); | |
1035 baseclasses.insert(i + j, b); | |
1036 } | |
1037 } | |
1038 else | |
1039 i++; | |
1040 } | |
1041 | |
1042 // Check for errors, handle forward references | |
1043 for (i = 0; i < baseclasses.dim; ) | |
1044 { TypeClass *tc; | |
1045 BaseClass *b; | |
1046 Type *tb; | |
1047 | |
1048 b = (BaseClass *)baseclasses.data[i]; | |
1049 b->type = b->type->semantic(loc, sc); | |
1050 tb = b->type->toBasetype(); | |
1051 if (tb->ty == Tclass) | |
1052 tc = (TypeClass *)tb; | |
1053 else | |
1054 tc = NULL; | |
1055 if (!tc || !tc->sym->isInterfaceDeclaration()) | |
1056 { | |
1057 error("base type must be interface, not %s", b->type->toChars()); | |
1058 baseclasses.remove(i); | |
1059 continue; | |
1060 } | |
1061 else | |
1062 { | |
1063 // Check for duplicate interfaces | |
1064 for (size_t j = 0; j < i; j++) | |
1065 { | |
1066 BaseClass *b2 = (BaseClass *)baseclasses.data[j]; | |
1067 if (b2->base == tc->sym) | |
1068 error("inherits from duplicate interface %s", b2->base->toChars()); | |
1069 } | |
1070 | |
1071 b->base = tc->sym; | |
1072 if (b->base == this || isBaseOf2(b->base)) | |
1073 { | |
1074 error("circular inheritance of interface"); | |
1075 baseclasses.remove(i); | |
1076 continue; | |
1077 } | |
1078 if (!b->base->symtab || b->base->scope || b->base->inuse) | |
1079 { | |
1080 //error("forward reference of base class %s", baseClass->toChars()); | |
1081 // Forward reference of base, try again later | |
1082 //printf("\ttry later, forward reference of base %s\n", b->base->toChars()); | |
1083 scope = scx ? scx : new Scope(*sc); | |
1084 scope->setNoFree(); | |
1085 scope->module->addDeferredSemantic(this); | |
1086 return; | |
1087 } | |
1088 } | |
1089 i++; | |
1090 } | |
1091 | |
1092 interfaces_dim = baseclasses.dim; | |
1093 interfaces = (BaseClass **)baseclasses.data; | |
1094 | |
1095 interfaceSemantic(sc); | |
1096 | |
1097 if (vtblOffset()) | |
1098 vtbl.push(this); // leave room at vtbl[0] for classinfo | |
1099 | |
1100 // Cat together the vtbl[]'s from base interfaces | |
1101 for (i = 0; i < interfaces_dim; i++) | |
1102 { BaseClass *b = interfaces[i]; | |
1103 | |
1104 // Skip if b has already appeared | |
1105 for (int k = 0; k < i; k++) | |
1106 { | |
1107 if (b == interfaces[i]) | |
1108 goto Lcontinue; | |
1109 } | |
1110 | |
1111 // Copy vtbl[] from base class | |
1112 if (b->base->vtblOffset()) | |
1113 { int d = b->base->vtbl.dim; | |
1114 if (d > 1) | |
1115 { | |
1116 vtbl.reserve(d - 1); | |
1117 for (int j = 1; j < d; j++) | |
1118 vtbl.push(b->base->vtbl.data[j]); | |
1119 } | |
1120 } | |
1121 else | |
1122 { | |
1123 vtbl.append(&b->base->vtbl); | |
1124 } | |
1125 | |
1126 Lcontinue: | |
1127 ; | |
1128 } | |
1129 | |
1130 for (i = 0; i < members->dim; i++) | |
1131 { | |
1132 Dsymbol *s = (Dsymbol *)members->data[i]; | |
1133 s->addMember(sc, this, 1); | |
1134 } | |
1135 | |
1136 sc = sc->push(this); | |
1137 sc->parent = this; | |
1138 if (isCOMinterface()) | |
1139 sc->linkage = LINKwindows; | |
1140 sc->structalign = 8; | |
1141 structalign = sc->structalign; | |
809
69a5e4a6fc0f
Changed some hardcoded offset/alignment for classes in DMD, broke offsets for 64bits.
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
658
diff
changeset
|
1142 sc->offset = 2*PTRSIZE; |
159 | 1143 inuse++; |
1144 for (i = 0; i < members->dim; i++) | |
1145 { | |
1146 Dsymbol *s = (Dsymbol *)members->data[i]; | |
1147 s->semantic(sc); | |
1148 } | |
1149 inuse--; | |
1150 //members->print(); | |
1151 sc->pop(); | |
1152 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); | |
1153 } | |
1154 | |
1155 | |
1156 /******************************************* | |
1157 * Determine if 'this' is a base class of cd. | |
1158 * (Actually, if it is an interface supported by cd) | |
1159 * Output: | |
1160 * *poffset offset to start of class | |
1161 * OFFSET_RUNTIME must determine offset at runtime | |
1162 * Returns: | |
1163 * 0 not a base | |
1164 * 1 is a base | |
1165 */ | |
1166 | |
1167 int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) | |
1168 { | |
1169 unsigned j; | |
1170 | |
1171 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars()); | |
1172 assert(!baseClass); | |
1173 for (j = 0; j < cd->interfaces_dim; j++) | |
1174 { | |
1175 BaseClass *b = cd->interfaces[j]; | |
1176 | |
1177 //printf("\tbase %s\n", b->base->toChars()); | |
1178 if (this == b->base) | |
1179 { | |
1180 //printf("\tfound at offset %d\n", b->offset); | |
1181 if (poffset) | |
1182 { *poffset = b->offset; | |
1183 if (j && cd->isInterfaceDeclaration()) | |
1184 *poffset = OFFSET_RUNTIME; | |
1185 } | |
1186 return 1; | |
1187 } | |
1188 if (isBaseOf(b, poffset)) | |
1189 { if (j && poffset && cd->isInterfaceDeclaration()) | |
1190 *poffset = OFFSET_RUNTIME; | |
1191 return 1; | |
1192 } | |
1193 } | |
1194 | |
1195 if (cd->baseClass && isBaseOf(cd->baseClass, poffset)) | |
1196 return 1; | |
1197 | |
1198 if (poffset) | |
1199 *poffset = 0; | |
1200 return 0; | |
1201 } | |
1202 | |
1203 | |
1204 int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset) | |
1205 { | |
1206 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars()); | |
1207 for (unsigned j = 0; j < bc->baseInterfaces_dim; j++) | |
1208 { | |
1209 BaseClass *b = &bc->baseInterfaces[j]; | |
1210 | |
1211 if (this == b->base) | |
1212 { | |
1213 if (poffset) | |
1214 { *poffset = b->offset; | |
1215 } | |
1216 return 1; | |
1217 } | |
1218 if (isBaseOf(b, poffset)) | |
1219 { | |
1220 return 1; | |
1221 } | |
1222 } | |
1223 if (poffset) | |
1224 *poffset = 0; | |
1225 return 0; | |
1226 } | |
1227 | |
1228 /**************************************** | |
1229 * Determine if slot 0 of the vtbl[] is reserved for something else. | |
1230 * For class objects, yes, this is where the ClassInfo ptr goes. | |
1231 * For COM interfaces, no. | |
1232 * For non-COM interfaces, yes, this is where the Interface ptr goes. | |
1233 */ | |
1234 | |
1235 int InterfaceDeclaration::vtblOffset() | |
1236 { | |
1237 if (isCOMinterface()) | |
1238 return 0; | |
1239 return 1; | |
1240 } | |
1241 | |
1242 int InterfaceDeclaration::isCOMinterface() | |
1243 { | |
1244 return com; | |
1245 } | |
1246 | |
1247 /******************************************* | |
1248 */ | |
1249 | |
336 | 1250 const char *InterfaceDeclaration::kind() |
159 | 1251 { |
1252 return "interface"; | |
1253 } | |
1254 | |
1255 | |
1256 /******************************** BaseClass *****************************/ | |
1257 | |
1258 BaseClass::BaseClass() | |
1259 { | |
1260 memset(this, 0, sizeof(BaseClass)); | |
1261 } | |
1262 | |
1263 BaseClass::BaseClass(Type *type, enum PROT protection) | |
1264 { | |
1265 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars()); | |
1266 this->type = type; | |
1267 this->protection = protection; | |
1268 base = NULL; | |
1269 offset = 0; | |
1270 | |
1271 baseInterfaces_dim = 0; | |
1272 baseInterfaces = NULL; | |
1273 } | |
1274 | |
1275 /**************************************** | |
1276 * Fill in vtbl[] for base class based on member functions of class cd. | |
1277 * Input: | |
1278 * vtbl if !=NULL, fill it in | |
1279 * newinstance !=0 means all entries must be filled in by members | |
1280 * of cd, not members of any base classes of cd. | |
1281 * Returns: | |
1282 * !=0 if any entries were filled in by members of cd (not exclusively | |
1283 * by base classes) | |
1284 */ | |
1285 | |
1286 int BaseClass::fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance) | |
1287 { | |
1288 ClassDeclaration *id = base; | |
1289 int j; | |
1290 int result = 0; | |
1291 | |
1292 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars()); | |
1293 if (vtbl) | |
1294 vtbl->setDim(base->vtbl.dim); | |
1295 | |
1296 // first entry is ClassInfo reference | |
1297 for (j = base->vtblOffset(); j < base->vtbl.dim; j++) | |
1298 { | |
1299 FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration(); | |
1300 FuncDeclaration *fd; | |
1301 TypeFunction *tf; | |
1302 | |
1303 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null"); | |
1304 | |
1305 assert(ifd); | |
1306 // Find corresponding function in this class | |
1307 tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL; | |
1308 fd = cd->findFunc(ifd->ident, tf); | |
1309 if (fd && !fd->isAbstract()) | |
1310 { | |
1311 //printf(" found\n"); | |
1312 // Check that calling conventions match | |
1313 if (fd->linkage != ifd->linkage) | |
1314 fd->error("linkage doesn't match interface function"); | |
1315 | |
1316 // Check that it is current | |
1317 if (newinstance && | |
1318 fd->toParent() != cd && | |
1319 ifd->toParent() == base) | |
1320 cd->error("interface function %s.%s is not implemented", | |
1321 id->toChars(), ifd->ident->toChars()); | |
1322 | |
1323 if (fd->toParent() == cd) | |
1324 result = 1; | |
1325 } | |
1326 else | |
1327 { | |
1328 //printf(" not found\n"); | |
1329 // BUG: should mark this class as abstract? | |
1330 if (!cd->isAbstract()) | |
1331 cd->error("interface function %s.%s isn't implemented", | |
1332 id->toChars(), ifd->ident->toChars()); | |
1333 fd = NULL; | |
1334 } | |
1335 if (vtbl) | |
1336 vtbl->data[j] = fd; | |
1337 } | |
1338 | |
1339 return result; | |
1340 } | |
1341 | |
1342 void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces) | |
1343 { | |
1344 //printf("+copyBaseInterfaces(), %s\n", base->toChars()); | |
1345 // if (baseInterfaces_dim) | |
1346 // return; | |
1347 | |
1348 baseInterfaces_dim = base->interfaces_dim; | |
1349 baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass)); | |
1350 | |
1351 //printf("%s.copyBaseInterfaces()\n", base->toChars()); | |
1352 for (int i = 0; i < baseInterfaces_dim; i++) | |
1353 { | |
1354 BaseClass *b = &baseInterfaces[i]; | |
1355 BaseClass *b2 = base->interfaces[i]; | |
1356 | |
1357 assert(b2->vtbl.dim == 0); // should not be filled yet | |
1358 memcpy(b, b2, sizeof(BaseClass)); | |
1359 | |
1360 if (i) // single inheritance is i==0 | |
1361 vtblInterfaces->push(b); // only need for M.I. | |
1362 b->copyBaseInterfaces(vtblInterfaces); | |
1363 } | |
1364 //printf("-copyBaseInterfaces\n"); | |
1365 } |