Mercurial > projects > ddmd
annotate dmd/TypeClass.d @ 135:af1bebfd96a4 dmd2037
dmd 2.038
author | Eldar Insafutdinov <e.insafutdinov@gmail.com> |
---|---|
date | Mon, 13 Sep 2010 22:19:42 +0100 |
parents | 60bb0fe4563e |
children | d8565fbd755c |
rev | line source |
---|---|
0 | 1 module dmd.TypeClass; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.Type; |
5 import dmd.ClassDeclaration; | |
64 | 6 import dmd.TypeInstance; |
0 | 7 import dmd.Loc; |
8 import dmd.Dsymbol; | |
9 import dmd.Scope; | |
10 import dmd.OutBuffer; | |
11 import dmd.HdrGenState; | |
12 import dmd.Expression; | |
13 import dmd.Identifier; | |
14 import dmd.MATCH; | |
64 | 15 import dmd.DYNCAST; |
0 | 16 import dmd.CppMangleState; |
17 import dmd.ArrayTypes; | |
18 import dmd.TypeInfoDeclaration; | |
19 import dmd.TY; | |
20 import dmd.MOD; | |
21 import dmd.Global; | |
22 import dmd.TypePointer; | |
23 import dmd.Declaration; | |
24 import dmd.VarDeclaration; | |
25 import dmd.TOK; | |
26 import dmd.DotExp; | |
27 import dmd.Id; | |
28 import dmd.ScopeExp; | |
29 import dmd.DotVarExp; | |
30 import dmd.VarExp; | |
31 import dmd.PtrExp; | |
32 import dmd.AddExp; | |
33 import dmd.IntegerExp; | |
34 import dmd.DotIdExp; | |
35 import dmd.EnumMember; | |
36 import dmd.TemplateMixin; | |
37 import dmd.TemplateDeclaration; | |
38 import dmd.TemplateInstance; | |
39 import dmd.OverloadSet; | |
40 import dmd.DotTypeExp; | |
41 import dmd.TupleExp; | |
42 import dmd.ClassInfoDeclaration; | |
43 import dmd.TypeInfoInterfaceDeclaration; | |
44 import dmd.TypeInfoClassDeclaration; | |
45 import dmd.Util; | |
46 import dmd.NullExp; | |
47 import dmd.TypeExp; | |
48 import dmd.DotTemplateExp; | |
49 import dmd.ErrorExp; | |
50 import dmd.ThisExp; | |
51 import dmd.CommaExp; | |
52 | |
53 import dmd.expression.Util; | |
54 import dmd.backend.Symbol; | |
55 import dmd.backend.TYPE; | |
56 import dmd.backend.Util; | |
57 import dmd.backend.SC; | |
58 import dmd.backend.STR; | |
59 import dmd.backend.TYM; | |
60 import dmd.backend.LIST; | |
61 import dmd.backend.Classsym; | |
62 | |
63 import std.string : toStringz; | |
64 | |
65 class TypeClass : Type | |
66 { | |
67 ClassDeclaration sym; | |
68 | |
69 this(ClassDeclaration sym) | |
70 { | |
71 super(TY.Tclass); | |
72 this.sym = sym; | |
73 } | |
74 | |
75 version (DumbClone) { | |
76 } else { | |
77 Type clone() | |
78 { | |
79 assert(false); | |
80 } | |
81 } | |
72 | 82 override ulong size(Loc loc) |
0 | 83 { |
84 return PTRSIZE; | |
85 } | |
86 | |
72 | 87 override string toChars() |
0 | 88 { |
89 if (mod) | |
90 return Type.toChars(); | |
91 return sym.toPrettyChars(); | |
92 } | |
93 | |
72 | 94 override Type syntaxCopy() |
0 | 95 { |
96 assert(false); | |
97 } | |
98 | |
72 | 99 override Type semantic(Loc loc, Scope sc) |
0 | 100 { |
101 //printf("TypeClass.semantic(%s)\n", sym.toChars()); | |
102 if (deco) | |
103 return this; | |
104 //printf("\t%s\n", merge().deco); | |
105 return merge(); | |
106 } | |
107 | |
72 | 108 override Dsymbol toDsymbol(Scope sc) |
0 | 109 { |
110 return sym; | |
111 } | |
112 | |
72 | 113 override void toDecoBuffer(OutBuffer buf, int flag) |
0 | 114 { |
115 string name = sym.mangle(); | |
116 //printf("TypeClass.toDecoBuffer('%s' flag=%d mod=%x) = '%s'\n", toChars(), flag, mod, name); | |
117 Type.toDecoBuffer(buf, flag); | |
118 buf.printf("%s", name); | |
119 } | |
120 | |
72 | 121 override void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod) |
0 | 122 { |
123 if (mod != this.mod) | |
124 { | |
125 toCBuffer3(buf, hgs, mod); | |
126 return; | |
127 } | |
128 buf.writestring(sym.toChars()); | |
129 } | |
130 | |
72 | 131 override Expression dotExp(Scope sc, Expression e, Identifier ident) |
0 | 132 { |
133 uint offset; | |
134 | |
135 Expression b; | |
136 VarDeclaration v; | |
137 Dsymbol s; | |
138 | |
139 version (LOGDOTEXP) { | |
140 printf("TypeClass.dotExp(e='%s', ident='%s')\n", e.toChars(), ident.toChars()); | |
141 } | |
142 | |
143 if (e.op == TOK.TOKdotexp) | |
144 { | |
145 DotExp de = cast(DotExp)e; | |
146 | |
147 if (de.e1.op == TOK.TOKimport) | |
148 { | |
149 ScopeExp se = cast(ScopeExp)de.e1; | |
150 | |
151 s = se.sds.search(e.loc, ident, 0); | |
152 e = de.e1; | |
153 goto L1; | |
154 } | |
155 } | |
156 | |
157 if (ident is Id.tupleof_) | |
158 { | |
159 /* Create a TupleExp | |
160 */ | |
161 e = e.semantic(sc); // do this before turning on noaccesscheck | |
162 Expressions exps = new Expressions; | |
163 exps.reserve(sym.fields.dim); | |
164 for (size_t i = 0; i < sym.fields.dim; i++) | |
165 { | |
79 | 166 VarDeclaration v2 = cast(VarDeclaration)sym.fields[i]; |
0 | 167 Expression fe = new DotVarExp(e.loc, e, v2); |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
168 exps.push(fe); |
0 | 169 } |
170 e = new TupleExp(e.loc, exps); | |
171 sc = sc.push(); | |
172 sc.noaccesscheck = 1; | |
173 e = e.semantic(sc); | |
174 sc.pop(); | |
175 return e; | |
176 } | |
177 | |
178 s = sym.search(e.loc, ident, 0); | |
179 L1: | |
180 if (!s) | |
181 { | |
182 // See if it's a base class | |
183 ClassDeclaration cbase; | |
184 for (cbase = sym.baseClass; cbase; cbase = cbase.baseClass) | |
185 { | |
186 if (cbase.ident.equals(ident)) | |
187 { | |
188 e = new DotTypeExp(Loc(0), e, cbase); | |
189 return e; | |
190 } | |
191 } | |
192 | |
193 if (ident is Id.classinfo_) | |
194 { | |
195 assert(ClassDeclaration.classinfo); | |
196 Type t = ClassDeclaration.classinfo.type; | |
197 if (e.op == TOK.TOKtype || e.op == TOK.TOKdottype) | |
198 { | |
199 /* For type.classinfo, we know the classinfo | |
200 * at compile time. | |
201 */ | |
202 if (!sym.vclassinfo) | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
203 sym.vclassinfo = new TypeInfoClassDeclaration(sym.type); |
0 | 204 |
205 e = new VarExp(e.loc, sym.vclassinfo); | |
206 e = e.addressOf(sc); | |
207 e.type = t; // do this so we don't get redundant dereference | |
208 } | |
209 else | |
210 { | |
211 /* For class objects, the classinfo reference is the first | |
212 * entry in the vtbl[] | |
213 */ | |
214 e = new PtrExp(e.loc, e); | |
215 e.type = t.pointerTo(); | |
216 if (sym.isInterfaceDeclaration()) | |
217 { | |
218 if (sym.isCPPinterface()) | |
219 { | |
220 /* C++ interface vtbl[]s are different in that the | |
221 * first entry is always pointer to the first virtual | |
222 * function, not classinfo. | |
223 * We can't get a .classinfo for it. | |
224 */ | |
225 error(e.loc, "no .classinfo for C++ interface objects"); | |
226 } | |
227 /* For an interface, the first entry in the vtbl[] | |
228 * is actually a pointer to an instance of struct Interface. | |
229 * The first member of Interface is the .classinfo, | |
230 * so add an extra pointer indirection. | |
231 */ | |
232 e.type = e.type.pointerTo(); | |
233 e = new PtrExp(e.loc, e); | |
234 e.type = t.pointerTo(); | |
235 } | |
236 e = new PtrExp(e.loc, e, t); | |
237 } | |
238 return e; | |
239 } | |
240 | |
241 if (ident is Id.__vptr) | |
242 { | |
243 /* The pointer to the vtbl[] | |
244 * *cast(invariant(void*)**)e | |
245 */ | |
246 e = e.castTo(sc, tvoidptr.invariantOf().pointerTo().pointerTo()); | |
247 e = new PtrExp(e.loc, e); | |
248 e = e.semantic(sc); | |
249 return e; | |
250 } | |
251 | |
252 if (ident is Id.__monitor) | |
253 { /* The handle to the monitor (call it a void*) | |
254 * *(cast(void**)e + 1) | |
255 */ | |
256 e = e.castTo(sc, tvoidptr.pointerTo()); | |
257 e = new AddExp(e.loc, e, new IntegerExp(1)); | |
258 e = new PtrExp(e.loc, e); | |
259 e = e.semantic(sc); | |
260 return e; | |
261 } | |
262 | |
263 if (ident is Id.typeinfo_) | |
264 { | |
265 if (!global.params.useDeprecated) | |
266 error(e.loc, ".typeinfo deprecated, use typeid(type)"); | |
267 | |
268 return getTypeInfo(sc); | |
269 } | |
270 if (ident is Id.outer && sym.vthis) | |
271 { | |
272 s = sym.vthis; | |
273 } | |
274 else | |
275 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
276 return noMember(sc, e, ident); |
0 | 277 } |
278 } | |
279 | |
280 if (!s.isFuncDeclaration()) // because of overloading | |
281 s.checkDeprecated(e.loc, sc); | |
282 | |
283 s = s.toAlias(); | |
284 v = s.isVarDeclaration(); | |
285 | |
286 if (v && !v.isDataseg()) | |
287 { | |
288 Expression ei = v.getConstInitializer(); | |
289 | |
290 if (ei) | |
291 { | |
292 e = ei.copy(); // need to copy it if it's a StringExp | |
293 e = e.semantic(sc); | |
294 return e; | |
295 } | |
296 } | |
297 | |
298 if (s.getType()) | |
299 { | |
300 // if (e.op == TOKtype) | |
301 return new TypeExp(e.loc, s.getType()); | |
302 // return new DotTypeExp(e.loc, e, s); | |
303 } | |
304 | |
305 EnumMember em = s.isEnumMember(); | |
306 if (em) | |
307 { | |
308 assert(em.value); | |
309 return em.value.copy(); | |
310 } | |
311 | |
312 TemplateMixin tm = s.isTemplateMixin(); | |
313 if (tm) | |
314 { | |
315 Expression de = new DotExp(e.loc, e, new ScopeExp(e.loc, tm)); | |
316 de.type = e.type; | |
317 return de; | |
318 } | |
319 | |
320 TemplateDeclaration td = s.isTemplateDeclaration(); | |
321 if (td) | |
322 { | |
323 e = new DotTemplateExp(e.loc, e, td); | |
324 e.semantic(sc); | |
325 return e; | |
326 } | |
327 | |
328 TemplateInstance ti = s.isTemplateInstance(); | |
329 if (ti) | |
330 { | |
331 if (!ti.semanticRun) | |
332 ti.semantic(sc); | |
333 s = ti.inst.toAlias(); | |
334 if (!s.isTemplateInstance()) | |
335 goto L1; | |
336 Expression de = new DotExp(e.loc, e, new ScopeExp(e.loc, ti)); | |
337 de.type = e.type; | |
338 return de; | |
339 } | |
340 | |
341 OverloadSet o = s.isOverloadSet(); | |
342 if (o) | |
343 { | |
344 /* We really should allow this | |
345 */ | |
346 error(e.loc, "overload set for %s.%s not allowed in struct declaration", e.toChars(), ident.toChars()); | |
347 return new ErrorExp(); | |
348 } | |
349 | |
350 Declaration d = s.isDeclaration(); | |
351 if (!d) | |
352 { | |
353 e.error("%s.%s is not a declaration", e.toChars(), ident.toChars()); | |
354 return new ErrorExp(); | |
355 } | |
356 | |
357 if (e.op == TOK.TOKtype) | |
358 { | |
359 /* It's: | |
360 * Class.d | |
361 */ | |
362 if (d.isTupleDeclaration()) | |
363 { | |
364 e = new TupleExp(e.loc, d.isTupleDeclaration()); | |
365 e = e.semantic(sc); | |
366 return e; | |
367 } | |
73 | 368 else if (d.needThis() && (hasThis(sc) || !(sc.intypeof || d.isFuncDeclaration()))) |
0 | 369 { |
370 if (sc.func) | |
371 { | |
372 ClassDeclaration thiscd; | |
373 thiscd = sc.func.toParent().isClassDeclaration(); | |
374 | |
375 if (thiscd) | |
376 { | |
377 ClassDeclaration cd = e.type.isClassHandle(); | |
378 | |
379 if (cd is thiscd) | |
380 { | |
381 e = new ThisExp(e.loc); | |
382 e = new DotTypeExp(e.loc, e, cd); | |
383 DotVarExp de = new DotVarExp(e.loc, e, d); | |
384 e = de.semantic(sc); | |
385 return e; | |
386 } | |
387 else if ((!cd || !cd.isBaseOf(thiscd, null)) && !d.isFuncDeclaration()) | |
388 e.error("'this' is required, but %s is not a base class of %s", e.type.toChars(), thiscd.toChars()); | |
389 } | |
390 } | |
391 | |
392 /* Rewrite as: | |
393 * this.d | |
394 */ | |
395 DotVarExp de = new DotVarExp(e.loc, new ThisExp(e.loc), d); | |
396 e = de.semantic(sc); | |
397 return e; | |
398 } | |
399 else | |
400 { | |
401 VarExp ve = new VarExp(e.loc, d, 1); | |
402 return ve; | |
403 } | |
404 } | |
405 | |
406 if (d.isDataseg()) | |
407 { | |
408 // (e, d) | |
409 accessCheck(e.loc, sc, e, d); | |
410 VarExp ve = new VarExp(e.loc, d); | |
411 e = new CommaExp(e.loc, e, ve); | |
412 e.type = d.type; | |
413 return e; | |
414 } | |
415 | |
416 if (d.parent && d.toParent().isModule()) | |
417 { | |
418 // (e, d) | |
419 VarExp ve = new VarExp(e.loc, d, 1); | |
420 e = new CommaExp(e.loc, e, ve); | |
421 e.type = d.type; | |
422 return e; | |
423 } | |
424 | |
425 DotVarExp de = new DotVarExp(e.loc, e, d); | |
426 return de.semantic(sc); | |
427 } | |
428 | |
72 | 429 override ClassDeclaration isClassHandle() |
0 | 430 { |
431 return sym; | |
432 } | |
433 | |
72 | 434 override bool isBaseOf(Type t, int* poffset) |
0 | 435 { |
56 | 436 if (t.ty == Tclass) |
437 { | |
438 ClassDeclaration cd; | |
439 | |
440 cd = (cast(TypeClass)t).sym; | |
441 if (sym.isBaseOf(cd, poffset)) | |
442 return true; | |
443 } | |
444 | |
445 return false; | |
0 | 446 } |
447 | |
72 | 448 override MATCH implicitConvTo(Type to) |
0 | 449 { |
450 //printf("TypeClass.implicitConvTo(to = '%s') %s\n", to.toChars(), toChars()); | |
451 MATCH m = constConv(to); | |
452 if (m != MATCH.MATCHnomatch) | |
453 return m; | |
454 | |
455 ClassDeclaration cdto = to.isClassHandle(); | |
456 if (cdto && cdto.isBaseOf(sym, null)) | |
457 { | |
458 //printf("'to' is base\n"); | |
459 return MATCH.MATCHconvert; | |
460 } | |
461 | |
462 if (global.params.Dversion == 1) | |
463 { | |
464 // Allow conversion to (void *) | |
465 if (to.ty == TY.Tpointer && (cast(TypePointer)to).next.ty == TY.Tvoid) | |
466 return MATCH.MATCHconvert; | |
467 } | |
468 | |
469 m = MATCH.MATCHnomatch; | |
470 if (sym.aliasthis) | |
471 { | |
472 Declaration d = sym.aliasthis.isDeclaration(); | |
473 if (d) | |
474 { | |
475 assert(d.type); | |
476 Type t = d.type.addMod(mod); | |
477 m = t.implicitConvTo(to); | |
478 } | |
479 } | |
480 | |
481 return m; | |
482 } | |
483 | |
72 | 484 override Expression defaultInit(Loc loc) |
0 | 485 { |
486 version (LOGDEFAULTINIT) { | |
487 printf("TypeClass::defaultInit() '%s'\n", toChars()); | |
488 } | |
135 | 489 return new NullExp(loc, this); |
0 | 490 } |
491 | |
72 | 492 override bool isZeroInit(Loc loc) |
0 | 493 { |
494 return true; | |
495 } | |
496 | |
72 | 497 override MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes) |
0 | 498 { |
64 | 499 //printf("TypeClass.deduceType(this = %s)\n", toChars()); |
500 | |
501 /* If this class is a template class, and we're matching | |
502 * it against a template instance, convert the class type | |
503 * to a template instance, too, and try again. | |
504 */ | |
505 TemplateInstance ti = sym.parent.isTemplateInstance(); | |
506 | |
507 if (tparam && tparam.ty == Tinstance) | |
508 { | |
509 if (ti && ti.toAlias() == sym) | |
510 { | |
511 TypeInstance t = new TypeInstance(Loc(0), ti); | |
512 return t.deduceType(sc, tparam, parameters, dedtypes); | |
513 } | |
514 | |
515 /* Match things like: | |
516 * S!(T).foo | |
517 */ | |
518 TypeInstance tpi = cast(TypeInstance)tparam; | |
519 if (tpi.idents.dim) | |
520 { Identifier id = cast(Identifier)tpi.idents.data[tpi.idents.dim - 1]; | |
521 if (id.dyncast() == DYNCAST.DYNCAST_IDENTIFIER && sym.ident.equals(id)) | |
522 { | |
523 Type tparent = sym.parent.getType(); | |
524 if (tparent) | |
525 { | |
526 /* Slice off the .foo in S!(T).foo | |
527 */ | |
528 tpi.idents.dim--; | |
529 MATCH m = tparent.deduceType(sc, tpi, parameters, dedtypes); | |
530 tpi.idents.dim++; | |
531 return m; | |
532 } | |
533 } | |
534 } | |
535 } | |
536 | |
537 // Extra check | |
538 if (tparam && tparam.ty == Tclass) | |
539 { | |
540 TypeClass tp = cast(TypeClass)tparam; | |
541 | |
542 //printf("\t%d\n", (MATCH) implicitConvTo(tp)); | |
543 return implicitConvTo(tp); | |
544 } | |
545 return Type.deduceType(sc, tparam, parameters, dedtypes); | |
0 | 546 } |
547 | |
72 | 548 override bool isauto() |
0 | 549 { |
550 return sym.isauto; | |
551 } | |
552 | |
72 | 553 override bool checkBoolean() |
0 | 554 { |
555 return true; | |
556 } | |
557 | |
72 | 558 override TypeInfoDeclaration getTypeInfoDeclaration() |
0 | 559 { |
560 if (sym.isInterfaceDeclaration()) | |
561 return new TypeInfoInterfaceDeclaration(this); | |
562 else | |
563 return new TypeInfoClassDeclaration(this); | |
564 } | |
565 | |
72 | 566 override bool hasPointers() |
0 | 567 { |
568 return true; | |
569 } | |
570 | |
72 | 571 override bool builtinTypeInfo() |
0 | 572 { |
573 /* This is statically put out with the ClassInfo, so | |
574 * claim it is built in so it isn't regenerated by each module. | |
575 */ | |
576 version (DMDV2) { | |
577 return mod ? false : true; | |
578 } else { | |
579 return true; | |
580 } | |
581 } | |
582 | |
583 version (DMDV2) { | |
72 | 584 override Type toHeadMutable() |
0 | 585 { |
586 assert(false); | |
587 } | |
588 | |
72 | 589 override MATCH constConv(Type to) |
0 | 590 { |
591 if (equals(to)) | |
592 return MATCH.MATCHexact; | |
593 | |
594 if (ty == to.ty && sym == (cast(TypeClass)to).sym && to.mod == MOD.MODconst) | |
595 return MATCH.MATCHconst; | |
596 | |
597 return MATCH.MATCHnomatch; | |
598 } | |
599 | |
600 version (CPP_MANGLE) { | |
601 void toCppMangle(OutBuffer buf, CppMangleState* cms) | |
602 { | |
603 assert(false); | |
604 } | |
605 } | |
606 } | |
607 | |
72 | 608 override type* toCtype() |
0 | 609 { |
610 type* t; | |
611 Symbol* s; | |
612 | |
613 //printf("TypeClass.toCtype() %s\n", toChars()); | |
614 if (ctype) | |
615 return ctype; | |
616 | |
617 /* Need this symbol to do C++ name mangling | |
618 */ | |
619 string name = sym.isCPPinterface() ? sym.ident.toChars() : sym.toPrettyChars(); | |
620 s = symbol_calloc(toStringz(name)); | |
621 s.Sclass = SC.SCstruct; | |
622 s.Sstruct = struct_calloc(); | |
623 s.Sstruct.Sflags |= STR.STRclass; | |
624 s.Sstruct.Salignsize = sym.alignsize; | |
625 s.Sstruct.Sstructalign = cast(ubyte)sym.structalign; | |
626 s.Sstruct.Sstructsize = sym.structsize; | |
627 | |
628 t = type_alloc(TYM.TYstruct); | |
629 t.Ttag = cast(Classsym*)s; // structure tag name | |
630 t.Tcount++; | |
631 s.Stype = t; | |
632 slist_add(s); | |
633 | |
634 t = type_allocn(TYM.TYnptr, t); | |
635 | |
636 t.Tcount++; | |
637 ctype = t; | |
638 | |
639 /* Add in fields of the class | |
640 * (after setting ctype to avoid infinite recursion) | |
641 */ | |
642 if (global.params.symdebug) | |
643 for (int i = 0; i < sym.fields.dim; i++) | |
644 { | |
79 | 645 VarDeclaration v = cast(VarDeclaration)sym.fields[i]; |
0 | 646 |
647 Symbol* s2 = symbol_name(toStringz(v.ident.toChars()), SC.SCmember, v.type.toCtype()); | |
648 s2.Smemoff = v.offset; | |
649 list_append(&s.Sstruct.Sfldlst, s2); | |
650 } | |
651 | |
652 return t; | |
653 } | |
654 | |
72 | 655 override Symbol* toSymbol() |
0 | 656 { |
657 return sym.toSymbol(); | |
658 } | |
72 | 659 } |