comparison dmd/TypeClass.d @ 0:10317f0c89a5

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