Mercurial > projects > ddmd
annotate dmd/TypeStruct.d @ 178:e3afd1303184
Many small bugs fixed
Made all classes derive from TObject to detect memory leaks (functionality is disabled for now)
Began work on overriding backend memory allocations (to avoid memory leaks)
author | korDen |
---|---|
date | Sun, 17 Oct 2010 07:42:00 +0400 |
parents | af724d3510d7 |
children | b0d41ff5e0df |
rev | line source |
---|---|
0 | 1 module dmd.TypeStruct; |
2 | |
114 | 3 import dmd.common; |
0 | 4 import dmd.Type; |
55 | 5 import dmd.TypeInstance; |
0 | 6 import dmd.StructDeclaration; |
7 import dmd.Declaration; | |
8 import dmd.STC; | |
9 import dmd.MOD; | |
10 import dmd.OutBuffer; | |
11 import dmd.DotVarExp; | |
12 import dmd.TemplateMixin; | |
13 import dmd.DotTemplateExp; | |
14 import dmd.DsymbolExp; | |
15 import dmd.TypeExp; | |
16 import dmd.EnumMember; | |
17 import dmd.Id; | |
18 import dmd.DotIdExp; | |
19 import dmd.ScopeExp; | |
20 import dmd.TupleExp; | |
21 import dmd.TemplateDeclaration; | |
22 import dmd.OverloadSet; | |
23 import dmd.Import; | |
24 import dmd.DotExp; | |
25 import dmd.ErrorExp; | |
26 import dmd.Loc; | |
27 import dmd.Scope; | |
28 import dmd.Dsymbol; | |
29 import dmd.HdrGenState; | |
30 import dmd.Expression; | |
31 import dmd.Identifier; | |
32 import dmd.MATCH; | |
33 import dmd.ArrayTypes; | |
55 | 34 import dmd.DYNCAST; |
0 | 35 import dmd.TemplateInstance; |
36 import dmd.FuncDeclaration; | |
37 import dmd.VarExp; | |
38 import dmd.CommaExp; | |
39 import dmd.ThisExp; | |
135 | 40 import dmd.StructLiteralExp; |
0 | 41 import dmd.SymbolDeclaration; |
42 import dmd.TypeInfoDeclaration; | |
43 import dmd.TypeInfoStructDeclaration; | |
44 import dmd.TY; | |
45 import dmd.TOK; | |
46 import dmd.Global; | |
47 import dmd.VarDeclaration; | |
48 import dmd.Util; | |
49 import dmd.expression.Util; | |
50 | |
51 import dmd.backend.TYPE; | |
52 import dmd.backend.dt_t; | |
53 import dmd.backend.Symbol; | |
54 import dmd.backend.Util; | |
55 import dmd.backend.STR; | |
56 import dmd.backend.TYM; | |
57 import dmd.backend.Classsym; | |
58 import dmd.backend.SC; | |
59 import dmd.backend.LIST; | |
60 | |
61 import std.string : toStringz; | |
62 | |
63 class TypeStruct : Type | |
64 { | |
65 StructDeclaration sym; | |
66 | |
67 this(StructDeclaration sym) | |
68 { | |
178 | 69 register(); |
0 | 70 super(TY.Tstruct); |
71 this.sym = sym; | |
72 } | |
72 | 73 override ulong size(Loc loc) |
0 | 74 { |
75 return sym.size(loc); | |
76 } | |
174 | 77 |
72 | 78 override uint alignsize() |
0 | 79 { |
80 uint sz; | |
81 | |
82 sym.size(Loc(0)); // give error for forward references | |
83 sz = sym.alignsize; | |
84 if (sz > sym.structalign) | |
85 sz = sym.structalign; | |
86 return sz; | |
87 } | |
174 | 88 |
72 | 89 override string toChars() |
0 | 90 { |
55 | 91 //printf("sym.parent: %s, deco = %s\n", sym.parent.toChars(), deco); |
92 if (mod) | |
93 return Type.toChars(); | |
94 TemplateInstance ti = sym.parent.isTemplateInstance(); | |
95 if (ti && ti.toAlias() == sym) | |
96 { | |
97 return ti.toChars(); | |
98 } | |
99 return sym.toChars(); | |
0 | 100 } |
174 | 101 |
72 | 102 override Type syntaxCopy() |
0 | 103 { |
104 assert(false); | |
105 } | |
174 | 106 |
72 | 107 override Type semantic(Loc loc, Scope sc) |
0 | 108 { |
109 //printf("TypeStruct.semantic('%s')\n", sym.toChars()); | |
110 | |
111 /* Cannot do semantic for sym because scope chain may not | |
112 * be right. | |
113 */ | |
114 //sym.semantic(sc); | |
115 | |
116 return merge(); | |
117 } | |
174 | 118 |
72 | 119 override Dsymbol toDsymbol(Scope sc) |
0 | 120 { |
121 return sym; | |
122 } | |
174 | 123 |
72 | 124 override void toDecoBuffer(OutBuffer buf, int flag) |
0 | 125 { |
126 string name = sym.mangle(); | |
127 //printf("TypeStruct.toDecoBuffer('%s') = '%s'\n", toChars(), name); | |
128 Type.toDecoBuffer(buf, flag); | |
129 buf.printf("%s", name); | |
130 } | |
174 | 131 |
72 | 132 override void toCBuffer2(OutBuffer buf, HdrGenState* hgs, MOD mod) |
0 | 133 { |
134 if (mod != this.mod) | |
174 | 135 { |
0 | 136 toCBuffer3(buf, hgs, mod); |
137 return; | |
138 } | |
139 TemplateInstance ti = sym.parent.isTemplateInstance(); | |
140 if (ti && ti.toAlias() == sym) | |
141 buf.writestring(ti.toChars()); | |
142 else | |
143 buf.writestring(sym.toChars()); | |
144 } | |
174 | 145 |
72 | 146 override Expression dotExp(Scope sc, Expression e, Identifier ident) |
0 | 147 { |
148 uint offset; | |
149 | |
150 VarDeclaration v; | |
151 Dsymbol s; | |
152 DotVarExp de; | |
153 Declaration d; | |
154 | |
155 version (LOGDOTEXP) { | |
156 printf("TypeStruct.dotExp(e = '%s', ident = '%s')\n", e.toChars(), ident.toChars()); | |
157 } | |
158 if (!sym.members) | |
159 { | |
160 error(e.loc, "struct %s is forward referenced", sym.toChars()); | |
161 return new ErrorExp(); | |
162 } | |
163 | |
164 /* If e.tupleof | |
165 */ | |
166 if (ident is Id.tupleof_) | |
167 { | |
168 /* Create a TupleExp out of the fields of the struct e: | |
169 * (e.field0, e.field1, e.field2, ...) | |
170 */ | |
171 e = e.semantic(sc); // do this before turning on noaccesscheck | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
172 auto exps = new Expressions; |
0 | 173 exps.reserve(sym.fields.dim); |
174 for (size_t i = 0; i < sym.fields.dim; i++) | |
174 | 175 { |
79 | 176 VarDeclaration v2 = cast(VarDeclaration)sym.fields[i]; |
0 | 177 Expression fe = new DotVarExp(e.loc, e, v2); |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
178 exps.push(fe); |
0 | 179 } |
180 e = new TupleExp(e.loc, exps); | |
181 sc = sc.push(); | |
182 sc.noaccesscheck = 1; | |
183 e = e.semantic(sc); | |
184 sc.pop(); | |
185 return e; | |
186 } | |
187 | |
188 if (e.op == TOK.TOKdotexp) | |
174 | 189 { |
0 | 190 DotExp de2 = cast(DotExp)e; |
191 | |
192 if (de2.e1.op == TOK.TOKimport) | |
193 { | |
194 assert(0); // cannot find a case where this happens; leave | |
195 // assert in until we do | |
196 ScopeExp se = cast(ScopeExp)de2.e1; | |
197 | |
198 s = se.sds.search(e.loc, ident, 0); | |
199 e = de2.e1; | |
200 goto L1; | |
201 } | |
202 } | |
203 | |
204 s = sym.search(e.loc, ident, 0); | |
205 L1: | |
206 if (!s) | |
207 { | |
130
60bb0fe4563e
dmdfe 2.037 first main iteration
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
114
diff
changeset
|
208 return noMember(sc, e, ident); |
0 | 209 } |
210 | |
211 if (!s.isFuncDeclaration()) // because of overloading | |
212 s.checkDeprecated(e.loc, sc); | |
213 | |
214 s = s.toAlias(); | |
215 | |
216 v = s.isVarDeclaration(); | |
217 if (v && !v.isDataseg()) | |
218 { | |
219 Expression ei = v.getConstInitializer(); | |
220 if (ei) | |
174 | 221 { |
0 | 222 e = ei.copy(); // need to copy it if it's a StringExp |
223 e = e.semantic(sc); | |
224 return e; | |
225 } | |
226 } | |
227 | |
228 if (s.getType()) | |
229 { | |
230 //return new DotTypeExp(e.loc, e, s); | |
231 return new TypeExp(e.loc, s.getType()); | |
232 } | |
233 | |
234 EnumMember em = s.isEnumMember(); | |
235 if (em) | |
236 { | |
237 assert(em.value); | |
238 return em.value.copy(); | |
239 } | |
240 | |
241 TemplateMixin tm = s.isTemplateMixin(); | |
242 if (tm) | |
243 { | |
244 Expression de2 = new DotExp(e.loc, e, new ScopeExp(e.loc, tm)); | |
245 de2.type = e.type; | |
246 return de2; | |
247 } | |
248 | |
249 TemplateDeclaration td = s.isTemplateDeclaration(); | |
250 if (td) | |
251 { | |
252 e = new DotTemplateExp(e.loc, e, td); | |
253 e.semantic(sc); | |
254 return e; | |
255 } | |
256 | |
257 TemplateInstance ti = s.isTemplateInstance(); | |
258 if (ti) | |
174 | 259 { |
0 | 260 if (!ti.semanticRun) |
261 ti.semantic(sc); | |
262 s = ti.inst.toAlias(); | |
263 if (!s.isTemplateInstance()) | |
264 goto L1; | |
265 Expression de2 = new DotExp(e.loc, e, new ScopeExp(e.loc, ti)); | |
266 de2.type = e.type; | |
267 return de2; | |
268 } | |
269 | |
270 Import timp = s.isImport(); | |
271 if (timp) | |
272 { | |
273 e = new DsymbolExp(e.loc, s, 0); | |
274 e = e.semantic(sc); | |
275 return e; | |
276 } | |
277 | |
278 OverloadSet o = s.isOverloadSet(); | |
279 if (o) | |
174 | 280 { |
0 | 281 /* We really should allow this, triggered by: |
282 * template c() | |
283 * { | |
284 * void a(); | |
285 * void b () { this.a(); } | |
286 * } | |
287 * struct S | |
288 * { | |
289 * mixin c; | |
290 * mixin c; | |
291 * } | |
292 * alias S e; | |
293 */ | |
294 error(e.loc, "overload set for %s.%s not allowed in struct declaration", e.toChars(), ident.toChars()); | |
295 return new ErrorExp(); | |
296 } | |
297 | |
298 d = s.isDeclaration(); | |
299 | |
300 debug { | |
301 if (!d) | |
302 writef("d = %s '%s'\n", s.kind(), s.toChars()); | |
303 } | |
304 assert(d); | |
305 | |
306 if (e.op == TOK.TOKtype) | |
174 | 307 { |
0 | 308 FuncDeclaration fd = sc.func; |
309 | |
310 if (d.isTupleDeclaration()) | |
311 { | |
312 e = new TupleExp(e.loc, d.isTupleDeclaration()); | |
313 e = e.semantic(sc); | |
314 return e; | |
315 } | |
316 | |
317 if (d.needThis() && fd && fd.vthis) | |
318 { | |
319 e = new DotVarExp(e.loc, new ThisExp(e.loc), d); | |
320 e = e.semantic(sc); | |
321 return e; | |
322 } | |
323 | |
324 return new VarExp(e.loc, d, 1); | |
325 } | |
326 | |
327 if (d.isDataseg()) | |
328 { | |
329 // (e, d) | |
330 accessCheck(e.loc, sc, e, d); | |
331 VarExp ve = new VarExp(e.loc, d); | |
332 e = new CommaExp(e.loc, e, ve); | |
333 e.type = d.type; | |
334 return e; | |
335 } | |
336 | |
337 if (v) | |
338 { | |
339 if (v.toParent() != sym) | |
340 sym.error(e.loc, "'%s' is not a member", v.toChars()); | |
341 | |
342 // *(&e + offset) | |
343 accessCheck(e.loc, sc, e, d); | |
344 static if (false) { | |
345 Expression b = new AddrExp(e.loc, e); | |
346 b.type = e.type.pointerTo(); | |
347 b = new AddExp(e.loc, b, new IntegerExp(e.loc, v.offset, Type.tint32)); | |
348 b.type = v.type.pointerTo(); | |
349 b = new PtrExp(e.loc, b); | |
350 b.type = v.type.addMod(e.type.mod); | |
351 return b; | |
352 } | |
353 } | |
354 | |
355 de = new DotVarExp(e.loc, e, d); | |
356 return de.semantic(sc); | |
357 } | |
174 | 358 |
72 | 359 override uint memalign(uint salign) |
0 | 360 { |
361 sym.size(Loc(0)); // give error for forward references | |
362 return sym.structalign; | |
363 } | |
174 | 364 |
72 | 365 override Expression defaultInit(Loc loc) |
0 | 366 { |
367 version (LOGDEFAULTINIT) { | |
368 printf("TypeStruct::defaultInit() '%s'\n", toChars()); | |
369 } | |
135 | 370 Symbol *s = sym.toInitializer(); |
371 Declaration d = new SymbolDeclaration(sym.loc, s, sym); | |
0 | 372 assert(d); |
373 d.type = this; | |
374 return new VarExp(sym.loc, d); | |
375 } | |
174 | 376 |
135 | 377 /*************************************** |
378 * Use when we prefer the default initializer to be a literal, | |
379 * rather than a global immutable variable. | |
380 */ | |
154
14feb7ae01a6
* changed the build system to build a release version if the debug one compiles
trass3r
parents:
135
diff
changeset
|
381 override Expression defaultInitLiteral(Loc loc) |
135 | 382 { |
383 version (LOGDEFAULTINIT) { | |
384 printf("TypeStruct::defaultInitLiteral() '%s'\n", toChars()); | |
385 } | |
386 auto structelems = new Expressions(); | |
387 structelems.setDim(sym.fields.dim); | |
388 for (size_t j = 0; j < structelems.dim; j++) | |
389 { | |
390 auto vd = cast(VarDeclaration)(sym.fields[j]); | |
391 Expression e; | |
392 if (vd.init) | |
393 e = vd.init.toExpression(); | |
394 else | |
174 | 395 e = vd.type.defaultInitLiteral(Loc(0)); |
135 | 396 structelems[j] = e; |
397 } | |
398 auto structinit = new StructLiteralExp(loc, cast(StructDeclaration)sym, structelems); | |
399 // Why doesn't the StructLiteralExp constructor do this, when | |
400 // sym->type != NULL ? | |
401 structinit.type = sym.type; | |
402 return structinit; | |
403 } | |
404 | |
72 | 405 override bool isZeroInit(Loc loc) |
0 | 406 { |
407 return sym.zeroInit; | |
408 } | |
174 | 409 |
73 | 410 override bool isAssignable() |
0 | 411 { |
412 /* If any of the fields are const or invariant, | |
413 * then one cannot assign this struct. | |
414 */ | |
415 for (size_t i = 0; i < sym.fields.dim; i++) | |
174 | 416 { |
79 | 417 VarDeclaration v = cast(VarDeclaration)sym.fields[i]; |
135 | 418 if (v.isConst() || v.isImmutable()) |
0 | 419 return false; |
420 } | |
421 return true; | |
422 } | |
174 | 423 |
72 | 424 override bool checkBoolean() |
0 | 425 { |
426 return false; | |
427 } | |
174 | 428 |
72 | 429 override dt_t** toDt(dt_t** pdt) |
0 | 430 { |
431 sym.toDt(pdt); | |
432 return pdt; | |
433 } | |
174 | 434 |
72 | 435 override MATCH deduceType(Scope sc, Type tparam, TemplateParameters parameters, Objects dedtypes) |
0 | 436 { |
55 | 437 //printf("TypeStruct.deduceType()\n"); |
438 //printf("\tthis.parent = %s, ", sym.parent.toChars()); print(); | |
439 //printf("\ttparam = %d, ", tparam.ty); tparam.print(); | |
440 | |
441 /* If this struct is a template struct, and we're matching | |
442 * it against a template instance, convert the struct type | |
443 * to a template instance, too, and try again. | |
444 */ | |
445 TemplateInstance ti = sym.parent.isTemplateInstance(); | |
446 | |
447 if (tparam && tparam.ty == Tinstance) | |
448 { | |
449 if (ti && ti.toAlias() == sym) | |
450 { | |
451 TypeInstance t = new TypeInstance(Loc(0), ti); | |
452 return t.deduceType(sc, tparam, parameters, dedtypes); | |
453 } | |
454 | |
455 /* Match things like: | |
456 * S!(T).foo | |
457 */ | |
458 TypeInstance tpi = cast(TypeInstance)tparam; | |
459 if (tpi.idents.dim) | |
460 { Identifier id = cast(Identifier)tpi.idents.data[tpi.idents.dim - 1]; | |
461 if (id.dyncast() == DYNCAST.DYNCAST_IDENTIFIER && sym.ident.equals(id)) | |
462 { | |
463 Type tparent = sym.parent.getType(); | |
464 if (tparent) | |
465 { | |
466 /* Slice off the .foo in S!(T).foo | |
467 */ | |
468 tpi.idents.dim--; | |
469 MATCH m = tparent.deduceType(sc, tpi, parameters, dedtypes); | |
470 tpi.idents.dim++; | |
471 return m; | |
472 } | |
473 } | |
474 } | |
475 } | |
476 | |
477 // Extra check | |
478 if (tparam && tparam.ty == Tstruct) | |
479 { | |
480 TypeStruct tp = cast(TypeStruct)tparam; | |
481 | |
482 if (sym != tp.sym) | |
483 return MATCHnomatch; | |
484 } | |
485 return Type.deduceType(sc, tparam, parameters, dedtypes); | |
0 | 486 } |
174 | 487 |
72 | 488 override TypeInfoDeclaration getTypeInfoDeclaration() |
0 | 489 { |
490 return new TypeInfoStructDeclaration(this); | |
491 } | |
174 | 492 |
72 | 493 override bool hasPointers() |
0 | 494 { |
135 | 495 // Probably should cache this information in sym rather than recompute |
0 | 496 StructDeclaration s = sym; |
497 | |
498 sym.size(Loc(0)); // give error for forward references | |
85
8e69d041a99d
Previous commit didn't compile. Fixed.
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
499 foreach (VarDeclaration sm; s.fields) |
0 | 500 { |
501 Declaration d = sm.isDeclaration(); | |
502 if (d.storage_class & STC.STCref || d.hasPointers()) | |
503 return true; | |
504 } | |
505 | |
506 return false; | |
507 } | |
174 | 508 |
72 | 509 override MATCH implicitConvTo(Type to) |
0 | 510 { |
511 MATCH m; | |
512 | |
513 //printf("TypeStruct.implicitConvTo(%s => %s)\n", toChars(), to.toChars()); | |
514 if (ty == to.ty && sym == (cast(TypeStruct)to).sym) | |
174 | 515 { |
0 | 516 m = MATCHexact; // exact match |
517 if (mod != to.mod) | |
518 { | |
135 | 519 if (MODimplicitConv(mod, to.mod)) |
0 | 520 m = MATCHconst; |
521 else | |
522 { /* Check all the fields. If they can all be converted, | |
523 * allow the conversion. | |
524 */ | |
85
8e69d041a99d
Previous commit didn't compile. Fixed.
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
525 foreach (VarDeclaration v; sym.fields) |
174 | 526 { |
0 | 527 assert(v && v.storage_class & STCfield); |
528 | |
529 // 'from' type | |
530 Type tvf = v.type.addMod(mod); | |
531 | |
532 // 'to' type | |
533 Type tv = v.type.castMod(to.mod); | |
534 | |
535 //printf("\t%s => %s, match = %d\n", v.type.toChars(), tv.toChars(), tvf.implicitConvTo(tv)); | |
536 if (tvf.implicitConvTo(tv) < MATCHconst) | |
537 return MATCHnomatch; | |
538 } | |
539 m = MATCHconst; | |
540 } | |
541 } | |
542 } | |
543 else if (sym.aliasthis) | |
544 { | |
545 m = MATCHnomatch; | |
546 Declaration d = sym.aliasthis.isDeclaration(); | |
547 if (d) | |
174 | 548 { |
0 | 549 assert(d.type); |
550 Type t = d.type.addMod(mod); | |
551 m = t.implicitConvTo(to); | |
552 } | |
553 } | |
554 else | |
555 m = MATCHnomatch; // no match | |
556 return m; | |
557 } | |
174 | 558 |
72 | 559 override MATCH constConv(Type to) |
0 | 560 { |
561 if (equals(to)) | |
562 return MATCHexact; | |
135 | 563 if (ty == to.ty && sym == (cast(TypeStruct)to).sym && |
564 MODimplicitConv(mod, to.mod)) | |
0 | 565 return MATCHconst; |
566 return MATCHnomatch; | |
567 } | |
174 | 568 |
72 | 569 override Type toHeadMutable() |
0 | 570 { |
571 assert(false); | |
572 } | |
174 | 573 |
0 | 574 version (CPP_MANGLE) { |
575 void toCppMangle(OutBuffer buf, CppMangleState* cms) | |
576 { | |
577 assert(false); | |
578 } | |
579 } | |
580 | |
72 | 581 override type* toCtype() |
0 | 582 { |
583 type* t; | |
584 Symbol* s; | |
585 | |
586 if (ctype) | |
587 return ctype; | |
588 | |
589 //printf("TypeStruct.toCtype() '%s'\n", sym.toChars()); | |
590 s = symbol_calloc(toStringz(sym.toPrettyChars())); | |
591 s.Sclass = SC.SCstruct; | |
592 s.Sstruct = struct_calloc(); | |
593 s.Sstruct.Sflags |= 0; /// huh? | |
594 s.Sstruct.Salignsize = sym.alignsize; | |
595 s.Sstruct.Sstructalign = cast(ubyte)sym.structalign; | |
596 s.Sstruct.Sstructsize = sym.structsize; | |
597 | |
598 if (sym.isUnionDeclaration()) | |
599 s.Sstruct.Sflags |= STR.STRunion; | |
600 | |
601 t = type_alloc(TYM.TYstruct); | |
602 t.Ttag = cast(Classsym*)s; // structure tag name | |
603 t.Tcount++; | |
604 s.Stype = t; | |
605 slist_add(s); | |
606 ctype = t; | |
607 | |
608 /* Add in fields of the struct | |
609 * (after setting ctype to avoid infinite recursion) | |
610 */ | |
611 if (global.params.symdebug) { | |
612 for (int i = 0; i < sym.fields.dim; i++) | |
174 | 613 { |
79 | 614 VarDeclaration v = cast(VarDeclaration)sym.fields[i]; |
0 | 615 |
616 Symbol* s2 = symbol_name(toStringz(v.ident.toChars()), SC.SCmember, v.type.toCtype()); | |
617 s2.Smemoff = v.offset; | |
618 list_append(&s.Sstruct.Sfldlst, s2); | |
619 } | |
620 } | |
621 | |
622 //printf("t = %p, Tflags = x%x\n", t, t.Tflags); | |
623 return t; | |
624 } | |
72 | 625 } |