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