1:
2: // Compiler implementation of the D programming language
3: // Copyright (c) 1999-2011 by Digital Mars
4: // All Rights Reserved
5: // written by Walter Bright
6: // http://www.digitalmars.com
7: // License for redistribution is by either the Artistic License
8: // in artistic.txt, or the GNU General Public License in gnu.txt.
9: // See the included readme.txt for details.
10:
11: #include <stdio.h>
12: #include <stdlib.h>
13: #include <math.h>
14: static char __file__[] = __FILE__; /* for tassert.h */
15: #include "tassert.h"
16:
17: #if __DMC__
18: #include <complex.h>
19: #endif
20:
21: #include "cdef.h"
22: #include "rmem.h"
23: #include "root.h"
24: #include "port.h"
25:
26: #include "mtype.h"
27: #include "expression.h"
28: #include "aggregate.h"
29: #include "declaration.h"
30: #include "utf.h"
31:
32: #define LOG 0
33:
34: int RealEquals(real_t x1, real_t x2);
35:
36: Expression *expType(Type *type, Expression *e)
37: {
38: if (type != e->type)
39: {
40: e = e->copy();
41: e->type = type;
42: }
43: return e;
44: }
45:
46: /* ================================== isConst() ============================== */
47:
48: int Expression::isConst()
49: {
50: //printf("Expression::isConst(): %s\n", toChars());
51: return 0;
52: }
53:
54: int IntegerExp::isConst()
55: {
56: return 1;
57: }
58:
59: int RealExp::isConst()
60: {
61: return 1;
62: }
63:
64: int ComplexExp::isConst()
65: {
66: return 1;
67: }
68:
69: int NullExp::isConst()
70: {
71: return 0;
72: }
73:
74: int SymOffExp::isConst()
75: {
76: return 2;
77: }
78:
79: /* =============================== constFold() ============================== */
80:
81: /* The constFold() functions were redundant with the optimize() ones,
82: * and so have been folded in with them.
83: */
84:
85: /* ========================================================================== */
86:
87: Expression *Neg(Type *type, Expression *e1)
88: { Expression *e;
89: Loc loc = e1->loc;
90:
91: if (e1->type->isreal())
92: {
93: e = new RealExp(loc, -e1->toReal(), type);
94: }
95: else if (e1->type->isimaginary())
96: {
97: e = new RealExp(loc, -e1->toImaginary(), type);
98: }
99: else if (e1->type->iscomplex())
100: {
101: e = new ComplexExp(loc, -e1->toComplex(), type);
102: }
103: else
104: e = new IntegerExp(loc, -e1->toInteger(), type);
warning C4146: unary minus operator applied to unsigned type, result still unsigned
105: return e;
106: }
107:
108: Expression *Com(Type *type, Expression *e1)
109: { Expression *e;
110: Loc loc = e1->loc;
111:
112: e = new IntegerExp(loc, ~e1->toInteger(), type);
113: return e;
114: }
115:
116: Expression *Not(Type *type, Expression *e1)
117: { Expression *e;
118: Loc loc = e1->loc;
119:
120: e = new IntegerExp(loc, e1->isBool(0), type);
121: return e;
122: }
123:
124: Expression *Bool(Type *type, Expression *e1)
125: { Expression *e;
126: Loc loc = e1->loc;
127:
128: e = new IntegerExp(loc, e1->isBool(1), type);
129: return e;
130: }
131:
132: Expression *Add(Type *type, Expression *e1, Expression *e2)
133: { Expression *e;
134: Loc loc = e1->loc;
135:
136: #if LOG
137: printf("Add(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
138: #endif
139: if (type->isreal())
140: {
141: e = new RealExp(loc, e1->toReal() + e2->toReal(), type);
142: }
143: else if (type->isimaginary())
144: {
145: e = new RealExp(loc, e1->toImaginary() + e2->toImaginary(), type);
146: }
147: else if (type->iscomplex())
148: {
149: // This rigamarole is necessary so that -0.0 doesn't get
150: // converted to +0.0 by doing an extraneous add with +0.0
151: complex_t c1;
152: real_t r1;
153: real_t i1;
154:
155: complex_t c2;
156: real_t r2;
157: real_t i2;
158:
159: complex_t v;
160: int x;
161:
162: if (e1->type->isreal())
163: { r1 = e1->toReal();
164: x = 0;
165: }
166: else if (e1->type->isimaginary())
167: { i1 = e1->toImaginary();
168: x = 3;
169: }
170: else
171: { c1 = e1->toComplex();
172: x = 6;
173: }
174:
175: if (e2->type->isreal())
176: { r2 = e2->toReal();
177: }
178: else if (e2->type->isimaginary())
179: { i2 = e2->toImaginary();
180: x += 1;
181: }
182: else
183: { c2 = e2->toComplex();
184: x += 2;
185: }
186:
187: switch (x)
188: {
189: #if __DMC__
190: case 0+0: v = (complex_t) (r1 + r2); break;
191: case 0+1: v = r1 + i2 * I; break;
192: case 0+2: v = r1 + c2; break;
193: case 3+0: v = i1 * I + r2; break;
194: case 3+1: v = (complex_t) ((i1 + i2) * I); break;
195: case 3+2: v = i1 * I + c2; break;
196: case 6+0: v = c1 + r2; break;
197: case 6+1: v = c1 + i2 * I; break;
198: case 6+2: v = c1 + c2; break;
199: #else
200: case 0+0: v = complex_t(r1 + r2, 0); break;
201: case 0+1: v = complex_t(r1, i2); break;
202: case 0+2: v = complex_t(r1 + creall(c2), cimagl(c2)); break;
203: case 3+0: v = complex_t(r2, i1); break;
204: case 3+1: v = complex_t(0, i1 + i2); break;
205: case 3+2: v = complex_t(creall(c2), i1 + cimagl(c2)); break;
206: case 6+0: v = complex_t(creall(c1) + r2, cimagl(c2)); break;
207: case 6+1: v = complex_t(creall(c1), cimagl(c1) + i2); break;
208: case 6+2: v = c1 + c2; break;
209: #endif
210: default: assert(0);
211: }
212: e = new ComplexExp(loc, v, type);
213: }
214: else if (e1->op == TOKsymoff)
215: {
216: SymOffExp *soe = (SymOffExp *)e1;
217: e = new SymOffExp(loc, soe->var, soe->offset + e2->toInteger());
warning C4244: 'argument' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
218: e->type = type;
219: }
220: else if (e2->op == TOKsymoff)
221: {
222: SymOffExp *soe = (SymOffExp *)e2;
223: e = new SymOffExp(loc, soe->var, soe->offset + e1->toInteger());
warning C4244: 'argument' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
224: e->type = type;
225: }
226: else
227: e = new IntegerExp(loc, e1->toInteger() + e2->toInteger(), type);
228: return e;
229: }
230:
231:
232: Expression *Min(Type *type, Expression *e1, Expression *e2)
233: { Expression *e;
234: Loc loc = e1->loc;
235:
236: if (type->isreal())
237: {
238: e = new RealExp(loc, e1->toReal() - e2->toReal(), type);
239: }
240: else if (type->isimaginary())
241: {
242: e = new RealExp(loc, e1->toImaginary() - e2->toImaginary(), type);
243: }
244: else if (type->iscomplex())
245: {
246: // This rigamarole is necessary so that -0.0 doesn't get
247: // converted to +0.0 by doing an extraneous add with +0.0
248: complex_t c1;
249: real_t r1;
250: real_t i1;
251:
252: complex_t c2;
253: real_t r2;
254: real_t i2;
255:
256: complex_t v;
257: int x;
258:
259: if (e1->type->isreal())
260: { r1 = e1->toReal();
261: x = 0;
262: }
263: else if (e1->type->isimaginary())
264: { i1 = e1->toImaginary();
265: x = 3;
266: }
267: else
268: { c1 = e1->toComplex();
269: x = 6;
270: }
271:
272: if (e2->type->isreal())
273: { r2 = e2->toReal();
274: }
275: else if (e2->type->isimaginary())
276: { i2 = e2->toImaginary();
277: x += 1;
278: }
279: else
280: { c2 = e2->toComplex();
281: x += 2;
282: }
283:
284: switch (x)
285: {
286: #if __DMC__
287: case 0+0: v = (complex_t) (r1 - r2); break;
288: case 0+1: v = r1 - i2 * I; break;
289: case 0+2: v = r1 - c2; break;
290: case 3+0: v = i1 * I - r2; break;
291: case 3+1: v = (complex_t) ((i1 - i2) * I); break;
292: case 3+2: v = i1 * I - c2; break;
293: case 6+0: v = c1 - r2; break;
294: case 6+1: v = c1 - i2 * I; break;
295: case 6+2: v = c1 - c2; break;
296: #else
297: case 0+0: v = complex_t(r1 - r2, 0); break;
298: case 0+1: v = complex_t(r1, -i2); break;
299: case 0+2: v = complex_t(r1 - creall(c2), -cimagl(c2)); break;
300: case 3+0: v = complex_t(-r2, i1); break;
301: case 3+1: v = complex_t(0, i1 - i2); break;
302: case 3+2: v = complex_t(-creall(c2), i1 - cimagl(c2)); break;
303: case 6+0: v = complex_t(creall(c1) - r2, cimagl(c1)); break;
304: case 6+1: v = complex_t(creall(c1), cimagl(c1) - i2); break;
305: case 6+2: v = c1 - c2; break;
306: #endif
307: default: assert(0);
308: }
309: e = new ComplexExp(loc, v, type);
310: }
311: else if (e1->op == TOKsymoff)
312: {
313: SymOffExp *soe = (SymOffExp *)e1;
314: e = new SymOffExp(loc, soe->var, soe->offset - e2->toInteger());
warning C4244: 'argument' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
315: e->type = type;
316: }
317: else
318: {
319: e = new IntegerExp(loc, e1->toInteger() - e2->toInteger(), type);
320: }
321: return e;
322: }
323:
324: Expression *Mul(Type *type, Expression *e1, Expression *e2)
325: { Expression *e;
326: Loc loc = e1->loc;
327:
328: if (type->isfloating())
329: { complex_t c;
330: #ifdef IN_GCC
331: real_t r;
332: #else
333: d_float80 r;
334: #endif
335:
336: if (e1->type->isreal())
337: {
338: #if __DMC__
339: c = e1->toReal() * e2->toComplex();
340: #else
341: r = e1->toReal();
342: c = e2->toComplex();
343: c = complex_t(r * creall(c), r * cimagl(c));
344: #endif
345: }
346: else if (e1->type->isimaginary())
347: {
348: #if __DMC__
349: c = e1->toImaginary() * I * e2->toComplex();
350: #else
351: r = e1->toImaginary();
352: c = e2->toComplex();
353: c = complex_t(-r * cimagl(c), r * creall(c));
354: #endif
355: }
356: else if (e2->type->isreal())
357: {
358: #if __DMC__
359: c = e2->toReal() * e1->toComplex();
360: #else
361: r = e2->toReal();
362: c = e1->toComplex();
363: c = complex_t(r * creall(c), r * cimagl(c));
364: #endif
365: }
366: else if (e2->type->isimaginary())
367: {
368: #if __DMC__
369: c = e1->toComplex() * e2->toImaginary() * I;
370: #else
371: r = e2->toImaginary();
372: c = e1->toComplex();
373: c = complex_t(-r * cimagl(c), r * creall(c));
374: #endif
375: }
376: else
377: c = e1->toComplex() * e2->toComplex();
378:
379: if (type->isreal())
380: e = new RealExp(loc, creall(c), type);
381: else if (type->isimaginary())
382: e = new RealExp(loc, cimagl(c), type);
383: else if (type->iscomplex())
384: e = new ComplexExp(loc, c, type);
385: else
386: assert(0);
387: }
388: else
389: {
390: e = new IntegerExp(loc, e1->toInteger() * e2->toInteger(), type);
391: }
392: return e;
393: }
394:
395: Expression *Div(Type *type, Expression *e1, Expression *e2)
396: { Expression *e;
397: Loc loc = e1->loc;
398:
399: if (type->isfloating())
400: { complex_t c;
401: #ifdef IN_GCC
402: real_t r;
403: #else
404: d_float80 r;
405: #endif
406:
407: //e1->type->print();
408: //e2->type->print();
409: if (e2->type->isreal())
410: {
411: if (e1->type->isreal())
412: {
413: e = new RealExp(loc, e1->toReal() / e2->toReal(), type);
414: return e;
415: }
416: #if __DMC__
417: //r = e2->toReal();
418: //c = e1->toComplex();
419: //printf("(%Lg + %Lgi) / %Lg\n", creall(c), cimagl(c), r);
420:
421: c = e1->toComplex() / e2->toReal();
422: #else
423: r = e2->toReal();
424: c = e1->toComplex();
425: c = complex_t(creall(c) / r, cimagl(c) / r);
426: #endif
427: }
428: else if (e2->type->isimaginary())
429: {
430: #if __DMC__
431: //r = e2->toImaginary();
432: //c = e1->toComplex();
433: //printf("(%Lg + %Lgi) / %Lgi\n", creall(c), cimagl(c), r);
434:
435: c = e1->toComplex() / (e2->toImaginary() * I);
436: #else
437: r = e2->toImaginary();
438: c = e1->toComplex();
439: c = complex_t(cimagl(c) / r, -creall(c) / r);
440: #endif
441: }
442: else
443: {
444: c = e1->toComplex() / e2->toComplex();
445: }
446:
447: if (type->isreal())
448: e = new RealExp(loc, creall(c), type);
449: else if (type->isimaginary())
450: e = new RealExp(loc, cimagl(c), type);
451: else if (type->iscomplex())
452: e = new ComplexExp(loc, c, type);
453: else
454: assert(0);
455: }
456: else
457: { sinteger_t n1;
458: sinteger_t n2;
459: sinteger_t n;
460:
461: n1 = e1->toInteger();
462: n2 = e2->toInteger();
463: if (n2 == 0)
464: { e2->error("divide by 0");
465: e2 = new IntegerExp(loc, 1, e2->type);
warning C6211: Leaking memory 'e2' due to an exception. Consider using a local catch block to clean up memory: Lines: 396, 397, 399, 457, 458, 459, 461, 462, 463, 464, 465, 466, 468, 471, 472
466: n2 = 1;
467: }
468: if (e1->type->isunsigned() || e2->type->isunsigned())
469: n = ((d_uns64) n1) / ((d_uns64) n2);
470: else
471: n = n1 / n2;
472: e = new IntegerExp(loc, n, type);
473: }
474: return e;
475: }
476:
477: Expression *Mod(Type *type, Expression *e1, Expression *e2)
478: { Expression *e;
479: Loc loc = e1->loc;
480:
481: if (type->isfloating())
482: {
483: complex_t c;
484:
485: if (e2->type->isreal())
486: { real_t r2 = e2->toReal();
487:
488: #ifdef __DMC__
489: c = Port::fmodl(e1->toReal(), r2) + Port::fmodl(e1->toImaginary(), r2) * I;
490: #elif defined(IN_GCC)
491: c = complex_t(e1->toReal() % r2, e1->toImaginary() % r2);
492: #else
493: c = complex_t(Port::fmodl(e1->toReal(), r2), Port::fmodl(e1->toImaginary(), r2));
494: #endif
495: }
496: else if (e2->type->isimaginary())
497: { real_t i2 = e2->toImaginary();
498:
499: #ifdef __DMC__
500: c = Port::fmodl(e1->toReal(), i2) + Port::fmodl(e1->toImaginary(), i2) * I;
501: #elif defined(IN_GCC)
502: c = complex_t(e1->toReal() % i2, e1->toImaginary() % i2);
503: #else
504: c = complex_t(Port::fmodl(e1->toReal(), i2), Port::fmodl(e1->toImaginary(), i2));
505: #endif
506: }
507: else
508: assert(0);
509:
510: if (type->isreal())
511: e = new RealExp(loc, creall(c), type);
512: else if (type->isimaginary())
513: e = new RealExp(loc, cimagl(c), type);
514: else if (type->iscomplex())
515: e = new ComplexExp(loc, c, type);
516: else
517: assert(0);
518: }
519: else
520: { sinteger_t n1;
521: sinteger_t n2;
522: sinteger_t n;
523:
524: n1 = e1->toInteger();
525: n2 = e2->toInteger();
526: if (n2 == 0)
527: { e2->error("divide by 0");
528: e2 = new IntegerExp(loc, 1, e2->type);
warning C6211: Leaking memory 'e2' due to an exception. Consider using a local catch block to clean up memory: Lines: 478, 479, 481, 520, 521, 522, 524, 525, 526, 527, 528, 529, 531, 546, 549, 550
529: n2 = 1;
530: }
531: if (n2 == -1 && !type->isunsigned())
532: { // Check for int.min % -1
533: if (n1 == 0xFFFFFFFF80000000ULL && type->toBasetype()->ty != Tint64)
534: {
535: e2->error("integer overflow: int.min % -1");
536: e2 = new IntegerExp(loc, 1, e2->type);
537: n2 = 1;
538: }
539: else if (n1 == 0x8000000000000000LL) // long.min % -1
540: {
541: e2->error("integer overflow: long.min % -1");
542: e2 = new IntegerExp(loc, 1, e2->type);
543: n2 = 1;
544: }
545: }
546: if (e1->type->isunsigned() || e2->type->isunsigned())
547: n = ((d_uns64) n1) % ((d_uns64) n2);
548: else
549: n = n1 % n2;
550: e = new IntegerExp(loc, n, type);
551: }
552: return e;
553: }
554:
555: Expression *Shl(Type *type, Expression *e1, Expression *e2)
556: { Expression *e;
557: Loc loc = e1->loc;
558:
559: e = new IntegerExp(loc, e1->toInteger() << e2->toInteger(), type);
560: return e;
561: }
562:
563: Expression *Shr(Type *type, Expression *e1, Expression *e2)
564: {
565: Loc loc = e1->loc;
566:
567: dinteger_t value = e1->toInteger();
568: unsigned count = e2->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
569: switch (e1->type->toBasetype()->ty)
570: {
571: case Tint8:
572: value = (d_int8)(value) >> count;
573: break;
574:
575: case Tuns8:
576: value = (d_uns8)(value) >> count;
577: break;
578:
579: case Tint16:
580: value = (d_int16)(value) >> count;
581: break;
582:
583: case Tuns16:
584: value = (d_uns16)(value) >> count;
585: break;
586:
587: case Tint32:
588: value = (d_int32)(value) >> count;
589: break;
590:
591: case Tuns32:
592: value = (d_uns32)(value) >> count;
593: break;
594:
595: case Tint64:
596: value = (d_int64)(value) >> count;
597: break;
598:
599: case Tuns64:
600: value = (d_uns64)(value) >> count;
601: break;
602:
603: case Terror:
604: return e1;
605:
606: default:
607: assert(0);
608: }
609: Expression *e = new IntegerExp(loc, value, type);
610: return e;
611: }
612:
613: Expression *Ushr(Type *type, Expression *e1, Expression *e2)
614: {
615: Loc loc = e1->loc;
616:
617: dinteger_t value = e1->toInteger();
618: unsigned count = e2->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
619: switch (e1->type->toBasetype()->ty)
620: {
621: case Tint8:
622: case Tuns8:
623: assert(0); // no way to trigger this
624: value = (value & 0xFF) >> count;
625: break;
626:
627: case Tint16:
628: case Tuns16:
629: assert(0); // no way to trigger this
630: value = (value & 0xFFFF) >> count;
631: break;
632:
633: case Tint32:
634: case Tuns32:
635: value = (value & 0xFFFFFFFF) >> count;
636: break;
637:
638: case Tint64:
639: case Tuns64:
640: value = (d_uns64)(value) >> count;
641: break;
642:
643: case Terror:
644: return e1;
645:
646: default:
647: assert(0);
648: }
649: Expression *e = new IntegerExp(loc, value, type);
650: return e;
651: }
652:
653: Expression *And(Type *type, Expression *e1, Expression *e2)
654: {
655: Expression *e;
656: e = new IntegerExp(e1->loc, e1->toInteger() & e2->toInteger(), type);
657: return e;
658: }
659:
660: Expression *Or(Type *type, Expression *e1, Expression *e2)
661: { Expression *e;
662: e = new IntegerExp(e1->loc, e1->toInteger() | e2->toInteger(), type);
663: return e;
664: }
665:
666: Expression *Xor(Type *type, Expression *e1, Expression *e2)
667: { Expression *e;
668: e = new IntegerExp(e1->loc, e1->toInteger() ^ e2->toInteger(), type);
669: return e;
670: }
671:
672: /* Also returns EXP_CANT_INTERPRET if cannot be computed.
673: */
674: Expression *Equal(enum TOK op, Type *type, Expression *e1, Expression *e2)
675: { Expression *e;
676: Loc loc = e1->loc;
677: int cmp;
678: real_t r1;
679: real_t r2;
680:
681: //printf("Equal(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
682:
683: assert(op == TOKequal || op == TOKnotequal);
684:
685: if (e1->op == TOKnull)
686: {
687: if (e2->op == TOKnull)
688: cmp = 1;
689: else if (e2->op == TOKstring)
690: { StringExp *es2 = (StringExp *)e2;
691: cmp = (0 == es2->len);
692: }
693: else if (e2->op == TOKarrayliteral)
694: { ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
695: cmp = !es2->elements || (0 == es2->elements->dim);
696: }
697: else
698: return EXP_CANT_INTERPRET;
699: }
700: else if (e2->op == TOKnull)
701: {
702: if (e1->op == TOKstring)
703: { StringExp *es1 = (StringExp *)e1;
704: cmp = (0 == es1->len);
705: }
706: else if (e1->op == TOKarrayliteral)
707: { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
708: cmp = !es1->elements || (0 == es1->elements->dim);
709: }
710: else
711: return EXP_CANT_INTERPRET;
712: }
713: else if (e1->op == TOKstring && e2->op == TOKstring)
714: { StringExp *es1 = (StringExp *)e1;
715: StringExp *es2 = (StringExp *)e2;
716:
717: if (es1->sz != es2->sz)
718: {
719: assert(global.errors);
720: return EXP_CANT_INTERPRET;
721: }
722: if (es1->len == es2->len &&
723: memcmp(es1->string, es2->string, es1->sz * es1->len) == 0)
724: cmp = 1;
725: else
726: cmp = 0;
727: }
728: else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral)
729: { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
730: ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
731:
732: if ((!es1->elements || !es1->elements->dim) &&
733: (!es2->elements || !es2->elements->dim))
734: cmp = 1; // both arrays are empty
735: else if (!es1->elements || !es2->elements)
736: cmp = 0;
737: else if (es1->elements->dim != es2->elements->dim)
738: cmp = 0;
739: else
740: {
741: for (size_t i = 0; i < es1->elements->dim; i++)
742: { Expression *ee1 = es1->elements->tdata()[i];
743: Expression *ee2 = es2->elements->tdata()[i];
744:
745: Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2);
746: if (v == EXP_CANT_INTERPRET)
747: return EXP_CANT_INTERPRET;
748: cmp = v->toInteger();
warning C4244: '=' : conversion from 'dinteger_t' to 'int', possible loss of data
749: if (cmp == 0)
750: break;
751: }
752: }
753: }
754: else if (e1->op == TOKarrayliteral && e2->op == TOKstring)
755: { // Swap operands and use common code
756: Expression *e = e1;
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '675' of 'c:\projects\extern\d\dmd\src\constfold.c': Lines: 675
757: e1 = e2;
758: e2 = e;
759: goto Lsa;
760: }
761: else if (e1->op == TOKstring && e2->op == TOKarrayliteral)
762: {
763: Lsa:
764: StringExp *es1 = (StringExp *)e1;
765: ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
766: size_t dim1 = es1->len;
767: size_t dim2 = es2->elements ? es2->elements->dim : 0;
768: if (dim1 != dim2)
769: cmp = 0;
770: else
771: {
772: cmp = 1; // if dim1 winds up being 0
773: for (size_t i = 0; i < dim1; i++)
774: {
775: uinteger_t c = es1->charAt(i);
776: Expression *ee2 = (*es2->elements)[i];
777: if (ee2->isConst() != 1)
778: return EXP_CANT_INTERPRET;
779: cmp = (c == ee2->toInteger());
780: if (cmp == 0)
781: break;
782: }
783: }
784: }
785: else if (e1->op == TOKstructliteral && e2->op == TOKstructliteral)
786: { StructLiteralExp *es1 = (StructLiteralExp *)e1;
787: StructLiteralExp *es2 = (StructLiteralExp *)e2;
788:
789: if (es1->sd != es2->sd)
790: cmp = 0;
791: else if ((!es1->elements || !es1->elements->dim) &&
792: (!es2->elements || !es2->elements->dim))
793: cmp = 1; // both arrays are empty
794: else if (!es1->elements || !es2->elements)
795: cmp = 0;
796: else if (es1->elements->dim != es2->elements->dim)
797: cmp = 0;
798: else
799: {
800: cmp = 1;
801: for (size_t i = 0; i < es1->elements->dim; i++)
802: { Expression *ee1 = es1->elements->tdata()[i];
803: Expression *ee2 = es2->elements->tdata()[i];
804:
805: if (ee1 == ee2)
806: continue;
807: if (!ee1 || !ee2)
808: { cmp = 0;
809: break;
810: }
811: Expression *v = Equal(TOKequal, Type::tint32, ee1, ee2);
812: if (v == EXP_CANT_INTERPRET)
813: return EXP_CANT_INTERPRET;
814: cmp = v->toInteger();
warning C4244: '=' : conversion from 'dinteger_t' to 'int', possible loss of data
815: if (cmp == 0)
816: break;
817: }
818: }
819: }
820: #if 0 // Should handle this
821: else if (e1->op == TOKarrayliteral && e2->op == TOKstring)
822: {
823: }
824: #endif
825: else if (e1->isConst() != 1 || e2->isConst() != 1)
826: return EXP_CANT_INTERPRET;
827: else if (e1->type->isreal())
828: {
829: r1 = e1->toReal();
830: r2 = e2->toReal();
831: goto L1;
832: }
833: else if (e1->type->isimaginary())
834: {
835: r1 = e1->toImaginary();
836: r2 = e2->toImaginary();
837: L1:
838: #if __DMC__
839: cmp = (r1 == r2);
840: #else
841: if (Port::isNan(r1) || Port::isNan(r2)) // if unordered
842: {
843: cmp = 0;
844: }
845: else
846: {
847: cmp = (r1 == r2);
848: }
849: #endif
850: }
851: else if (e1->type->iscomplex())
852: {
853: cmp = e1->toComplex() == e2->toComplex();
854: }
855: else if (e1->type->isintegral() || e1->type->toBasetype()->ty == Tpointer)
856: {
857: cmp = (e1->toInteger() == e2->toInteger());
858: }
859: else
860: return EXP_CANT_INTERPRET;
861: if (op == TOKnotequal)
862: cmp ^= 1;
863: e = new IntegerExp(loc, cmp, type);
864: return e;
865: }
866:
867: Expression *Identity(enum TOK op, Type *type, Expression *e1, Expression *e2)
868: {
869: Loc loc = e1->loc;
870: int cmp;
871:
872: if (e1->op == TOKnull)
873: {
874: cmp = (e2->op == TOKnull);
875: }
876: else if (e2->op == TOKnull)
877: {
878: cmp = 0;
879: }
880: else if (e1->op == TOKsymoff && e2->op == TOKsymoff)
881: {
882: SymOffExp *es1 = (SymOffExp *)e1;
883: SymOffExp *es2 = (SymOffExp *)e2;
884:
885: cmp = (es1->var == es2->var && es1->offset == es2->offset);
886: }
887: else
888: {
889: if (e1->type->isreal())
890: {
891: cmp = RealEquals(e1->toReal(), e2->toReal());
892: }
893: else if (e1->type->isimaginary())
894: {
895: cmp = RealEquals(e1->toImaginary(), e2->toImaginary());
896: }
897: else if (e1->type->iscomplex())
898: {
899: complex_t v1 = e1->toComplex();
900: complex_t v2 = e2->toComplex();
901: cmp = RealEquals(creall(v1), creall(v2)) &&
902: RealEquals(cimagl(v1), cimagl(v1));
903: }
904: else
905: return Equal((op == TOKidentity) ? TOKequal : TOKnotequal,
906: type, e1, e2);
907: }
908: if (op == TOKnotidentity)
909: cmp ^= 1;
910: return new IntegerExp(loc, cmp, type);
911: }
912:
913:
914: Expression *Cmp(enum TOK op, Type *type, Expression *e1, Expression *e2)
915: { Expression *e;
916: Loc loc = e1->loc;
917: dinteger_t n;
918: real_t r1;
919: real_t r2;
920:
921: //printf("Cmp(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
922:
923: if (e1->op == TOKstring && e2->op == TOKstring)
924: { StringExp *es1 = (StringExp *)e1;
925: StringExp *es2 = (StringExp *)e2;
926: size_t sz = es1->sz;
927: assert(sz == es2->sz);
928:
929: size_t len = es1->len;
930: if (es2->len < len)
931: len = es2->len;
932:
933: int cmp = memcmp(es1->string, es2->string, sz * len);
934: if (cmp == 0)
935: cmp = es1->len - es2->len;
936:
937: switch (op)
938: {
939: case TOKlt: n = cmp < 0; break;
940: case TOKle: n = cmp <= 0; break;
941: case TOKgt: n = cmp > 0; break;
942: case TOKge: n = cmp >= 0; break;
943:
944: case TOKleg: n = 1; break;
945: case TOKlg: n = cmp != 0; break;
946: case TOKunord: n = 0; break;
947: case TOKue: n = cmp == 0; break;
948: case TOKug: n = cmp > 0; break;
949: case TOKuge: n = cmp >= 0; break;
950: case TOKul: n = cmp < 0; break;
951: case TOKule: n = cmp <= 0; break;
952:
953: default:
954: assert(0);
955: }
956: }
957: else if (e1->isConst() != 1 || e2->isConst() != 1)
958: return EXP_CANT_INTERPRET;
959: else if (e1->type->isreal())
960: {
961: r1 = e1->toReal();
962: r2 = e2->toReal();
963: goto L1;
964: }
965: else if (e1->type->isimaginary())
966: {
967: r1 = e1->toImaginary();
968: r2 = e2->toImaginary();
969: L1:
970: #if __DMC__
971: // DMC is the only compiler I know of that handles NAN arguments
972: // correctly in comparisons.
973: switch (op)
974: {
975: case TOKlt: n = r1 < r2; break;
976: case TOKle: n = r1 <= r2; break;
977: case TOKgt: n = r1 > r2; break;
978: case TOKge: n = r1 >= r2; break;
979:
980: case TOKleg: n = r1 <>= r2; break;
981: case TOKlg: n = r1 <> r2; break;
982: case TOKunord: n = r1 !<>= r2; break;
983: case TOKue: n = r1 !<> r2; break;
984: case TOKug: n = r1 !<= r2; break;
985: case TOKuge: n = r1 !< r2; break;
986: case TOKul: n = r1 !>= r2; break;
987: case TOKule: n = r1 !> r2; break;
988:
989: default:
990: assert(0);
991: }
992: #else
993: // Don't rely on compiler, handle NAN arguments separately
994: if (Port::isNan(r1) || Port::isNan(r2)) // if unordered
995: {
996: switch (op)
997: {
998: case TOKlt: n = 0; break;
999: case TOKle: n = 0; break;
1000: case TOKgt: n = 0; break;
1001: case TOKge: n = 0; break;
1002:
1003: case TOKleg: n = 0; break;
1004: case TOKlg: n = 0; break;
1005: case TOKunord: n = 1; break;
1006: case TOKue: n = 1; break;
1007: case TOKug: n = 1; break;
1008: case TOKuge: n = 1; break;
1009: case TOKul: n = 1; break;
1010: case TOKule: n = 1; break;
1011:
1012: default:
1013: assert(0);
1014: }
1015: }
1016: else
1017: {
1018: switch (op)
1019: {
1020: case TOKlt: n = r1 < r2; break;
1021: case TOKle: n = r1 <= r2; break;
1022: case TOKgt: n = r1 > r2; break;
1023: case TOKge: n = r1 >= r2; break;
1024:
1025: case TOKleg: n = 1; break;
1026: case TOKlg: n = r1 != r2; break;
1027: case TOKunord: n = 0; break;
1028: case TOKue: n = r1 == r2; break;
1029: case TOKug: n = r1 > r2; break;
1030: case TOKuge: n = r1 >= r2; break;
1031: case TOKul: n = r1 < r2; break;
1032: case TOKule: n = r1 <= r2; break;
1033:
1034: default:
1035: assert(0);
1036: }
1037: }
1038: #endif
1039: }
1040: else if (e1->type->iscomplex())
1041: {
1042: assert(0);
1043: }
1044: else
1045: { sinteger_t n1;
1046: sinteger_t n2;
1047:
1048: n1 = e1->toInteger();
1049: n2 = e2->toInteger();
1050: if (e1->type->isunsigned() || e2->type->isunsigned())
1051: {
1052: switch (op)
1053: {
1054: case TOKlt: n = ((d_uns64) n1) < ((d_uns64) n2); break;
1055: case TOKle: n = ((d_uns64) n1) <= ((d_uns64) n2); break;
1056: case TOKgt: n = ((d_uns64) n1) > ((d_uns64) n2); break;
1057: case TOKge: n = ((d_uns64) n1) >= ((d_uns64) n2); break;
1058:
1059: case TOKleg: n = 1; break;
1060: case TOKlg: n = ((d_uns64) n1) != ((d_uns64) n2); break;
1061: case TOKunord: n = 0; break;
1062: case TOKue: n = ((d_uns64) n1) == ((d_uns64) n2); break;
1063: case TOKug: n = ((d_uns64) n1) > ((d_uns64) n2); break;
1064: case TOKuge: n = ((d_uns64) n1) >= ((d_uns64) n2); break;
1065: case TOKul: n = ((d_uns64) n1) < ((d_uns64) n2); break;
1066: case TOKule: n = ((d_uns64) n1) <= ((d_uns64) n2); break;
1067:
1068: default:
1069: assert(0);
1070: }
1071: }
1072: else
1073: {
1074: switch (op)
1075: {
1076: case TOKlt: n = n1 < n2; break;
1077: case TOKle: n = n1 <= n2; break;
1078: case TOKgt: n = n1 > n2; break;
1079: case TOKge: n = n1 >= n2; break;
1080:
1081: case TOKleg: n = 1; break;
1082: case TOKlg: n = n1 != n2; break;
1083: case TOKunord: n = 0; break;
1084: case TOKue: n = n1 == n2; break;
1085: case TOKug: n = n1 > n2; break;
1086: case TOKuge: n = n1 >= n2; break;
1087: case TOKul: n = n1 < n2; break;
1088: case TOKule: n = n1 <= n2; break;
1089:
1090: default:
1091: assert(0);
1092: }
1093: }
1094: }
1095: e = new IntegerExp(loc, n, type);
1096: return e;
1097: }
1098:
1099: /* Also returns EXP_CANT_INTERPRET if cannot be computed.
1100: * to: type to cast to
1101: * type: type to paint the result
1102: */
1103:
1104: Expression *Cast(Type *type, Type *to, Expression *e1)
1105: { Expression *e = EXP_CANT_INTERPRET;
1106: Loc loc = e1->loc;
1107:
1108: //printf("Cast(type = %s, to = %s, e1 = %s)\n", type->toChars(), to->toChars(), e1->toChars());
1109: //printf("\te1->type = %s\n", e1->type->toChars());
1110: if (e1->type->equals(type) && type->equals(to))
1111: return e1;
1112: if (e1->type->implicitConvTo(to) >= MATCHconst ||
1113: to->implicitConvTo(e1->type) >= MATCHconst)
1114: return expType(to, e1);
1115:
1116: // Allow covariant converions of delegates
1117: // (Perhaps implicit conversion from pure to impure should be a MATCHconst,
1118: // then we wouldn't need this extra check.)
1119: if (e1->type->toBasetype()->ty == Tdelegate &&
1120: e1->type->implicitConvTo(to) == MATCHconvert)
1121: return expType(to, e1);
1122:
1123: Type *tb = to->toBasetype();
1124: Type *typeb = type->toBasetype();
1125:
1126: /* Allow casting from one string type to another
1127: */
1128: if (e1->op == TOKstring)
1129: {
1130: if (tb->ty == Tarray && typeb->ty == Tarray &&
1131: tb->nextOf()->size() == typeb->nextOf()->size())
1132: {
1133: return expType(to, e1);
1134: }
1135: }
1136:
1137: if (e1->op == TOKarrayliteral && typeb == tb)
1138: return e1;
1139:
1140: if (e1->isConst() != 1)
1141: return EXP_CANT_INTERPRET;
1142:
1143: if (tb->ty == Tbool)
1144: e = new IntegerExp(loc, e1->toInteger() != 0, type);
1145: else if (type->isintegral())
1146: {
1147: if (e1->type->isfloating())
1148: { dinteger_t result;
1149: real_t r = e1->toReal();
1150:
1151: switch (typeb->ty)
1152: {
1153: case Tint8: result = (d_int8)r; break;
1154: case Tchar:
1155: case Tuns8: result = (d_uns8)r; break;
1156: case Tint16: result = (d_int16)r; break;
1157: case Twchar:
1158: case Tuns16: result = (d_uns16)r; break;
1159: case Tint32: result = (d_int32)r; break;
1160: case Tdchar:
1161: case Tuns32: result = (d_uns32)r; break;
1162: case Tint64: result = (d_int64)r; break;
1163: case Tuns64: result = (d_uns64)r; break;
1164: default:
1165: assert(0);
1166: }
1167:
1168: e = new IntegerExp(loc, result, type);
1169: }
1170: else if (type->isunsigned())
1171: e = new IntegerExp(loc, e1->toUInteger(), type);
1172: else
1173: e = new IntegerExp(loc, e1->toInteger(), type);
1174: }
1175: else if (tb->isreal())
1176: { real_t value = e1->toReal();
1177:
1178: e = new RealExp(loc, value, type);
1179: }
1180: else if (tb->isimaginary())
1181: { real_t value = e1->toImaginary();
1182:
1183: e = new RealExp(loc, value, type);
1184: }
1185: else if (tb->iscomplex())
1186: { complex_t value = e1->toComplex();
1187:
1188: e = new ComplexExp(loc, value, type);
1189: }
1190: else if (tb->isscalar())
1191: e = new IntegerExp(loc, e1->toInteger(), type);
1192: else if (tb->ty == Tvoid)
1193: e = EXP_CANT_INTERPRET;
1194: else if (tb->ty == Tstruct && e1->op == TOKint64)
1195: { // Struct = 0;
1196: StructDeclaration *sd = tb->toDsymbol(NULL)->isStructDeclaration();
1197: assert(sd);
1198: Expressions *elements = new Expressions;
1199: for (size_t i = 0; i < sd->fields.dim; i++)
1200: { Dsymbol *s = sd->fields.tdata()[i];
1201: VarDeclaration *v = s->isVarDeclaration();
1202: assert(v);
1203:
1204: Expression *exp = new IntegerExp(0);
1205: exp = Cast(v->type, v->type, exp);
1206: if (exp == EXP_CANT_INTERPRET)
1207: return exp;
1208: elements->push(exp);
1209: }
1210: e = new StructLiteralExp(loc, sd, elements);
1211: e->type = type;
1212: }
1213: else
1214: {
1215: if (type != Type::terror)
1216: error(loc, "cannot cast %s to %s", e1->type->toChars(), type->toChars());
1217: e = new ErrorExp();
1218: }
1219: return e;
1220: }
1221:
1222:
1223: Expression *ArrayLength(Type *type, Expression *e1)
1224: { Expression *e;
1225: Loc loc = e1->loc;
1226:
1227: if (e1->op == TOKstring)
1228: { StringExp *es1 = (StringExp *)e1;
1229:
1230: e = new IntegerExp(loc, es1->len, type);
1231: }
1232: else if (e1->op == TOKarrayliteral)
1233: { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
1234: size_t dim;
1235:
1236: dim = ale->elements ? ale->elements->dim : 0;
1237: e = new IntegerExp(loc, dim, type);
1238: }
1239: else if (e1->op == TOKassocarrayliteral)
1240: { AssocArrayLiteralExp *ale = (AssocArrayLiteralExp *)e1;
1241: size_t dim = ale->keys->dim;
1242:
1243: e = new IntegerExp(loc, dim, type);
1244: }
1245: else
1246: e = EXP_CANT_INTERPRET;
1247: return e;
1248: }
1249:
1250: /* Also return EXP_CANT_INTERPRET if this fails
1251: */
1252: Expression *Index(Type *type, Expression *e1, Expression *e2)
1253: { Expression *e = EXP_CANT_INTERPRET;
1254: Loc loc = e1->loc;
1255:
1256: //printf("Index(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
1257: assert(e1->type);
1258: if (e1->op == TOKstring && e2->op == TOKint64)
1259: { StringExp *es1 = (StringExp *)e1;
1260: uinteger_t i = e2->toInteger();
1261:
1262: if (i >= es1->len)
1263: e1->error("string index %ju is out of bounds [0 .. %"SIZE_T_FORMAT"u]", i, es1->len);
1264: else
1265: { unsigned value = es1->charAt(i);
warning C4244: 'argument' : conversion from 'uinteger_t' to 'size_t', possible loss of data
1266: e = new IntegerExp(loc, value, type);
1267: }
1268: }
1269: else if (e1->type->toBasetype()->ty == Tsarray && e2->op == TOKint64)
1270: { TypeSArray *tsa = (TypeSArray *)e1->type->toBasetype();
1271: uinteger_t length = tsa->dim->toInteger();
1272: uinteger_t i = e2->toInteger();
1273:
1274: if (i >= length)
1275: { e1->error("array index %ju is out of bounds %s[0 .. %ju]", i, e1->toChars(), length);
1276: }
1277: else if (e1->op == TOKarrayliteral)
1278: { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
1279: e = ale->elements->tdata()[i];
1280: e->type = type;
1281: if (e->checkSideEffect(2))
1282: e = EXP_CANT_INTERPRET;
1283: }
1284: }
1285: else if (e1->type->toBasetype()->ty == Tarray && e2->op == TOKint64)
1286: {
1287: uinteger_t i = e2->toInteger();
1288:
1289: if (e1->op == TOKarrayliteral)
1290: { ArrayLiteralExp *ale = (ArrayLiteralExp *)e1;
1291: if (i >= ale->elements->dim)
1292: { e1->error("array index %ju is out of bounds %s[0 .. %u]", i, e1->toChars(), ale->elements->dim);
1293: }
1294: else
1295: { e = ale->elements->tdata()[i];
1296: e->type = type;
1297: if (e->checkSideEffect(2))
1298: e = EXP_CANT_INTERPRET;
1299: }
1300: }
1301: }
1302: else if (e1->op == TOKassocarrayliteral)
1303: {
1304: AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)e1;
1305: /* Search the keys backwards, in case there are duplicate keys
1306: */
1307: for (size_t i = ae->keys->dim; i;)
1308: {
1309: i--;
1310: Expression *ekey = ae->keys->tdata()[i];
1311: Expression *ex = Equal(TOKequal, Type::tbool, ekey, e2);
1312: if (ex == EXP_CANT_INTERPRET)
1313: return ex;
1314: if (ex->isBool(TRUE))
1315: { e = ae->values->tdata()[i];
1316: e->type = type;
1317: if (e->checkSideEffect(2))
1318: e = EXP_CANT_INTERPRET;
1319: break;
1320: }
1321: }
1322: }
1323: return e;
1324: }
1325:
1326: /* Also return EXP_CANT_INTERPRET if this fails
1327: */
1328: Expression *Slice(Type *type, Expression *e1, Expression *lwr, Expression *upr)
1329: { Expression *e = EXP_CANT_INTERPRET;
1330: Loc loc = e1->loc;
1331:
1332: #if LOG
1333: printf("Slice()\n");
1334: if (lwr)
1335: { printf("\te1 = %s\n", e1->toChars());
1336: printf("\tlwr = %s\n", lwr->toChars());
1337: printf("\tupr = %s\n", upr->toChars());
1338: }
1339: #endif
1340: if (e1->op == TOKstring && lwr->op == TOKint64 && upr->op == TOKint64)
1341: { StringExp *es1 = (StringExp *)e1;
1342: uinteger_t ilwr = lwr->toInteger();
1343: uinteger_t iupr = upr->toInteger();
1344:
1345: if (iupr > es1->len || ilwr > iupr)
1346: e1->error("string slice [%ju .. %ju] is out of bounds", ilwr, iupr);
1347: else
1348: { dinteger_t value;
warning C4101: 'value' : unreferenced local variable
1349: void *s;
1350: size_t len = iupr - ilwr;
warning C4244: 'initializing' : conversion from 'uinteger_t' to 'size_t', possible loss of data
1351: int sz = es1->sz;
1352: StringExp *es;
1353:
1354: s = mem.malloc((len + 1) * sz);
1355: memcpy((unsigned char *)s, (unsigned char *)es1->string + ilwr * sz, len * sz);
1356: memset((unsigned char *)s + len * sz, 0, sz);
1357:
1358: es = new StringExp(loc, s, len, es1->postfix);
1359: es->sz = sz;
1360: es->committed = 1;
1361: es->type = type;
1362: e = es;
1363: }
1364: }
1365: else if (e1->op == TOKarrayliteral &&
1366: lwr->op == TOKint64 && upr->op == TOKint64 &&
1367: !e1->checkSideEffect(2))
1368: { ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
1369: uinteger_t ilwr = lwr->toInteger();
1370: uinteger_t iupr = upr->toInteger();
1371:
1372: if (iupr > es1->elements->dim || ilwr > iupr)
1373: e1->error("array slice [%ju .. %ju] is out of bounds", ilwr, iupr);
1374: else
1375: {
1376: Expressions *elements = new Expressions();
1377: elements->setDim(iupr - ilwr);
warning C4244: 'argument' : conversion from 'uinteger_t' to 'unsigned int', possible loss of data
1378: memcpy(elements->tdata(),
1379: es1->elements->tdata() + ilwr,
1380: (iupr - ilwr) * sizeof(es1->elements->tdata()[0]));
warning C4244: 'argument' : conversion from 'uinteger_t' to 'size_t', possible loss of data
1381: e = new ArrayLiteralExp(e1->loc, elements);
1382: e->type = type;
1383: }
1384: }
1385: return e;
1386: }
1387:
1388: /* Also return EXP_CANT_INTERPRET if this fails
1389: */
1390: Expression *Cat(Type *type, Expression *e1, Expression *e2)
1391: { Expression *e = EXP_CANT_INTERPRET;
1392: Loc loc = e1->loc;
1393: Type *t;
1394: Type *t1 = e1->type->toBasetype();
1395: Type *t2 = e2->type->toBasetype();
1396:
1397: //printf("Cat(e1 = %s, e2 = %s)\n", e1->toChars(), e2->toChars());
1398: //printf("\tt1 = %s, t2 = %s, type = %s\n", t1->toChars(), t2->toChars(), type->toChars());
1399:
1400: if (e1->op == TOKnull && (e2->op == TOKint64 || e2->op == TOKstructliteral))
1401: { e = e2;
1402: t = t1;
1403: goto L2;
1404: }
1405: else if ((e1->op == TOKint64 || e1->op == TOKstructliteral) && e2->op == TOKnull)
1406: { e = e1;
1407: t = t2;
1408: L2:
1409: Type *tn = e->type->toBasetype();
1410: if (tn->ty == Tchar || tn->ty == Twchar || tn->ty == Tdchar)
1411: {
1412: // Create a StringExp
1413: void *s;
1414: StringExp *es;
1415: if (t->nextOf())
1416: t = t->nextOf()->toBasetype();
1417: int sz = t->size();
warning C4244: 'initializing' : conversion from 'd_uns64' to 'int', possible loss of data
1418:
1419: dinteger_t v = e->toInteger();
1420:
1421: size_t len = (t->ty == tn->ty) ? 1 : utf_codeLength(sz, v);
warning C4244: 'argument' : conversion from 'dinteger_t' to 'dchar_t', possible loss of data
1422: s = mem.malloc((len + 1) * sz);
1423: if (t->ty == tn->ty)
1424: memcpy((unsigned char *)s, &v, sz);
1425: else
1426: utf_encode(sz, s, v);
warning C4244: 'argument' : conversion from 'dinteger_t' to 'dchar_t', possible loss of data
1427:
1428: // Add terminating 0
1429: memset((unsigned char *)s + len * sz, 0, sz);
1430:
1431: es = new StringExp(loc, s, len);
1432: es->sz = sz;
1433: es->committed = 1;
1434: e = es;
1435: }
1436: else
1437: { // Create an ArrayLiteralExp
1438: Expressions *elements = new Expressions();
1439: elements->push(e);
1440: e = new ArrayLiteralExp(e->loc, elements);
1441: }
1442: e->type = type;
1443: return e;
1444: }
1445: else if (e1->op == TOKnull && e2->op == TOKnull)
1446: {
1447: if (type == e1->type)
1448: return e1;
1449: if (type == e2->type)
1450: return e2;
1451: return new NullExp(e1->loc, type);
1452: }
1453: else if (e1->op == TOKstring && e2->op == TOKstring)
1454: {
1455: // Concatenate the strings
1456: void *s;
1457: StringExp *es1 = (StringExp *)e1;
1458: StringExp *es2 = (StringExp *)e2;
1459: StringExp *es;
1460: Type *t;
warning C6246: Local declaration of 't' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '1393' of 'c:\projects\extern\d\dmd\src\constfold.c': Lines: 1393
1461: size_t len = es1->len + es2->len;
1462: int sz = es1->sz;
1463:
1464: if (sz != es2->sz)
1465: {
1466: /* Can happen with:
1467: * auto s = "foo"d ~ "bar"c;
1468: */
1469: assert(global.errors);
1470: return e;
1471: }
1472: s = mem.malloc((len + 1) * sz);
1473: memcpy(s, es1->string, es1->len * sz);
1474: memcpy((unsigned char *)s + es1->len * sz, es2->string, es2->len * sz);
1475:
1476: // Add terminating 0
1477: memset((unsigned char *)s + len * sz, 0, sz);
1478:
1479: es = new StringExp(loc, s, len);
1480: es->sz = sz;
1481: es->committed = es1->committed | es2->committed;
1482: if (es1->committed)
1483: t = es1->type;
1484: else
1485: t = es2->type;
1486: es->type = type;
1487: e = es;
1488: }
1489: else if (e2->op == TOKstring && e1->op == TOKarrayliteral &&
1490: t1->nextOf()->isintegral())
1491: {
1492: // Concatenate the strings
1493: StringExp *es1 = (StringExp *)e2;
1494: ArrayLiteralExp *es2 = (ArrayLiteralExp *)e1;
1495: size_t len = es1->len + es2->elements->dim;
1496: int sz = es1->sz;
1497:
1498: void *s = mem.malloc((len + 1) * sz);
1499: memcpy((char *)s + sz * es2->elements->dim, es1->string, es1->len * sz);
1500: for (int i = 0; i < es2->elements->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1501: { Expression *es2e = es2->elements->tdata()[i];
1502: if (es2e->op != TOKint64)
1503: return EXP_CANT_INTERPRET;
1504: dinteger_t v = es2e->toInteger();
1505: memcpy((unsigned char *)s + i * sz, &v, sz);
1506: }
1507:
1508: // Add terminating 0
1509: memset((unsigned char *)s + len * sz, 0, sz);
1510:
1511: StringExp *es = new StringExp(loc, s, len);
1512: es->sz = sz;
1513: es->committed = 0;
1514: es->type = type;
1515: e = es;
1516: }
1517: else if (e1->op == TOKstring && e2->op == TOKarrayliteral &&
1518: t2->nextOf()->isintegral())
1519: {
1520: // Concatenate the strings
1521: StringExp *es1 = (StringExp *)e1;
1522: ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
1523: size_t len = es1->len + es2->elements->dim;
1524: int sz = es1->sz;
1525:
1526: void *s = mem.malloc((len + 1) * sz);
1527: memcpy(s, es1->string, es1->len * sz);
1528: for (int i = 0; i < es2->elements->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1529: { Expression *es2e = es2->elements->tdata()[i];
1530: if (es2e->op != TOKint64)
1531: return EXP_CANT_INTERPRET;
1532: dinteger_t v = es2e->toInteger();
1533: memcpy((unsigned char *)s + (es1->len + i) * sz, &v, sz);
1534: }
1535:
1536: // Add terminating 0
1537: memset((unsigned char *)s + len * sz, 0, sz);
1538:
1539: StringExp *es = new StringExp(loc, s, len);
1540: es->sz = sz;
1541: es->committed = 0; //es1->committed;
1542: es->type = type;
1543: e = es;
1544: }
1545: else if (e1->op == TOKstring && e2->op == TOKint64)
1546: {
1547: // Concatenate the strings
1548: void *s;
1549: StringExp *es1 = (StringExp *)e1;
1550: StringExp *es;
1551: Type *t;
warning C6246: Local declaration of 't' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '1393' of 'c:\projects\extern\d\dmd\src\constfold.c': Lines: 1393
1552: int sz = es1->sz;
1553: dinteger_t v = e2->toInteger();
1554:
1555: // Is it a concatentation of homogenous types?
1556: // (char[] ~ char, wchar[]~wchar, or dchar[]~dchar)
1557: bool homoConcat = (sz == t2->size());
1558: size_t len = es1->len;
1559: len += homoConcat ? 1 : utf_codeLength(sz, v);
warning C4244: 'argument' : conversion from 'dinteger_t' to 'dchar_t', possible loss of data
1560:
1561: s = mem.malloc((len + 1) * sz);
1562: memcpy(s, es1->string, es1->len * sz);
1563: if (homoConcat)
1564: memcpy((unsigned char *)s + (sz * es1->len), &v, sz);
1565: else
1566: utf_encode(sz, (unsigned char *)s + (sz * es1->len), v);
warning C4244: 'argument' : conversion from 'dinteger_t' to 'dchar_t', possible loss of data
1567:
1568: // Add terminating 0
1569: memset((unsigned char *)s + len * sz, 0, sz);
1570:
1571: es = new StringExp(loc, s, len);
1572: es->sz = sz;
1573: es->committed = es1->committed;
1574: t = es1->type;
1575: es->type = type;
1576: e = es;
1577: }
1578: else if (e1->op == TOKint64 && e2->op == TOKstring)
1579: {
1580: // Concatenate the strings
1581: void *s;
1582: StringExp *es2 = (StringExp *)e2;
1583: StringExp *es;
1584: Type *t;
warning C6246: Local declaration of 't' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '1393' of 'c:\projects\extern\d\dmd\src\constfold.c': Lines: 1393
1585: size_t len = 1 + es2->len;
1586: int sz = es2->sz;
1587: dinteger_t v = e1->toInteger();
1588:
1589: s = mem.malloc((len + 1) * sz);
1590: memcpy((unsigned char *)s, &v, sz);
1591: memcpy((unsigned char *)s + sz, es2->string, es2->len * sz);
1592:
1593: // Add terminating 0
1594: memset((unsigned char *)s + len * sz, 0, sz);
1595:
1596: es = new StringExp(loc, s, len);
1597: es->sz = sz;
1598: es->committed = es2->committed;
1599: t = es2->type;
1600: es->type = type;
1601: e = es;
1602: }
1603: else if (e1->op == TOKarrayliteral && e2->op == TOKarrayliteral &&
1604: t1->nextOf()->equals(t2->nextOf()))
1605: {
1606: // Concatenate the arrays
1607: ArrayLiteralExp *es1 = (ArrayLiteralExp *)e1;
1608: ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
1609:
1610: es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy());
1611: es1->elements->insert(es1->elements->dim, es2->elements);
1612: e = es1;
1613:
1614: if (type->toBasetype()->ty == Tsarray)
1615: {
1616: e->type = new TypeSArray(t1->nextOf(), new IntegerExp(loc, es1->elements->dim, Type::tindex));
1617: e->type = e->type->semantic(loc, NULL);
1618: }
1619: else
1620: e->type = type;
1621: }
1622: else if (e1->op == TOKarrayliteral && e2->op == TOKnull &&
1623: t1->nextOf()->equals(t2->nextOf()))
1624: {
1625: e = e1;
1626: goto L3;
1627: }
1628: else if (e1->op == TOKnull && e2->op == TOKarrayliteral &&
1629: t1->nextOf()->equals(t2->nextOf()))
1630: {
1631: e = e2;
1632: L3:
1633: // Concatenate the array with null
1634: ArrayLiteralExp *es = (ArrayLiteralExp *)e;
1635:
1636: es = new ArrayLiteralExp(es->loc, (Expressions *)es->elements->copy());
1637: e = es;
1638:
1639: if (type->toBasetype()->ty == Tsarray)
1640: {
1641: e->type = new TypeSArray(t1->nextOf(), new IntegerExp(loc, es->elements->dim, Type::tindex));
1642: e->type = e->type->semantic(loc, NULL);
1643: }
1644: else
1645: e->type = type;
1646: }
1647: else if ((e1->op == TOKarrayliteral || e1->op == TOKnull) &&
1648: e1->type->toBasetype()->nextOf()->equals(e2->type))
1649: {
1650: ArrayLiteralExp *es1;
1651: if (e1->op == TOKarrayliteral)
1652: { es1 = (ArrayLiteralExp *)e1;
1653: es1 = new ArrayLiteralExp(es1->loc, (Expressions *)es1->elements->copy());
1654: es1->elements->push(e2);
1655: }
1656: else
1657: {
1658: es1 = new ArrayLiteralExp(e1->loc, e2);
warning C6211: Leaking memory 'return value' due to an exception. Consider using a local catch block to clean up memory: Lines: 1391, 1392, 1393, 1394, 1395, 1400, 1405, 1445, 1453, 1489, 1517, 1545, 1578, 1603, 1622, 1628, 1647, 1650, 1651, 1658, 1660, 1662, 1664
1659: }
1660: e = es1;
1661:
1662: if (type->toBasetype()->ty == Tsarray)
1663: {
1664: e->type = new TypeSArray(e2->type, new IntegerExp(loc, es1->elements->dim, Type::tindex));
1665: e->type = e->type->semantic(loc, NULL);
1666: }
1667: else
1668: e->type = type;
1669: }
1670: else if (e2->op == TOKarrayliteral &&
1671: e2->type->toBasetype()->nextOf()->equals(e1->type))
1672: {
1673: ArrayLiteralExp *es2 = (ArrayLiteralExp *)e2;
1674:
1675: es2 = new ArrayLiteralExp(es2->loc, (Expressions *)es2->elements->copy());
1676: es2->elements->shift(e1);
1677: e = es2;
1678:
1679: if (type->toBasetype()->ty == Tsarray)
1680: {
1681: e->type = new TypeSArray(e1->type, new IntegerExp(loc, es2->elements->dim, Type::tindex));
1682: e->type = e->type->semantic(loc, NULL);
1683: }
1684: else
1685: e->type = type;
1686: }
1687: else if (e1->op == TOKnull && e2->op == TOKstring)
1688: {
1689: t = e1->type;
1690: e = e2;
1691: goto L1;
1692: }
1693: else if (e1->op == TOKstring && e2->op == TOKnull)
1694: { e = e1;
1695: t = e2->type;
1696: L1:
1697: Type *tb = t->toBasetype();
1698: if (tb->ty == Tarray && tb->nextOf()->equals(e->type))
1699: { Expressions *expressions = new Expressions();
1700: expressions->push(e);
1701: e = new ArrayLiteralExp(loc, expressions);
1702: e->type = t;
1703: }
1704: if (!e->type->equals(type))
1705: { StringExp *se = (StringExp *)e->copy();
1706: e = se->castTo(NULL, type);
1707: }
1708: }
1709: return e;
1710: }
1711:
1712: Expression *Ptr(Type *type, Expression *e1)
1713: {
1714: //printf("Ptr(e1 = %s)\n", e1->toChars());
1715: if (e1->op == TOKadd)
1716: { AddExp *ae = (AddExp *)e1;
1717: if (ae->e1->op == TOKaddress && ae->e2->op == TOKint64)
1718: { AddrExp *ade = (AddrExp *)ae->e1;
1719: if (ade->e1->op == TOKstructliteral)
1720: { StructLiteralExp *se = (StructLiteralExp *)ade->e1;
1721: unsigned offset = ae->e2->toInteger();
warning C4244: 'initializing' : conversion from 'dinteger_t' to 'unsigned int', possible loss of data
1722: Expression *e = se->getField(type, offset);
1723: if (!e)
1724: e = EXP_CANT_INTERPRET;
1725: return e;
1726: }
1727: }
1728: }
1729: return EXP_CANT_INTERPRET;
1730: }
1731:
1732: