Mercurial > projects > ddmd
annotate dmd/StructLiteralExp.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 | 9a2a1ae6c8e5 |
children | b0d41ff5e0df |
rev | line source |
---|---|
72 | 1 module dmd.StructLiteralExp; |
2 | |
114 | 3 import dmd.common; |
72 | 4 import dmd.Expression; |
123 | 5 import dmd.GlobalExpressions; |
72 | 6 import dmd.MOD; |
7 import dmd.TypeStruct; | |
8 import dmd.TypeSArray; | |
9 import dmd.expression.Util; | |
10 import dmd.ErrorExp; | |
123 | 11 import dmd.Array; |
72 | 12 import dmd.Dsymbol; |
13 import dmd.VarDeclaration; | |
14 import dmd.StructDeclaration; | |
15 import dmd.FuncDeclaration; | |
16 import dmd.ThisDeclaration; | |
17 import dmd.backend.elem; | |
18 import dmd.InterState; | |
19 import dmd.MATCH; | |
20 import dmd.WANT; | |
21 import dmd.TY; | |
22 import dmd.Type; | |
23 import dmd.OutBuffer; | |
24 import dmd.Loc; | |
25 import dmd.Scope; | |
109 | 26 import dmd.Initializer; |
72 | 27 import dmd.InlineCostState; |
28 import dmd.IRState; | |
29 import dmd.InlineDoState; | |
30 import dmd.backend.Symbol; | |
31 import dmd.HdrGenState; | |
32 import dmd.backend.dt_t; | |
33 import dmd.InlineScanState; | |
79 | 34 import dmd.ArrayLiteralExp; |
72 | 35 import dmd.ArrayTypes; |
36 import dmd.TOK; | |
37 | |
38 import dmd.codegen.Util; | |
39 import dmd.backend.Util; | |
40 import dmd.backend.RTLSYM; | |
41 import dmd.backend.TYM; | |
42 import dmd.backend.mTY; | |
43 import dmd.backend.OPER; | |
44 | |
45 | |
0 | 46 class StructLiteralExp : Expression |
47 { | |
72 | 48 StructDeclaration sd; // which aggregate this is for |
79 | 49 Expressions elements; // parallels sd.fields[] with |
72 | 50 // NULL entries for fields to skip |
51 | |
52 Symbol* sym; // back end symbol to initialize with literal | |
53 size_t soffset; // offset from start of s | |
0 | 54 int fillHoles; // fill alignment 'holes' with zero |
55 | |
56 this(Loc loc, StructDeclaration sd, Expressions elements) | |
57 { | |
178 | 58 register(); |
72 | 59 super(loc, TOKstructliteral, StructLiteralExp.sizeof); |
60 this.sd = sd; | |
61 this.elements = elements; | |
62 this.sym = null; | |
63 this.soffset = 0; | |
64 this.fillHoles = 1; | |
0 | 65 } |
66 | |
72 | 67 override Expression syntaxCopy() |
0 | 68 { |
123 | 69 return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements)); |
0 | 70 } |
71 | |
72 | 72 override Expression semantic(Scope sc) |
0 | 73 { |
72 | 74 Expression e; |
75 int nfields = sd.fields.dim - sd.isnested; | |
76 | |
77 version (LOGSEMANTIC) { | |
78 printf("StructLiteralExp.semantic('%s')\n", toChars()); | |
79 } | |
80 if (type) | |
81 return this; | |
82 | |
83 // Run semantic() on each element | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
84 foreach(size_t i, Expression e; elements) |
72 | 85 { |
86 if (!e) | |
87 continue; | |
88 e = e.semantic(sc); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
89 elements[i] = e; |
72 | 90 } |
91 expandTuples(elements); | |
92 size_t offset = 0; | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
93 foreach(size_t i, Expression e; elements) |
72 | 94 { |
95 if (!e) | |
96 continue; | |
97 | |
98 if (!e.type) | |
99 error("%s has no value", e.toChars()); | |
100 e = resolveProperties(sc, e); | |
101 if (i >= nfields) | |
102 { | |
103 error("more initializers than fields of %s", sd.toChars()); | |
104 return new ErrorExp(); | |
105 } | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
106 auto s = sd.fields[i]; |
72 | 107 VarDeclaration v = s.isVarDeclaration(); |
108 assert(v); | |
109 if (v.offset < offset) | |
110 error("overlapping initialization for %s", v.toChars()); | |
111 offset = v.offset + cast(uint)v.type.size(); | |
112 | |
113 Type telem = v.type; | |
114 while (!e.implicitConvTo(telem) && telem.toBasetype().ty == Tsarray) | |
115 { | |
116 /* Static array initialization, as in: | |
117 * T[3][5] = e; | |
118 */ | |
119 telem = telem.toBasetype().nextOf(); | |
120 } | |
121 | |
122 e = e.implicitCastTo(sc, telem); | |
123 | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
124 elements[i] = e; |
72 | 125 } |
126 | |
127 /* Fill out remainder of elements[] with default initializers for fields[] | |
128 */ | |
129 for (size_t i = elements.dim; i < nfields; i++) | |
130 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
131 VarDeclaration v = sd.fields[i]; |
72 | 132 assert(v); |
133 assert(!v.isThisDeclaration()); | |
134 | |
135 if (v.offset < offset) | |
136 { | |
137 e = null; | |
138 sd.hasUnions = 1; | |
139 } | |
140 else | |
141 { | |
142 if (v.init) | |
143 { | |
144 e = v.init.toExpression(); | |
145 if (!e) | |
109 | 146 { |
72 | 147 error("cannot make expression out of initializer for %s", v.toChars()); |
109 | 148 e = new ErrorExp(); |
149 } | |
150 else if (v.scope_) | |
151 { | |
152 // Do deferred semantic anaylsis | |
153 Initializer i2 = v.init.syntaxCopy(); | |
154 i2 = i2.semantic(v.scope_, v.type); | |
155 e = i2.toExpression(); | |
156 v.scope_ = null; | |
157 } | |
72 | 158 } |
159 else | |
160 { | |
135 | 161 e = v.type.defaultInitLiteral(loc); |
72 | 162 } |
163 offset = v.offset + cast(uint)v.type.size(); | |
164 } | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
165 elements.push(e); |
72 | 166 } |
167 | |
168 type = sd.type; | |
63 | 169 return this; |
0 | 170 } |
171 | |
109 | 172 /************************************** |
173 * Gets expression at offset of type. | |
174 * Returns null if not found. | |
175 */ | |
0 | 176 Expression getField(Type type, uint offset) |
177 { | |
79 | 178 //printf("StructLiteralExp.getField(this = %s, type = %s, offset = %u)\n", |
179 // /*toChars()*/"", type.toChars(), offset); | |
180 Expression e = null; | |
181 int i = getFieldIndex(type, offset); | |
182 | |
183 if (i != -1) | |
184 { | |
185 //printf("\ti = %d\n", i); | |
186 assert(i < elements.dim); | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
85
diff
changeset
|
187 e = elements[i]; |
79 | 188 if (e) |
189 { | |
190 //writef("e = %s, e.type = %s\n", e.toChars(), e.type.toChars()); | |
191 | |
192 /* If type is a static array, and e is an initializer for that array, | |
193 * then the field initializer should be an array literal of e. | |
194 */ | |
195 if (e.type != type && type.ty == Tsarray) | |
196 { | |
197 TypeSArray tsa = cast(TypeSArray)type; | |
198 size_t length = cast(size_t) tsa.dim.toInteger(); | |
199 Expressions z = new Expressions; | |
200 z.setDim(length); | |
201 for (int q = 0; q < length; ++q) | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
85
diff
changeset
|
202 z[q] = e.copy(); |
79 | 203 e = new ArrayLiteralExp(loc, z); |
204 e.type = type; | |
205 } | |
206 else | |
207 { | |
208 e = e.copy(); | |
209 e.type = type; | |
210 } | |
211 } | |
212 } | |
213 return e; | |
0 | 214 } |
215 | |
216 int getFieldIndex(Type type, uint offset) | |
217 { | |
79 | 218 /* Find which field offset is by looking at the field offsets |
219 */ | |
220 if (elements.dim) | |
221 { | |
85
8e69d041a99d
Previous commit didn't compile. Fixed.
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
84
diff
changeset
|
222 foreach (size_t i, VarDeclaration v; sd.fields) |
79 | 223 { |
224 assert(v); | |
225 | |
226 if (offset == v.offset && type.size() == v.type.size()) | |
227 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
85
diff
changeset
|
228 auto e = elements[i]; |
79 | 229 if (e) |
230 { | |
231 return i; | |
232 } | |
233 break; | |
234 } | |
235 } | |
236 } | |
237 return -1; | |
0 | 238 } |
239 | |
72 | 240 override elem* toElem(IRState* irs) |
0 | 241 { |
72 | 242 elem* e; |
243 size_t dim; | |
244 | |
245 //printf("StructLiteralExp.toElem() %s\n", toChars()); | |
246 | |
247 // struct symbol to initialize with the literal | |
248 Symbol* stmp = sym ? sym : symbol_genauto(sd.type.toCtype()); | |
249 | |
250 e = null; | |
251 | |
252 if (fillHoles) | |
253 { | |
254 /* Initialize all alignment 'holes' to zero. | |
255 * Do before initializing fields, as the hole filling process | |
256 * can spill over into the fields. | |
257 */ | |
258 size_t offset = 0; | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
259 foreach (VarDeclaration v; sd.fields) |
72 | 260 { |
261 assert(v); | |
262 | |
263 e = el_combine(e, fillHole(stmp, &offset, v.offset, sd.structsize)); | |
264 size_t vend = v.offset + cast(uint)v.type.size(); | |
265 if (offset < vend) | |
266 offset = vend; | |
267 } | |
268 e = el_combine(e, fillHole(stmp, &offset, sd.structsize, sd.structsize)); | |
269 } | |
270 | |
271 if (elements) | |
272 { | |
273 dim = elements.dim; | |
274 assert(dim <= sd.fields.dim); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
275 foreach (size_t i, Expression el; elements) |
72 | 276 { |
277 if (!el) | |
278 continue; | |
279 | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
280 VarDeclaration v = sd.fields[i]; |
72 | 281 assert(v); |
282 assert(!v.isThisDeclaration()); | |
283 | |
284 elem* e1; | |
285 if (tybasic(stmp.Stype.Tty) == TYnptr) | |
286 { | |
287 e1 = el_var(stmp); | |
288 e1.EV.sp.Voffset = soffset; | |
289 } | |
290 else | |
291 { | |
292 e1 = el_ptr(stmp); | |
293 if (soffset) | |
294 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset)); | |
295 } | |
296 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v.offset)); | |
297 elem* ec = e1; // pointer to destination | |
298 | |
299 elem* ep = el.toElem(irs); | |
300 | |
301 Type t1b = v.type.toBasetype(); | |
302 Type t2b = el.type.toBasetype(); | |
303 if (t1b.ty == Tsarray) | |
304 { | |
305 if (t2b.implicitConvTo(t1b)) | |
306 { | |
307 ///version (DMDV2) { | |
308 // Determine if postblit is needed | |
309 int postblit = 0; | |
310 if (needsPostblit(t1b)) | |
311 postblit = 1; | |
312 | |
313 if (postblit) | |
314 { | |
315 /* Generate: | |
316 * _d_arrayctor(ti, From: ep, To: e1) | |
317 */ | |
318 Expression ti = t1b.nextOf().toBasetype().getTypeInfo(null); | |
319 elem* esize = el_long(TYsize_t, (cast(TypeSArray)t1b).dim.toInteger()); | |
320 e1 = el_pair(TYdarray, esize, e1); | |
321 ep = el_pair(TYdarray, el_copytree(esize), array_toPtr(el.type, ep)); | |
322 ep = el_params(e1, ep, ti.toElem(irs), null); | |
323 int rtl = RTLSYM_ARRAYCTOR; | |
324 e1 = el_bin(OPcall, type.totym(), el_var(rtlsym[rtl]), ep); | |
325 } | |
326 else | |
327 ///} | |
328 { | |
329 elem* esize = el_long(TYsize_t, t1b.size()); | |
330 ep = array_toPtr(el.type, ep); | |
331 e1 = el_bin(OPmemcpy, TYnptr, e1, el_param(ep, esize)); | |
332 } | |
333 } | |
334 else | |
335 { | |
336 elem* edim = el_long(TYsize_t, t1b.size() / t2b.size()); | |
337 e1 = setArray(e1, edim, t2b, ep, irs, TOKconstruct); | |
338 } | |
339 } | |
340 else | |
341 { | |
342 tym_t ty = v.type.totym(); | |
343 e1 = el_una(OPind, ty, e1); | |
344 if (tybasic(ty) == TYstruct) | |
345 e1.Enumbytes = cast(uint)v.type.size(); | |
346 e1 = el_bin(OPeq, ty, e1, ep); | |
347 if (tybasic(ty) == TYstruct) | |
348 { | |
349 e1.Eoper = OPstreq; | |
350 e1.Enumbytes = cast(uint)v.type.size(); | |
351 } | |
352 version (DMDV2) { | |
353 /* Call postblit() on e1 | |
354 */ | |
355 StructDeclaration sd = needsPostblit(v.type); | |
356 if (sd) | |
357 { | |
358 FuncDeclaration fd = sd.postblit; | |
359 ec = el_copytree(ec); | |
360 ec = callfunc(loc, irs, 1, Type.tvoid, ec, sd.type.pointerTo(), fd, fd.type, null, null); | |
361 e1 = el_bin(OPcomma, ec.Ety, e1, ec); | |
362 } | |
363 } | |
364 } | |
365 e = el_combine(e, e1); | |
366 } | |
367 } | |
368 | |
79 | 369 version (DMDV2) |
370 { | |
72 | 371 if (sd.isnested) |
372 { // Initialize the hidden 'this' pointer | |
373 assert(sd.fields.dim); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
374 auto s = sd.fields[sd.fields.dim - 1]; |
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
375 auto v = s.isThisDeclaration(); |
72 | 376 assert(v); |
377 | |
378 elem* e1; | |
379 if (tybasic(stmp.Stype.Tty) == TYnptr) | |
380 { | |
381 e1 = el_var(stmp); | |
382 e1.EV.sp.Voffset = soffset; | |
383 } | |
384 else | |
385 { | |
386 e1 = el_ptr(stmp); | |
387 if (soffset) | |
388 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, soffset)); | |
389 } | |
390 e1 = el_bin(OPadd, TYnptr, e1, el_long(TYsize_t, v.offset)); | |
391 e1 = setEthis(loc, irs, e1, sd); | |
392 | |
393 e = el_combine(e, e1); | |
394 } | |
395 } | |
396 | |
397 elem* ev = el_var(stmp); | |
398 ev.Enumbytes = sd.structsize; | |
399 e = el_combine(e, ev); | |
400 el_setLoc(e,loc); | |
67 | 401 return e; |
0 | 402 } |
403 | |
72 | 404 override bool checkSideEffect(int flag) |
0 | 405 { |
79 | 406 bool f = 0; |
407 | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
85
diff
changeset
|
408 foreach (e; elements) |
79 | 409 { |
410 if (!e) | |
411 continue; | |
412 | |
413 f |= e.checkSideEffect(2); | |
414 } | |
415 if (flag == 0 && f == 0) | |
416 Expression.checkSideEffect(0); | |
417 return f; | |
0 | 418 } |
419 | |
72 | 420 override void toCBuffer(OutBuffer buf, HdrGenState* hgs) |
0 | 421 { |
79 | 422 buf.writestring(sd.toChars()); |
423 buf.writeByte('('); | |
424 argsToCBuffer(buf, elements, hgs); | |
425 buf.writeByte(')'); | |
0 | 426 } |
427 | |
72 | 428 override void toMangleBuffer(OutBuffer buf) |
0 | 429 { |
79 | 430 size_t dim = elements ? elements.dim : 0; |
431 buf.printf("S%u", dim); | |
432 for (size_t i = 0; i < dim; i++) | |
433 { | |
90
39648eb578f6
more Expressions work
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
85
diff
changeset
|
434 auto e = elements[i]; |
79 | 435 if (e) |
436 e.toMangleBuffer(buf); | |
437 else | |
438 buf.writeByte('v'); // 'v' for void | |
439 } | |
0 | 440 } |
441 | |
72 | 442 override void scanForNestedRef(Scope sc) |
0 | 443 { |
444 assert(false); | |
445 } | |
446 | |
72 | 447 override Expression optimize(int result) |
0 | 448 { |
72 | 449 if (elements) |
450 { | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
451 foreach (size_t i, Expression e; elements) |
72 | 452 { |
453 if (!e) | |
454 continue; | |
455 e = e.optimize(WANTvalue | (result & WANTinterpret)); | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
456 elements[i] = e; |
72 | 457 } |
458 } | |
56 | 459 return this; |
0 | 460 } |
461 | |
72 | 462 override Expression interpret(InterState istate) |
0 | 463 { |
123 | 464 Expressions expsx = null; |
465 | |
466 version (LOG) { | |
467 printf("StructLiteralExp.interpret() %.*s\n", toChars()); | |
468 } | |
469 /* We don't know how to deal with overlapping fields | |
470 */ | |
471 if (sd.hasUnions) | |
472 { | |
473 error("Unions with overlapping fields are not yet supported in CTFE"); | |
474 return EXP_CANT_INTERPRET; | |
475 } | |
476 | |
477 if (elements) | |
478 { | |
479 foreach (size_t i, Expression e; elements) | |
480 { | |
481 if (!e) | |
482 continue; | |
483 | |
484 Expression ex = e.interpret(istate); | |
485 if (ex is EXP_CANT_INTERPRET) | |
486 { | |
487 delete expsx; | |
488 return EXP_CANT_INTERPRET; | |
489 } | |
490 | |
491 /* If any changes, do Copy On Write | |
492 */ | |
493 if (ex != e) | |
494 { | |
495 if (!expsx) | |
496 { | |
497 expsx = new Expressions(); | |
498 expsx.setDim(elements.dim); | |
499 for (size_t j = 0; j < elements.dim; j++) | |
500 { | |
501 expsx[j] = elements[j]; | |
502 } | |
503 } | |
504 expsx[i] = ex; | |
505 } | |
506 } | |
507 } | |
508 if (elements && expsx) | |
509 { | |
510 expandTuples(expsx); | |
511 if (expsx.dim != elements.dim) | |
512 { | |
513 delete expsx; | |
514 return EXP_CANT_INTERPRET; | |
515 } | |
516 StructLiteralExp se = new StructLiteralExp(loc, sd, expsx); | |
517 se.type = type; | |
518 return se; | |
519 } | |
520 return this; | |
0 | 521 } |
522 | |
72 | 523 override dt_t** toDt(dt_t** pdt) |
0 | 524 { |
147
9a2a1ae6c8e5
fix test runnable\structlit.d
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
135
diff
changeset
|
525 scope dts = new Array; |
123 | 526 dt_t *dt; |
527 dt_t *d; | |
528 uint offset; | |
529 | |
530 //printf("StructLiteralExp.toDt() %s)\n", toChars()); | |
531 dts.setDim(sd.fields.dim); | |
532 dts.zero(); | |
533 assert(elements.dim <= sd.fields.dim); | |
534 | |
535 foreach (uint i, Expression e; elements) | |
536 { | |
537 if (!e) | |
538 continue; | |
539 | |
540 dt = null; | |
541 e.toDt(&dt); | |
542 dts.data[i] = dt; | |
543 } | |
544 | |
545 offset = 0; | |
546 foreach (uint j, VarDeclaration v; sd.fields) | |
547 { | |
548 d = cast(dt_t*)dts.data[j]; | |
549 if (!d) | |
550 { // An instance specific initializer was not provided. | |
551 // Look to see if there's a default initializer from the | |
552 // struct definition | |
553 if (v.init) | |
554 { | |
555 d = v.init.toDt(); | |
556 } | |
557 else if (v.offset >= offset) | |
558 { | |
559 uint k; | |
560 uint offset2 = v.offset + cast(uint)v.type.size(); | |
561 // Make sure this field (v) does not overlap any explicitly | |
562 // initialized field. | |
563 for (k = j + 1; 1; k++) | |
564 { | |
565 if (k == dts.dim) // didn't find any overlap | |
566 { | |
567 v.type.toDt(&d); | |
568 break; | |
569 } | |
570 VarDeclaration v2 = sd.fields[k]; | |
571 | |
572 if (v2.offset < offset2 && dts.data[k]) | |
573 break; // overlap | |
574 } | |
575 } | |
576 } | |
577 if (d) | |
578 { | |
579 if (v.offset < offset) | |
580 error("duplicate union initialization for %s", v.toChars()); | |
581 else | |
582 { | |
583 uint sz = dt_size(d); | |
584 uint vsz = cast(uint)v.type.size(); | |
585 uint voffset = v.offset; | |
586 assert(sz <= vsz); | |
587 | |
588 uint dim = 1; | |
589 for (Type vt = v.type.toBasetype(); vt.ty == Tsarray; vt = vt.nextOf().toBasetype()) | |
590 { | |
591 TypeSArray tsa = cast(TypeSArray)vt; | |
592 dim *= tsa.dim.toInteger(); | |
593 } | |
594 | |
595 for (size_t i = 0; i < dim; i++) | |
596 { | |
597 if (offset < voffset) | |
598 pdt = dtnzeros(pdt, voffset - offset); | |
599 if (!d) | |
600 { | |
601 if (v.init) | |
602 d = v.init.toDt(); | |
603 else | |
604 v.type.toDt(&d); | |
605 } | |
606 pdt = dtcat(pdt, d); | |
607 d = null; | |
608 offset = voffset + sz; | |
609 voffset += vsz / dim; | |
610 if (sz == vsz) | |
611 break; | |
612 } | |
613 } | |
614 } | |
615 } | |
616 | |
617 if (offset < sd.structsize) | |
618 pdt = dtnzeros(pdt, sd.structsize - offset); | |
619 | |
620 return pdt; | |
0 | 621 } |
622 | |
79 | 623 version(DMDV2) |
624 { | |
72 | 625 override int isLvalue() |
0 | 626 { |
79 | 627 return 1; |
0 | 628 } |
79 | 629 } |
0 | 630 |
72 | 631 override Expression toLvalue(Scope sc, Expression e) |
0 | 632 { |
79 | 633 return this; |
0 | 634 } |
635 | |
79 | 636 version(DMDV2) |
637 { | |
72 | 638 override bool canThrow() |
0 | 639 { |
64 | 640 return arrayExpressionCanThrow(elements); |
0 | 641 } |
79 | 642 } |
0 | 643 |
72 | 644 override MATCH implicitConvTo(Type t) |
0 | 645 { |
72 | 646 static if (false) { |
647 printf("StructLiteralExp.implicitConvTo(this=%.*s, type=%.*s, t=%.*s)\n", | |
648 toChars(), type.toChars(), t.toChars()); | |
649 } | |
650 MATCH m = Expression.implicitConvTo(t); | |
651 if (m != MATCHnomatch) | |
652 return m; | |
653 if (type.ty == t.ty && type.ty == Tstruct && (cast(TypeStruct)type).sym == (cast(TypeStruct)t).sym) | |
654 { | |
655 m = MATCHconst; | |
84
be2ab491772e
Expressions -> Vector!Expression
Eldar Insafutdinov <e.insafutdinov@gmail.com>
parents:
79
diff
changeset
|
656 foreach(e; elements) |
72 | 657 { |
658 Type te = e.type; | |
659 if (t.mod == 0) | |
660 te = te.mutableOf(); | |
661 else | |
662 { | |
135 | 663 assert(t.mod == MODimmutable); |
72 | 664 te = te.invariantOf(); |
665 } | |
666 MATCH m2 = e.implicitConvTo(te); | |
667 //printf("\t%s => %s, match = %d\n", e.toChars(), te.toChars(), m2); | |
668 if (m2 < m) | |
669 m = m2; | |
670 } | |
671 } | |
64 | 672 return m; |
0 | 673 } |
674 | |
72 | 675 override int inlineCost(InlineCostState* ics) |
0 | 676 { |
677 assert(false); | |
678 } | |
679 | |
72 | 680 override Expression doInline(InlineDoState ids) |
0 | 681 { |
682 assert(false); | |
683 } | |
684 | |
72 | 685 override Expression inlineScan(InlineScanState* iss) |
0 | 686 { |
687 assert(false); | |
688 } | |
689 } | |
690 |