Mercurial > projects > ldc
comparison dmd2/cast.c @ 758:f04dde6e882c
Added initial D2 support, D2 frontend and changes to codegen to make things compile.
author | Tomas Lindquist Olsen <tomas.l.olsen@gmail.com> |
---|---|
date | Tue, 11 Nov 2008 01:38:48 +0100 |
parents | |
children | 356e65836fb5 |
comparison
equal
deleted
inserted
replaced
757:2c730d530c98 | 758:f04dde6e882c |
---|---|
1 | |
2 // Copyright (c) 1999-2008 by Digital Mars | |
3 // All Rights Reserved | |
4 // written by Walter Bright | |
5 // http://www.digitalmars.com | |
6 // License for redistribution is by either the Artistic License | |
7 // in artistic.txt, or the GNU General Public License in gnu.txt. | |
8 // See the included readme.txt for details. | |
9 | |
10 #include <stdio.h> | |
11 #include <assert.h> | |
12 | |
13 #if _WIN32 || IN_GCC || IN_LLVM | |
14 #include "mem.h" | |
15 #else | |
16 #include "../root/mem.h" | |
17 #endif | |
18 | |
19 #include "expression.h" | |
20 #include "mtype.h" | |
21 #include "utf.h" | |
22 #include "declaration.h" | |
23 #include "aggregate.h" | |
24 | |
25 /* ==================== implicitCast ====================== */ | |
26 | |
27 /************************************** | |
28 * Do an implicit cast. | |
29 * Issue error if it can't be done. | |
30 */ | |
31 | |
32 Expression *Expression::implicitCastTo(Scope *sc, Type *t) | |
33 { | |
34 //printf("Expression::implicitCastTo(%s of type %s) => %s\n", toChars(), type->toChars(), t->toChars()); | |
35 | |
36 MATCH match = implicitConvTo(t); | |
37 if (match) | |
38 { | |
39 if (global.params.warnings && | |
40 Type::impcnvWarn[type->toBasetype()->ty][t->toBasetype()->ty] && | |
41 op != TOKint64) | |
42 { | |
43 Expression *e = optimize(WANTflags | WANTvalue); | |
44 | |
45 if (e->op == TOKint64) | |
46 return e->implicitCastTo(sc, t); | |
47 | |
48 warning("%s: implicit conversion of expression (%s) of type %s to %s can cause loss of data", | |
49 loc.toChars(), toChars(), type->toChars(), t->toChars()); | |
50 } | |
51 #if DMDV2 | |
52 if (match == MATCHconst && t == type->constOf()) | |
53 { | |
54 Expression *e = copy(); | |
55 e->type = t; | |
56 return e; | |
57 } | |
58 #endif | |
59 return castTo(sc, t); | |
60 } | |
61 | |
62 Expression *e = optimize(WANTflags | WANTvalue); | |
63 if (e != this) | |
64 return e->implicitCastTo(sc, t); | |
65 | |
66 #if 0 | |
67 printf("ty = %d\n", type->ty); | |
68 print(); | |
69 type->print(); | |
70 printf("to:\n"); | |
71 t->print(); | |
72 printf("%p %p type: %s to: %s\n", type->deco, t->deco, type->deco, t->deco); | |
73 //printf("%p %p %p\n", type->nextOf()->arrayOf(), type, t); | |
74 fflush(stdout); | |
75 #endif | |
76 if (!t->deco) | |
77 { /* Can happen with: | |
78 * enum E { One } | |
79 * class A | |
80 * { static void fork(EDG dg) { dg(E.One); } | |
81 * alias void delegate(E) EDG; | |
82 * } | |
83 * Should eventually make it work. | |
84 */ | |
85 error("forward reference to type %s", t->toChars()); | |
86 } | |
87 else if (t->reliesOnTident()) | |
88 error("forward reference to type %s", t->reliesOnTident()->toChars()); | |
89 | |
90 error("cannot implicitly convert expression (%s) of type %s to %s", | |
91 toChars(), type->toChars(), t->toChars()); | |
92 return castTo(sc, t); | |
93 } | |
94 | |
95 /******************************************* | |
96 * Return !=0 if we can implicitly convert this to type t. | |
97 * Don't do the actual cast. | |
98 */ | |
99 | |
100 MATCH Expression::implicitConvTo(Type *t) | |
101 { | |
102 #if 0 | |
103 printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n", | |
104 toChars(), type->toChars(), t->toChars()); | |
105 #endif | |
106 //static int nest; if (++nest == 10) halt(); | |
107 if (!type) | |
108 { error("%s is not an expression", toChars()); | |
109 type = Type::terror; | |
110 } | |
111 Expression *e = optimize(WANTvalue | WANTflags); | |
112 if (e->type == t) | |
113 return MATCHexact; | |
114 if (e != this) | |
115 { //printf("\toptimized to %s of type %s\n", e->toChars(), e->type->toChars()); | |
116 return e->implicitConvTo(t); | |
117 } | |
118 MATCH match = type->implicitConvTo(t); | |
119 if (match != MATCHnomatch) | |
120 return match; | |
121 #if 0 | |
122 Type *tb = t->toBasetype(); | |
123 if (tb->ty == Tdelegate) | |
124 { TypeDelegate *td = (TypeDelegate *)tb; | |
125 TypeFunction *tf = (TypeFunction *)td->nextOf(); | |
126 | |
127 if (!tf->varargs && | |
128 !(tf->arguments && tf->arguments->dim) | |
129 ) | |
130 { | |
131 match = type->implicitConvTo(tf->nextOf()); | |
132 if (match) | |
133 return match; | |
134 if (tf->nextOf()->toBasetype()->ty == Tvoid) | |
135 return MATCHconvert; | |
136 } | |
137 } | |
138 #endif | |
139 return MATCHnomatch; | |
140 } | |
141 | |
142 | |
143 MATCH IntegerExp::implicitConvTo(Type *t) | |
144 { | |
145 #if 0 | |
146 printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n", | |
147 toChars(), type->toChars(), t->toChars()); | |
148 #endif | |
149 MATCH m = type->implicitConvTo(t); | |
150 if (m >= MATCHconst) | |
151 return m; | |
152 | |
153 TY ty = type->toBasetype()->ty; | |
154 TY toty = t->toBasetype()->ty; | |
155 | |
156 if (m == MATCHnomatch && t->ty == Tenum) | |
157 goto Lno; | |
158 | |
159 switch (ty) | |
160 { | |
161 case Tbit: | |
162 case Tbool: | |
163 value &= 1; | |
164 ty = Tint32; | |
165 break; | |
166 | |
167 case Tint8: | |
168 value = (signed char)value; | |
169 ty = Tint32; | |
170 break; | |
171 | |
172 case Tchar: | |
173 case Tuns8: | |
174 value &= 0xFF; | |
175 ty = Tint32; | |
176 break; | |
177 | |
178 case Tint16: | |
179 value = (short)value; | |
180 ty = Tint32; | |
181 break; | |
182 | |
183 case Tuns16: | |
184 case Twchar: | |
185 value &= 0xFFFF; | |
186 ty = Tint32; | |
187 break; | |
188 | |
189 case Tint32: | |
190 value = (int)value; | |
191 break; | |
192 | |
193 case Tuns32: | |
194 case Tdchar: | |
195 value &= 0xFFFFFFFF; | |
196 ty = Tuns32; | |
197 break; | |
198 | |
199 default: | |
200 break; | |
201 } | |
202 | |
203 // Only allow conversion if no change in value | |
204 switch (toty) | |
205 { | |
206 case Tbit: | |
207 case Tbool: | |
208 if ((value & 1) != value) | |
209 goto Lno; | |
210 goto Lyes; | |
211 | |
212 case Tint8: | |
213 if ((signed char)value != value) | |
214 goto Lno; | |
215 goto Lyes; | |
216 | |
217 case Tchar: | |
218 case Tuns8: | |
219 //printf("value = %llu %llu\n", (integer_t)(unsigned char)value, value); | |
220 if ((unsigned char)value != value) | |
221 goto Lno; | |
222 goto Lyes; | |
223 | |
224 case Tint16: | |
225 if ((short)value != value) | |
226 goto Lno; | |
227 goto Lyes; | |
228 | |
229 case Tuns16: | |
230 if ((unsigned short)value != value) | |
231 goto Lno; | |
232 goto Lyes; | |
233 | |
234 case Tint32: | |
235 if (ty == Tuns32) | |
236 { | |
237 } | |
238 else if ((int)value != value) | |
239 goto Lno; | |
240 goto Lyes; | |
241 | |
242 case Tuns32: | |
243 if (ty == Tint32) | |
244 { | |
245 } | |
246 else if ((unsigned)value != value) | |
247 goto Lno; | |
248 goto Lyes; | |
249 | |
250 case Tdchar: | |
251 if (value > 0x10FFFFUL) | |
252 goto Lno; | |
253 goto Lyes; | |
254 | |
255 case Twchar: | |
256 if ((unsigned short)value != value) | |
257 goto Lno; | |
258 goto Lyes; | |
259 | |
260 case Tfloat32: | |
261 { | |
262 volatile float f; | |
263 if (type->isunsigned()) | |
264 { | |
265 f = (float)value; | |
266 if (f != value) | |
267 goto Lno; | |
268 } | |
269 else | |
270 { | |
271 f = (float)(long long)value; | |
272 if (f != (long long)value) | |
273 goto Lno; | |
274 } | |
275 goto Lyes; | |
276 } | |
277 | |
278 case Tfloat64: | |
279 { | |
280 volatile double f; | |
281 if (type->isunsigned()) | |
282 { | |
283 f = (double)value; | |
284 if (f != value) | |
285 goto Lno; | |
286 } | |
287 else | |
288 { | |
289 f = (double)(long long)value; | |
290 if (f != (long long)value) | |
291 goto Lno; | |
292 } | |
293 goto Lyes; | |
294 } | |
295 | |
296 case Tfloat80: | |
297 { | |
298 volatile long double f; | |
299 if (type->isunsigned()) | |
300 { | |
301 f = (long double)value; | |
302 if (f != value) | |
303 goto Lno; | |
304 } | |
305 else | |
306 { | |
307 f = (long double)(long long)value; | |
308 if (f != (long long)value) | |
309 goto Lno; | |
310 } | |
311 goto Lyes; | |
312 } | |
313 | |
314 case Tpointer: | |
315 //printf("type = %s\n", type->toBasetype()->toChars()); | |
316 //printf("t = %s\n", t->toBasetype()->toChars()); | |
317 if (ty == Tpointer && | |
318 type->toBasetype()->nextOf()->ty == t->toBasetype()->nextOf()->ty) | |
319 { /* Allow things like: | |
320 * const char* P = cast(char *)3; | |
321 * char* q = P; | |
322 */ | |
323 goto Lyes; | |
324 } | |
325 break; | |
326 } | |
327 return Expression::implicitConvTo(t); | |
328 | |
329 Lyes: | |
330 //printf("MATCHconvert\n"); | |
331 return MATCHconvert; | |
332 | |
333 Lno: | |
334 //printf("MATCHnomatch\n"); | |
335 return MATCHnomatch; | |
336 } | |
337 | |
338 MATCH NullExp::implicitConvTo(Type *t) | |
339 { | |
340 #if 0 | |
341 printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s, committed = %d)\n", | |
342 toChars(), type->toChars(), t->toChars(), committed); | |
343 #endif | |
344 if (this->type->equals(t)) | |
345 return MATCHexact; | |
346 | |
347 /* Allow implicit conversions from invariant to mutable|const, | |
348 * and mutable to invariant. It works because, after all, a null | |
349 * doesn't actually point to anything. | |
350 */ | |
351 if (t->invariantOf()->equals(type->invariantOf())) | |
352 return MATCHconst; | |
353 | |
354 // NULL implicitly converts to any pointer type or dynamic array | |
355 if (type->ty == Tpointer && type->nextOf()->ty == Tvoid) | |
356 { | |
357 if (t->ty == Ttypedef) | |
358 t = ((TypeTypedef *)t)->sym->basetype; | |
359 if (t->ty == Tpointer || t->ty == Tarray || | |
360 t->ty == Taarray || t->ty == Tclass || | |
361 t->ty == Tdelegate) | |
362 return committed ? MATCHconvert : MATCHexact; | |
363 } | |
364 return Expression::implicitConvTo(t); | |
365 } | |
366 | |
367 #if DMDV2 | |
368 MATCH StructLiteralExp::implicitConvTo(Type *t) | |
369 { | |
370 #if 0 | |
371 printf("StructLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", | |
372 toChars(), type->toChars(), t->toChars()); | |
373 #endif | |
374 MATCH m = Expression::implicitConvTo(t); | |
375 if (m != MATCHnomatch) | |
376 return m; | |
377 if (type->ty == t->ty && type->ty == Tstruct && | |
378 ((TypeStruct *)type)->sym == ((TypeStruct *)t)->sym) | |
379 { | |
380 m = MATCHconst; | |
381 for (int i = 0; i < elements->dim; i++) | |
382 { Expression *e = (Expression *)elements->data[i]; | |
383 Type *te = e->type; | |
384 if (t->mod == 0) | |
385 te = te->mutableOf(); | |
386 else | |
387 { assert(t->mod == MODinvariant); | |
388 te = te->invariantOf(); | |
389 } | |
390 MATCH m2 = e->implicitConvTo(te); | |
391 //printf("\t%s => %s, match = %d\n", e->toChars(), te->toChars(), m2); | |
392 if (m2 < m) | |
393 m = m2; | |
394 } | |
395 } | |
396 return m; | |
397 } | |
398 #endif | |
399 | |
400 MATCH StringExp::implicitConvTo(Type *t) | |
401 { MATCH m; | |
402 | |
403 #if 0 | |
404 printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n", | |
405 toChars(), committed, type->toChars(), t->toChars()); | |
406 #endif | |
407 if (!committed) | |
408 { | |
409 if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid) | |
410 { | |
411 return MATCHnomatch; | |
412 } | |
413 if (type->ty == Tsarray || type->ty == Tarray || type->ty == Tpointer) | |
414 { | |
415 TY tyn = type->nextOf()->ty; | |
416 if (tyn == Tchar || tyn == Twchar || tyn == Tdchar) | |
417 { Type *tn; | |
418 MATCH m; | |
419 | |
420 switch (t->ty) | |
421 { | |
422 case Tsarray: | |
423 if (type->ty == Tsarray) | |
424 { | |
425 if (((TypeSArray *)type)->dim->toInteger() != | |
426 ((TypeSArray *)t)->dim->toInteger()) | |
427 return MATCHnomatch; | |
428 TY tynto = t->nextOf()->ty; | |
429 if (tynto == Tchar || tynto == Twchar || tynto == Tdchar) | |
430 return MATCHexact; | |
431 } | |
432 case Tarray: | |
433 case Tpointer: | |
434 tn = t->nextOf(); | |
435 m = MATCHexact; | |
436 if (type->nextOf()->mod != tn->mod) | |
437 { if (!tn->isConst()) | |
438 return MATCHnomatch; | |
439 m = MATCHconst; | |
440 } | |
441 switch (tn->ty) | |
442 { | |
443 case Tchar: | |
444 case Twchar: | |
445 case Tdchar: | |
446 return m; | |
447 } | |
448 break; | |
449 } | |
450 } | |
451 } | |
452 } | |
453 return Expression::implicitConvTo(t); | |
454 #if 0 | |
455 m = (MATCH)type->implicitConvTo(t); | |
456 if (m) | |
457 { | |
458 return m; | |
459 } | |
460 | |
461 return MATCHnomatch; | |
462 #endif | |
463 } | |
464 | |
465 MATCH ArrayLiteralExp::implicitConvTo(Type *t) | |
466 { MATCH result = MATCHexact; | |
467 | |
468 #if 0 | |
469 printf("ArrayLiteralExp::implicitConvTo(this=%s, type=%s, t=%s)\n", | |
470 toChars(), type->toChars(), t->toChars()); | |
471 #endif | |
472 Type *typeb = type->toBasetype(); | |
473 Type *tb = t->toBasetype(); | |
474 if ((tb->ty == Tarray || tb->ty == Tsarray) && | |
475 (typeb->ty == Tarray || typeb->ty == Tsarray)) | |
476 { | |
477 if (tb->ty == Tsarray) | |
478 { TypeSArray *tsa = (TypeSArray *)tb; | |
479 if (elements->dim != tsa->dim->toInteger()) | |
480 result = MATCHnomatch; | |
481 } | |
482 | |
483 for (int i = 0; i < elements->dim; i++) | |
484 { Expression *e = (Expression *)elements->data[i]; | |
485 MATCH m = (MATCH)e->implicitConvTo(tb->nextOf()); | |
486 if (m < result) | |
487 result = m; // remember worst match | |
488 if (result == MATCHnomatch) | |
489 break; // no need to check for worse | |
490 } | |
491 return result; | |
492 } | |
493 else | |
494 return Expression::implicitConvTo(t); | |
495 } | |
496 | |
497 MATCH AssocArrayLiteralExp::implicitConvTo(Type *t) | |
498 { MATCH result = MATCHexact; | |
499 | |
500 Type *typeb = type->toBasetype(); | |
501 Type *tb = t->toBasetype(); | |
502 if (tb->ty == Taarray && typeb->ty == Taarray) | |
503 { | |
504 for (size_t i = 0; i < keys->dim; i++) | |
505 { Expression *e = (Expression *)keys->data[i]; | |
506 MATCH m = (MATCH)e->implicitConvTo(((TypeAArray *)tb)->index); | |
507 if (m < result) | |
508 result = m; // remember worst match | |
509 if (result == MATCHnomatch) | |
510 break; // no need to check for worse | |
511 e = (Expression *)values->data[i]; | |
512 m = (MATCH)e->implicitConvTo(tb->nextOf()); | |
513 if (m < result) | |
514 result = m; // remember worst match | |
515 if (result == MATCHnomatch) | |
516 break; // no need to check for worse | |
517 } | |
518 return result; | |
519 } | |
520 else | |
521 return Expression::implicitConvTo(t); | |
522 } | |
523 | |
524 MATCH AddrExp::implicitConvTo(Type *t) | |
525 { | |
526 #if 0 | |
527 printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n", | |
528 toChars(), type->toChars(), t->toChars()); | |
529 #endif | |
530 MATCH result; | |
531 | |
532 result = type->implicitConvTo(t); | |
533 //printf("\tresult = %d\n", result); | |
534 | |
535 if (result == MATCHnomatch) | |
536 { | |
537 // Look for pointers to functions where the functions are overloaded. | |
538 | |
539 t = t->toBasetype(); | |
540 | |
541 if (e1->op == TOKoverloadset && | |
542 (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction) | |
543 { OverExp *eo = (OverExp *)e1; | |
544 FuncDeclaration *f = NULL; | |
545 for (int i = 0; i < eo->vars->a.dim; i++) | |
546 { Dsymbol *s = (Dsymbol *)eo->vars->a.data[i]; | |
547 FuncDeclaration *f2 = s->isFuncDeclaration(); | |
548 assert(f2); | |
549 if (f2->overloadExactMatch(t->nextOf())) | |
550 { if (f) | |
551 /* Error if match in more than one overload set, | |
552 * even if one is a 'better' match than the other. | |
553 */ | |
554 ScopeDsymbol::multiplyDefined(loc, f, f2); | |
555 else | |
556 f = f2; | |
557 result = MATCHexact; | |
558 } | |
559 } | |
560 } | |
561 | |
562 if (type->ty == Tpointer && type->nextOf()->ty == Tfunction && | |
563 t->ty == Tpointer && t->nextOf()->ty == Tfunction && | |
564 e1->op == TOKvar) | |
565 { | |
566 // LDC: it happens for us | |
567 #if !IN_LLVM | |
568 /* I don't think this can ever happen - | |
569 * it should have been | |
570 * converted to a SymOffExp. | |
571 */ | |
572 assert(0); | |
573 #endif | |
574 VarExp *ve = (VarExp *)e1; | |
575 FuncDeclaration *f = ve->var->isFuncDeclaration(); | |
576 if (f && f->overloadExactMatch(t->nextOf())) | |
577 result = MATCHexact; | |
578 } | |
579 } | |
580 //printf("\tresult = %d\n", result); | |
581 return result; | |
582 } | |
583 | |
584 MATCH SymOffExp::implicitConvTo(Type *t) | |
585 { | |
586 #if 0 | |
587 printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n", | |
588 toChars(), type->toChars(), t->toChars()); | |
589 #endif | |
590 MATCH result; | |
591 | |
592 result = type->implicitConvTo(t); | |
593 //printf("\tresult = %d\n", result); | |
594 | |
595 if (result == MATCHnomatch) | |
596 { | |
597 // Look for pointers to functions where the functions are overloaded. | |
598 FuncDeclaration *f; | |
599 | |
600 t = t->toBasetype(); | |
601 if (type->ty == Tpointer && type->nextOf()->ty == Tfunction && | |
602 (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction) | |
603 { | |
604 f = var->isFuncDeclaration(); | |
605 if (f) | |
606 { f = f->overloadExactMatch(t->nextOf()); | |
607 if (f) | |
608 { if ((t->ty == Tdelegate && (f->needThis() || f->isNested())) || | |
609 (t->ty == Tpointer && !(f->needThis() || f->isNested()))) | |
610 { | |
611 result = MATCHexact; | |
612 } | |
613 } | |
614 } | |
615 } | |
616 } | |
617 //printf("\tresult = %d\n", result); | |
618 return result; | |
619 } | |
620 | |
621 MATCH DelegateExp::implicitConvTo(Type *t) | |
622 { | |
623 #if 0 | |
624 printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n", | |
625 toChars(), type->toChars(), t->toChars()); | |
626 #endif | |
627 MATCH result; | |
628 | |
629 result = type->implicitConvTo(t); | |
630 | |
631 if (result == MATCHnomatch) | |
632 { | |
633 // Look for pointers to functions where the functions are overloaded. | |
634 FuncDeclaration *f; | |
635 | |
636 t = t->toBasetype(); | |
637 if (type->ty == Tdelegate && type->nextOf()->ty == Tfunction && | |
638 t->ty == Tdelegate && t->nextOf()->ty == Tfunction) | |
639 { | |
640 if (func && func->overloadExactMatch(t->nextOf())) | |
641 result = MATCHexact; | |
642 } | |
643 } | |
644 return result; | |
645 } | |
646 | |
647 MATCH CondExp::implicitConvTo(Type *t) | |
648 { | |
649 MATCH m1; | |
650 MATCH m2; | |
651 | |
652 m1 = e1->implicitConvTo(t); | |
653 m2 = e2->implicitConvTo(t); | |
654 | |
655 // Pick the worst match | |
656 return (m1 < m2) ? m1 : m2; | |
657 } | |
658 | |
659 | |
660 /* ==================== castTo ====================== */ | |
661 | |
662 /************************************** | |
663 * Do an explicit cast. | |
664 */ | |
665 | |
666 Expression *Expression::castTo(Scope *sc, Type *t) | |
667 { | |
668 //printf("Expression::castTo(this=%s, t=%s)\n", toChars(), t->toChars()); | |
669 #if 0 | |
670 printf("Expression::castTo(this=%s, type=%s, t=%s)\n", | |
671 toChars(), type->toChars(), t->toChars()); | |
672 #endif | |
673 if (type == t) | |
674 return this; | |
675 Expression *e = this; | |
676 Type *tb = t->toBasetype(); | |
677 Type *typeb = type->toBasetype(); | |
678 if (tb != typeb) | |
679 { | |
680 // Do (type *) cast of (type [dim]) | |
681 if (tb->ty == Tpointer && | |
682 typeb->ty == Tsarray | |
683 ) | |
684 { | |
685 //printf("Converting [dim] to *\n"); | |
686 | |
687 if (typeb->size(loc) == 0) | |
688 e = new NullExp(loc); | |
689 else | |
690 e = new AddrExp(loc, e); | |
691 } | |
692 #if 0 | |
693 else if (tb->ty == Tdelegate && type->ty != Tdelegate) | |
694 { | |
695 TypeDelegate *td = (TypeDelegate *)tb; | |
696 TypeFunction *tf = (TypeFunction *)td->nextOf(); | |
697 return toDelegate(sc, tf->nextOf()); | |
698 } | |
699 #endif | |
700 else | |
701 { | |
702 e = new CastExp(loc, e, tb); | |
703 } | |
704 } | |
705 else | |
706 { | |
707 e = e->copy(); // because of COW for assignment to e->type | |
708 } | |
709 assert(e != this); | |
710 e->type = t; | |
711 //printf("Returning: %s\n", e->toChars()); | |
712 return e; | |
713 } | |
714 | |
715 | |
716 Expression *RealExp::castTo(Scope *sc, Type *t) | |
717 { Expression *e = this; | |
718 if (type != t) | |
719 { | |
720 if ((type->isreal() && t->isreal()) || | |
721 (type->isimaginary() && t->isimaginary()) | |
722 ) | |
723 { e = copy(); | |
724 e->type = t; | |
725 } | |
726 else | |
727 e = Expression::castTo(sc, t); | |
728 } | |
729 return e; | |
730 } | |
731 | |
732 | |
733 Expression *ComplexExp::castTo(Scope *sc, Type *t) | |
734 { Expression *e = this; | |
735 if (type != t) | |
736 { | |
737 if (type->iscomplex() && t->iscomplex()) | |
738 { e = copy(); | |
739 e->type = t; | |
740 } | |
741 else | |
742 e = Expression::castTo(sc, t); | |
743 } | |
744 return e; | |
745 } | |
746 | |
747 | |
748 Expression *NullExp::castTo(Scope *sc, Type *t) | |
749 { NullExp *e; | |
750 Type *tb; | |
751 | |
752 //printf("NullExp::castTo(t = %p)\n", t); | |
753 if (type == t) | |
754 { | |
755 committed = 1; | |
756 return this; | |
757 } | |
758 e = (NullExp *)copy(); | |
759 e->committed = 1; | |
760 tb = t->toBasetype(); | |
761 e->type = type->toBasetype(); | |
762 if (tb != e->type) | |
763 { | |
764 // NULL implicitly converts to any pointer type or dynamic array | |
765 if (e->type->ty == Tpointer && e->type->nextOf()->ty == Tvoid && | |
766 (tb->ty == Tpointer || tb->ty == Tarray || tb->ty == Taarray || | |
767 tb->ty == Tdelegate)) | |
768 { | |
769 #if 0 | |
770 if (tb->ty == Tdelegate) | |
771 { TypeDelegate *td = (TypeDelegate *)tb; | |
772 TypeFunction *tf = (TypeFunction *)td->nextOf(); | |
773 | |
774 if (!tf->varargs && | |
775 !(tf->arguments && tf->arguments->dim) | |
776 ) | |
777 { | |
778 return Expression::castTo(sc, t); | |
779 } | |
780 } | |
781 #endif | |
782 } | |
783 else | |
784 { | |
785 return e->Expression::castTo(sc, t); | |
786 } | |
787 } | |
788 e->type = t; | |
789 return e; | |
790 } | |
791 | |
792 Expression *StringExp::castTo(Scope *sc, Type *t) | |
793 { | |
794 /* This follows copy-on-write; any changes to 'this' | |
795 * will result in a copy. | |
796 * The this->string member is considered immutable. | |
797 */ | |
798 StringExp *se; | |
799 Type *tb; | |
800 int copied = 0; | |
801 | |
802 //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t->toChars(), toChars(), committed); | |
803 | |
804 if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid) | |
805 { | |
806 error("cannot convert string literal to void*"); | |
807 } | |
808 | |
809 se = this; | |
810 if (!committed) | |
811 { se = (StringExp *)copy(); | |
812 se->committed = 1; | |
813 copied = 1; | |
814 } | |
815 | |
816 if (type == t) | |
817 { | |
818 return se; | |
819 } | |
820 | |
821 tb = t->toBasetype(); | |
822 //printf("\ttype = %s\n", type->toChars()); | |
823 if (tb->ty == Tdelegate && type->toBasetype()->ty != Tdelegate) | |
824 return Expression::castTo(sc, t); | |
825 | |
826 Type *typeb = type->toBasetype(); | |
827 if (typeb == tb) | |
828 { | |
829 if (!copied) | |
830 { se = (StringExp *)copy(); | |
831 copied = 1; | |
832 } | |
833 se->type = t; | |
834 return se; | |
835 } | |
836 | |
837 if (tb->ty != Tsarray && tb->ty != Tarray && tb->ty != Tpointer) | |
838 { if (!copied) | |
839 { se = (StringExp *)copy(); | |
840 copied = 1; | |
841 } | |
842 goto Lcast; | |
843 } | |
844 if (typeb->ty != Tsarray && typeb->ty != Tarray && typeb->ty != Tpointer) | |
845 { if (!copied) | |
846 { se = (StringExp *)copy(); | |
847 copied = 1; | |
848 } | |
849 goto Lcast; | |
850 } | |
851 | |
852 if (typeb->nextOf()->size() == tb->nextOf()->size()) | |
853 { | |
854 if (!copied) | |
855 { se = (StringExp *)copy(); | |
856 copied = 1; | |
857 } | |
858 if (tb->ty == Tsarray) | |
859 goto L2; // handle possible change in static array dimension | |
860 se->type = t; | |
861 return se; | |
862 } | |
863 | |
864 if (committed) | |
865 goto Lcast; | |
866 | |
867 #define X(tf,tt) ((tf) * 256 + (tt)) | |
868 { | |
869 OutBuffer buffer; | |
870 size_t newlen = 0; | |
871 int tfty = typeb->nextOf()->toBasetype()->ty; | |
872 int ttty = tb->nextOf()->toBasetype()->ty; | |
873 switch (X(tfty, ttty)) | |
874 { | |
875 case X(Tchar, Tchar): | |
876 case X(Twchar,Twchar): | |
877 case X(Tdchar,Tdchar): | |
878 break; | |
879 | |
880 case X(Tchar, Twchar): | |
881 for (size_t u = 0; u < len;) | |
882 { unsigned c; | |
883 const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); | |
884 if (p) | |
885 error("%s", p); | |
886 else | |
887 buffer.writeUTF16(c); | |
888 } | |
889 newlen = buffer.offset / 2; | |
890 buffer.writeUTF16(0); | |
891 goto L1; | |
892 | |
893 case X(Tchar, Tdchar): | |
894 for (size_t u = 0; u < len;) | |
895 { unsigned c; | |
896 const char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); | |
897 if (p) | |
898 error("%s", p); | |
899 buffer.write4(c); | |
900 newlen++; | |
901 } | |
902 buffer.write4(0); | |
903 goto L1; | |
904 | |
905 case X(Twchar,Tchar): | |
906 for (size_t u = 0; u < len;) | |
907 { unsigned c; | |
908 const char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); | |
909 if (p) | |
910 error("%s", p); | |
911 else | |
912 buffer.writeUTF8(c); | |
913 } | |
914 newlen = buffer.offset; | |
915 buffer.writeUTF8(0); | |
916 goto L1; | |
917 | |
918 case X(Twchar,Tdchar): | |
919 for (size_t u = 0; u < len;) | |
920 { unsigned c; | |
921 const char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); | |
922 if (p) | |
923 error("%s", p); | |
924 buffer.write4(c); | |
925 newlen++; | |
926 } | |
927 buffer.write4(0); | |
928 goto L1; | |
929 | |
930 case X(Tdchar,Tchar): | |
931 for (size_t u = 0; u < len; u++) | |
932 { | |
933 unsigned c = ((unsigned *)se->string)[u]; | |
934 if (!utf_isValidDchar(c)) | |
935 error("invalid UCS-32 char \\U%08x", c); | |
936 else | |
937 buffer.writeUTF8(c); | |
938 newlen++; | |
939 } | |
940 newlen = buffer.offset; | |
941 buffer.writeUTF8(0); | |
942 goto L1; | |
943 | |
944 case X(Tdchar,Twchar): | |
945 for (size_t u = 0; u < len; u++) | |
946 { | |
947 unsigned c = ((unsigned *)se->string)[u]; | |
948 if (!utf_isValidDchar(c)) | |
949 error("invalid UCS-32 char \\U%08x", c); | |
950 else | |
951 buffer.writeUTF16(c); | |
952 newlen++; | |
953 } | |
954 newlen = buffer.offset / 2; | |
955 buffer.writeUTF16(0); | |
956 goto L1; | |
957 | |
958 L1: | |
959 if (!copied) | |
960 { se = (StringExp *)copy(); | |
961 copied = 1; | |
962 } | |
963 se->string = buffer.extractData(); | |
964 se->len = newlen; | |
965 se->sz = tb->nextOf()->size(); | |
966 break; | |
967 | |
968 default: | |
969 assert(typeb->nextOf()->size() != tb->nextOf()->size()); | |
970 goto Lcast; | |
971 } | |
972 } | |
973 #undef X | |
974 L2: | |
975 assert(copied); | |
976 | |
977 // See if need to truncate or extend the literal | |
978 if (tb->ty == Tsarray) | |
979 { | |
980 int dim2 = ((TypeSArray *)tb)->dim->toInteger(); | |
981 | |
982 //printf("dim from = %d, to = %d\n", se->len, dim2); | |
983 | |
984 // Changing dimensions | |
985 if (dim2 != se->len) | |
986 { | |
987 // Copy when changing the string literal | |
988 unsigned newsz = se->sz; | |
989 void *s; | |
990 int d; | |
991 | |
992 d = (dim2 < se->len) ? dim2 : se->len; | |
993 s = (unsigned char *)mem.malloc((dim2 + 1) * newsz); | |
994 memcpy(s, se->string, d * newsz); | |
995 // Extend with 0, add terminating 0 | |
996 memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz); | |
997 se->string = s; | |
998 se->len = dim2; | |
999 } | |
1000 } | |
1001 se->type = t; | |
1002 return se; | |
1003 | |
1004 Lcast: | |
1005 Expression *e = new CastExp(loc, se, t); | |
1006 e->type = t; // so semantic() won't be run on e | |
1007 return e; | |
1008 } | |
1009 | |
1010 Expression *AddrExp::castTo(Scope *sc, Type *t) | |
1011 { | |
1012 Type *tb; | |
1013 | |
1014 #if 0 | |
1015 printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n", | |
1016 toChars(), type->toChars(), t->toChars()); | |
1017 #endif | |
1018 Expression *e = this; | |
1019 | |
1020 tb = t->toBasetype(); | |
1021 type = type->toBasetype(); | |
1022 if (tb != type) | |
1023 { | |
1024 // Look for pointers to functions where the functions are overloaded. | |
1025 | |
1026 if (e1->op == TOKoverloadset && | |
1027 (t->ty == Tpointer || t->ty == Tdelegate) && t->nextOf()->ty == Tfunction) | |
1028 { OverExp *eo = (OverExp *)e1; | |
1029 FuncDeclaration *f = NULL; | |
1030 for (int i = 0; i < eo->vars->a.dim; i++) | |
1031 { Dsymbol *s = (Dsymbol *)eo->vars->a.data[i]; | |
1032 FuncDeclaration *f2 = s->isFuncDeclaration(); | |
1033 assert(f2); | |
1034 if (f2->overloadExactMatch(t->nextOf())) | |
1035 { if (f) | |
1036 /* Error if match in more than one overload set, | |
1037 * even if one is a 'better' match than the other. | |
1038 */ | |
1039 ScopeDsymbol::multiplyDefined(loc, f, f2); | |
1040 else | |
1041 f = f2; | |
1042 } | |
1043 } | |
1044 if (f) | |
1045 { f->tookAddressOf = 1; | |
1046 SymOffExp *se = new SymOffExp(loc, f, 0, 0); | |
1047 se->semantic(sc); | |
1048 // Let SymOffExp::castTo() do the heavy lifting | |
1049 return se->castTo(sc, t); | |
1050 } | |
1051 } | |
1052 | |
1053 | |
1054 if (type->ty == Tpointer && type->nextOf()->ty == Tfunction && | |
1055 tb->ty == Tpointer && tb->nextOf()->ty == Tfunction && | |
1056 e1->op == TOKvar) | |
1057 { | |
1058 VarExp *ve = (VarExp *)e1; | |
1059 FuncDeclaration *f = ve->var->isFuncDeclaration(); | |
1060 if (f) | |
1061 { | |
1062 // LDC: not in ldc | |
1063 #if !IN_LLVM | |
1064 assert(0); // should be SymOffExp instead | |
1065 #endif | |
1066 f = f->overloadExactMatch(tb->nextOf()); | |
1067 if (f) | |
1068 { | |
1069 e = new VarExp(loc, f); | |
1070 e->type = f->type; | |
1071 e = new AddrExp(loc, e); | |
1072 e->type = t; | |
1073 return e; | |
1074 } | |
1075 } | |
1076 } | |
1077 e = Expression::castTo(sc, t); | |
1078 } | |
1079 e->type = t; | |
1080 return e; | |
1081 } | |
1082 | |
1083 | |
1084 Expression *TupleExp::castTo(Scope *sc, Type *t) | |
1085 { TupleExp *e = (TupleExp *)copy(); | |
1086 e->exps = (Expressions *)exps->copy(); | |
1087 for (size_t i = 0; i < e->exps->dim; i++) | |
1088 { Expression *ex = (Expression *)e->exps->data[i]; | |
1089 ex = ex->castTo(sc, t); | |
1090 e->exps->data[i] = (void *)ex; | |
1091 } | |
1092 return e; | |
1093 } | |
1094 | |
1095 | |
1096 Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t) | |
1097 { | |
1098 #if 0 | |
1099 printf("ArrayLiteralExp::castTo(this=%s, type=%s, => %s)\n", | |
1100 toChars(), type->toChars(), t->toChars()); | |
1101 #endif | |
1102 if (type == t) | |
1103 return this; | |
1104 ArrayLiteralExp *e = this; | |
1105 Type *typeb = type->toBasetype(); | |
1106 Type *tb = t->toBasetype(); | |
1107 if ((tb->ty == Tarray || tb->ty == Tsarray) && | |
1108 (typeb->ty == Tarray || typeb->ty == Tsarray) && | |
1109 // Not trying to convert non-void[] to void[] | |
1110 !(tb->nextOf()->toBasetype()->ty == Tvoid && typeb->nextOf()->toBasetype()->ty != Tvoid)) | |
1111 { | |
1112 if (tb->ty == Tsarray) | |
1113 { TypeSArray *tsa = (TypeSArray *)tb; | |
1114 if (elements->dim != tsa->dim->toInteger()) | |
1115 goto L1; | |
1116 } | |
1117 | |
1118 e = (ArrayLiteralExp *)copy(); | |
1119 e->elements = (Expressions *)elements->copy(); | |
1120 for (int i = 0; i < elements->dim; i++) | |
1121 { Expression *ex = (Expression *)elements->data[i]; | |
1122 ex = ex->castTo(sc, tb->nextOf()); | |
1123 e->elements->data[i] = (void *)ex; | |
1124 } | |
1125 e->type = t; | |
1126 return e; | |
1127 } | |
1128 if (tb->ty == Tpointer && typeb->ty == Tsarray) | |
1129 { | |
1130 e = (ArrayLiteralExp *)copy(); | |
1131 e->type = typeb->nextOf()->pointerTo(); | |
1132 } | |
1133 L1: | |
1134 return e->Expression::castTo(sc, t); | |
1135 } | |
1136 | |
1137 Expression *AssocArrayLiteralExp::castTo(Scope *sc, Type *t) | |
1138 { | |
1139 if (type == t) | |
1140 return this; | |
1141 AssocArrayLiteralExp *e = this; | |
1142 Type *typeb = type->toBasetype(); | |
1143 Type *tb = t->toBasetype(); | |
1144 if (tb->ty == Taarray && typeb->ty == Taarray && | |
1145 tb->nextOf()->toBasetype()->ty != Tvoid) | |
1146 { | |
1147 e = (AssocArrayLiteralExp *)copy(); | |
1148 e->keys = (Expressions *)keys->copy(); | |
1149 e->values = (Expressions *)values->copy(); | |
1150 assert(keys->dim == values->dim); | |
1151 for (size_t i = 0; i < keys->dim; i++) | |
1152 { Expression *ex = (Expression *)values->data[i]; | |
1153 ex = ex->castTo(sc, tb->nextOf()); | |
1154 e->values->data[i] = (void *)ex; | |
1155 | |
1156 ex = (Expression *)keys->data[i]; | |
1157 ex = ex->castTo(sc, ((TypeAArray *)tb)->index); | |
1158 e->keys->data[i] = (void *)ex; | |
1159 } | |
1160 e->type = t; | |
1161 return e; | |
1162 } | |
1163 L1: | |
1164 return e->Expression::castTo(sc, t); | |
1165 } | |
1166 | |
1167 Expression *SymOffExp::castTo(Scope *sc, Type *t) | |
1168 { | |
1169 #if 0 | |
1170 printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", | |
1171 toChars(), type->toChars(), t->toChars()); | |
1172 #endif | |
1173 if (type == t && hasOverloads == 0) | |
1174 return this; | |
1175 Expression *e; | |
1176 Type *tb = t->toBasetype(); | |
1177 Type *typeb = type->toBasetype(); | |
1178 if (tb != typeb) | |
1179 { | |
1180 // Look for pointers to functions where the functions are overloaded. | |
1181 FuncDeclaration *f; | |
1182 | |
1183 if (hasOverloads && | |
1184 typeb->ty == Tpointer && typeb->nextOf()->ty == Tfunction && | |
1185 (tb->ty == Tpointer || tb->ty == Tdelegate) && tb->nextOf()->ty == Tfunction) | |
1186 { | |
1187 f = var->isFuncDeclaration(); | |
1188 if (f) | |
1189 { | |
1190 f = f->overloadExactMatch(tb->nextOf()); | |
1191 if (f) | |
1192 { | |
1193 if (tb->ty == Tdelegate && f->needThis() && hasThis(sc)) | |
1194 { | |
1195 e = new DelegateExp(loc, new ThisExp(loc), f); | |
1196 e = e->semantic(sc); | |
1197 } | |
1198 else if (tb->ty == Tdelegate && f->isNested()) | |
1199 { | |
1200 e = new DelegateExp(loc, new IntegerExp(0), f); | |
1201 e = e->semantic(sc); | |
1202 } | |
1203 else | |
1204 { | |
1205 e = new SymOffExp(loc, f, 0); | |
1206 e->type = t; | |
1207 } | |
1208 f->tookAddressOf = 1; | |
1209 return e; | |
1210 } | |
1211 } | |
1212 } | |
1213 e = Expression::castTo(sc, t); | |
1214 } | |
1215 else | |
1216 { e = copy(); | |
1217 e->type = t; | |
1218 ((SymOffExp *)e)->hasOverloads = 0; | |
1219 } | |
1220 return e; | |
1221 } | |
1222 | |
1223 Expression *DelegateExp::castTo(Scope *sc, Type *t) | |
1224 { | |
1225 #if 0 | |
1226 printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", | |
1227 toChars(), type->toChars(), t->toChars()); | |
1228 #endif | |
1229 static char msg[] = "cannot form delegate due to covariant return type"; | |
1230 | |
1231 Expression *e = this; | |
1232 Type *tb = t->toBasetype(); | |
1233 Type *typeb = type->toBasetype(); | |
1234 if (tb != typeb) | |
1235 { | |
1236 // Look for delegates to functions where the functions are overloaded. | |
1237 FuncDeclaration *f; | |
1238 | |
1239 if (typeb->ty == Tdelegate && typeb->nextOf()->ty == Tfunction && | |
1240 tb->ty == Tdelegate && tb->nextOf()->ty == Tfunction) | |
1241 { | |
1242 if (func) | |
1243 { | |
1244 f = func->overloadExactMatch(tb->nextOf()); | |
1245 if (f) | |
1246 { int offset; | |
1247 if (f->tintro && f->tintro->nextOf()->isBaseOf(f->type->nextOf(), &offset) && offset) | |
1248 error("%s", msg); | |
1249 f->tookAddressOf = 1; | |
1250 e = new DelegateExp(loc, e1, f); | |
1251 e->type = t; | |
1252 return e; | |
1253 } | |
1254 if (func->tintro) | |
1255 error("%s", msg); | |
1256 } | |
1257 } | |
1258 e = Expression::castTo(sc, t); | |
1259 } | |
1260 else | |
1261 { int offset; | |
1262 | |
1263 func->tookAddressOf = 1; | |
1264 if (func->tintro && func->tintro->nextOf()->isBaseOf(func->type->nextOf(), &offset) && offset) | |
1265 error("%s", msg); | |
1266 e = copy(); | |
1267 e->type = t; | |
1268 } | |
1269 return e; | |
1270 } | |
1271 | |
1272 Expression *CondExp::castTo(Scope *sc, Type *t) | |
1273 { | |
1274 Expression *e = this; | |
1275 | |
1276 if (type != t) | |
1277 { | |
1278 if (1 || e1->op == TOKstring || e2->op == TOKstring) | |
1279 { e = new CondExp(loc, econd, e1->castTo(sc, t), e2->castTo(sc, t)); | |
1280 e->type = t; | |
1281 } | |
1282 else | |
1283 e = Expression::castTo(sc, t); | |
1284 } | |
1285 return e; | |
1286 } | |
1287 | |
1288 /* ==================== ====================== */ | |
1289 | |
1290 /**************************************** | |
1291 * Scale addition/subtraction to/from pointer. | |
1292 */ | |
1293 | |
1294 Expression *BinExp::scaleFactor(Scope *sc) | |
1295 { d_uns64 stride; | |
1296 Type *t1b = e1->type->toBasetype(); | |
1297 Type *t2b = e2->type->toBasetype(); | |
1298 | |
1299 if (t1b->ty == Tpointer && t2b->isintegral()) | |
1300 { // Need to adjust operator by the stride | |
1301 // Replace (ptr + int) with (ptr + (int * stride)) | |
1302 Type *t = Type::tptrdiff_t; | |
1303 | |
1304 stride = t1b->nextOf()->size(loc); | |
1305 if (!t->equals(t2b)) | |
1306 e2 = e2->castTo(sc, t); | |
1307 // LDC: llvm uses typesafe pointer arithmetic | |
1308 #if !IN_LLVM | |
1309 e2 = new MulExp(loc, e2, new IntegerExp(0, stride, t)); | |
1310 #endif | |
1311 e2->type = t; | |
1312 type = e1->type; | |
1313 } | |
1314 else if (t2b->ty == Tpointer && t1b->isintegral()) | |
1315 { // Need to adjust operator by the stride | |
1316 // Replace (int + ptr) with (ptr + (int * stride)) | |
1317 Type *t = Type::tptrdiff_t; | |
1318 Expression *e; | |
1319 | |
1320 stride = t2b->nextOf()->size(loc); | |
1321 if (!t->equals(t1b)) | |
1322 e = e1->castTo(sc, t); | |
1323 else | |
1324 e = e1; | |
1325 #if !IN_LLVM | |
1326 e = new MulExp(loc, e, new IntegerExp(0, stride, t)); | |
1327 #endif | |
1328 e->type = t; | |
1329 type = e2->type; | |
1330 e1 = e2; | |
1331 e2 = e; | |
1332 } | |
1333 return this; | |
1334 } | |
1335 | |
1336 /************************************** | |
1337 * Combine types. | |
1338 * Output: | |
1339 * *pt merged type, if *pt is not NULL | |
1340 * *pe1 rewritten e1 | |
1341 * *pe2 rewritten e2 | |
1342 * Returns: | |
1343 * !=0 success | |
1344 * 0 failed | |
1345 */ | |
1346 | |
1347 int typeMerge(Scope *sc, Expression *e, Type **pt, Expression **pe1, Expression **pe2) | |
1348 { | |
1349 //printf("typeMerge() %s op %s\n", (*pe1)->toChars(), (*pe2)->toChars()); | |
1350 //dump(0); | |
1351 | |
1352 Expression *e1 = (*pe1)->integralPromotions(sc); | |
1353 Expression *e2 = (*pe2)->integralPromotions(sc); | |
1354 | |
1355 Type *t1 = e1->type; | |
1356 Type *t2 = e2->type; | |
1357 assert(t1); | |
1358 Type *t = t1; | |
1359 | |
1360 //if (t1) printf("\tt1 = %s\n", t1->toChars()); | |
1361 //if (t2) printf("\tt2 = %s\n", t2->toChars()); | |
1362 #ifdef DEBUG | |
1363 if (!t2) printf("\te2 = '%s'\n", e2->toChars()); | |
1364 #endif | |
1365 assert(t2); | |
1366 | |
1367 Type *t1b = t1->toBasetype(); | |
1368 Type *t2b = t2->toBasetype(); | |
1369 | |
1370 TY ty = (TY)Type::impcnvResult[t1b->ty][t2b->ty]; | |
1371 if (ty != Terror) | |
1372 { TY ty1; | |
1373 TY ty2; | |
1374 | |
1375 ty1 = (TY)Type::impcnvType1[t1b->ty][t2b->ty]; | |
1376 ty2 = (TY)Type::impcnvType2[t1b->ty][t2b->ty]; | |
1377 | |
1378 if (t1b->ty == ty1) // if no promotions | |
1379 { | |
1380 if (t1 == t2) | |
1381 { | |
1382 t = t1; | |
1383 goto Lret; | |
1384 } | |
1385 | |
1386 if (t1b == t2b) | |
1387 { | |
1388 t = t1b; | |
1389 goto Lret; | |
1390 } | |
1391 } | |
1392 | |
1393 t = Type::basic[ty]; | |
1394 | |
1395 t1 = Type::basic[ty1]; | |
1396 t2 = Type::basic[ty2]; | |
1397 e1 = e1->castTo(sc, t1); | |
1398 e2 = e2->castTo(sc, t2); | |
1399 //printf("after typeCombine():\n"); | |
1400 //dump(0); | |
1401 //printf("ty = %d, ty1 = %d, ty2 = %d\n", ty, ty1, ty2); | |
1402 goto Lret; | |
1403 } | |
1404 | |
1405 t1 = t1b; | |
1406 t2 = t2b; | |
1407 | |
1408 Lagain: | |
1409 if (t1 == t2) | |
1410 { | |
1411 } | |
1412 else if (t1->ty == Tpointer && t2->ty == Tpointer) | |
1413 { | |
1414 // Bring pointers to compatible type | |
1415 Type *t1n = t1->nextOf(); | |
1416 Type *t2n = t2->nextOf(); | |
1417 | |
1418 if (t1n == t2n) | |
1419 ; | |
1420 else if (t1n->ty == Tvoid) // pointers to void are always compatible | |
1421 t = t2; | |
1422 else if (t2n->ty == Tvoid) | |
1423 ; | |
1424 else if (t1n->mod != t2n->mod) | |
1425 { | |
1426 t1 = t1n->mutableOf()->constOf()->pointerTo(); | |
1427 t2 = t2n->mutableOf()->constOf()->pointerTo(); | |
1428 t = t1; | |
1429 goto Lagain; | |
1430 } | |
1431 else if (t1n->ty == Tclass && t2n->ty == Tclass) | |
1432 { ClassDeclaration *cd1 = t1n->isClassHandle(); | |
1433 ClassDeclaration *cd2 = t2n->isClassHandle(); | |
1434 int offset; | |
1435 | |
1436 if (cd1->isBaseOf(cd2, &offset)) | |
1437 { | |
1438 if (offset) | |
1439 e2 = e2->castTo(sc, t); | |
1440 } | |
1441 else if (cd2->isBaseOf(cd1, &offset)) | |
1442 { | |
1443 t = t2; | |
1444 if (offset) | |
1445 e1 = e1->castTo(sc, t); | |
1446 } | |
1447 else | |
1448 goto Lincompatible; | |
1449 } | |
1450 else | |
1451 goto Lincompatible; | |
1452 } | |
1453 else if ((t1->ty == Tsarray || t1->ty == Tarray) && | |
1454 e2->op == TOKnull && t2->ty == Tpointer && t2->nextOf()->ty == Tvoid) | |
1455 { /* (T[n] op void*) | |
1456 * (T[] op void*) | |
1457 */ | |
1458 goto Lx1; | |
1459 } | |
1460 else if ((t2->ty == Tsarray || t2->ty == Tarray) && | |
1461 e1->op == TOKnull && t1->ty == Tpointer && t1->nextOf()->ty == Tvoid) | |
1462 { /* (void* op T[n]) | |
1463 * (void* op T[]) | |
1464 */ | |
1465 goto Lx2; | |
1466 } | |
1467 else if ((t1->ty == Tsarray || t1->ty == Tarray) && t1->implicitConvTo(t2)) | |
1468 { | |
1469 goto Lt2; | |
1470 } | |
1471 else if ((t2->ty == Tsarray || t2->ty == Tarray) && t2->implicitConvTo(t1)) | |
1472 { | |
1473 goto Lt1; | |
1474 } | |
1475 /* If one is mutable and the other invariant, then retry | |
1476 * with both of them as const | |
1477 */ | |
1478 else if ((t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Tpointer) && | |
1479 (t2->ty == Tsarray || t2->ty == Tarray || t2->ty == Tpointer) && | |
1480 t1->nextOf()->mod != t2->nextOf()->mod | |
1481 ) | |
1482 { | |
1483 if (t1->ty == Tpointer) | |
1484 t1 = t1->nextOf()->mutableOf()->constOf()->pointerTo(); | |
1485 else | |
1486 t1 = t1->nextOf()->mutableOf()->constOf()->arrayOf(); | |
1487 | |
1488 if (t2->ty == Tpointer) | |
1489 t2 = t2->nextOf()->mutableOf()->constOf()->pointerTo(); | |
1490 else | |
1491 t2 = t2->nextOf()->mutableOf()->constOf()->arrayOf(); | |
1492 t = t1; | |
1493 goto Lagain; | |
1494 } | |
1495 else if (t1->ty == Tclass || t2->ty == Tclass) | |
1496 { | |
1497 while (1) | |
1498 { | |
1499 int i1 = e2->implicitConvTo(t1); | |
1500 int i2 = e1->implicitConvTo(t2); | |
1501 | |
1502 if (i1 && i2) | |
1503 { | |
1504 // We have the case of class vs. void*, so pick class | |
1505 if (t1->ty == Tpointer) | |
1506 i1 = 0; | |
1507 else if (t2->ty == Tpointer) | |
1508 i2 = 0; | |
1509 } | |
1510 | |
1511 if (i2) | |
1512 { | |
1513 goto Lt2; | |
1514 } | |
1515 else if (i1) | |
1516 { | |
1517 goto Lt1; | |
1518 } | |
1519 else if (t1->ty == Tclass && t2->ty == Tclass) | |
1520 { TypeClass *tc1 = (TypeClass *)t1; | |
1521 TypeClass *tc2 = (TypeClass *)t2; | |
1522 | |
1523 /* Pick 'tightest' type | |
1524 */ | |
1525 ClassDeclaration *cd1 = tc1->sym->baseClass; | |
1526 ClassDeclaration *cd2 = tc2->sym->baseClass; | |
1527 | |
1528 if (cd1 && cd2) | |
1529 { t1 = cd1->type; | |
1530 t2 = cd2->type; | |
1531 } | |
1532 else if (cd1) | |
1533 t1 = cd1->type; | |
1534 else if (cd2) | |
1535 t2 = cd2->type; | |
1536 else | |
1537 goto Lincompatible; | |
1538 } | |
1539 else | |
1540 goto Lincompatible; | |
1541 } | |
1542 } | |
1543 else if (t1->ty == Tstruct && t2->ty == Tstruct) | |
1544 { | |
1545 if (((TypeStruct *)t1)->sym != ((TypeStruct *)t2)->sym) | |
1546 goto Lincompatible; | |
1547 } | |
1548 else if ((e1->op == TOKstring || e1->op == TOKnull) && e1->implicitConvTo(t2)) | |
1549 { | |
1550 goto Lt2; | |
1551 } | |
1552 else if ((e2->op == TOKstring || e2->op == TOKnull) && e2->implicitConvTo(t1)) | |
1553 { | |
1554 goto Lt1; | |
1555 } | |
1556 else if (t1->ty == Tsarray && t2->ty == Tsarray && | |
1557 e2->implicitConvTo(t1->nextOf()->arrayOf())) | |
1558 { | |
1559 Lx1: | |
1560 t = t1->nextOf()->arrayOf(); | |
1561 e1 = e1->castTo(sc, t); | |
1562 e2 = e2->castTo(sc, t); | |
1563 } | |
1564 else if (t1->ty == Tsarray && t2->ty == Tsarray && | |
1565 e1->implicitConvTo(t2->nextOf()->arrayOf())) | |
1566 { | |
1567 Lx2: | |
1568 t = t2->nextOf()->arrayOf(); | |
1569 e1 = e1->castTo(sc, t); | |
1570 e2 = e2->castTo(sc, t); | |
1571 } | |
1572 else if (t1->isintegral() && t2->isintegral()) | |
1573 { | |
1574 assert(0); | |
1575 } | |
1576 else if (e1->op == TOKslice && t1->ty == Tarray && | |
1577 e2->implicitConvTo(t1->nextOf())) | |
1578 { // T[] op T | |
1579 e2 = e2->castTo(sc, t1->nextOf()); | |
1580 t = t1->nextOf()->arrayOf(); | |
1581 } | |
1582 else if (e2->op == TOKslice && t2->ty == Tarray && | |
1583 e1->implicitConvTo(t2->nextOf())) | |
1584 { // T op T[] | |
1585 e1 = e1->castTo(sc, t2->nextOf()); | |
1586 t = t2->nextOf()->arrayOf(); | |
1587 | |
1588 //printf("test %s\n", e->toChars()); | |
1589 e1 = e1->optimize(WANTvalue); | |
1590 if (e && e->isCommutative() && e1->isConst()) | |
1591 { /* Swap operands to minimize number of functions generated | |
1592 */ | |
1593 //printf("swap %s\n", e->toChars()); | |
1594 Expression *tmp = e1; | |
1595 e1 = e2; | |
1596 e2 = tmp; | |
1597 } | |
1598 } | |
1599 else | |
1600 { | |
1601 Lincompatible: | |
1602 return 0; | |
1603 } | |
1604 Lret: | |
1605 if (!*pt) | |
1606 *pt = t; | |
1607 *pe1 = e1; | |
1608 *pe2 = e2; | |
1609 #if 0 | |
1610 printf("-typeMerge() %s op %s\n", e1->toChars(), e2->toChars()); | |
1611 if (e1->type) printf("\tt1 = %s\n", e1->type->toChars()); | |
1612 if (e2->type) printf("\tt2 = %s\n", e2->type->toChars()); | |
1613 printf("\ttype = %s\n", t->toChars()); | |
1614 #endif | |
1615 //dump(0); | |
1616 return 1; | |
1617 | |
1618 | |
1619 Lt1: | |
1620 e2 = e2->castTo(sc, t1); | |
1621 t = t1; | |
1622 goto Lret; | |
1623 | |
1624 Lt2: | |
1625 e1 = e1->castTo(sc, t2); | |
1626 t = t2; | |
1627 goto Lret; | |
1628 } | |
1629 | |
1630 /************************************ | |
1631 * Bring leaves to common type. | |
1632 */ | |
1633 | |
1634 Expression *BinExp::typeCombine(Scope *sc) | |
1635 { | |
1636 Type *t1 = e1->type->toBasetype(); | |
1637 Type *t2 = e2->type->toBasetype(); | |
1638 | |
1639 if (op == TOKmin || op == TOKadd) | |
1640 { | |
1641 if (t1 == t2 && (t1->ty == Tstruct || t1->ty == Tclass)) | |
1642 goto Lerror; | |
1643 } | |
1644 | |
1645 if (!typeMerge(sc, this, &type, &e1, &e2)) | |
1646 goto Lerror; | |
1647 return this; | |
1648 | |
1649 Lerror: | |
1650 incompatibleTypes(); | |
1651 type = Type::terror; | |
1652 return this; | |
1653 } | |
1654 | |
1655 /*********************************** | |
1656 * Do integral promotions (convertchk). | |
1657 * Don't convert <array of> to <pointer to> | |
1658 */ | |
1659 | |
1660 Expression *Expression::integralPromotions(Scope *sc) | |
1661 { | |
1662 Expression *e = this; | |
1663 | |
1664 //printf("integralPromotions %s %s\n", e->toChars(), e->type->toChars()); | |
1665 switch (type->toBasetype()->ty) | |
1666 { | |
1667 case Tvoid: | |
1668 error("void has no value"); | |
1669 break; | |
1670 | |
1671 case Tint8: | |
1672 case Tuns8: | |
1673 case Tint16: | |
1674 case Tuns16: | |
1675 case Tbit: | |
1676 case Tbool: | |
1677 case Tchar: | |
1678 case Twchar: | |
1679 e = e->castTo(sc, Type::tint32); | |
1680 break; | |
1681 | |
1682 case Tdchar: | |
1683 e = e->castTo(sc, Type::tuns32); | |
1684 break; | |
1685 } | |
1686 return e; | |
1687 } | |
1688 |