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