Mercurial > projects > ldc
annotate dmd/class.c @ 1064:f0b6549055ab
Make LDC work with LLVM trunk (s/LinkOnceLinkage/LinkOnceOdrLinkage/)
Also moved the #defines for linkage types into a separate header instead of
mars.h so we can #include revisions.h without having to rebuild the entire
frontend every time we update.
(I'm using revisions.h to get the LLVM revision for use in preprocessor
conditionals. It should work with LLVM release 2.5, old trunk and new trunk)
author | Frits van Bommel <fvbommel wxs.nl> |
---|---|
date | Sun, 08 Mar 2009 16:13:10 +0100 |
parents | 330f999ade44 |
children | b30fe7e1dbb9 |
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()) | |
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 { | |
860 FuncDeclaration *fd = (FuncDeclaration *)vtbl->data[i]; | |
861 | |
862 //printf("\t[%d] = %s\n", i, fd->toChars()); | |
863 if (ident == fd->ident && | |
864 //tf->equals(fd->type) | |
865 fd->type->covariant(tf) == 1 | |
866 ) | |
867 { //printf("\t\tfound\n"); | |
868 return fd; | |
869 } | |
870 //else printf("\t\t%d\n", fd->type->covariant(tf)); | |
871 } | |
872 if (!cd) | |
873 break; | |
874 vtbl = &cd->vtblFinal; | |
875 cd = cd->baseClass; | |
876 } | |
877 | |
878 return NULL; | |
879 } | |
880 | |
881 void ClassDeclaration::interfaceSemantic(Scope *sc) | |
336 | 882 { |
159 | 883 vtblInterfaces = new BaseClasses(); |
884 vtblInterfaces->reserve(interfaces_dim); | |
885 | |
336 | 886 for (size_t i = 0; i < interfaces_dim; i++) |
159 | 887 { |
888 BaseClass *b = interfaces[i]; | |
889 | |
890 // If this is an interface, and it derives from a COM interface, | |
891 // then this is a COM interface too. | |
892 if (b->base->isCOMinterface()) | |
893 com = 1; | |
894 | |
895 vtblInterfaces->push(b); | |
896 b->copyBaseInterfaces(vtblInterfaces); | |
897 } | |
898 } | |
899 | |
900 /**************************************** | |
901 */ | |
902 | |
903 int ClassDeclaration::isCOMclass() | |
904 { | |
905 return com; | |
906 } | |
907 | |
908 int ClassDeclaration::isCOMinterface() | |
909 { | |
910 return 0; | |
911 } | |
912 | |
913 | |
914 /**************************************** | |
915 */ | |
916 | |
917 int ClassDeclaration::isAbstract() | |
918 { | |
919 if (isabstract) | |
920 return TRUE; | |
921 for (int i = 1; i < vtbl.dim; i++) | |
922 { | |
923 FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration(); | |
924 | |
925 //printf("\tvtbl[%d] = %p\n", i, fd); | |
926 if (!fd || fd->isAbstract()) | |
927 { | |
928 isabstract |= 1; | |
929 return TRUE; | |
930 } | |
931 } | |
932 return FALSE; | |
933 } | |
934 | |
336 | 935 |
159 | 936 /**************************************** |
937 * Returns !=0 if there's an extra member which is the 'this' | |
938 * pointer to the enclosing context (enclosing class or function) | |
939 */ | |
940 | |
941 int ClassDeclaration::isNested() | |
942 { | |
943 return isnested; | |
944 } | |
945 | |
946 /**************************************** | |
947 * Determine if slot 0 of the vtbl[] is reserved for something else. | |
948 * For class objects, yes, this is where the classinfo ptr goes. | |
949 * For COM interfaces, no. | |
950 * For non-COM interfaces, yes, this is where the Interface ptr goes. | |
951 */ | |
952 | |
953 int ClassDeclaration::vtblOffset() | |
954 { | |
955 return 1; | |
956 } | |
957 | |
958 /**************************************** | |
959 */ | |
960 | |
336 | 961 const char *ClassDeclaration::kind() |
159 | 962 { |
963 return "class"; | |
964 } | |
965 | |
966 /**************************************** | |
967 */ | |
968 | |
969 void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses) | |
970 { | |
971 aclasses->push(this); | |
972 } | |
973 | |
974 /********************************* InterfaceDeclaration ****************************/ | |
975 | |
976 InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses) | |
977 : ClassDeclaration(loc, id, baseclasses) | |
978 { | |
979 com = 0; | |
980 if (id == Id::IUnknown) // IUnknown is the root of all COM objects | |
981 com = 1; | |
982 } | |
983 | |
984 Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s) | |
985 { | |
986 InterfaceDeclaration *id; | |
987 | |
988 if (s) | |
989 id = (InterfaceDeclaration *)s; | |
990 else | |
991 id = new InterfaceDeclaration(loc, ident, NULL); | |
992 | |
993 ClassDeclaration::syntaxCopy(id); | |
994 return id; | |
995 } | |
996 | |
997 void InterfaceDeclaration::semantic(Scope *sc) | |
998 { int i; | |
999 | |
1000 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); | |
1001 if (inuse) | |
1002 return; | |
1003 if (!scope) | |
1004 { type = type->semantic(loc, sc); | |
1005 handle = handle->semantic(loc, sc); | |
1006 } | |
1007 if (!members) // if forward reference | |
1008 { //printf("\tinterface '%s' is forward referenced\n", toChars()); | |
1009 return; | |
1010 } | |
1011 if (symtab) // if already done | |
1012 { if (!scope) | |
1013 return; | |
1014 } | |
1015 else | |
1016 symtab = new DsymbolTable(); | |
1017 | |
1018 Scope *scx = NULL; | |
1019 if (scope) | |
1020 { sc = scope; | |
1021 scx = scope; // save so we don't make redundant copies | |
1022 scope = NULL; | |
1023 } | |
1024 | |
1025 if (sc->stc & STCdeprecated) | |
1026 { | |
1027 isdeprecated = 1; | |
1028 } | |
1029 | |
1030 // Expand any tuples in baseclasses[] | |
1031 for (i = 0; i < baseclasses.dim; ) | |
1032 { BaseClass *b = (BaseClass *)baseclasses.data[0]; | |
1033 b->type = b->type->semantic(loc, sc); | |
1034 Type *tb = b->type->toBasetype(); | |
1035 | |
1036 if (tb->ty == Ttuple) | |
1037 { TypeTuple *tup = (TypeTuple *)tb; | |
1038 enum PROT protection = b->protection; | |
1039 baseclasses.remove(i); | |
1040 size_t dim = Argument::dim(tup->arguments); | |
1041 for (size_t j = 0; j < dim; j++) | |
1042 { Argument *arg = Argument::getNth(tup->arguments, j); | |
1043 b = new BaseClass(arg->type, protection); | |
1044 baseclasses.insert(i + j, b); | |
1045 } | |
1046 } | |
1047 else | |
1048 i++; | |
1049 } | |
1050 | |
1051 // Check for errors, handle forward references | |
1052 for (i = 0; i < baseclasses.dim; ) | |
1053 { TypeClass *tc; | |
1054 BaseClass *b; | |
1055 Type *tb; | |
1056 | |
1057 b = (BaseClass *)baseclasses.data[i]; | |
1058 b->type = b->type->semantic(loc, sc); | |
1059 tb = b->type->toBasetype(); | |
1060 if (tb->ty == Tclass) | |
1061 tc = (TypeClass *)tb; | |
1062 else | |
1063 tc = NULL; | |
1064 if (!tc || !tc->sym->isInterfaceDeclaration()) | |
1065 { | |
1066 error("base type must be interface, not %s", b->type->toChars()); | |
1067 baseclasses.remove(i); | |
1068 continue; | |
1069 } | |
1070 else | |
1071 { | |
1072 // Check for duplicate interfaces | |
1073 for (size_t j = 0; j < i; j++) | |
1074 { | |
1075 BaseClass *b2 = (BaseClass *)baseclasses.data[j]; | |
1076 if (b2->base == tc->sym) | |
1077 error("inherits from duplicate interface %s", b2->base->toChars()); | |
1078 } | |
1079 | |
1080 b->base = tc->sym; | |
1081 if (b->base == this || isBaseOf2(b->base)) | |
1082 { | |
1083 error("circular inheritance of interface"); | |
1084 baseclasses.remove(i); | |
1085 continue; | |
1086 } | |
1087 if (!b->base->symtab || b->base->scope || b->base->inuse) | |
1088 { | |
1089 //error("forward reference of base class %s", baseClass->toChars()); | |
1090 // Forward reference of base, try again later | |
1091 //printf("\ttry later, forward reference of base %s\n", b->base->toChars()); | |
1092 scope = scx ? scx : new Scope(*sc); | |
1093 scope->setNoFree(); | |
1094 scope->module->addDeferredSemantic(this); | |
1095 return; | |
1096 } | |
1097 } | |
1098 i++; | |
1099 } | |
1100 | |
1101 interfaces_dim = baseclasses.dim; | |
1102 interfaces = (BaseClass **)baseclasses.data; | |
1103 | |
1104 interfaceSemantic(sc); | |
1105 | |
1106 if (vtblOffset()) | |
1107 vtbl.push(this); // leave room at vtbl[0] for classinfo | |
1108 | |
1109 // Cat together the vtbl[]'s from base interfaces | |
1110 for (i = 0; i < interfaces_dim; i++) | |
1111 { BaseClass *b = interfaces[i]; | |
1112 | |
1113 // Skip if b has already appeared | |
1114 for (int k = 0; k < i; k++) | |
1115 { | |
1116 if (b == interfaces[i]) | |
1117 goto Lcontinue; | |
1118 } | |
1119 | |
1120 // Copy vtbl[] from base class | |
1121 if (b->base->vtblOffset()) | |
1122 { int d = b->base->vtbl.dim; | |
1123 if (d > 1) | |
1124 { | |
1125 vtbl.reserve(d - 1); | |
1126 for (int j = 1; j < d; j++) | |
1127 vtbl.push(b->base->vtbl.data[j]); | |
1128 } | |
1129 } | |
1130 else | |
1131 { | |
1132 vtbl.append(&b->base->vtbl); | |
1133 } | |
1134 | |
1135 Lcontinue: | |
1136 ; | |
1137 } | |
1138 | |
1139 for (i = 0; i < members->dim; i++) | |
1140 { | |
1141 Dsymbol *s = (Dsymbol *)members->data[i]; | |
1142 s->addMember(sc, this, 1); | |
1143 } | |
1144 | |
1145 sc = sc->push(this); | |
1146 sc->parent = this; | |
1147 if (isCOMinterface()) | |
1148 sc->linkage = LINKwindows; | |
1149 sc->structalign = 8; | |
1150 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
|
1151 sc->offset = 2*PTRSIZE; |
159 | 1152 inuse++; |
1153 for (i = 0; i < members->dim; i++) | |
1154 { | |
1155 Dsymbol *s = (Dsymbol *)members->data[i]; | |
1156 s->semantic(sc); | |
1157 } | |
1158 inuse--; | |
1159 //members->print(); | |
1160 sc->pop(); | |
1161 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); | |
1162 } | |
1163 | |
1164 | |
1165 /******************************************* | |
1166 * Determine if 'this' is a base class of cd. | |
1167 * (Actually, if it is an interface supported by cd) | |
1168 * Output: | |
1169 * *poffset offset to start of class | |
1170 * OFFSET_RUNTIME must determine offset at runtime | |
1171 * Returns: | |
1172 * 0 not a base | |
1173 * 1 is a base | |
1174 */ | |
1175 | |
1176 int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) | |
1177 { | |
1178 unsigned j; | |
1179 | |
1180 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars()); | |
1181 assert(!baseClass); | |
1182 for (j = 0; j < cd->interfaces_dim; j++) | |
1183 { | |
1184 BaseClass *b = cd->interfaces[j]; | |
1185 | |
1186 //printf("\tbase %s\n", b->base->toChars()); | |
1187 if (this == b->base) | |
1188 { | |
1189 //printf("\tfound at offset %d\n", b->offset); | |
1190 if (poffset) | |
1191 { *poffset = b->offset; | |
1192 if (j && cd->isInterfaceDeclaration()) | |
1193 *poffset = OFFSET_RUNTIME; | |
1194 } | |
1195 return 1; | |
1196 } | |
1197 if (isBaseOf(b, poffset)) | |
1198 { if (j && poffset && cd->isInterfaceDeclaration()) | |
1199 *poffset = OFFSET_RUNTIME; | |
1200 return 1; | |
1201 } | |
1202 } | |
1203 | |
1204 if (cd->baseClass && isBaseOf(cd->baseClass, poffset)) | |
1205 return 1; | |
1206 | |
1207 if (poffset) | |
1208 *poffset = 0; | |
1209 return 0; | |
1210 } | |
1211 | |
1212 | |
1213 int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset) | |
1214 { | |
1215 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars()); | |
1216 for (unsigned j = 0; j < bc->baseInterfaces_dim; j++) | |
1217 { | |
1218 BaseClass *b = &bc->baseInterfaces[j]; | |
1219 | |
1220 if (this == b->base) | |
1221 { | |
1222 if (poffset) | |
1223 { *poffset = b->offset; | |
1224 } | |
1225 return 1; | |
1226 } | |
1227 if (isBaseOf(b, poffset)) | |
1228 { | |
1229 return 1; | |
1230 } | |
1231 } | |
1232 if (poffset) | |
1233 *poffset = 0; | |
1234 return 0; | |
1235 } | |
1236 | |
1237 /**************************************** | |
1238 * Determine if slot 0 of the vtbl[] is reserved for something else. | |
1239 * For class objects, yes, this is where the ClassInfo ptr goes. | |
1240 * For COM interfaces, no. | |
1241 * For non-COM interfaces, yes, this is where the Interface ptr goes. | |
1242 */ | |
1243 | |
1244 int InterfaceDeclaration::vtblOffset() | |
1245 { | |
1246 if (isCOMinterface()) | |
1247 return 0; | |
1248 return 1; | |
1249 } | |
1250 | |
1251 int InterfaceDeclaration::isCOMinterface() | |
1252 { | |
1253 return com; | |
1254 } | |
1255 | |
1256 /******************************************* | |
1257 */ | |
1258 | |
336 | 1259 const char *InterfaceDeclaration::kind() |
159 | 1260 { |
1261 return "interface"; | |
1262 } | |
1263 | |
1264 | |
1265 /******************************** BaseClass *****************************/ | |
1266 | |
1267 BaseClass::BaseClass() | |
1268 { | |
1269 memset(this, 0, sizeof(BaseClass)); | |
1270 } | |
1271 | |
1272 BaseClass::BaseClass(Type *type, enum PROT protection) | |
1273 { | |
1274 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars()); | |
1275 this->type = type; | |
1276 this->protection = protection; | |
1277 base = NULL; | |
1278 offset = 0; | |
1279 | |
1280 baseInterfaces_dim = 0; | |
1281 baseInterfaces = NULL; | |
1282 } | |
1283 | |
1284 /**************************************** | |
1285 * Fill in vtbl[] for base class based on member functions of class cd. | |
1286 * Input: | |
1287 * vtbl if !=NULL, fill it in | |
1288 * newinstance !=0 means all entries must be filled in by members | |
1289 * of cd, not members of any base classes of cd. | |
1290 * Returns: | |
1291 * !=0 if any entries were filled in by members of cd (not exclusively | |
1292 * by base classes) | |
1293 */ | |
1294 | |
1295 int BaseClass::fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance) | |
1296 { | |
1297 ClassDeclaration *id = base; | |
1298 int j; | |
1299 int result = 0; | |
1300 | |
1301 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars()); | |
1302 if (vtbl) | |
1303 vtbl->setDim(base->vtbl.dim); | |
1304 | |
1305 // first entry is ClassInfo reference | |
1306 for (j = base->vtblOffset(); j < base->vtbl.dim; j++) | |
1307 { | |
1308 FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration(); | |
1309 FuncDeclaration *fd; | |
1310 TypeFunction *tf; | |
1311 | |
1312 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null"); | |
1313 | |
1314 assert(ifd); | |
1315 // Find corresponding function in this class | |
1316 tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL; | |
1317 fd = cd->findFunc(ifd->ident, tf); | |
1318 if (fd && !fd->isAbstract()) | |
1319 { | |
1320 //printf(" found\n"); | |
1321 // Check that calling conventions match | |
1322 if (fd->linkage != ifd->linkage) | |
1323 fd->error("linkage doesn't match interface function"); | |
1324 | |
1325 // Check that it is current | |
1326 if (newinstance && | |
1327 fd->toParent() != cd && | |
1328 ifd->toParent() == base) | |
1329 cd->error("interface function %s.%s is not implemented", | |
1330 id->toChars(), ifd->ident->toChars()); | |
1331 | |
1332 if (fd->toParent() == cd) | |
1333 result = 1; | |
1334 } | |
1335 else | |
1336 { | |
1337 //printf(" not found\n"); | |
1338 // BUG: should mark this class as abstract? | |
1339 if (!cd->isAbstract()) | |
1340 cd->error("interface function %s.%s isn't implemented", | |
1341 id->toChars(), ifd->ident->toChars()); | |
1342 fd = NULL; | |
1343 } | |
1344 if (vtbl) | |
1345 vtbl->data[j] = fd; | |
1346 } | |
1347 | |
1348 return result; | |
1349 } | |
1350 | |
1351 void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces) | |
1352 { | |
1353 //printf("+copyBaseInterfaces(), %s\n", base->toChars()); | |
1354 // if (baseInterfaces_dim) | |
1355 // return; | |
1356 | |
1357 baseInterfaces_dim = base->interfaces_dim; | |
1358 baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass)); | |
1359 | |
1360 //printf("%s.copyBaseInterfaces()\n", base->toChars()); | |
1361 for (int i = 0; i < baseInterfaces_dim; i++) | |
1362 { | |
1363 BaseClass *b = &baseInterfaces[i]; | |
1364 BaseClass *b2 = base->interfaces[i]; | |
1365 | |
1366 assert(b2->vtbl.dim == 0); // should not be filled yet | |
1367 memcpy(b, b2, sizeof(BaseClass)); | |
1368 | |
1369 if (i) // single inheritance is i==0 | |
1370 vtblInterfaces->push(b); // only need for M.I. | |
1371 b->copyBaseInterfaces(vtblInterfaces); | |
1372 } | |
1373 //printf("-copyBaseInterfaces\n"); | |
1374 } |