Mercurial > projects > ddmd
annotate dmd/StructLiteralExp.d @ 123:9e39c7de8438
Make dmd test suite compile
author | korDen |
---|---|
date | Fri, 03 Sep 2010 20:46:58 +0400 |
parents | e28b18c23469 |
children | af1bebfd96a4 |
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 { | |
160 e = v.type.defaultInit(Loc(0)); | |
161 e.loc = loc; | |
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 { |
123 | 525 Array dts; |
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 { | |
663 assert(t.mod == MODinvariant); | |
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 |