Mercurial > projects > ldc
annotate dmd/class.c @ 1138:4c8bb03e4fbc
Update DtoConstFP() to be correct after LLVM r67562, which changed the way the
APFloat constructor expects its i80 APInts to be formatted. (They're now
actually consistent with the x87 format)
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Tue, 24 Mar 2009 15:24:59 +0100 |
parents | b30fe7e1dbb9 |
children | 1860414bf3b7 |
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" | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
875
diff
changeset
|
16 #include "rmem.h" |
159 | 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()) | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
542 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
543 #if _WIN32 |
159 | 544 sc->linkage = LINKwindows; |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
545 #else |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
546 /* This enables us to use COM objects under Linux and |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
547 * work with things like XPCOM |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
548 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
549 sc->linkage = LINKc; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
550 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
551 } |
159 | 552 sc->protection = PROTpublic; |
553 sc->explicitProtection = 0; | |
554 sc->structalign = 8; | |
555 structalign = sc->structalign; | |
556 if (baseClass) | |
557 { sc->offset = baseClass->structsize; | |
558 alignsize = baseClass->alignsize; | |
559 // if (isnested) | |
560 // sc->offset += PTRSIZE; // room for uplevel context pointer | |
561 } | |
562 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
|
563 { 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
|
564 alignsize = PTRSIZE; |
159 | 565 } |
566 structsize = sc->offset; | |
567 Scope scsave = *sc; | |
568 int members_dim = members->dim; | |
569 sizeok = 0; | |
570 for (i = 0; i < members_dim; i++) | |
571 { | |
572 Dsymbol *s = (Dsymbol *)members->data[i]; | |
573 s->semantic(sc); | |
574 } | |
575 | |
576 if (sizeok == 2) | |
577 { // semantic() failed because of forward references. | |
578 // Unwind what we did, and defer it for later | |
579 fields.setDim(0); | |
580 structsize = 0; | |
581 alignsize = 0; | |
582 structalign = 0; | |
583 | |
584 sc = sc->pop(); | |
585 | |
586 scope = scx ? scx : new Scope(*sc); | |
587 scope->setNoFree(); | |
588 scope->module->addDeferredSemantic(this); | |
589 | |
336 | 590 //printf("\tsemantic('%s') failed due to forward references\n", toChars()); |
159 | 591 return; |
592 } | |
593 | |
594 //printf("\tsemantic('%s') successful\n", toChars()); | |
595 | |
596 structsize = sc->offset; | |
597 //members->print(); | |
598 | |
599 /* Look for special member functions. | |
600 * They must be in this class, not in a base class. | |
601 */ | |
602 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
|
603 if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration())) |
159 | 604 ctor = NULL; |
605 | |
606 // dtor = (DtorDeclaration *)search(Id::dtor, 0); | |
607 // if (dtor && dtor->toParent() != this) | |
608 // dtor = NULL; | |
609 | |
610 // inv = (InvariantDeclaration *)search(Id::classInvariant, 0); | |
611 // if (inv && inv->toParent() != this) | |
612 // inv = NULL; | |
613 | |
614 // Can be in base class | |
615 aggNew = (NewDeclaration *)search(0, Id::classNew, 0); | |
616 aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0); | |
617 | |
618 // If this class has no constructor, but base class does, create | |
619 // a constructor: | |
620 // this() { } | |
621 if (!ctor && baseClass && baseClass->ctor) | |
622 { | |
623 //printf("Creating default this(){} for class %s\n", toChars()); | |
336 | 624 ctor = new CtorDeclaration(loc, 0, NULL, 0); |
159 | 625 ctor->fbody = new CompoundStatement(0, new Statements()); |
626 members->push(ctor); | |
627 ctor->addMember(sc, this, 1); | |
628 *sc = scsave; // why? What about sc->nofree? | |
629 sc->offset = structsize; | |
630 ctor->semantic(sc); | |
631 defaultCtor = ctor; | |
632 } | |
633 | |
634 #if 0 | |
635 if (baseClass) | |
636 { if (!aggDelete) | |
637 aggDelete = baseClass->aggDelete; | |
638 if (!aggNew) | |
639 aggNew = baseClass->aggNew; | |
640 } | |
641 #endif | |
642 | |
643 // Allocate instance of each new interface | |
644 for (i = 0; i < vtblInterfaces->dim; i++) | |
645 { | |
646 BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; | |
647 unsigned thissize = PTRSIZE; | |
648 | |
649 alignmember(structalign, thissize, &sc->offset); | |
650 assert(b->offset == 0); | |
651 b->offset = sc->offset; | |
652 | |
653 // Take care of single inheritance offsets | |
654 while (b->baseInterfaces_dim) | |
655 { | |
656 b = &b->baseInterfaces[0]; | |
657 b->offset = sc->offset; | |
658 } | |
659 | |
660 sc->offset += thissize; | |
661 if (alignsize < thissize) | |
662 alignsize = thissize; | |
663 } | |
664 structsize = sc->offset; | |
665 sizeok = 1; | |
666 Module::dprogress++; | |
667 | |
668 dtor = buildDtor(sc); | |
669 | |
670 sc->pop(); | |
671 | |
672 #if 0 // Do not call until toObjfile() because of forward references | |
673 // Fill in base class vtbl[]s | |
674 for (i = 0; i < vtblInterfaces->dim; i++) | |
675 { | |
676 BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; | |
677 | |
678 //b->fillVtbl(this, &b->vtbl, 1); | |
679 } | |
680 #endif | |
681 //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type); | |
682 } | |
683 | |
684 void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
685 { | |
686 if (!isAnonymous()) | |
687 { | |
688 buf->printf("%s ", kind()); | |
689 buf->writestring(toChars()); | |
690 if (baseclasses.dim) | |
691 buf->writestring(" : "); | |
692 } | |
693 for (int i = 0; i < baseclasses.dim; i++) | |
694 { | |
695 BaseClass *b = (BaseClass *)baseclasses.data[i]; | |
696 | |
697 if (i) | |
698 buf->writeByte(','); | |
699 //buf->writestring(b->base->ident->toChars()); | |
700 b->type->toCBuffer(buf, NULL, hgs); | |
701 } | |
702 buf->writenl(); | |
703 buf->writeByte('{'); | |
704 buf->writenl(); | |
705 for (int i = 0; i < members->dim; i++) | |
706 { | |
707 Dsymbol *s = (Dsymbol *)members->data[i]; | |
708 | |
709 buf->writestring(" "); | |
710 s->toCBuffer(buf, hgs); | |
711 } | |
712 buf->writestring("}"); | |
713 buf->writenl(); | |
714 } | |
715 | |
716 #if 0 | |
717 void ClassDeclaration::defineRef(Dsymbol *s) | |
718 { | |
719 ClassDeclaration *cd; | |
720 | |
721 AggregateDeclaration::defineRef(s); | |
722 cd = s->isClassDeclaration(); | |
723 baseType = cd->baseType; | |
724 cd->baseType = NULL; | |
725 } | |
726 #endif | |
727 | |
728 /********************************************* | |
729 * Determine if 'this' is a base class of cd. | |
730 * This is used to detect circular inheritance only. | |
731 */ | |
732 | |
733 int ClassDeclaration::isBaseOf2(ClassDeclaration *cd) | |
734 { | |
735 if (!cd) | |
736 return 0; | |
737 //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); | |
738 for (int i = 0; i < cd->baseclasses.dim; i++) | |
739 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i]; | |
740 | |
741 if (b->base == this || isBaseOf2(b->base)) | |
742 return 1; | |
743 } | |
744 return 0; | |
745 } | |
746 | |
747 /******************************************* | |
748 * Determine if 'this' is a base class of cd. | |
749 */ | |
750 | |
751 int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) | |
752 { | |
753 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); | |
754 if (poffset) | |
755 *poffset = 0; | |
756 while (cd) | |
757 { | |
758 if (this == cd->baseClass) | |
759 return 1; | |
760 | |
761 /* cd->baseClass might not be set if cd is forward referenced. | |
762 */ | |
763 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration()) | |
764 { | |
765 cd->error("base class is forward referenced by %s", toChars()); | |
766 } | |
767 | |
768 cd = cd->baseClass; | |
769 } | |
770 return 0; | |
771 } | |
772 | |
773 Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) | |
774 { | |
775 Dsymbol *s; | |
776 | |
777 //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); | |
778 if (scope) | |
779 semantic(scope); | |
780 | |
781 if (!members || !symtab || scope) | |
782 { error("is forward referenced when looking for '%s'", ident->toChars()); | |
783 //*(char*)0=0; | |
784 return NULL; | |
785 } | |
786 | |
787 s = ScopeDsymbol::search(loc, ident, flags); | |
788 if (!s) | |
789 { | |
790 // Search bases classes in depth-first, left to right order | |
791 | |
792 int i; | |
793 | |
794 for (i = 0; i < baseclasses.dim; i++) | |
795 { | |
796 BaseClass *b = (BaseClass *)baseclasses.data[i]; | |
797 | |
798 if (b->base) | |
799 { | |
800 if (!b->base->symtab) | |
801 error("base %s is forward referenced", b->base->ident->toChars()); | |
802 else | |
803 { | |
804 s = b->base->search(loc, ident, flags); | |
805 if (s == this) // happens if s is nested in this and derives from this | |
806 s = NULL; | |
807 else if (s) | |
808 break; | |
809 } | |
810 } | |
811 } | |
812 } | |
813 return s; | |
814 } | |
815 | |
816 /********************************************************** | |
817 * fd is in the vtbl[] for this class. | |
818 * Return 1 if function is hidden (not findable through search). | |
819 */ | |
820 | |
336 | 821 #if DMDV2 |
159 | 822 int isf(void *param, FuncDeclaration *fd) |
823 { | |
824 //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars()); | |
825 return param == fd; | |
826 } | |
827 | |
828 int ClassDeclaration::isFuncHidden(FuncDeclaration *fd) | |
829 { | |
830 //printf("ClassDeclaration::isFuncHidden(%s)\n", fd->toChars()); | |
831 Dsymbol *s = search(0, fd->ident, 4|2); | |
832 if (!s) | |
833 { //printf("not found\n"); | |
834 /* Because, due to a hack, if there are multiple definitions | |
835 * of fd->ident, NULL is returned. | |
836 */ | |
837 return 0; | |
838 } | |
839 FuncDeclaration *fdstart = s->toAlias()->isFuncDeclaration(); | |
840 //printf("%s fdstart = %p\n", s->kind(), fdstart); | |
841 return !overloadApply(fdstart, &isf, fd); | |
842 } | |
843 #endif | |
844 | |
845 /**************** | |
846 * Find virtual function matching identifier and type. | |
847 * Used to build virtual function tables for interface implementations. | |
848 */ | |
849 | |
850 FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) | |
851 { | |
852 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars()); | |
853 | |
854 ClassDeclaration *cd = this; | |
855 Array *vtbl = &cd->vtbl; | |
856 while (1) | |
857 { | |
858 for (size_t i = 0; i < vtbl->dim; i++) | |
859 { | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
875
diff
changeset
|
860 FuncDeclaration *fd = ((Dsymbol*)vtbl->data[i])->isFuncDeclaration(); |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
875
diff
changeset
|
861 if (!fd) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
875
diff
changeset
|
862 continue; // the first entry might be a ClassInfo |
159 | 863 |
864 //printf("\t[%d] = %s\n", i, fd->toChars()); | |
865 if (ident == fd->ident && | |
866 //tf->equals(fd->type) | |
867 fd->type->covariant(tf) == 1 | |
868 ) | |
869 { //printf("\t\tfound\n"); | |
870 return fd; | |
871 } | |
872 //else printf("\t\t%d\n", fd->type->covariant(tf)); | |
873 } | |
874 if (!cd) | |
875 break; | |
876 vtbl = &cd->vtblFinal; | |
877 cd = cd->baseClass; | |
878 } | |
879 | |
880 return NULL; | |
881 } | |
882 | |
883 void ClassDeclaration::interfaceSemantic(Scope *sc) | |
336 | 884 { |
159 | 885 vtblInterfaces = new BaseClasses(); |
886 vtblInterfaces->reserve(interfaces_dim); | |
887 | |
336 | 888 for (size_t i = 0; i < interfaces_dim; i++) |
159 | 889 { |
890 BaseClass *b = interfaces[i]; | |
891 | |
892 // If this is an interface, and it derives from a COM interface, | |
893 // then this is a COM interface too. | |
894 if (b->base->isCOMinterface()) | |
895 com = 1; | |
896 | |
897 vtblInterfaces->push(b); | |
898 b->copyBaseInterfaces(vtblInterfaces); | |
899 } | |
900 } | |
901 | |
902 /**************************************** | |
903 */ | |
904 | |
905 int ClassDeclaration::isCOMclass() | |
906 { | |
907 return com; | |
908 } | |
909 | |
910 int ClassDeclaration::isCOMinterface() | |
911 { | |
912 return 0; | |
913 } | |
914 | |
915 | |
916 /**************************************** | |
917 */ | |
918 | |
919 int ClassDeclaration::isAbstract() | |
920 { | |
921 if (isabstract) | |
922 return TRUE; | |
923 for (int i = 1; i < vtbl.dim; i++) | |
924 { | |
925 FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration(); | |
926 | |
927 //printf("\tvtbl[%d] = %p\n", i, fd); | |
928 if (!fd || fd->isAbstract()) | |
929 { | |
930 isabstract |= 1; | |
931 return TRUE; | |
932 } | |
933 } | |
934 return FALSE; | |
935 } | |
936 | |
336 | 937 |
159 | 938 /**************************************** |
939 * Returns !=0 if there's an extra member which is the 'this' | |
940 * pointer to the enclosing context (enclosing class or function) | |
941 */ | |
942 | |
943 int ClassDeclaration::isNested() | |
944 { | |
945 return isnested; | |
946 } | |
947 | |
948 /**************************************** | |
949 * Determine if slot 0 of the vtbl[] is reserved for something else. | |
950 * For class objects, yes, this is where the classinfo ptr goes. | |
951 * For COM interfaces, no. | |
952 * For non-COM interfaces, yes, this is where the Interface ptr goes. | |
953 */ | |
954 | |
955 int ClassDeclaration::vtblOffset() | |
956 { | |
957 return 1; | |
958 } | |
959 | |
960 /**************************************** | |
961 */ | |
962 | |
336 | 963 const char *ClassDeclaration::kind() |
159 | 964 { |
965 return "class"; | |
966 } | |
967 | |
968 /**************************************** | |
969 */ | |
970 | |
971 void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses) | |
972 { | |
973 aclasses->push(this); | |
974 } | |
975 | |
976 /********************************* InterfaceDeclaration ****************************/ | |
977 | |
978 InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses) | |
979 : ClassDeclaration(loc, id, baseclasses) | |
980 { | |
981 com = 0; | |
982 if (id == Id::IUnknown) // IUnknown is the root of all COM objects | |
983 com = 1; | |
984 } | |
985 | |
986 Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s) | |
987 { | |
988 InterfaceDeclaration *id; | |
989 | |
990 if (s) | |
991 id = (InterfaceDeclaration *)s; | |
992 else | |
993 id = new InterfaceDeclaration(loc, ident, NULL); | |
994 | |
995 ClassDeclaration::syntaxCopy(id); | |
996 return id; | |
997 } | |
998 | |
999 void InterfaceDeclaration::semantic(Scope *sc) | |
1000 { int i; | |
1001 | |
1002 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); | |
1003 if (inuse) | |
1004 return; | |
1005 if (!scope) | |
1006 { type = type->semantic(loc, sc); | |
1007 handle = handle->semantic(loc, sc); | |
1008 } | |
1009 if (!members) // if forward reference | |
1010 { //printf("\tinterface '%s' is forward referenced\n", toChars()); | |
1011 return; | |
1012 } | |
1013 if (symtab) // if already done | |
1014 { if (!scope) | |
1015 return; | |
1016 } | |
1017 else | |
1018 symtab = new DsymbolTable(); | |
1019 | |
1020 Scope *scx = NULL; | |
1021 if (scope) | |
1022 { sc = scope; | |
1023 scx = scope; // save so we don't make redundant copies | |
1024 scope = NULL; | |
1025 } | |
1026 | |
1027 if (sc->stc & STCdeprecated) | |
1028 { | |
1029 isdeprecated = 1; | |
1030 } | |
1031 | |
1032 // Expand any tuples in baseclasses[] | |
1033 for (i = 0; i < baseclasses.dim; ) | |
1034 { BaseClass *b = (BaseClass *)baseclasses.data[0]; | |
1035 b->type = b->type->semantic(loc, sc); | |
1036 Type *tb = b->type->toBasetype(); | |
1037 | |
1038 if (tb->ty == Ttuple) | |
1039 { TypeTuple *tup = (TypeTuple *)tb; | |
1040 enum PROT protection = b->protection; | |
1041 baseclasses.remove(i); | |
1042 size_t dim = Argument::dim(tup->arguments); | |
1043 for (size_t j = 0; j < dim; j++) | |
1044 { Argument *arg = Argument::getNth(tup->arguments, j); | |
1045 b = new BaseClass(arg->type, protection); | |
1046 baseclasses.insert(i + j, b); | |
1047 } | |
1048 } | |
1049 else | |
1050 i++; | |
1051 } | |
1052 | |
1053 // Check for errors, handle forward references | |
1054 for (i = 0; i < baseclasses.dim; ) | |
1055 { TypeClass *tc; | |
1056 BaseClass *b; | |
1057 Type *tb; | |
1058 | |
1059 b = (BaseClass *)baseclasses.data[i]; | |
1060 b->type = b->type->semantic(loc, sc); | |
1061 tb = b->type->toBasetype(); | |
1062 if (tb->ty == Tclass) | |
1063 tc = (TypeClass *)tb; | |
1064 else | |
1065 tc = NULL; | |
1066 if (!tc || !tc->sym->isInterfaceDeclaration()) | |
1067 { | |
1068 error("base type must be interface, not %s", b->type->toChars()); | |
1069 baseclasses.remove(i); | |
1070 continue; | |
1071 } | |
1072 else | |
1073 { | |
1074 // Check for duplicate interfaces | |
1075 for (size_t j = 0; j < i; j++) | |
1076 { | |
1077 BaseClass *b2 = (BaseClass *)baseclasses.data[j]; | |
1078 if (b2->base == tc->sym) | |
1079 error("inherits from duplicate interface %s", b2->base->toChars()); | |
1080 } | |
1081 | |
1082 b->base = tc->sym; | |
1083 if (b->base == this || isBaseOf2(b->base)) | |
1084 { | |
1085 error("circular inheritance of interface"); | |
1086 baseclasses.remove(i); | |
1087 continue; | |
1088 } | |
1089 if (!b->base->symtab || b->base->scope || b->base->inuse) | |
1090 { | |
1091 //error("forward reference of base class %s", baseClass->toChars()); | |
1092 // Forward reference of base, try again later | |
1093 //printf("\ttry later, forward reference of base %s\n", b->base->toChars()); | |
1094 scope = scx ? scx : new Scope(*sc); | |
1095 scope->setNoFree(); | |
1096 scope->module->addDeferredSemantic(this); | |
1097 return; | |
1098 } | |
1099 } | |
1100 i++; | |
1101 } | |
1102 | |
1103 interfaces_dim = baseclasses.dim; | |
1104 interfaces = (BaseClass **)baseclasses.data; | |
1105 | |
1106 interfaceSemantic(sc); | |
1107 | |
1108 if (vtblOffset()) | |
1109 vtbl.push(this); // leave room at vtbl[0] for classinfo | |
1110 | |
1111 // Cat together the vtbl[]'s from base interfaces | |
1112 for (i = 0; i < interfaces_dim; i++) | |
1113 { BaseClass *b = interfaces[i]; | |
1114 | |
1115 // Skip if b has already appeared | |
1116 for (int k = 0; k < i; k++) | |
1117 { | |
1118 if (b == interfaces[i]) | |
1119 goto Lcontinue; | |
1120 } | |
1121 | |
1122 // Copy vtbl[] from base class | |
1123 if (b->base->vtblOffset()) | |
1124 { int d = b->base->vtbl.dim; | |
1125 if (d > 1) | |
1126 { | |
1127 vtbl.reserve(d - 1); | |
1128 for (int j = 1; j < d; j++) | |
1129 vtbl.push(b->base->vtbl.data[j]); | |
1130 } | |
1131 } | |
1132 else | |
1133 { | |
1134 vtbl.append(&b->base->vtbl); | |
1135 } | |
1136 | |
1137 Lcontinue: | |
1138 ; | |
1139 } | |
1140 | |
1141 for (i = 0; i < members->dim; i++) | |
1142 { | |
1143 Dsymbol *s = (Dsymbol *)members->data[i]; | |
1144 s->addMember(sc, this, 1); | |
1145 } | |
1146 | |
1147 sc = sc->push(this); | |
1148 sc->parent = this; | |
1149 if (isCOMinterface()) | |
1150 sc->linkage = LINKwindows; | |
1151 sc->structalign = 8; | |
1152 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
|
1153 sc->offset = 2*PTRSIZE; |
159 | 1154 inuse++; |
1155 for (i = 0; i < members->dim; i++) | |
1156 { | |
1157 Dsymbol *s = (Dsymbol *)members->data[i]; | |
1158 s->semantic(sc); | |
1159 } | |
1160 inuse--; | |
1161 //members->print(); | |
1162 sc->pop(); | |
1163 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); | |
1164 } | |
1165 | |
1166 | |
1167 /******************************************* | |
1168 * Determine if 'this' is a base class of cd. | |
1169 * (Actually, if it is an interface supported by cd) | |
1170 * Output: | |
1171 * *poffset offset to start of class | |
1172 * OFFSET_RUNTIME must determine offset at runtime | |
1173 * Returns: | |
1174 * 0 not a base | |
1175 * 1 is a base | |
1176 */ | |
1177 | |
1178 int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) | |
1179 { | |
1180 unsigned j; | |
1181 | |
1182 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars()); | |
1183 assert(!baseClass); | |
1184 for (j = 0; j < cd->interfaces_dim; j++) | |
1185 { | |
1186 BaseClass *b = cd->interfaces[j]; | |
1187 | |
1188 //printf("\tbase %s\n", b->base->toChars()); | |
1189 if (this == b->base) | |
1190 { | |
1191 //printf("\tfound at offset %d\n", b->offset); | |
1192 if (poffset) | |
1193 { *poffset = b->offset; | |
1194 if (j && cd->isInterfaceDeclaration()) | |
1195 *poffset = OFFSET_RUNTIME; | |
1196 } | |
1197 return 1; | |
1198 } | |
1199 if (isBaseOf(b, poffset)) | |
1200 { if (j && poffset && cd->isInterfaceDeclaration()) | |
1201 *poffset = OFFSET_RUNTIME; | |
1202 return 1; | |
1203 } | |
1204 } | |
1205 | |
1206 if (cd->baseClass && isBaseOf(cd->baseClass, poffset)) | |
1207 return 1; | |
1208 | |
1209 if (poffset) | |
1210 *poffset = 0; | |
1211 return 0; | |
1212 } | |
1213 | |
1214 | |
1215 int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset) | |
1216 { | |
1217 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars()); | |
1218 for (unsigned j = 0; j < bc->baseInterfaces_dim; j++) | |
1219 { | |
1220 BaseClass *b = &bc->baseInterfaces[j]; | |
1221 | |
1222 if (this == b->base) | |
1223 { | |
1224 if (poffset) | |
1225 { *poffset = b->offset; | |
1226 } | |
1227 return 1; | |
1228 } | |
1229 if (isBaseOf(b, poffset)) | |
1230 { | |
1231 return 1; | |
1232 } | |
1233 } | |
1234 if (poffset) | |
1235 *poffset = 0; | |
1236 return 0; | |
1237 } | |
1238 | |
1239 /**************************************** | |
1240 * Determine if slot 0 of the vtbl[] is reserved for something else. | |
1241 * For class objects, yes, this is where the ClassInfo ptr goes. | |
1242 * For COM interfaces, no. | |
1243 * For non-COM interfaces, yes, this is where the Interface ptr goes. | |
1244 */ | |
1245 | |
1246 int InterfaceDeclaration::vtblOffset() | |
1247 { | |
1248 if (isCOMinterface()) | |
1249 return 0; | |
1250 return 1; | |
1251 } | |
1252 | |
1253 int InterfaceDeclaration::isCOMinterface() | |
1254 { | |
1255 return com; | |
1256 } | |
1257 | |
1258 /******************************************* | |
1259 */ | |
1260 | |
336 | 1261 const char *InterfaceDeclaration::kind() |
159 | 1262 { |
1263 return "interface"; | |
1264 } | |
1265 | |
1266 | |
1267 /******************************** BaseClass *****************************/ | |
1268 | |
1269 BaseClass::BaseClass() | |
1270 { | |
1271 memset(this, 0, sizeof(BaseClass)); | |
1272 } | |
1273 | |
1274 BaseClass::BaseClass(Type *type, enum PROT protection) | |
1275 { | |
1276 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars()); | |
1277 this->type = type; | |
1278 this->protection = protection; | |
1279 base = NULL; | |
1280 offset = 0; | |
1281 | |
1282 baseInterfaces_dim = 0; | |
1283 baseInterfaces = NULL; | |
1284 } | |
1285 | |
1286 /**************************************** | |
1287 * Fill in vtbl[] for base class based on member functions of class cd. | |
1288 * Input: | |
1289 * vtbl if !=NULL, fill it in | |
1290 * newinstance !=0 means all entries must be filled in by members | |
1291 * of cd, not members of any base classes of cd. | |
1292 * Returns: | |
1293 * !=0 if any entries were filled in by members of cd (not exclusively | |
1294 * by base classes) | |
1295 */ | |
1296 | |
1297 int BaseClass::fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance) | |
1298 { | |
1299 ClassDeclaration *id = base; | |
1300 int j; | |
1301 int result = 0; | |
1302 | |
1303 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars()); | |
1304 if (vtbl) | |
1305 vtbl->setDim(base->vtbl.dim); | |
1306 | |
1307 // first entry is ClassInfo reference | |
1308 for (j = base->vtblOffset(); j < base->vtbl.dim; j++) | |
1309 { | |
1310 FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration(); | |
1311 FuncDeclaration *fd; | |
1312 TypeFunction *tf; | |
1313 | |
1314 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null"); | |
1315 | |
1316 assert(ifd); | |
1317 // Find corresponding function in this class | |
1318 tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL; | |
1319 fd = cd->findFunc(ifd->ident, tf); | |
1320 if (fd && !fd->isAbstract()) | |
1321 { | |
1322 //printf(" found\n"); | |
1323 // Check that calling conventions match | |
1324 if (fd->linkage != ifd->linkage) | |
1325 fd->error("linkage doesn't match interface function"); | |
1326 | |
1327 // Check that it is current | |
1328 if (newinstance && | |
1329 fd->toParent() != cd && | |
1330 ifd->toParent() == base) | |
1331 cd->error("interface function %s.%s is not implemented", | |
1332 id->toChars(), ifd->ident->toChars()); | |
1333 | |
1334 if (fd->toParent() == cd) | |
1335 result = 1; | |
1336 } | |
1337 else | |
1338 { | |
1339 //printf(" not found\n"); | |
1340 // BUG: should mark this class as abstract? | |
1341 if (!cd->isAbstract()) | |
1342 cd->error("interface function %s.%s isn't implemented", | |
1343 id->toChars(), ifd->ident->toChars()); | |
1344 fd = NULL; | |
1345 } | |
1346 if (vtbl) | |
1347 vtbl->data[j] = fd; | |
1348 } | |
1349 | |
1350 return result; | |
1351 } | |
1352 | |
1353 void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces) | |
1354 { | |
1355 //printf("+copyBaseInterfaces(), %s\n", base->toChars()); | |
1356 // if (baseInterfaces_dim) | |
1357 // return; | |
1358 | |
1359 baseInterfaces_dim = base->interfaces_dim; | |
1360 baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass)); | |
1361 | |
1362 //printf("%s.copyBaseInterfaces()\n", base->toChars()); | |
1363 for (int i = 0; i < baseInterfaces_dim; i++) | |
1364 { | |
1365 BaseClass *b = &baseInterfaces[i]; | |
1366 BaseClass *b2 = base->interfaces[i]; | |
1367 | |
1368 assert(b2->vtbl.dim == 0); // should not be filled yet | |
1369 memcpy(b, b2, sizeof(BaseClass)); | |
1370 | |
1371 if (i) // single inheritance is i==0 | |
1372 vtblInterfaces->push(b); // only need for M.I. | |
1373 b->copyBaseInterfaces(vtblInterfaces); | |
1374 } | |
1375 //printf("-copyBaseInterfaces\n"); | |
1376 } |