Mercurial > projects > ldc
annotate dmd/cast.c @ 305:2b72433d5c8c trunk
[svn r326] Fixed a bunch of issues with printf's that MinGW32 did not support.
Fixed problems with label collisions when using labels inside inline asm. LabelStatement is now easily reached given its
Identifier, which should be useful elsewhere too.
Enabled inline asm for building the lib/compiler/llvmdc runtime code, fixing branches out of asm makes this possible.
author | lindquist |
---|---|
date | Fri, 27 Jun 2008 22:04:35 +0200 |
parents | a58d8f4b84df |
children | aaade6ded589 |
rev | line source |
---|---|
159 | 1 |
2 // Copyright (c) 1999-2006 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("implicitCastTo(%s) => %s\n", type->toChars(), t->toChars()); | |
35 if (implicitConvTo(t)) | |
36 { | |
37 if (global.params.warnings && | |
38 Type::impcnvWarn[type->toBasetype()->ty][t->toBasetype()->ty] && | |
39 op != TOKint64) | |
40 { | |
41 Expression *e = optimize(WANTflags | WANTvalue); | |
42 | |
43 if (e->op == TOKint64) | |
44 return e->implicitCastTo(sc, t); | |
45 | |
215
a58d8f4b84df
[svn r231] Changed: warnings are no longer treated as an error.
lindquist
parents:
159
diff
changeset
|
46 warning("%s: implicit conversion of expression (%s) of type %s to %s can cause loss of data", |
a58d8f4b84df
[svn r231] Changed: warnings are no longer treated as an error.
lindquist
parents:
159
diff
changeset
|
47 loc.toChars(), toChars(), type->toChars(), t->toChars()); |
159 | 48 } |
49 return castTo(sc, t); | |
50 } | |
51 | |
52 Expression *e = optimize(WANTflags | WANTvalue); | |
53 if (e != this) | |
54 return e->implicitCastTo(sc, t); | |
55 | |
56 #if 0 | |
57 print(); | |
58 type->print(); | |
59 printf("to:\n"); | |
60 t->print(); | |
61 printf("%p %p type: %s to: %s\n", type->deco, t->deco, type->deco, t->deco); | |
62 //printf("%p %p %p\n", type->next->arrayOf(), type, t); | |
63 fflush(stdout); | |
64 #endif | |
65 if (!t->deco) | |
66 { /* Can happen with: | |
67 * enum E { One } | |
68 * class A | |
69 * { static void fork(EDG dg) { dg(E.One); } | |
70 * alias void delegate(E) EDG; | |
71 * } | |
72 * Should eventually make it work. | |
73 */ | |
74 error("forward reference to type %s", t->toChars()); | |
75 } | |
76 else if (t->reliesOnTident()) | |
77 error("forward reference to type %s", t->reliesOnTident()->toChars()); | |
78 | |
79 error("cannot implicitly convert expression (%s) of type %s to %s", | |
80 toChars(), type->toChars(), t->toChars()); | |
81 return castTo(sc, t); | |
82 } | |
83 | |
84 /******************************************* | |
85 * Return !=0 if we can implicitly convert this to type t. | |
86 * Don't do the actual cast. | |
87 */ | |
88 | |
89 MATCH Expression::implicitConvTo(Type *t) | |
90 { | |
91 #if 0 | |
92 printf("Expression::implicitConvTo(this=%s, type=%s, t=%s)\n", | |
93 toChars(), type->toChars(), t->toChars()); | |
94 #endif | |
95 if (!type) | |
96 { error("%s is not an expression", toChars()); | |
97 type = Type::terror; | |
98 } | |
99 if (t->ty == Tbit && isBit()) | |
100 return MATCHconvert; | |
101 Expression *e = optimize(WANTvalue | WANTflags); | |
102 if (e != this) | |
103 { //printf("optimzed to %s\n", e->toChars()); | |
104 return e->implicitConvTo(t); | |
105 } | |
106 MATCH match = type->implicitConvTo(t); | |
107 if (match) | |
108 return match; | |
109 #if 0 | |
110 Type *tb = t->toBasetype(); | |
111 if (tb->ty == Tdelegate) | |
112 { TypeDelegate *td = (TypeDelegate *)tb; | |
113 TypeFunction *tf = (TypeFunction *)td->next; | |
114 | |
115 if (!tf->varargs && | |
116 !(tf->arguments && tf->arguments->dim) | |
117 ) | |
118 { | |
119 match = type->implicitConvTo(tf->next); | |
120 if (match) | |
121 return match; | |
122 if (tf->next->toBasetype()->ty == Tvoid) | |
123 return MATCHconvert; | |
124 } | |
125 } | |
126 #endif | |
127 return MATCHnomatch; | |
128 } | |
129 | |
130 | |
131 MATCH IntegerExp::implicitConvTo(Type *t) | |
132 { | |
133 #if 0 | |
134 printf("IntegerExp::implicitConvTo(this=%s, type=%s, t=%s)\n", | |
135 toChars(), type->toChars(), t->toChars()); | |
136 #endif | |
137 if (type->equals(t)) | |
138 return MATCHexact; | |
139 | |
140 enum TY ty = type->toBasetype()->ty; | |
141 enum TY toty = t->toBasetype()->ty; | |
142 | |
143 if (type->implicitConvTo(t) == MATCHnomatch && t->ty == Tenum) | |
144 { | |
145 return MATCHnomatch; | |
146 } | |
147 | |
148 switch (ty) | |
149 { | |
150 case Tbit: | |
151 case Tbool: | |
152 value &= 1; | |
153 ty = Tint32; | |
154 break; | |
155 | |
156 case Tint8: | |
157 value = (signed char)value; | |
158 ty = Tint32; | |
159 break; | |
160 | |
161 case Tchar: | |
162 case Tuns8: | |
163 value &= 0xFF; | |
164 ty = Tint32; | |
165 break; | |
166 | |
167 case Tint16: | |
168 value = (short)value; | |
169 ty = Tint32; | |
170 break; | |
171 | |
172 case Tuns16: | |
173 case Twchar: | |
174 value &= 0xFFFF; | |
175 ty = Tint32; | |
176 break; | |
177 | |
178 case Tint32: | |
179 value = (int)value; | |
180 break; | |
181 | |
182 case Tuns32: | |
183 case Tdchar: | |
184 value &= 0xFFFFFFFF; | |
185 ty = Tuns32; | |
186 break; | |
187 | |
188 default: | |
189 break; | |
190 } | |
191 | |
192 // Only allow conversion if no change in value | |
193 switch (toty) | |
194 { | |
195 case Tbit: | |
196 case Tbool: | |
197 if ((value & 1) != value) | |
198 goto Lno; | |
199 goto Lyes; | |
200 | |
201 case Tint8: | |
202 if ((signed char)value != value) | |
203 goto Lno; | |
204 goto Lyes; | |
205 | |
206 case Tchar: | |
207 case Tuns8: | |
208 //printf("value = %llu %llu\n", (integer_t)(unsigned char)value, value); | |
209 if ((unsigned char)value != value) | |
210 goto Lno; | |
211 goto Lyes; | |
212 | |
213 case Tint16: | |
214 if ((short)value != value) | |
215 goto Lno; | |
216 goto Lyes; | |
217 | |
218 case Tuns16: | |
219 if ((unsigned short)value != value) | |
220 goto Lno; | |
221 goto Lyes; | |
222 | |
223 case Tint32: | |
224 if (ty == Tuns32) | |
225 { | |
226 } | |
227 else if ((int)value != value) | |
228 goto Lno; | |
229 goto Lyes; | |
230 | |
231 case Tuns32: | |
232 if (ty == Tint32) | |
233 { | |
234 } | |
235 else if ((unsigned)value != value) | |
236 goto Lno; | |
237 goto Lyes; | |
238 | |
239 case Tdchar: | |
240 if (value > 0x10FFFFUL) | |
241 goto Lno; | |
242 goto Lyes; | |
243 | |
244 case Twchar: | |
245 if ((unsigned short)value != value) | |
246 goto Lno; | |
247 goto Lyes; | |
248 | |
249 case Tfloat32: | |
250 { | |
251 volatile float f; | |
252 if (type->isunsigned()) | |
253 { | |
254 f = (float)value; | |
255 if (f != value) | |
256 goto Lno; | |
257 } | |
258 else | |
259 { | |
260 f = (float)(long long)value; | |
261 if (f != (long long)value) | |
262 goto Lno; | |
263 } | |
264 goto Lyes; | |
265 } | |
266 | |
267 case Tfloat64: | |
268 { | |
269 volatile double f; | |
270 if (type->isunsigned()) | |
271 { | |
272 f = (double)value; | |
273 if (f != value) | |
274 goto Lno; | |
275 } | |
276 else | |
277 { | |
278 f = (double)(long long)value; | |
279 if (f != (long long)value) | |
280 goto Lno; | |
281 } | |
282 goto Lyes; | |
283 } | |
284 | |
285 case Tfloat80: | |
286 { | |
287 volatile long double f; | |
288 if (type->isunsigned()) | |
289 { | |
290 f = (long double)value; | |
291 if (f != value) | |
292 goto Lno; | |
293 } | |
294 else | |
295 { | |
296 f = (long double)(long long)value; | |
297 if (f != (long long)value) | |
298 goto Lno; | |
299 } | |
300 goto Lyes; | |
301 } | |
302 } | |
303 return Expression::implicitConvTo(t); | |
304 | |
305 Lyes: | |
306 //printf("MATCHconvert\n"); | |
307 return MATCHconvert; | |
308 | |
309 Lno: | |
310 //printf("MATCHnomatch\n"); | |
311 return MATCHnomatch; | |
312 } | |
313 | |
314 MATCH NullExp::implicitConvTo(Type *t) | |
315 { | |
316 #if 0 | |
317 printf("NullExp::implicitConvTo(this=%s, type=%s, t=%s)\n", | |
318 toChars(), type->toChars(), t->toChars()); | |
319 #endif | |
320 if (this->type->equals(t)) | |
321 return MATCHexact; | |
322 // NULL implicitly converts to any pointer type or dynamic array | |
323 if (type->ty == Tpointer && type->next->ty == Tvoid) | |
324 { | |
325 if (t->ty == Ttypedef) | |
326 t = ((TypeTypedef *)t)->sym->basetype; | |
327 if (t->ty == Tpointer || t->ty == Tarray || | |
328 t->ty == Taarray || t->ty == Tclass || | |
329 t->ty == Tdelegate) | |
330 return committed ? MATCHconvert : MATCHexact; | |
331 } | |
332 return Expression::implicitConvTo(t); | |
333 } | |
334 | |
335 MATCH StringExp::implicitConvTo(Type *t) | |
336 { MATCH m; | |
337 | |
338 #if 0 | |
339 printf("StringExp::implicitConvTo(this=%s, committed=%d, type=%s, t=%s)\n", | |
340 toChars(), committed, type->toChars(), t->toChars()); | |
341 #endif | |
342 if (!committed) | |
343 { | |
344 if (!committed && t->ty == Tpointer && t->next->ty == Tvoid) | |
345 { | |
346 return MATCHnomatch; | |
347 } | |
348 if (type->ty == Tsarray || type->ty == Tarray || type->ty == Tpointer) | |
349 { | |
350 if (type->next->ty == Tchar) | |
351 { | |
352 switch (t->ty) | |
353 { | |
354 case Tsarray: | |
355 if (type->ty == Tsarray && | |
356 ((TypeSArray *)type)->dim->toInteger() != | |
357 ((TypeSArray *)t)->dim->toInteger()) | |
358 return MATCHnomatch; | |
359 goto L1; | |
360 case Tarray: | |
361 goto L1; | |
362 case Tpointer: | |
363 L1: | |
364 if (t->next->ty == Tchar) | |
365 return MATCHexact; | |
366 else if (t->next->ty == Twchar) | |
367 return MATCHexact; | |
368 else if (t->next->ty == Tdchar) | |
369 return MATCHexact; | |
370 break; | |
371 } | |
372 } | |
373 } | |
374 } | |
375 return Expression::implicitConvTo(t); | |
376 #if 0 | |
377 m = (MATCH)type->implicitConvTo(t); | |
378 if (m) | |
379 { | |
380 return m; | |
381 } | |
382 | |
383 return MATCHnomatch; | |
384 #endif | |
385 } | |
386 | |
387 MATCH ArrayLiteralExp::implicitConvTo(Type *t) | |
388 { MATCH result = MATCHexact; | |
389 | |
390 Type *typeb = type->toBasetype(); | |
391 Type *tb = t->toBasetype(); | |
392 if ((tb->ty == Tarray || tb->ty == Tsarray) && | |
393 (typeb->ty == Tarray || typeb->ty == Tsarray)) | |
394 { | |
395 if (tb->ty == Tsarray) | |
396 { TypeSArray *tsa = (TypeSArray *)tb; | |
397 if (elements->dim != tsa->dim->toInteger()) | |
398 result = MATCHnomatch; | |
399 } | |
400 | |
401 for (int i = 0; i < elements->dim; i++) | |
402 { Expression *e = (Expression *)elements->data[i]; | |
403 MATCH m = (MATCH)e->implicitConvTo(tb->next); | |
404 if (m < result) | |
405 result = m; // remember worst match | |
406 if (result == MATCHnomatch) | |
407 break; // no need to check for worse | |
408 } | |
409 return result; | |
410 } | |
411 else | |
412 return Expression::implicitConvTo(t); | |
413 } | |
414 | |
415 MATCH AssocArrayLiteralExp::implicitConvTo(Type *t) | |
416 { MATCH result = MATCHexact; | |
417 | |
418 Type *typeb = type->toBasetype(); | |
419 Type *tb = t->toBasetype(); | |
420 if (tb->ty == Taarray && typeb->ty == Taarray) | |
421 { | |
422 for (size_t i = 0; i < keys->dim; i++) | |
423 { Expression *e = (Expression *)keys->data[i]; | |
424 MATCH m = (MATCH)e->implicitConvTo(((TypeAArray *)tb)->key); | |
425 if (m < result) | |
426 result = m; // remember worst match | |
427 if (result == MATCHnomatch) | |
428 break; // no need to check for worse | |
429 e = (Expression *)values->data[i]; | |
430 m = (MATCH)e->implicitConvTo(tb->next); | |
431 if (m < result) | |
432 result = m; // remember worst match | |
433 if (result == MATCHnomatch) | |
434 break; // no need to check for worse | |
435 } | |
436 return result; | |
437 } | |
438 else | |
439 return Expression::implicitConvTo(t); | |
440 } | |
441 | |
442 MATCH AddrExp::implicitConvTo(Type *t) | |
443 { | |
444 #if 0 | |
445 printf("AddrExp::implicitConvTo(this=%s, type=%s, t=%s)\n", | |
446 toChars(), type->toChars(), t->toChars()); | |
447 #endif | |
448 MATCH result; | |
449 | |
450 result = type->implicitConvTo(t); | |
451 //printf("\tresult = %d\n", result); | |
452 | |
453 if (result == MATCHnomatch) | |
454 { | |
455 // Look for pointers to functions where the functions are overloaded. | |
456 VarExp *ve; | |
457 FuncDeclaration *f; | |
458 | |
459 t = t->toBasetype(); | |
460 if (type->ty == Tpointer && type->next->ty == Tfunction && | |
461 t->ty == Tpointer && t->next->ty == Tfunction && | |
462 e1->op == TOKvar) | |
463 { | |
464 ve = (VarExp *)e1; | |
465 f = ve->var->isFuncDeclaration(); | |
466 if (f && f->overloadExactMatch(t->next)) | |
467 result = MATCHexact; | |
468 } | |
469 } | |
470 //printf("\tresult = %d\n", result); | |
471 return result; | |
472 } | |
473 | |
474 MATCH SymOffExp::implicitConvTo(Type *t) | |
475 { | |
476 #if 0 | |
477 printf("SymOffExp::implicitConvTo(this=%s, type=%s, t=%s)\n", | |
478 toChars(), type->toChars(), t->toChars()); | |
479 #endif | |
480 MATCH result; | |
481 | |
482 result = type->implicitConvTo(t); | |
483 //printf("\tresult = %d\n", result); | |
484 | |
485 if (result == MATCHnomatch) | |
486 { | |
487 // Look for pointers to functions where the functions are overloaded. | |
488 FuncDeclaration *f; | |
489 | |
490 t = t->toBasetype(); | |
491 if (type->ty == Tpointer && type->next->ty == Tfunction && | |
492 t->ty == Tpointer && t->next->ty == Tfunction) | |
493 { | |
494 f = var->isFuncDeclaration(); | |
495 if (f && f->overloadExactMatch(t->next)) | |
496 result = MATCHexact; | |
497 } | |
498 } | |
499 //printf("\tresult = %d\n", result); | |
500 return result; | |
501 } | |
502 | |
503 MATCH DelegateExp::implicitConvTo(Type *t) | |
504 { | |
505 #if 0 | |
506 printf("DelegateExp::implicitConvTo(this=%s, type=%s, t=%s)\n", | |
507 toChars(), type->toChars(), t->toChars()); | |
508 #endif | |
509 MATCH result; | |
510 | |
511 result = type->implicitConvTo(t); | |
512 | |
513 if (result == 0) | |
514 { | |
515 // Look for pointers to functions where the functions are overloaded. | |
516 FuncDeclaration *f; | |
517 | |
518 t = t->toBasetype(); | |
519 if (type->ty == Tdelegate && type->next->ty == Tfunction && | |
520 t->ty == Tdelegate && t->next->ty == Tfunction) | |
521 { | |
522 if (func && func->overloadExactMatch(t->next)) | |
523 result = MATCHexact; | |
524 } | |
525 } | |
526 return result; | |
527 } | |
528 | |
529 MATCH CondExp::implicitConvTo(Type *t) | |
530 { | |
531 MATCH m1; | |
532 MATCH m2; | |
533 | |
534 m1 = e1->implicitConvTo(t); | |
535 m2 = e2->implicitConvTo(t); | |
536 | |
537 // Pick the worst match | |
538 return (m1 < m2) ? m1 : m2; | |
539 } | |
540 | |
541 | |
542 /* ==================== castTo ====================== */ | |
543 | |
544 /************************************** | |
545 * Do an explicit cast. | |
546 */ | |
547 | |
548 Expression *Expression::castTo(Scope *sc, Type *t) | |
549 { | |
550 //printf("Expression::castTo(this=%s, t=%s)\n", toChars(), t->toChars()); | |
551 #if 0 | |
552 printf("Expression::castTo(this=%s, type=%s, t=%s)\n", | |
553 toChars(), type->toChars(), t->toChars()); | |
554 #endif | |
555 if (type == t) | |
556 return this; | |
557 Expression *e = this; | |
558 Type *tb = t->toBasetype(); | |
559 Type *typeb = type->toBasetype(); | |
560 if (tb != typeb) | |
561 { | |
562 // Do (type *) cast of (type [dim]) | |
563 if (tb->ty == Tpointer && | |
564 typeb->ty == Tsarray | |
565 ) | |
566 { | |
567 //printf("Converting [dim] to *\n"); | |
568 | |
569 if (typeb->size(loc) == 0) | |
570 e = new NullExp(loc); | |
571 else | |
572 e = new AddrExp(loc, e); | |
573 } | |
574 #if 0 | |
575 else if (tb->ty == Tdelegate && type->ty != Tdelegate) | |
576 { | |
577 TypeDelegate *td = (TypeDelegate *)tb; | |
578 TypeFunction *tf = (TypeFunction *)td->nextOf(); | |
579 return toDelegate(sc, tf->nextOf()); | |
580 } | |
581 #endif | |
582 else | |
583 { | |
584 e = new CastExp(loc, e, tb); | |
585 } | |
586 } | |
587 else | |
588 { | |
589 e = e->copy(); // because of COW for assignment to e->type | |
590 } | |
591 assert(e != this); | |
592 e->type = t; | |
593 //printf("Returning: %s\n", e->toChars()); | |
594 return e; | |
595 } | |
596 | |
597 | |
598 Expression *RealExp::castTo(Scope *sc, Type *t) | |
599 { Expression *e = this; | |
600 if (type != t) | |
601 { | |
602 if ((type->isreal() && t->isreal()) || | |
603 (type->isimaginary() && t->isimaginary()) | |
604 ) | |
605 { e = copy(); | |
606 e->type = t; | |
607 } | |
608 else | |
609 e = Expression::castTo(sc, t); | |
610 } | |
611 return e; | |
612 } | |
613 | |
614 | |
615 Expression *ComplexExp::castTo(Scope *sc, Type *t) | |
616 { Expression *e = this; | |
617 if (type != t) | |
618 { | |
619 if (type->iscomplex() && t->iscomplex()) | |
620 { e = copy(); | |
621 e->type = t; | |
622 } | |
623 else | |
624 e = Expression::castTo(sc, t); | |
625 } | |
626 return e; | |
627 } | |
628 | |
629 | |
630 Expression *NullExp::castTo(Scope *sc, Type *t) | |
631 { NullExp *e; | |
632 Type *tb; | |
633 | |
634 //printf("NullExp::castTo(t = %p)\n", t); | |
635 if (type == t) | |
636 { | |
637 committed = 1; | |
638 return this; | |
639 } | |
640 e = (NullExp *)copy(); | |
641 e->committed = 1; | |
642 tb = t->toBasetype(); | |
643 e->type = type->toBasetype(); | |
644 if (tb != e->type) | |
645 { | |
646 // NULL implicitly converts to any pointer type or dynamic array | |
647 if (e->type->ty == Tpointer && e->type->nextOf()->ty == Tvoid && | |
648 (tb->ty == Tpointer || tb->ty == Tarray || tb->ty == Taarray || | |
649 tb->ty == Tdelegate)) | |
650 { | |
651 #if 0 | |
652 if (tb->ty == Tdelegate) | |
653 { TypeDelegate *td = (TypeDelegate *)tb; | |
654 TypeFunction *tf = (TypeFunction *)td->nextOf(); | |
655 | |
656 if (!tf->varargs && | |
657 !(tf->arguments && tf->arguments->dim) | |
658 ) | |
659 { | |
660 return Expression::castTo(sc, t); | |
661 } | |
662 } | |
663 #endif | |
664 } | |
665 else | |
666 { | |
667 return e->Expression::castTo(sc, t); | |
668 } | |
669 } | |
670 e->type = t; | |
671 return e; | |
672 } | |
673 | |
674 Expression *StringExp::castTo(Scope *sc, Type *t) | |
675 { | |
676 /* This follows copy-on-write; any changes to 'this' | |
677 * will result in a copy. | |
678 * The this->string member is considered immutable. | |
679 */ | |
680 StringExp *se; | |
681 Type *tb; | |
682 int copied = 0; | |
683 | |
684 //printf("StringExp::castTo(t = %s), '%s' committed = %d\n", t->toChars(), toChars(), committed); | |
685 | |
686 if (!committed && t->ty == Tpointer && t->nextOf()->ty == Tvoid) | |
687 { | |
688 error("cannot convert string literal to void*"); | |
689 } | |
690 | |
691 se = this; | |
692 if (!committed) | |
693 { se = (StringExp *)copy(); | |
694 se->committed = 1; | |
695 copied = 1; | |
696 } | |
697 | |
698 if (type == t) | |
699 { | |
700 return se; | |
701 } | |
702 | |
703 tb = t->toBasetype(); | |
704 //printf("\ttype = %s\n", type->toChars()); | |
705 if (tb->ty == Tdelegate && type->toBasetype()->ty != Tdelegate) | |
706 return Expression::castTo(sc, t); | |
707 | |
708 Type *typeb = type->toBasetype(); | |
709 if (typeb == tb) | |
710 { | |
711 if (!copied) | |
712 { se = (StringExp *)copy(); | |
713 copied = 1; | |
714 } | |
715 se->type = t; | |
716 return se; | |
717 } | |
718 | |
719 if (tb->ty != Tsarray && tb->ty != Tarray && tb->ty != Tpointer) | |
720 { if (!copied) | |
721 { se = (StringExp *)copy(); | |
722 copied = 1; | |
723 } | |
724 goto Lcast; | |
725 } | |
726 if (typeb->ty != Tsarray && typeb->ty != Tarray && typeb->ty != Tpointer) | |
727 { if (!copied) | |
728 { se = (StringExp *)copy(); | |
729 copied = 1; | |
730 } | |
731 goto Lcast; | |
732 } | |
733 | |
734 if (typeb->nextOf()->size() == tb->nextOf()->size()) | |
735 { | |
736 if (!copied) | |
737 { se = (StringExp *)copy(); | |
738 copied = 1; | |
739 } | |
740 if (tb->ty == Tsarray) | |
741 goto L2; // handle possible change in static array dimension | |
742 se->type = t; | |
743 return se; | |
744 } | |
745 | |
746 if (committed) | |
747 goto Lcast; | |
748 | |
749 #define X(tf,tt) ((tf) * 256 + (tt)) | |
750 { | |
751 OutBuffer buffer; | |
752 size_t newlen = 0; | |
753 int tfty = typeb->nextOf()->toBasetype()->ty; | |
754 int ttty = tb->nextOf()->toBasetype()->ty; | |
755 switch (X(tfty, ttty)) | |
756 { | |
757 case X(Tchar, Tchar): | |
758 case X(Twchar,Twchar): | |
759 case X(Tdchar,Tdchar): | |
760 break; | |
761 | |
762 case X(Tchar, Twchar): | |
763 for (size_t u = 0; u < len;) | |
764 { unsigned c; | |
765 char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); | |
766 if (p) | |
767 error("%s", p); | |
768 else | |
769 buffer.writeUTF16(c); | |
770 } | |
771 newlen = buffer.offset / 2; | |
772 buffer.writeUTF16(0); | |
773 goto L1; | |
774 | |
775 case X(Tchar, Tdchar): | |
776 for (size_t u = 0; u < len;) | |
777 { unsigned c; | |
778 char *p = utf_decodeChar((unsigned char *)se->string, len, &u, &c); | |
779 if (p) | |
780 error("%s", p); | |
781 buffer.write4(c); | |
782 newlen++; | |
783 } | |
784 buffer.write4(0); | |
785 goto L1; | |
786 | |
787 case X(Twchar,Tchar): | |
788 for (size_t u = 0; u < len;) | |
789 { unsigned c; | |
790 char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); | |
791 if (p) | |
792 error("%s", p); | |
793 else | |
794 buffer.writeUTF8(c); | |
795 } | |
796 newlen = buffer.offset; | |
797 buffer.writeUTF8(0); | |
798 goto L1; | |
799 | |
800 case X(Twchar,Tdchar): | |
801 for (size_t u = 0; u < len;) | |
802 { unsigned c; | |
803 char *p = utf_decodeWchar((unsigned short *)se->string, len, &u, &c); | |
804 if (p) | |
805 error("%s", p); | |
806 buffer.write4(c); | |
807 newlen++; | |
808 } | |
809 buffer.write4(0); | |
810 goto L1; | |
811 | |
812 case X(Tdchar,Tchar): | |
813 for (size_t u = 0; u < len; u++) | |
814 { | |
815 unsigned c = ((unsigned *)se->string)[u]; | |
816 if (!utf_isValidDchar(c)) | |
817 error("invalid UCS-32 char \\U%08x", c); | |
818 else | |
819 buffer.writeUTF8(c); | |
820 newlen++; | |
821 } | |
822 newlen = buffer.offset; | |
823 buffer.writeUTF8(0); | |
824 goto L1; | |
825 | |
826 case X(Tdchar,Twchar): | |
827 for (size_t u = 0; u < len; u++) | |
828 { | |
829 unsigned c = ((unsigned *)se->string)[u]; | |
830 if (!utf_isValidDchar(c)) | |
831 error("invalid UCS-32 char \\U%08x", c); | |
832 else | |
833 buffer.writeUTF16(c); | |
834 newlen++; | |
835 } | |
836 newlen = buffer.offset / 2; | |
837 buffer.writeUTF16(0); | |
838 goto L1; | |
839 | |
840 L1: | |
841 if (!copied) | |
842 { se = (StringExp *)copy(); | |
843 copied = 1; | |
844 } | |
845 se->string = buffer.extractData(); | |
846 se->len = newlen; | |
847 se->sz = tb->nextOf()->size(); | |
848 break; | |
849 | |
850 default: | |
851 assert(typeb->nextOf()->size() != tb->nextOf()->size()); | |
852 goto Lcast; | |
853 } | |
854 } | |
855 #undef X | |
856 L2: | |
857 assert(copied); | |
858 | |
859 // See if need to truncate or extend the literal | |
860 if (tb->ty == Tsarray) | |
861 { | |
862 int dim2 = ((TypeSArray *)tb)->dim->toInteger(); | |
863 | |
864 //printf("dim from = %d, to = %d\n", se->len, dim2); | |
865 | |
866 // Changing dimensions | |
867 if (dim2 != se->len) | |
868 { | |
869 // Copy when changing the string literal | |
870 unsigned newsz = se->sz; | |
871 void *s; | |
872 int d; | |
873 | |
874 d = (dim2 < se->len) ? dim2 : se->len; | |
875 s = (unsigned char *)mem.malloc((dim2 + 1) * newsz); | |
876 memcpy(s, se->string, d * newsz); | |
877 // Extend with 0, add terminating 0 | |
878 memset((char *)s + d * newsz, 0, (dim2 + 1 - d) * newsz); | |
879 se->string = s; | |
880 se->len = dim2; | |
881 } | |
882 } | |
883 se->type = t; | |
884 return se; | |
885 | |
886 Lcast: | |
887 Expression *e = new CastExp(loc, se, t); | |
888 e->type = t; // so semantic() won't be run on e | |
889 return e; | |
890 } | |
891 | |
892 Expression *AddrExp::castTo(Scope *sc, Type *t) | |
893 { | |
894 Type *tb; | |
895 | |
896 #if 0 | |
897 printf("AddrExp::castTo(this=%s, type=%s, t=%s)\n", | |
898 toChars(), type->toChars(), t->toChars()); | |
899 #endif | |
900 Expression *e = this; | |
901 | |
902 tb = t->toBasetype(); | |
903 type = type->toBasetype(); | |
904 if (tb != type) | |
905 { | |
906 // Look for pointers to functions where the functions are overloaded. | |
907 VarExp *ve; | |
908 FuncDeclaration *f; | |
909 | |
910 if (type->ty == Tpointer && type->next->ty == Tfunction && | |
911 tb->ty == Tpointer && tb->next->ty == Tfunction && | |
912 e1->op == TOKvar) | |
913 { | |
914 ve = (VarExp *)e1; | |
915 f = ve->var->isFuncDeclaration(); | |
916 if (f) | |
917 { | |
918 f = f->overloadExactMatch(tb->next); | |
919 if (f) | |
920 { | |
921 e = new VarExp(loc, f); | |
922 e->type = f->type; | |
923 e = new AddrExp(loc, e); | |
924 e->type = t; | |
925 return e; | |
926 } | |
927 } | |
928 } | |
929 e = Expression::castTo(sc, t); | |
930 } | |
931 e->type = t; | |
932 return e; | |
933 } | |
934 | |
935 | |
936 Expression *TupleExp::castTo(Scope *sc, Type *t) | |
937 { TupleExp *e = (TupleExp *)copy(); | |
938 e->exps = (Expressions *)exps->copy(); | |
939 for (size_t i = 0; i < e->exps->dim; i++) | |
940 { Expression *ex = (Expression *)e->exps->data[i]; | |
941 ex = ex->castTo(sc, t); | |
942 e->exps->data[i] = (void *)ex; | |
943 } | |
944 return e; | |
945 } | |
946 | |
947 | |
948 Expression *ArrayLiteralExp::castTo(Scope *sc, Type *t) | |
949 { | |
950 #if 0 | |
951 printf("ArrayLiteralExp::castTo(this=%s, type=%s, t=%s)\n", | |
952 toChars(), type->toChars(), t->toChars()); | |
953 #endif | |
954 if (type == t) | |
955 return this; | |
956 ArrayLiteralExp *e = this; | |
957 Type *typeb = type->toBasetype(); | |
958 Type *tb = t->toBasetype(); | |
959 if ((tb->ty == Tarray || tb->ty == Tsarray) && | |
960 (typeb->ty == Tarray || typeb->ty == Tsarray) && | |
961 // Not trying to convert non-void[] to void[] | |
962 !(tb->nextOf()->toBasetype()->ty == Tvoid && typeb->nextOf()->toBasetype()->ty != Tvoid)) | |
963 { | |
964 if (tb->ty == Tsarray) | |
965 { TypeSArray *tsa = (TypeSArray *)tb; | |
966 if (elements->dim != tsa->dim->toInteger()) | |
967 goto L1; | |
968 } | |
969 | |
970 e = (ArrayLiteralExp *)copy(); | |
971 e->elements = (Expressions *)elements->copy(); | |
972 for (int i = 0; i < elements->dim; i++) | |
973 { Expression *ex = (Expression *)elements->data[i]; | |
974 ex = ex->castTo(sc, tb->nextOf()); | |
975 e->elements->data[i] = (void *)ex; | |
976 } | |
977 e->type = t; | |
978 return e; | |
979 } | |
980 if (tb->ty == Tpointer && typeb->ty == Tsarray) | |
981 { | |
982 e = (ArrayLiteralExp *)copy(); | |
983 e->type = typeb->nextOf()->pointerTo(); | |
984 } | |
985 L1: | |
986 return e->Expression::castTo(sc, t); | |
987 } | |
988 | |
989 Expression *AssocArrayLiteralExp::castTo(Scope *sc, Type *t) | |
990 { | |
991 if (type == t) | |
992 return this; | |
993 AssocArrayLiteralExp *e = this; | |
994 Type *typeb = type->toBasetype(); | |
995 Type *tb = t->toBasetype(); | |
996 if (tb->ty == Taarray && typeb->ty == Taarray && | |
997 tb->nextOf()->toBasetype()->ty != Tvoid) | |
998 { | |
999 e = (AssocArrayLiteralExp *)copy(); | |
1000 e->keys = (Expressions *)keys->copy(); | |
1001 e->values = (Expressions *)values->copy(); | |
1002 assert(keys->dim == values->dim); | |
1003 for (size_t i = 0; i < keys->dim; i++) | |
1004 { Expression *ex = (Expression *)values->data[i]; | |
1005 ex = ex->castTo(sc, tb->nextOf()); | |
1006 e->values->data[i] = (void *)ex; | |
1007 | |
1008 ex = (Expression *)keys->data[i]; | |
1009 ex = ex->castTo(sc, ((TypeAArray *)tb)->index); | |
1010 e->keys->data[i] = (void *)ex; | |
1011 } | |
1012 e->type = t; | |
1013 return e; | |
1014 } | |
1015 L1: | |
1016 return e->Expression::castTo(sc, t); | |
1017 } | |
1018 | |
1019 | |
1020 Expression *SymOffExp::castTo(Scope *sc, Type *t) | |
1021 { | |
1022 Type *tb; | |
1023 | |
1024 #if 0 | |
1025 printf("SymOffExp::castTo(this=%s, type=%s, t=%s)\n", | |
1026 toChars(), type->toChars(), t->toChars()); | |
1027 #endif | |
1028 Expression *e = this; | |
1029 | |
1030 tb = t->toBasetype(); | |
1031 type = type->toBasetype(); | |
1032 if (tb != type) | |
1033 { | |
1034 // Look for pointers to functions where the functions are overloaded. | |
1035 FuncDeclaration *f; | |
1036 | |
1037 if (type->ty == Tpointer && type->next->ty == Tfunction && | |
1038 tb->ty == Tpointer && tb->next->ty == Tfunction) | |
1039 { | |
1040 f = var->isFuncDeclaration(); | |
1041 if (f) | |
1042 { | |
1043 f = f->overloadExactMatch(tb->next); | |
1044 if (f) | |
1045 { | |
1046 e = new SymOffExp(loc, f, 0); | |
1047 e->type = t; | |
1048 return e; | |
1049 } | |
1050 } | |
1051 } | |
1052 e = Expression::castTo(sc, t); | |
1053 } | |
1054 e->type = t; | |
1055 return e; | |
1056 } | |
1057 | |
1058 Expression *DelegateExp::castTo(Scope *sc, Type *t) | |
1059 { | |
1060 Type *tb; | |
1061 #if 0 | |
1062 printf("DelegateExp::castTo(this=%s, type=%s, t=%s)\n", | |
1063 toChars(), type->toChars(), t->toChars()); | |
1064 #endif | |
1065 Expression *e = this; | |
1066 static char msg[] = "cannot form delegate due to covariant return type"; | |
1067 | |
1068 tb = t->toBasetype(); | |
1069 type = type->toBasetype(); | |
1070 if (tb != type) | |
1071 { | |
1072 // Look for delegates to functions where the functions are overloaded. | |
1073 FuncDeclaration *f; | |
1074 | |
1075 if (type->ty == Tdelegate && type->next->ty == Tfunction && | |
1076 tb->ty == Tdelegate && tb->next->ty == Tfunction) | |
1077 { | |
1078 if (func) | |
1079 { | |
1080 f = func->overloadExactMatch(tb->next); | |
1081 if (f) | |
1082 { int offset; | |
1083 if (f->tintro && f->tintro->next->isBaseOf(f->type->next, &offset) && offset) | |
1084 error("%s", msg); | |
1085 e = new DelegateExp(loc, e1, f); | |
1086 e->type = t; | |
1087 return e; | |
1088 } | |
1089 if (func->tintro) | |
1090 error("%s", msg); | |
1091 } | |
1092 } | |
1093 e = Expression::castTo(sc, t); | |
1094 } | |
1095 else | |
1096 { int offset; | |
1097 | |
1098 if (func->tintro && func->tintro->next->isBaseOf(func->type->next, &offset) && offset) | |
1099 error("%s", msg); | |
1100 } | |
1101 e->type = t; | |
1102 return e; | |
1103 } | |
1104 | |
1105 Expression *CondExp::castTo(Scope *sc, Type *t) | |
1106 { | |
1107 Expression *e = this; | |
1108 | |
1109 if (type != t) | |
1110 { | |
1111 if (1 || e1->op == TOKstring || e2->op == TOKstring) | |
1112 { e = new CondExp(loc, econd, e1->castTo(sc, t), e2->castTo(sc, t)); | |
1113 e->type = t; | |
1114 } | |
1115 else | |
1116 e = Expression::castTo(sc, t); | |
1117 } | |
1118 return e; | |
1119 } | |
1120 | |
1121 /* ==================== ====================== */ | |
1122 | |
1123 /**************************************** | |
1124 * Scale addition/subtraction to/from pointer. | |
1125 */ | |
1126 | |
1127 Expression *BinExp::scaleFactor(Scope *sc) | |
1128 { d_uns64 stride; | |
1129 Type *t1b = e1->type->toBasetype(); | |
1130 Type *t2b = e2->type->toBasetype(); | |
1131 | |
1132 if (t1b->ty == Tpointer && t2b->isintegral()) | |
1133 { // Need to adjust operator by the stride | |
1134 // Replace (ptr + int) with (ptr + (int * stride)) | |
1135 Type *t = Type::tptrdiff_t; | |
1136 | |
1137 stride = t1b->next->size(); | |
1138 if (!t->equals(t2b)) | |
1139 e2 = e2->castTo(sc, t); | |
1140 // LLVMDC: llvm uses typesafe pointer arithmetic | |
1141 #if !IN_LLVM | |
1142 if (t1b->next->isbit()) | |
1143 // BUG: should add runtime check for misaligned offsets | |
1144 // This perhaps should be done by rewriting as &p[i] | |
1145 // and letting back end do it. | |
1146 e2 = new UshrExp(loc, e2, new IntegerExp(0, 3, t)); | |
1147 else | |
1148 e2 = new MulExp(loc, e2, new IntegerExp(0, stride, t)); | |
1149 #endif | |
1150 e2->type = t; | |
1151 type = e1->type; | |
1152 } | |
1153 else if (t2b->ty == Tpointer && t1b->isintegral()) | |
1154 { // Need to adjust operator by the stride | |
1155 // Replace (int + ptr) with (ptr + (int * stride)) | |
1156 Type *t = Type::tptrdiff_t; | |
1157 Expression *e; | |
1158 | |
1159 stride = t2b->next->size(); | |
1160 if (!t->equals(t1b)) | |
1161 e = e1->castTo(sc, t); | |
1162 else | |
1163 e = e1; | |
1164 #if !IN_LLVM | |
1165 if (t2b->next->isbit()) | |
1166 // BUG: should add runtime check for misaligned offsets | |
1167 e = new UshrExp(loc, e, new IntegerExp(0, 3, t)); | |
1168 else | |
1169 e = new MulExp(loc, e, new IntegerExp(0, stride, t)); | |
1170 #endif | |
1171 e->type = t; | |
1172 type = e2->type; | |
1173 e1 = e2; | |
1174 e2 = e; | |
1175 } | |
1176 return this; | |
1177 } | |
1178 | |
1179 /************************************ | |
1180 * Bring leaves to common type. | |
1181 */ | |
1182 | |
1183 Expression *BinExp::typeCombine(Scope *sc) | |
1184 { | |
1185 Type *t1; | |
1186 Type *t2; | |
1187 Type *t; | |
1188 TY ty; | |
1189 | |
1190 //printf("BinExp::typeCombine()\n"); | |
1191 //dump(0); | |
1192 | |
1193 e1 = e1->integralPromotions(sc); | |
1194 e2 = e2->integralPromotions(sc); | |
1195 | |
1196 // BUG: do toBasetype() | |
1197 t1 = e1->type; | |
1198 t2 = e2->type; | |
1199 assert(t1); | |
1200 | |
1201 //if (t1) printf("\tt1 = %s\n", t1->toChars()); | |
1202 //if (t2) printf("\tt2 = %s\n", t2->toChars()); | |
1203 #ifdef DEBUG | |
1204 if (!t2) printf("\te2 = '%s'\n", e2->toChars()); | |
1205 #endif | |
1206 assert(t2); | |
1207 | |
1208 Type *t1b = t1->toBasetype(); | |
1209 Type *t2b = t2->toBasetype(); | |
1210 | |
1211 ty = (TY)Type::impcnvResult[t1b->ty][t2b->ty]; | |
1212 if (ty != Terror) | |
1213 { TY ty1; | |
1214 TY ty2; | |
1215 | |
1216 ty1 = (TY)Type::impcnvType1[t1b->ty][t2b->ty]; | |
1217 ty2 = (TY)Type::impcnvType2[t1b->ty][t2b->ty]; | |
1218 | |
1219 if (t1b->ty == ty1) // if no promotions | |
1220 { | |
1221 if (t1 == t2) | |
1222 { | |
1223 if (!type) | |
1224 type = t1; | |
1225 return this; | |
1226 } | |
1227 | |
1228 if (t1b == t2b) | |
1229 { | |
1230 if (!type) | |
1231 type = t1b; | |
1232 return this; | |
1233 } | |
1234 } | |
1235 | |
1236 if (!type) | |
1237 type = Type::basic[ty]; | |
1238 | |
1239 t1 = Type::basic[ty1]; | |
1240 t2 = Type::basic[ty2]; | |
1241 e1 = e1->castTo(sc, t1); | |
1242 e2 = e2->castTo(sc, t2); | |
1243 #if 0 | |
1244 if (type != Type::basic[ty]) | |
1245 { t = type; | |
1246 type = Type::basic[ty]; | |
1247 return castTo(sc, t); | |
1248 } | |
1249 #endif | |
1250 //printf("after typeCombine():\n"); | |
1251 //dump(0); | |
1252 //printf("ty = %d, ty1 = %d, ty2 = %d\n", ty, ty1, ty2); | |
1253 return this; | |
1254 } | |
1255 | |
1256 t = t1; | |
1257 if (t1 == t2) | |
1258 { | |
1259 if ((t1->ty == Tstruct || t1->ty == Tclass) && | |
1260 (op == TOKmin || op == TOKadd)) | |
1261 goto Lincompatible; | |
1262 } | |
1263 else if (t1->isintegral() && t2->isintegral()) | |
1264 { | |
1265 printf("t1 = %s, t2 = %s\n", t1->toChars(), t2->toChars()); | |
1266 int sz1 = t1->size(); | |
1267 int sz2 = t2->size(); | |
1268 int sign1 = t1->isunsigned() == 0; | |
1269 int sign2 = t2->isunsigned() == 0; | |
1270 | |
1271 if (sign1 == sign2) | |
1272 { | |
1273 if (sz1 < sz2) | |
1274 goto Lt2; | |
1275 else | |
1276 goto Lt1; | |
1277 } | |
1278 if (!sign1) | |
1279 { | |
1280 if (sz1 >= sz2) | |
1281 goto Lt1; | |
1282 else | |
1283 goto Lt2; | |
1284 } | |
1285 else | |
1286 { | |
1287 if (sz2 >= sz1) | |
1288 goto Lt2; | |
1289 else | |
1290 goto Lt1; | |
1291 } | |
1292 } | |
1293 else if (t1->ty == Tpointer && t2->ty == Tpointer) | |
1294 { | |
1295 // Bring pointers to compatible type | |
1296 Type *t1n = t1->next; | |
1297 Type *t2n = t2->next; | |
1298 | |
1299 //t1->print(); | |
1300 //t2->print(); | |
1301 //if (t1n == t2n) *(char *)0 = 0; | |
1302 assert(t1n != t2n); | |
1303 if (t1n->ty == Tvoid) // pointers to void are always compatible | |
1304 t = t2; | |
1305 else if (t2n->ty == Tvoid) | |
1306 ; | |
1307 else if (t1n->ty == Tclass && t2n->ty == Tclass) | |
1308 { ClassDeclaration *cd1 = t1n->isClassHandle(); | |
1309 ClassDeclaration *cd2 = t2n->isClassHandle(); | |
1310 int offset; | |
1311 | |
1312 if (cd1->isBaseOf(cd2, &offset)) | |
1313 { | |
1314 if (offset) | |
1315 e2 = e2->castTo(sc, t); | |
1316 } | |
1317 else if (cd2->isBaseOf(cd1, &offset)) | |
1318 { | |
1319 t = t2; | |
1320 if (offset) | |
1321 e1 = e1->castTo(sc, t); | |
1322 } | |
1323 else | |
1324 goto Lincompatible; | |
1325 } | |
1326 else | |
1327 goto Lincompatible; | |
1328 } | |
1329 else if ((t1->ty == Tsarray || t1->ty == Tarray) && | |
1330 e2->op == TOKnull && t2->ty == Tpointer && t2->next->ty == Tvoid) | |
1331 { | |
1332 goto Lx1; | |
1333 } | |
1334 else if ((t2->ty == Tsarray || t2->ty == Tarray) && | |
1335 e1->op == TOKnull && t1->ty == Tpointer && t1->next->ty == Tvoid) | |
1336 { | |
1337 goto Lx2; | |
1338 } | |
1339 else if ((t1->ty == Tsarray || t1->ty == Tarray) && t1->implicitConvTo(t2)) | |
1340 { | |
1341 goto Lt2; | |
1342 } | |
1343 else if ((t2->ty == Tsarray || t2->ty == Tarray) && t2->implicitConvTo(t1)) | |
1344 { | |
1345 goto Lt1; | |
1346 } | |
1347 else if (t1->ty == Tclass || t2->ty == Tclass) | |
1348 { int i1; | |
1349 int i2; | |
1350 | |
1351 i1 = e2->implicitConvTo(t1); | |
1352 i2 = e1->implicitConvTo(t2); | |
1353 | |
1354 if (i1 && i2) | |
1355 { | |
1356 // We have the case of class vs. void*, so pick class | |
1357 if (t1->ty == Tpointer) | |
1358 i1 = 0; | |
1359 else if (t2->ty == Tpointer) | |
1360 i2 = 0; | |
1361 } | |
1362 | |
1363 if (i2) | |
1364 { | |
1365 goto Lt2; | |
1366 } | |
1367 else if (i1) | |
1368 { | |
1369 goto Lt1; | |
1370 } | |
1371 else | |
1372 goto Lincompatible; | |
1373 } | |
1374 else if ((e1->op == TOKstring || e1->op == TOKnull) && e1->implicitConvTo(t2)) | |
1375 { | |
1376 goto Lt2; | |
1377 } | |
1378 //else if (e2->op == TOKstring) { printf("test2\n"); } | |
1379 else if ((e2->op == TOKstring || e2->op == TOKnull) && e2->implicitConvTo(t1)) | |
1380 { | |
1381 goto Lt1; | |
1382 } | |
1383 else if (t1->ty == Tsarray && t2->ty == Tsarray && | |
1384 e2->implicitConvTo(t1->next->arrayOf())) | |
1385 { | |
1386 Lx1: | |
1387 t = t1->next->arrayOf(); | |
1388 e1 = e1->castTo(sc, t); | |
1389 e2 = e2->castTo(sc, t); | |
1390 } | |
1391 else if (t1->ty == Tsarray && t2->ty == Tsarray && | |
1392 e1->implicitConvTo(t2->next->arrayOf())) | |
1393 { | |
1394 Lx2: | |
1395 t = t2->next->arrayOf(); | |
1396 e1 = e1->castTo(sc, t); | |
1397 e2 = e2->castTo(sc, t); | |
1398 } | |
1399 else | |
1400 { | |
1401 Lincompatible: | |
1402 incompatibleTypes(); | |
1403 } | |
1404 Lret: | |
1405 if (!type) | |
1406 type = t; | |
1407 //dump(0); | |
1408 return this; | |
1409 | |
1410 | |
1411 Lt1: | |
1412 e2 = e2->castTo(sc, t1); | |
1413 t = t1; | |
1414 goto Lret; | |
1415 | |
1416 Lt2: | |
1417 e1 = e1->castTo(sc, t2); | |
1418 t = t2; | |
1419 goto Lret; | |
1420 } | |
1421 | |
1422 /*********************************** | |
1423 * Do integral promotions (convertchk). | |
1424 * Don't convert <array of> to <pointer to> | |
1425 */ | |
1426 | |
1427 Expression *Expression::integralPromotions(Scope *sc) | |
1428 { Expression *e; | |
1429 | |
1430 e = this; | |
1431 switch (type->toBasetype()->ty) | |
1432 { | |
1433 case Tvoid: | |
1434 error("void has no value"); | |
1435 break; | |
1436 | |
1437 case Tint8: | |
1438 case Tuns8: | |
1439 case Tint16: | |
1440 case Tuns16: | |
1441 case Tbit: | |
1442 case Tbool: | |
1443 case Tchar: | |
1444 case Twchar: | |
1445 e = e->castTo(sc, Type::tint32); | |
1446 break; | |
1447 | |
1448 case Tdchar: | |
1449 e = e->castTo(sc, Type::tuns32); | |
1450 break; | |
1451 } | |
1452 return e; | |
1453 } | |
1454 |