Mercurial > projects > ldc
annotate dmd/class.c @ 1650:40bd4a0d4870
Update to work with LLVM 2.7.
Removed use of dyn_cast, llvm no compiles
without exceptions and rtti by
default. We do need exceptions for the libconfig stuff, but rtti isn't
necessary (anymore).
Debug info needs to be rewritten, as in LLVM 2.7 the format has
completely changed. To have something to look at while rewriting, the
old code has been wrapped inside #ifndef DISABLE_DEBUG_INFO , this means
that you have to define this to compile at the moment.
Updated tango 0.99.9 patch to include updated EH runtime code, which is
needed for LLVM 2.7 as well.
author | Tomas Lindquist Olsen |
---|---|
date | Wed, 19 May 2010 12:42:32 +0200 |
parents | 44b145be2ef5 |
children |
rev | line source |
---|---|
159 | 1 |
2 // Compiler implementation of the D programming language | |
1587 | 3 // Copyright (c) 1999-2009 by Digital Mars |
159 | 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 | |
1146
1860414bf3b7
* Moved ir/irsymbol.cpp/h into ir/irdsymbol.cpp/h.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1103
diff
changeset
|
60 #if IN_DMD |
159 | 61 vtblsym = NULL; |
1146
1860414bf3b7
* Moved ir/irsymbol.cpp/h into ir/irdsymbol.cpp/h.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1103
diff
changeset
|
62 #endif |
159 | 63 vclassinfo = NULL; |
64 | |
65 if (id) | |
66 { // Look for special class names | |
67 | |
68 if (id == Id::__sizeof || id == Id::alignof || id == Id::mangleof) | |
69 error("illegal class name"); | |
70 | |
71 // BUG: What if this is the wrong TypeInfo, i.e. it is nested? | |
72 if (id->toChars()[0] == 'T') | |
73 { | |
74 if (id == Id::TypeInfo) | |
75 { if (Type::typeinfo) | |
76 Type::typeinfo->error("%s", msg); | |
77 Type::typeinfo = this; | |
78 } | |
79 | |
80 if (id == Id::TypeInfo_Class) | |
81 { if (Type::typeinfoclass) | |
82 Type::typeinfoclass->error("%s", msg); | |
83 Type::typeinfoclass = this; | |
84 } | |
85 | |
86 if (id == Id::TypeInfo_Interface) | |
87 { if (Type::typeinfointerface) | |
88 Type::typeinfointerface->error("%s", msg); | |
89 Type::typeinfointerface = this; | |
90 } | |
91 | |
92 if (id == Id::TypeInfo_Struct) | |
93 { if (Type::typeinfostruct) | |
94 Type::typeinfostruct->error("%s", msg); | |
95 Type::typeinfostruct = this; | |
96 } | |
97 | |
98 if (id == Id::TypeInfo_Typedef) | |
99 { if (Type::typeinfotypedef) | |
100 Type::typeinfotypedef->error("%s", msg); | |
101 Type::typeinfotypedef = this; | |
102 } | |
103 | |
104 if (id == Id::TypeInfo_Pointer) | |
105 { if (Type::typeinfopointer) | |
106 Type::typeinfopointer->error("%s", msg); | |
107 Type::typeinfopointer = this; | |
108 } | |
109 | |
110 if (id == Id::TypeInfo_Array) | |
111 { if (Type::typeinfoarray) | |
112 Type::typeinfoarray->error("%s", msg); | |
113 Type::typeinfoarray = this; | |
114 } | |
115 | |
116 if (id == Id::TypeInfo_StaticArray) | |
117 { //if (Type::typeinfostaticarray) | |
118 //Type::typeinfostaticarray->error("%s", msg); | |
119 Type::typeinfostaticarray = this; | |
120 } | |
121 | |
122 if (id == Id::TypeInfo_AssociativeArray) | |
123 { if (Type::typeinfoassociativearray) | |
124 Type::typeinfoassociativearray->error("%s", msg); | |
125 Type::typeinfoassociativearray = this; | |
126 } | |
127 | |
128 if (id == Id::TypeInfo_Enum) | |
129 { if (Type::typeinfoenum) | |
130 Type::typeinfoenum->error("%s", msg); | |
131 Type::typeinfoenum = this; | |
132 } | |
133 | |
134 if (id == Id::TypeInfo_Function) | |
135 { if (Type::typeinfofunction) | |
136 Type::typeinfofunction->error("%s", msg); | |
137 Type::typeinfofunction = this; | |
138 } | |
139 | |
140 if (id == Id::TypeInfo_Delegate) | |
141 { if (Type::typeinfodelegate) | |
142 Type::typeinfodelegate->error("%s", msg); | |
143 Type::typeinfodelegate = this; | |
144 } | |
145 | |
146 if (id == Id::TypeInfo_Tuple) | |
147 { if (Type::typeinfotypelist) | |
148 Type::typeinfotypelist->error("%s", msg); | |
149 Type::typeinfotypelist = this; | |
150 } | |
151 | |
336 | 152 #if DMDV2 |
159 | 153 if (id == Id::TypeInfo_Const) |
154 { if (Type::typeinfoconst) | |
155 Type::typeinfoconst->error("%s", msg); | |
156 Type::typeinfoconst = this; | |
157 } | |
158 | |
159 if (id == Id::TypeInfo_Invariant) | |
160 { if (Type::typeinfoinvariant) | |
161 Type::typeinfoinvariant->error("%s", msg); | |
162 Type::typeinfoinvariant = this; | |
163 } | |
1587 | 164 |
165 if (id == Id::TypeInfo_Shared) | |
166 { if (Type::typeinfoshared) | |
167 Type::typeinfoshared->error("%s", msg); | |
168 Type::typeinfoshared = this; | |
169 } | |
159 | 170 #endif |
171 } | |
172 | |
173 if (id == Id::Object) | |
174 { if (object) | |
175 object->error("%s", msg); | |
176 object = this; | |
177 } | |
178 | |
179 if (id == Id::ClassInfo) | |
180 { if (classinfo) | |
181 classinfo->error("%s", msg); | |
182 classinfo = this; | |
183 } | |
184 | |
185 if (id == Id::ModuleInfo) | |
186 { if (Module::moduleinfo) | |
187 Module::moduleinfo->error("%s", msg); | |
188 Module::moduleinfo = this; | |
189 } | |
190 } | |
191 | |
192 com = 0; | |
1530
05c235309d6f
Make the auto storage class never have the same meaning as scope.
Christian Kamm <kamm incasoftware de>
parents:
1367
diff
changeset
|
193 isscope = 0; |
159 | 194 isabstract = 0; |
195 isnested = 0; | |
196 vthis = NULL; | |
197 inuse = 0; | |
198 } | |
199 | |
200 Dsymbol *ClassDeclaration::syntaxCopy(Dsymbol *s) | |
201 { | |
202 ClassDeclaration *cd; | |
203 | |
204 //printf("ClassDeclaration::syntaxCopy('%s')\n", toChars()); | |
205 if (s) | |
206 cd = (ClassDeclaration *)s; | |
207 else | |
208 cd = new ClassDeclaration(loc, ident, NULL); | |
209 | |
210 cd->storage_class |= storage_class; | |
211 | |
212 cd->baseclasses.setDim(this->baseclasses.dim); | |
213 for (int i = 0; i < cd->baseclasses.dim; i++) | |
214 { | |
215 BaseClass *b = (BaseClass *)this->baseclasses.data[i]; | |
216 BaseClass *b2 = new BaseClass(b->type->syntaxCopy(), b->protection); | |
217 cd->baseclasses.data[i] = b2; | |
218 } | |
219 | |
220 ScopeDsymbol::syntaxCopy(cd); | |
221 return cd; | |
222 } | |
223 | |
224 void ClassDeclaration::semantic(Scope *sc) | |
225 { int i; | |
226 unsigned offset; | |
227 | |
228 //printf("ClassDeclaration::semantic(%s), type = %p, sizeok = %d, this = %p\n", toChars(), type, sizeok, this); | |
229 //printf("\tparent = %p, '%s'\n", sc->parent, sc->parent ? sc->parent->toChars() : ""); | |
230 //printf("sc->stc = %x\n", sc->stc); | |
231 | |
232 //{ static int n; if (++n == 20) *(char*)0=0; } | |
233 | |
234 if (!ident) // if anonymous class | |
1587 | 235 { const char *id = "__anonclass"; |
159 | 236 |
237 ident = Identifier::generateId(id); | |
238 } | |
239 | |
1587 | 240 if (!sc) |
241 sc = scope; | |
242 if (!parent && sc->parent && !sc->parent->isModule()) | |
243 parent = sc->parent; | |
159 | 244 |
1587 | 245 type = type->semantic(loc, sc); |
246 handle = type; | |
247 | |
159 | 248 if (!members) // if forward reference |
249 { //printf("\tclass '%s' is forward referenced\n", toChars()); | |
250 return; | |
251 } | |
252 if (symtab) | |
1628
6c36e3f49b28
Merge DMD r324: bugzilla 3663 and 3664 - fwd ref regressions
Leandro Lucarella <llucax@gmail.com>
parents:
1625
diff
changeset
|
253 { if (sizeok == 1 || !scope) |
159 | 254 { //printf("\tsemantic for '%s' is already completed\n", toChars()); |
255 return; // semantic() already completed | |
256 } | |
257 } | |
258 else | |
259 symtab = new DsymbolTable(); | |
260 | |
261 Scope *scx = NULL; | |
262 if (scope) | |
263 { sc = scope; | |
264 scx = scope; // save so we don't make redundant copies | |
265 scope = NULL; | |
266 } | |
1630
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1628
diff
changeset
|
267 unsigned dprogress_save = Module::dprogress; |
159 | 268 #ifdef IN_GCC |
269 methods.setDim(0); | |
270 #endif | |
271 | |
272 if (sc->stc & STCdeprecated) | |
336 | 273 { |
159 | 274 isdeprecated = 1; |
275 } | |
276 | |
277 // Expand any tuples in baseclasses[] | |
278 for (i = 0; i < baseclasses.dim; ) | |
279 { BaseClass *b = (BaseClass *)baseclasses.data[i]; | |
280 b->type = b->type->semantic(loc, sc); | |
281 Type *tb = b->type->toBasetype(); | |
282 | |
283 if (tb->ty == Ttuple) | |
284 { TypeTuple *tup = (TypeTuple *)tb; | |
285 enum PROT protection = b->protection; | |
286 baseclasses.remove(i); | |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
287 size_t dim = Parameter::dim(tup->arguments); |
159 | 288 for (size_t j = 0; j < dim; j++) |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
289 { Parameter *arg = Parameter::getNth(tup->arguments, j); |
159 | 290 b = new BaseClass(arg->type, protection); |
291 baseclasses.insert(i + j, b); | |
292 } | |
293 } | |
294 else | |
295 i++; | |
296 } | |
297 | |
298 // See if there's a base class as first in baseclasses[] | |
299 if (baseclasses.dim) | |
300 { TypeClass *tc; | |
301 BaseClass *b; | |
302 Type *tb; | |
303 | |
304 b = (BaseClass *)baseclasses.data[0]; | |
305 //b->type = b->type->semantic(loc, sc); | |
306 tb = b->type->toBasetype(); | |
307 if (tb->ty != Tclass) | |
308 { error("base type must be class or interface, not %s", b->type->toChars()); | |
309 baseclasses.remove(0); | |
310 } | |
311 else | |
312 { | |
313 tc = (TypeClass *)(tb); | |
336 | 314 |
159 | 315 if (tc->sym->isDeprecated()) |
316 { | |
317 if (!isDeprecated()) | |
318 { | |
319 // Deriving from deprecated class makes this one deprecated too | |
320 isdeprecated = 1; | |
321 | |
322 tc->checkDeprecated(loc, sc); | |
323 } | |
324 } | |
325 | |
326 if (tc->sym->isInterfaceDeclaration()) | |
327 ; | |
328 else | |
329 { | |
330 for (ClassDeclaration *cdb = tc->sym; cdb; cdb = cdb->baseClass) | |
331 { | |
332 if (cdb == this) | |
333 { | |
334 error("circular inheritance"); | |
335 baseclasses.remove(0); | |
336 goto L7; | |
337 } | |
338 } | |
1587 | 339 if (!tc->sym->symtab || tc->sym->sizeok == 0) |
340 { // Try to resolve forward reference | |
341 if (sc->mustsemantic && tc->sym->scope) | |
342 tc->sym->semantic(NULL); | |
343 } | |
159 | 344 if (!tc->sym->symtab || tc->sym->scope || tc->sym->sizeok == 0) |
345 { | |
1587 | 346 //printf("%s: forward reference of base class %s\n", toChars(), tc->sym->toChars()); |
159 | 347 //error("forward reference of base class %s", baseClass->toChars()); |
348 // Forward reference of base class, try again later | |
349 //printf("\ttry later, forward reference of base class %s\n", tc->sym->toChars()); | |
350 scope = scx ? scx : new Scope(*sc); | |
351 scope->setNoFree(); | |
1587 | 352 if (tc->sym->scope) |
353 tc->sym->scope->module->addDeferredSemantic(tc->sym); | |
159 | 354 scope->module->addDeferredSemantic(this); |
355 return; | |
356 } | |
357 else | |
358 { baseClass = tc->sym; | |
359 b->base = baseClass; | |
360 } | |
361 L7: ; | |
362 } | |
363 } | |
364 } | |
365 | |
366 // Treat the remaining entries in baseclasses as interfaces | |
367 // Check for errors, handle forward references | |
368 for (i = (baseClass ? 1 : 0); i < baseclasses.dim; ) | |
369 { TypeClass *tc; | |
370 BaseClass *b; | |
371 Type *tb; | |
372 | |
373 b = (BaseClass *)baseclasses.data[i]; | |
374 b->type = b->type->semantic(loc, sc); | |
375 tb = b->type->toBasetype(); | |
376 if (tb->ty == Tclass) | |
377 tc = (TypeClass *)tb; | |
378 else | |
379 tc = NULL; | |
380 if (!tc || !tc->sym->isInterfaceDeclaration()) | |
381 { | |
382 error("base type must be interface, not %s", b->type->toChars()); | |
383 baseclasses.remove(i); | |
384 continue; | |
385 } | |
386 else | |
387 { | |
388 if (tc->sym->isDeprecated()) | |
389 { | |
390 if (!isDeprecated()) | |
391 { | |
392 // Deriving from deprecated class makes this one deprecated too | |
393 isdeprecated = 1; | |
394 | |
395 tc->checkDeprecated(loc, sc); | |
396 } | |
397 } | |
398 | |
399 // Check for duplicate interfaces | |
400 for (size_t j = (baseClass ? 1 : 0); j < i; j++) | |
401 { | |
402 BaseClass *b2 = (BaseClass *)baseclasses.data[j]; | |
403 if (b2->base == tc->sym) | |
404 error("inherits from duplicate interface %s", b2->base->toChars()); | |
405 } | |
406 | |
1587 | 407 if (!tc->sym->symtab) |
408 { // Try to resolve forward reference | |
409 if (sc->mustsemantic && tc->sym->scope) | |
410 tc->sym->semantic(NULL); | |
411 } | |
412 | |
159 | 413 b->base = tc->sym; |
414 if (!b->base->symtab || b->base->scope) | |
415 { | |
416 //error("forward reference of base class %s", baseClass->toChars()); | |
417 // Forward reference of base, try again later | |
418 //printf("\ttry later, forward reference of base %s\n", baseClass->toChars()); | |
419 scope = scx ? scx : new Scope(*sc); | |
420 scope->setNoFree(); | |
1587 | 421 if (tc->sym->scope) |
422 tc->sym->scope->module->addDeferredSemantic(tc->sym); | |
159 | 423 scope->module->addDeferredSemantic(this); |
424 return; | |
425 } | |
426 } | |
427 i++; | |
428 } | |
429 | |
430 | |
431 // If no base class, and this is not an Object, use Object as base class | |
432 if (!baseClass && ident != Id::Object) | |
433 { | |
434 // BUG: what if Object is redefined in an inner scope? | |
435 Type *tbase = new TypeIdentifier(0, Id::Object); | |
436 BaseClass *b; | |
437 TypeClass *tc; | |
438 Type *bt; | |
439 | |
440 if (!object) | |
441 { | |
442 error("missing or corrupt object.d"); | |
443 fatal(); | |
444 } | |
445 bt = tbase->semantic(loc, sc)->toBasetype(); | |
446 b = new BaseClass(bt, PROTpublic); | |
447 baseclasses.shift(b); | |
448 assert(b->type->ty == Tclass); | |
449 tc = (TypeClass *)(b->type); | |
450 baseClass = tc->sym; | |
451 assert(!baseClass->isInterfaceDeclaration()); | |
452 b->base = baseClass; | |
453 } | |
454 | |
455 interfaces_dim = baseclasses.dim; | |
456 interfaces = (BaseClass **)baseclasses.data; | |
457 | |
458 | |
459 if (baseClass) | |
460 { | |
461 if (baseClass->storage_class & STCfinal) | |
462 error("cannot inherit from final class %s", baseClass->toChars()); | |
463 | |
464 interfaces_dim--; | |
465 interfaces++; | |
466 | |
467 // Copy vtbl[] from base class | |
468 vtbl.setDim(baseClass->vtbl.dim); | |
469 memcpy(vtbl.data, baseClass->vtbl.data, sizeof(void *) * vtbl.dim); | |
470 | |
471 // Inherit properties from base class | |
472 com = baseClass->isCOMclass(); | |
1530
05c235309d6f
Make the auto storage class never have the same meaning as scope.
Christian Kamm <kamm incasoftware de>
parents:
1367
diff
changeset
|
473 isscope = baseClass->isscope; |
159 | 474 vthis = baseClass->vthis; |
475 } | |
476 else | |
477 { | |
478 // No base class, so this is the root of the class hierarchy | |
479 vtbl.setDim(0); | |
480 vtbl.push(this); // leave room for classinfo as first member | |
481 } | |
482 | |
483 protection = sc->protection; | |
484 storage_class |= sc->stc; | |
485 | |
486 if (sizeok == 0) | |
487 { | |
488 interfaceSemantic(sc); | |
489 | |
490 for (i = 0; i < members->dim; i++) | |
491 { | |
492 Dsymbol *s = (Dsymbol *)members->data[i]; | |
493 s->addMember(sc, this, 1); | |
494 } | |
495 | |
496 /* If this is a nested class, add the hidden 'this' | |
497 * member which is a pointer to the enclosing scope. | |
498 */ | |
499 if (vthis) // if inheriting from nested class | |
500 { // Use the base class's 'this' member | |
501 isnested = 1; | |
502 if (storage_class & STCstatic) | |
503 error("static class cannot inherit from nested class %s", baseClass->toChars()); | |
504 if (toParent2() != baseClass->toParent2()) | |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
505 { |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
506 if (toParent2()) |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
507 { |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
508 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
|
509 toParent2()->toChars(), |
159 | 510 baseClass->toChars(), |
658
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
511 baseClass->toParent2()->toChars()); |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
512 } |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
513 else |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
514 { |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
515 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
|
516 baseClass->toChars(), |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
517 baseClass->toParent2()->toChars()); |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
518 } |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
519 isnested = 0; |
50383e476c7e
Upgraded frontend to DMD 1.035
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
336
diff
changeset
|
520 } |
159 | 521 } |
522 else if (!(storage_class & STCstatic)) | |
523 { Dsymbol *s = toParent2(); | |
524 if (s) | |
525 { | |
1587 | 526 AggregateDeclaration *ad = s->isClassDeclaration(); |
159 | 527 FuncDeclaration *fd = s->isFuncDeclaration(); |
528 | |
529 | |
1587 | 530 if (ad || fd) |
159 | 531 { isnested = 1; |
532 Type *t; | |
1587 | 533 if (ad) |
534 t = ad->handle; | |
159 | 535 else if (fd) |
536 { AggregateDeclaration *ad = fd->isMember2(); | |
537 if (ad) | |
538 t = ad->handle; | |
539 else | |
540 { | |
541 t = new TypePointer(Type::tvoid); | |
542 t = t->semantic(0, sc); | |
543 } | |
544 } | |
545 else | |
546 assert(0); | |
547 assert(!vthis); | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1358
diff
changeset
|
548 vthis = new ThisDeclaration(loc, t); |
159 | 549 members->push(vthis); |
550 } | |
551 } | |
552 } | |
553 } | |
554 | |
1530
05c235309d6f
Make the auto storage class never have the same meaning as scope.
Christian Kamm <kamm incasoftware de>
parents:
1367
diff
changeset
|
555 if (storage_class & STCauto) |
05c235309d6f
Make the auto storage class never have the same meaning as scope.
Christian Kamm <kamm incasoftware de>
parents:
1367
diff
changeset
|
556 error("storage class has no effect: auto"); |
05c235309d6f
Make the auto storage class never have the same meaning as scope.
Christian Kamm <kamm incasoftware de>
parents:
1367
diff
changeset
|
557 if (storage_class & STCscope) |
05c235309d6f
Make the auto storage class never have the same meaning as scope.
Christian Kamm <kamm incasoftware de>
parents:
1367
diff
changeset
|
558 isscope = 1; |
159 | 559 if (storage_class & STCabstract) |
560 isabstract = 1; | |
561 | |
562 sc = sc->push(this); | |
563 sc->stc &= ~(STCfinal | STCauto | STCscope | STCstatic | | |
564 STCabstract | STCdeprecated); | |
565 sc->parent = this; | |
566 sc->inunion = 0; | |
567 | |
568 if (isCOMclass()) | |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
569 { |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
570 #if _WIN32 |
159 | 571 sc->linkage = LINKwindows; |
875
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
572 #else |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
573 /* 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
|
574 * work with things like XPCOM |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
575 */ |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
576 sc->linkage = LINKc; |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
577 #endif |
330f999ade44
Merged DMD 1.038
Tomas Lindquist Olsen <tomas.l.olsen@gmail.com>
parents:
809
diff
changeset
|
578 } |
159 | 579 sc->protection = PROTpublic; |
580 sc->explicitProtection = 0; | |
581 sc->structalign = 8; | |
582 structalign = sc->structalign; | |
583 if (baseClass) | |
584 { sc->offset = baseClass->structsize; | |
585 alignsize = baseClass->alignsize; | |
586 // if (isnested) | |
587 // sc->offset += PTRSIZE; // room for uplevel context pointer | |
588 } | |
589 else | |
1587 | 590 { sc->offset = PTRSIZE * 2; // allow room for __vptr and __monitor |
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
|
591 alignsize = PTRSIZE; |
159 | 592 } |
593 structsize = sc->offset; | |
594 Scope scsave = *sc; | |
595 int members_dim = members->dim; | |
596 sizeok = 0; | |
1625
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
597 |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
598 /* Set scope so if there are forward references, we still might be able to |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
599 * resolve individual members like enums. |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
600 */ |
159 | 601 for (i = 0; i < members_dim; i++) |
1625
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
602 { Dsymbol *s = (Dsymbol *)members->data[i]; |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
603 /* There are problems doing this in the general case because |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
604 * Scope keeps track of things like 'offset' |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
605 */ |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
606 if (s->isEnumDeclaration() || (s->isAggregateDeclaration() && s->ident)) |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
607 { |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
608 //printf("setScope %s %s\n", s->kind(), s->toChars()); |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
609 s->setScope(sc); |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
610 } |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
611 } |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
612 |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
613 for (i = 0; i < members_dim; i++) |
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
614 { Dsymbol *s = (Dsymbol *)members->data[i]; |
159 | 615 s->semantic(sc); |
616 } | |
617 | |
618 if (sizeok == 2) | |
619 { // semantic() failed because of forward references. | |
620 // Unwind what we did, and defer it for later | |
621 fields.setDim(0); | |
622 structsize = 0; | |
623 alignsize = 0; | |
624 structalign = 0; | |
625 | |
626 sc = sc->pop(); | |
627 | |
628 scope = scx ? scx : new Scope(*sc); | |
629 scope->setNoFree(); | |
630 scope->module->addDeferredSemantic(this); | |
631 | |
1630
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1628
diff
changeset
|
632 Module::dprogress = dprogress_save; |
44b145be2ef5
Merge dmd 1.056.
Robert Clipsham <robert@octarineparrot.com>
parents:
1628
diff
changeset
|
633 |
336 | 634 //printf("\tsemantic('%s') failed due to forward references\n", toChars()); |
159 | 635 return; |
636 } | |
637 | |
638 //printf("\tsemantic('%s') successful\n", toChars()); | |
639 | |
640 structsize = sc->offset; | |
641 //members->print(); | |
642 | |
643 /* Look for special member functions. | |
644 * They must be in this class, not in a base class. | |
645 */ | |
646 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
|
647 if (ctor && (ctor->toParent() != this || !ctor->isCtorDeclaration())) |
159 | 648 ctor = NULL; |
649 | |
650 // dtor = (DtorDeclaration *)search(Id::dtor, 0); | |
651 // if (dtor && dtor->toParent() != this) | |
652 // dtor = NULL; | |
653 | |
654 // inv = (InvariantDeclaration *)search(Id::classInvariant, 0); | |
655 // if (inv && inv->toParent() != this) | |
656 // inv = NULL; | |
657 | |
658 // Can be in base class | |
659 aggNew = (NewDeclaration *)search(0, Id::classNew, 0); | |
660 aggDelete = (DeleteDeclaration *)search(0, Id::classDelete, 0); | |
661 | |
662 // If this class has no constructor, but base class does, create | |
663 // a constructor: | |
664 // this() { } | |
665 if (!ctor && baseClass && baseClass->ctor) | |
666 { | |
667 //printf("Creating default this(){} for class %s\n", toChars()); | |
336 | 668 ctor = new CtorDeclaration(loc, 0, NULL, 0); |
159 | 669 ctor->fbody = new CompoundStatement(0, new Statements()); |
670 members->push(ctor); | |
671 ctor->addMember(sc, this, 1); | |
672 *sc = scsave; // why? What about sc->nofree? | |
673 sc->offset = structsize; | |
674 ctor->semantic(sc); | |
675 defaultCtor = ctor; | |
676 } | |
677 | |
678 #if 0 | |
679 if (baseClass) | |
680 { if (!aggDelete) | |
681 aggDelete = baseClass->aggDelete; | |
682 if (!aggNew) | |
683 aggNew = baseClass->aggNew; | |
684 } | |
685 #endif | |
686 | |
687 // Allocate instance of each new interface | |
688 for (i = 0; i < vtblInterfaces->dim; i++) | |
689 { | |
690 BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; | |
691 unsigned thissize = PTRSIZE; | |
692 | |
693 alignmember(structalign, thissize, &sc->offset); | |
694 assert(b->offset == 0); | |
695 b->offset = sc->offset; | |
696 | |
697 // Take care of single inheritance offsets | |
698 while (b->baseInterfaces_dim) | |
699 { | |
700 b = &b->baseInterfaces[0]; | |
701 b->offset = sc->offset; | |
702 } | |
703 | |
704 sc->offset += thissize; | |
705 if (alignsize < thissize) | |
706 alignsize = thissize; | |
707 } | |
708 structsize = sc->offset; | |
709 sizeok = 1; | |
710 Module::dprogress++; | |
711 | |
712 dtor = buildDtor(sc); | |
713 | |
714 sc->pop(); | |
715 | |
716 #if 0 // Do not call until toObjfile() because of forward references | |
717 // Fill in base class vtbl[]s | |
718 for (i = 0; i < vtblInterfaces->dim; i++) | |
719 { | |
720 BaseClass *b = (BaseClass *)vtblInterfaces->data[i]; | |
721 | |
722 //b->fillVtbl(this, &b->vtbl, 1); | |
723 } | |
724 #endif | |
725 //printf("-ClassDeclaration::semantic(%s), type = %p\n", toChars(), type); | |
726 } | |
727 | |
728 void ClassDeclaration::toCBuffer(OutBuffer *buf, HdrGenState *hgs) | |
729 { | |
730 if (!isAnonymous()) | |
731 { | |
732 buf->printf("%s ", kind()); | |
733 buf->writestring(toChars()); | |
734 if (baseclasses.dim) | |
735 buf->writestring(" : "); | |
736 } | |
737 for (int i = 0; i < baseclasses.dim; i++) | |
738 { | |
739 BaseClass *b = (BaseClass *)baseclasses.data[i]; | |
740 | |
741 if (i) | |
742 buf->writeByte(','); | |
743 //buf->writestring(b->base->ident->toChars()); | |
744 b->type->toCBuffer(buf, NULL, hgs); | |
745 } | |
1587 | 746 if (members) |
159 | 747 { |
1587 | 748 buf->writenl(); |
749 buf->writeByte('{'); | |
750 buf->writenl(); | |
751 for (int i = 0; i < members->dim; i++) | |
752 { | |
753 Dsymbol *s = (Dsymbol *)members->data[i]; | |
159 | 754 |
1587 | 755 buf->writestring(" "); |
756 s->toCBuffer(buf, hgs); | |
757 } | |
758 buf->writestring("}"); | |
159 | 759 } |
1587 | 760 else |
761 buf->writeByte(';'); | |
159 | 762 buf->writenl(); |
763 } | |
764 | |
765 #if 0 | |
766 void ClassDeclaration::defineRef(Dsymbol *s) | |
767 { | |
768 ClassDeclaration *cd; | |
769 | |
770 AggregateDeclaration::defineRef(s); | |
771 cd = s->isClassDeclaration(); | |
772 baseType = cd->baseType; | |
773 cd->baseType = NULL; | |
774 } | |
775 #endif | |
776 | |
777 /********************************************* | |
778 * Determine if 'this' is a base class of cd. | |
779 * This is used to detect circular inheritance only. | |
780 */ | |
781 | |
782 int ClassDeclaration::isBaseOf2(ClassDeclaration *cd) | |
783 { | |
784 if (!cd) | |
785 return 0; | |
786 //printf("ClassDeclaration::isBaseOf2(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); | |
787 for (int i = 0; i < cd->baseclasses.dim; i++) | |
788 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i]; | |
789 | |
790 if (b->base == this || isBaseOf2(b->base)) | |
791 return 1; | |
792 } | |
793 return 0; | |
794 } | |
795 | |
796 /******************************************* | |
797 * Determine if 'this' is a base class of cd. | |
798 */ | |
799 | |
800 int ClassDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) | |
801 { | |
802 //printf("ClassDeclaration::isBaseOf(this = '%s', cd = '%s')\n", toChars(), cd->toChars()); | |
803 if (poffset) | |
804 *poffset = 0; | |
805 while (cd) | |
806 { | |
807 if (this == cd->baseClass) | |
808 return 1; | |
809 | |
810 /* cd->baseClass might not be set if cd is forward referenced. | |
811 */ | |
812 if (!cd->baseClass && cd->baseclasses.dim && !cd->isInterfaceDeclaration()) | |
813 { | |
814 cd->error("base class is forward referenced by %s", toChars()); | |
815 } | |
816 | |
817 cd = cd->baseClass; | |
818 } | |
819 return 0; | |
820 } | |
821 | |
822 Dsymbol *ClassDeclaration::search(Loc loc, Identifier *ident, int flags) | |
823 { | |
824 Dsymbol *s; | |
1587 | 825 //printf("%s.ClassDeclaration::search('%s')\n", toChars(), ident->toChars()); |
159 | 826 |
827 if (scope) | |
1587 | 828 { Scope *sc = scope; |
829 sc->mustsemantic++; | |
830 semantic(sc); | |
831 sc->mustsemantic--; | |
832 } | |
159 | 833 |
834 if (!members || !symtab || scope) | |
1587 | 835 { |
836 error("is forward referenced when looking for '%s'", ident->toChars()); | |
159 | 837 //*(char*)0=0; |
838 return NULL; | |
839 } | |
840 | |
841 s = ScopeDsymbol::search(loc, ident, flags); | |
842 if (!s) | |
843 { | |
844 // Search bases classes in depth-first, left to right order | |
845 | |
846 int i; | |
847 | |
848 for (i = 0; i < baseclasses.dim; i++) | |
849 { | |
850 BaseClass *b = (BaseClass *)baseclasses.data[i]; | |
851 | |
852 if (b->base) | |
853 { | |
854 if (!b->base->symtab) | |
855 error("base %s is forward referenced", b->base->ident->toChars()); | |
856 else | |
857 { | |
858 s = b->base->search(loc, ident, flags); | |
859 if (s == this) // happens if s is nested in this and derives from this | |
860 s = NULL; | |
861 else if (s) | |
862 break; | |
863 } | |
864 } | |
865 } | |
866 } | |
867 return s; | |
868 } | |
869 | |
870 /********************************************************** | |
871 * fd is in the vtbl[] for this class. | |
872 * Return 1 if function is hidden (not findable through search). | |
873 */ | |
874 | |
336 | 875 #if DMDV2 |
159 | 876 int isf(void *param, FuncDeclaration *fd) |
877 { | |
878 //printf("param = %p, fd = %p %s\n", param, fd, fd->toChars()); | |
879 return param == fd; | |
880 } | |
881 | |
882 int ClassDeclaration::isFuncHidden(FuncDeclaration *fd) | |
883 { | |
1587 | 884 //printf("ClassDeclaration::isFuncHidden(class = %s, fd = %s)\n", toChars(), fd->toChars()); |
159 | 885 Dsymbol *s = search(0, fd->ident, 4|2); |
886 if (!s) | |
887 { //printf("not found\n"); | |
888 /* Because, due to a hack, if there are multiple definitions | |
889 * of fd->ident, NULL is returned. | |
890 */ | |
891 return 0; | |
892 } | |
893 FuncDeclaration *fdstart = s->toAlias()->isFuncDeclaration(); | |
894 //printf("%s fdstart = %p\n", s->kind(), fdstart); | |
1358
78038e540342
Fix overload resolution issue in dmd bug 313/314 fix.
Christian Kamm <kamm incasoftware de>
parents:
1195
diff
changeset
|
895 return !overloadApply(getModule(), fdstart, &isf, fd); |
159 | 896 } |
897 #endif | |
898 | |
899 /**************** | |
900 * Find virtual function matching identifier and type. | |
901 * Used to build virtual function tables for interface implementations. | |
902 */ | |
903 | |
904 FuncDeclaration *ClassDeclaration::findFunc(Identifier *ident, TypeFunction *tf) | |
905 { | |
906 //printf("ClassDeclaration::findFunc(%s, %s) %s\n", ident->toChars(), tf->toChars(), toChars()); | |
907 | |
908 ClassDeclaration *cd = this; | |
909 Array *vtbl = &cd->vtbl; | |
910 while (1) | |
911 { | |
912 for (size_t i = 0; i < vtbl->dim; i++) | |
913 { | |
1103
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
875
diff
changeset
|
914 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
|
915 if (!fd) |
b30fe7e1dbb9
- Updated to DMD frontend 1.041.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
875
diff
changeset
|
916 continue; // the first entry might be a ClassInfo |
159 | 917 |
918 //printf("\t[%d] = %s\n", i, fd->toChars()); | |
919 if (ident == fd->ident && | |
920 //tf->equals(fd->type) | |
921 fd->type->covariant(tf) == 1 | |
922 ) | |
923 { //printf("\t\tfound\n"); | |
924 return fd; | |
925 } | |
926 //else printf("\t\t%d\n", fd->type->covariant(tf)); | |
927 } | |
928 if (!cd) | |
929 break; | |
930 vtbl = &cd->vtblFinal; | |
931 cd = cd->baseClass; | |
932 } | |
933 | |
934 return NULL; | |
935 } | |
936 | |
937 void ClassDeclaration::interfaceSemantic(Scope *sc) | |
336 | 938 { |
159 | 939 vtblInterfaces = new BaseClasses(); |
940 vtblInterfaces->reserve(interfaces_dim); | |
941 | |
336 | 942 for (size_t i = 0; i < interfaces_dim; i++) |
159 | 943 { |
944 BaseClass *b = interfaces[i]; | |
945 | |
946 // If this is an interface, and it derives from a COM interface, | |
947 // then this is a COM interface too. | |
948 if (b->base->isCOMinterface()) | |
949 com = 1; | |
950 | |
951 vtblInterfaces->push(b); | |
952 b->copyBaseInterfaces(vtblInterfaces); | |
953 } | |
954 } | |
955 | |
956 /**************************************** | |
957 */ | |
958 | |
959 int ClassDeclaration::isCOMclass() | |
960 { | |
961 return com; | |
962 } | |
963 | |
964 int ClassDeclaration::isCOMinterface() | |
965 { | |
966 return 0; | |
967 } | |
968 | |
1587 | 969 #if DMDV2 |
970 int ClassDeclaration::isCPPinterface() | |
971 { | |
972 return 0; | |
973 } | |
974 #endif | |
975 | |
159 | 976 |
977 /**************************************** | |
978 */ | |
979 | |
980 int ClassDeclaration::isAbstract() | |
981 { | |
982 if (isabstract) | |
983 return TRUE; | |
984 for (int i = 1; i < vtbl.dim; i++) | |
985 { | |
986 FuncDeclaration *fd = ((Dsymbol *)vtbl.data[i])->isFuncDeclaration(); | |
987 | |
988 //printf("\tvtbl[%d] = %p\n", i, fd); | |
989 if (!fd || fd->isAbstract()) | |
990 { | |
991 isabstract |= 1; | |
992 return TRUE; | |
993 } | |
994 } | |
995 return FALSE; | |
996 } | |
997 | |
336 | 998 |
159 | 999 /**************************************** |
1000 * Returns !=0 if there's an extra member which is the 'this' | |
1001 * pointer to the enclosing context (enclosing class or function) | |
1002 */ | |
1003 | |
1004 int ClassDeclaration::isNested() | |
1005 { | |
1006 return isnested; | |
1007 } | |
1008 | |
1009 /**************************************** | |
1010 * Determine if slot 0 of the vtbl[] is reserved for something else. | |
1011 * For class objects, yes, this is where the classinfo ptr goes. | |
1012 * For COM interfaces, no. | |
1013 * For non-COM interfaces, yes, this is where the Interface ptr goes. | |
1014 */ | |
1015 | |
1016 int ClassDeclaration::vtblOffset() | |
1017 { | |
1018 return 1; | |
1019 } | |
1020 | |
1021 /**************************************** | |
1022 */ | |
1023 | |
336 | 1024 const char *ClassDeclaration::kind() |
159 | 1025 { |
1026 return "class"; | |
1027 } | |
1028 | |
1029 /**************************************** | |
1030 */ | |
1031 | |
1032 void ClassDeclaration::addLocalClass(ClassDeclarations *aclasses) | |
1033 { | |
1034 aclasses->push(this); | |
1035 } | |
1036 | |
1037 /********************************* InterfaceDeclaration ****************************/ | |
1038 | |
1039 InterfaceDeclaration::InterfaceDeclaration(Loc loc, Identifier *id, BaseClasses *baseclasses) | |
1040 : ClassDeclaration(loc, id, baseclasses) | |
1041 { | |
1042 com = 0; | |
1043 if (id == Id::IUnknown) // IUnknown is the root of all COM objects | |
1044 com = 1; | |
1045 } | |
1046 | |
1047 Dsymbol *InterfaceDeclaration::syntaxCopy(Dsymbol *s) | |
1048 { | |
1049 InterfaceDeclaration *id; | |
1050 | |
1051 if (s) | |
1052 id = (InterfaceDeclaration *)s; | |
1053 else | |
1054 id = new InterfaceDeclaration(loc, ident, NULL); | |
1055 | |
1056 ClassDeclaration::syntaxCopy(id); | |
1057 return id; | |
1058 } | |
1059 | |
1060 void InterfaceDeclaration::semantic(Scope *sc) | |
1061 { int i; | |
1062 | |
1063 //printf("InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); | |
1064 if (inuse) | |
1065 return; | |
1587 | 1066 |
1067 if (!sc) | |
1068 sc = scope; | |
1069 if (!parent && sc->parent && !sc->parent->isModule()) | |
1070 parent = sc->parent; | |
1071 | |
1072 type = type->semantic(loc, sc); | |
1073 handle = type; | |
1074 | |
159 | 1075 if (!members) // if forward reference |
1076 { //printf("\tinterface '%s' is forward referenced\n", toChars()); | |
1077 return; | |
1078 } | |
1079 if (symtab) // if already done | |
1080 { if (!scope) | |
1081 return; | |
1082 } | |
1083 else | |
1084 symtab = new DsymbolTable(); | |
1085 | |
1086 Scope *scx = NULL; | |
1087 if (scope) | |
1088 { sc = scope; | |
1089 scx = scope; // save so we don't make redundant copies | |
1090 scope = NULL; | |
1091 } | |
1092 | |
1093 if (sc->stc & STCdeprecated) | |
1094 { | |
1095 isdeprecated = 1; | |
1096 } | |
1097 | |
1098 // Expand any tuples in baseclasses[] | |
1099 for (i = 0; i < baseclasses.dim; ) | |
1100 { BaseClass *b = (BaseClass *)baseclasses.data[0]; | |
1101 b->type = b->type->semantic(loc, sc); | |
1102 Type *tb = b->type->toBasetype(); | |
1103 | |
1104 if (tb->ty == Ttuple) | |
1105 { TypeTuple *tup = (TypeTuple *)tb; | |
1106 enum PROT protection = b->protection; | |
1107 baseclasses.remove(i); | |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
1108 size_t dim = Parameter::dim(tup->arguments); |
159 | 1109 for (size_t j = 0; j < dim; j++) |
1607
207a8a438dea
Merge DMD r253: refactor: Argument => Parameter
Leandro Lucarella <llucax@gmail.com>
parents:
1587
diff
changeset
|
1110 { Parameter *arg = Parameter::getNth(tup->arguments, j); |
159 | 1111 b = new BaseClass(arg->type, protection); |
1112 baseclasses.insert(i + j, b); | |
1113 } | |
1114 } | |
1115 else | |
1116 i++; | |
1117 } | |
1118 | |
1119 // Check for errors, handle forward references | |
1120 for (i = 0; i < baseclasses.dim; ) | |
1121 { TypeClass *tc; | |
1122 BaseClass *b; | |
1123 Type *tb; | |
1124 | |
1125 b = (BaseClass *)baseclasses.data[i]; | |
1126 b->type = b->type->semantic(loc, sc); | |
1127 tb = b->type->toBasetype(); | |
1128 if (tb->ty == Tclass) | |
1129 tc = (TypeClass *)tb; | |
1130 else | |
1131 tc = NULL; | |
1132 if (!tc || !tc->sym->isInterfaceDeclaration()) | |
1133 { | |
1134 error("base type must be interface, not %s", b->type->toChars()); | |
1135 baseclasses.remove(i); | |
1136 continue; | |
1137 } | |
1138 else | |
1139 { | |
1140 // Check for duplicate interfaces | |
1141 for (size_t j = 0; j < i; j++) | |
1142 { | |
1143 BaseClass *b2 = (BaseClass *)baseclasses.data[j]; | |
1144 if (b2->base == tc->sym) | |
1145 error("inherits from duplicate interface %s", b2->base->toChars()); | |
1146 } | |
1147 | |
1148 b->base = tc->sym; | |
1149 if (b->base == this || isBaseOf2(b->base)) | |
1150 { | |
1151 error("circular inheritance of interface"); | |
1152 baseclasses.remove(i); | |
1153 continue; | |
1154 } | |
1587 | 1155 if (!b->base->symtab) |
1156 { // Try to resolve forward reference | |
1157 if (sc->mustsemantic && b->base->scope) | |
1158 b->base->semantic(NULL); | |
1159 } | |
159 | 1160 if (!b->base->symtab || b->base->scope || b->base->inuse) |
1161 { | |
1162 //error("forward reference of base class %s", baseClass->toChars()); | |
1163 // Forward reference of base, try again later | |
1164 //printf("\ttry later, forward reference of base %s\n", b->base->toChars()); | |
1165 scope = scx ? scx : new Scope(*sc); | |
1166 scope->setNoFree(); | |
1167 scope->module->addDeferredSemantic(this); | |
1168 return; | |
1169 } | |
1170 } | |
1171 i++; | |
1172 } | |
1173 | |
1174 interfaces_dim = baseclasses.dim; | |
1175 interfaces = (BaseClass **)baseclasses.data; | |
1176 | |
1177 interfaceSemantic(sc); | |
1178 | |
1179 if (vtblOffset()) | |
1180 vtbl.push(this); // leave room at vtbl[0] for classinfo | |
1181 | |
1182 // Cat together the vtbl[]'s from base interfaces | |
1183 for (i = 0; i < interfaces_dim; i++) | |
1184 { BaseClass *b = interfaces[i]; | |
1185 | |
1186 // Skip if b has already appeared | |
1187 for (int k = 0; k < i; k++) | |
1188 { | |
1625
79f64d5fee9e
Merge DMD r319: bugzilla 400 forward reference error...
Leandro Lucarella <llucax@gmail.com>
parents:
1607
diff
changeset
|
1189 if (b == interfaces[k]) |
159 | 1190 goto Lcontinue; |
1191 } | |
1192 | |
1193 // Copy vtbl[] from base class | |
1194 if (b->base->vtblOffset()) | |
1195 { int d = b->base->vtbl.dim; | |
1196 if (d > 1) | |
1197 { | |
1198 vtbl.reserve(d - 1); | |
1199 for (int j = 1; j < d; j++) | |
1200 vtbl.push(b->base->vtbl.data[j]); | |
1201 } | |
1202 } | |
1203 else | |
1204 { | |
1205 vtbl.append(&b->base->vtbl); | |
1206 } | |
1207 | |
1208 Lcontinue: | |
1209 ; | |
1210 } | |
1211 | |
1212 for (i = 0; i < members->dim; i++) | |
1213 { | |
1214 Dsymbol *s = (Dsymbol *)members->data[i]; | |
1215 s->addMember(sc, this, 1); | |
1216 } | |
1217 | |
1218 sc = sc->push(this); | |
1219 sc->parent = this; | |
1220 if (isCOMinterface()) | |
1221 sc->linkage = LINKwindows; | |
1222 sc->structalign = 8; | |
1223 structalign = sc->structalign; | |
1195
e961851fb8be
Merged DMD 1.042.
Tomas Lindquist Olsen <tomas.l.olsen gmail.com>
parents:
1146
diff
changeset
|
1224 sc->offset = PTRSIZE * 2; |
159 | 1225 inuse++; |
1226 for (i = 0; i < members->dim; i++) | |
1227 { | |
1228 Dsymbol *s = (Dsymbol *)members->data[i]; | |
1229 s->semantic(sc); | |
1230 } | |
1231 inuse--; | |
1232 //members->print(); | |
1233 sc->pop(); | |
1234 //printf("-InterfaceDeclaration::semantic(%s), type = %p\n", toChars(), type); | |
1235 } | |
1236 | |
1237 | |
1238 /******************************************* | |
1239 * Determine if 'this' is a base class of cd. | |
1240 * (Actually, if it is an interface supported by cd) | |
1241 * Output: | |
1242 * *poffset offset to start of class | |
1243 * OFFSET_RUNTIME must determine offset at runtime | |
1244 * Returns: | |
1245 * 0 not a base | |
1246 * 1 is a base | |
1247 */ | |
1248 | |
1249 int InterfaceDeclaration::isBaseOf(ClassDeclaration *cd, int *poffset) | |
1250 { | |
1251 unsigned j; | |
1252 | |
1253 //printf("%s.InterfaceDeclaration::isBaseOf(cd = '%s')\n", toChars(), cd->toChars()); | |
1254 assert(!baseClass); | |
1255 for (j = 0; j < cd->interfaces_dim; j++) | |
1256 { | |
1257 BaseClass *b = cd->interfaces[j]; | |
1258 | |
1259 //printf("\tbase %s\n", b->base->toChars()); | |
1260 if (this == b->base) | |
1261 { | |
1262 //printf("\tfound at offset %d\n", b->offset); | |
1263 if (poffset) | |
1264 { *poffset = b->offset; | |
1265 if (j && cd->isInterfaceDeclaration()) | |
1266 *poffset = OFFSET_RUNTIME; | |
1267 } | |
1268 return 1; | |
1269 } | |
1270 if (isBaseOf(b, poffset)) | |
1271 { if (j && poffset && cd->isInterfaceDeclaration()) | |
1272 *poffset = OFFSET_RUNTIME; | |
1273 return 1; | |
1274 } | |
1275 } | |
1276 | |
1277 if (cd->baseClass && isBaseOf(cd->baseClass, poffset)) | |
1278 return 1; | |
1279 | |
1280 if (poffset) | |
1281 *poffset = 0; | |
1282 return 0; | |
1283 } | |
1284 | |
1285 | |
1286 int InterfaceDeclaration::isBaseOf(BaseClass *bc, int *poffset) | |
1287 { | |
1288 //printf("%s.InterfaceDeclaration::isBaseOf(bc = '%s')\n", toChars(), bc->base->toChars()); | |
1289 for (unsigned j = 0; j < bc->baseInterfaces_dim; j++) | |
1290 { | |
1291 BaseClass *b = &bc->baseInterfaces[j]; | |
1292 | |
1293 if (this == b->base) | |
1294 { | |
1295 if (poffset) | |
1296 { *poffset = b->offset; | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1358
diff
changeset
|
1297 if (j && bc->base->isInterfaceDeclaration()) |
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1358
diff
changeset
|
1298 *poffset = OFFSET_RUNTIME; |
159 | 1299 } |
1300 return 1; | |
1301 } | |
1302 if (isBaseOf(b, poffset)) | |
1367
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1358
diff
changeset
|
1303 { if (j && poffset && bc->base->isInterfaceDeclaration()) |
8026319762be
Merged DMD 1.045 !!!
Tomas Lindquist Olsen <tomas.l.olsen gmail com>
parents:
1358
diff
changeset
|
1304 *poffset = OFFSET_RUNTIME; |
159 | 1305 return 1; |
1306 } | |
1307 } | |
1308 if (poffset) | |
1309 *poffset = 0; | |
1310 return 0; | |
1311 } | |
1312 | |
1313 /**************************************** | |
1314 * Determine if slot 0 of the vtbl[] is reserved for something else. | |
1315 * For class objects, yes, this is where the ClassInfo ptr goes. | |
1316 * For COM interfaces, no. | |
1317 * For non-COM interfaces, yes, this is where the Interface ptr goes. | |
1318 */ | |
1319 | |
1320 int InterfaceDeclaration::vtblOffset() | |
1321 { | |
1322 if (isCOMinterface()) | |
1323 return 0; | |
1324 return 1; | |
1325 } | |
1326 | |
1327 int InterfaceDeclaration::isCOMinterface() | |
1328 { | |
1329 return com; | |
1330 } | |
1331 | |
1587 | 1332 #if DMDV2 |
1333 int InterfaceDeclaration::isCPPinterface() | |
1334 { | |
1335 return cpp; | |
1336 } | |
1337 #endif | |
1338 | |
159 | 1339 /******************************************* |
1340 */ | |
1341 | |
336 | 1342 const char *InterfaceDeclaration::kind() |
159 | 1343 { |
1344 return "interface"; | |
1345 } | |
1346 | |
1347 | |
1348 /******************************** BaseClass *****************************/ | |
1349 | |
1350 BaseClass::BaseClass() | |
1351 { | |
1352 memset(this, 0, sizeof(BaseClass)); | |
1353 } | |
1354 | |
1355 BaseClass::BaseClass(Type *type, enum PROT protection) | |
1356 { | |
1357 //printf("BaseClass(this = %p, '%s')\n", this, type->toChars()); | |
1358 this->type = type; | |
1359 this->protection = protection; | |
1360 base = NULL; | |
1361 offset = 0; | |
1362 | |
1363 baseInterfaces_dim = 0; | |
1364 baseInterfaces = NULL; | |
1365 } | |
1366 | |
1367 /**************************************** | |
1368 * Fill in vtbl[] for base class based on member functions of class cd. | |
1369 * Input: | |
1370 * vtbl if !=NULL, fill it in | |
1371 * newinstance !=0 means all entries must be filled in by members | |
1372 * of cd, not members of any base classes of cd. | |
1373 * Returns: | |
1374 * !=0 if any entries were filled in by members of cd (not exclusively | |
1375 * by base classes) | |
1376 */ | |
1377 | |
1378 int BaseClass::fillVtbl(ClassDeclaration *cd, Array *vtbl, int newinstance) | |
1379 { | |
1380 ClassDeclaration *id = base; | |
1381 int j; | |
1382 int result = 0; | |
1383 | |
1384 //printf("BaseClass::fillVtbl(this='%s', cd='%s')\n", base->toChars(), cd->toChars()); | |
1385 if (vtbl) | |
1386 vtbl->setDim(base->vtbl.dim); | |
1387 | |
1388 // first entry is ClassInfo reference | |
1389 for (j = base->vtblOffset(); j < base->vtbl.dim; j++) | |
1390 { | |
1391 FuncDeclaration *ifd = ((Dsymbol *)base->vtbl.data[j])->isFuncDeclaration(); | |
1392 FuncDeclaration *fd; | |
1393 TypeFunction *tf; | |
1394 | |
1395 //printf(" vtbl[%d] is '%s'\n", j, ifd ? ifd->toChars() : "null"); | |
1396 | |
1397 assert(ifd); | |
1398 // Find corresponding function in this class | |
1399 tf = (ifd->type->ty == Tfunction) ? (TypeFunction *)(ifd->type) : NULL; | |
1400 fd = cd->findFunc(ifd->ident, tf); | |
1401 if (fd && !fd->isAbstract()) | |
1402 { | |
1403 //printf(" found\n"); | |
1404 // Check that calling conventions match | |
1405 if (fd->linkage != ifd->linkage) | |
1406 fd->error("linkage doesn't match interface function"); | |
1407 | |
1408 // Check that it is current | |
1409 if (newinstance && | |
1410 fd->toParent() != cd && | |
1411 ifd->toParent() == base) | |
1412 cd->error("interface function %s.%s is not implemented", | |
1413 id->toChars(), ifd->ident->toChars()); | |
1414 | |
1415 if (fd->toParent() == cd) | |
1416 result = 1; | |
1417 } | |
1418 else | |
1419 { | |
1420 //printf(" not found\n"); | |
1421 // BUG: should mark this class as abstract? | |
1422 if (!cd->isAbstract()) | |
1423 cd->error("interface function %s.%s isn't implemented", | |
1424 id->toChars(), ifd->ident->toChars()); | |
1425 fd = NULL; | |
1426 } | |
1427 if (vtbl) | |
1428 vtbl->data[j] = fd; | |
1429 } | |
1430 | |
1431 return result; | |
1432 } | |
1433 | |
1434 void BaseClass::copyBaseInterfaces(BaseClasses *vtblInterfaces) | |
1435 { | |
1436 //printf("+copyBaseInterfaces(), %s\n", base->toChars()); | |
1437 // if (baseInterfaces_dim) | |
1438 // return; | |
1439 | |
1440 baseInterfaces_dim = base->interfaces_dim; | |
1441 baseInterfaces = (BaseClass *)mem.calloc(baseInterfaces_dim, sizeof(BaseClass)); | |
1442 | |
1443 //printf("%s.copyBaseInterfaces()\n", base->toChars()); | |
1444 for (int i = 0; i < baseInterfaces_dim; i++) | |
1445 { | |
1446 BaseClass *b = &baseInterfaces[i]; | |
1447 BaseClass *b2 = base->interfaces[i]; | |
1448 | |
1449 assert(b2->vtbl.dim == 0); // should not be filled yet | |
1450 memcpy(b, b2, sizeof(BaseClass)); | |
1451 | |
1452 if (i) // single inheritance is i==0 | |
1453 vtblInterfaces->push(b); // only need for M.I. | |
1454 b->copyBaseInterfaces(vtblInterfaces); | |
1455 } | |
1456 //printf("-copyBaseInterfaces\n"); | |
1457 } |