comparison dmd2/expression.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 783f67fbdf4a
comparison
equal deleted inserted replaced
757:2c730d530c98 758:f04dde6e882c
1
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 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 <ctype.h>
14 #include <assert.h>
15 #include <complex>
16 #include <math.h>
17
18 #if _WIN32 && __DMC__
19 extern "C" char * __cdecl __locale_decpoint;
20 #endif
21
22 #if __MINGW32__
23 #ifndef isnan
24 #define isnan _isnan
25 #endif
26 #endif
27
28 #ifdef __APPLE__
29 #ifndef isnan
30 int isnan(double);
31 #endif
32 #endif
33
34 #if IN_GCC
35 // Issues with using -include total.h (defines integer_t) and then complex.h fails...
36 #undef integer_t
37 #endif
38
39 #ifdef __APPLE__
40 #define integer_t dmd_integer_t
41 #endif
42
43 #if IN_GCC || IN_LLVM
44 #include "mem.h"
45 #elif _WIN32
46 #include "..\root\mem.h"
47 #elif POSIX
48 #include "../root/mem.h"
49 #endif
50
51 //#include "port.h"
52 #include "mtype.h"
53 #include "init.h"
54 #include "expression.h"
55 #include "template.h"
56 #include "utf.h"
57 #include "enum.h"
58 #include "scope.h"
59 #include "statement.h"
60 #include "declaration.h"
61 #include "aggregate.h"
62 #include "import.h"
63 #include "id.h"
64 #include "dsymbol.h"
65 #include "module.h"
66 #include "attrib.h"
67 #include "hdrgen.h"
68 #include "parse.h"
69
70 Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim);
71 Expression *expandVar(int result, VarDeclaration *v);
72
73 #define LOGSEMANTIC 0
74
75 /**********************************
76 * Set operator precedence for each operator.
77 */
78
79 // Operator precedence - greater values are higher precedence
80
81 enum PREC
82 {
83 PREC_zero,
84 PREC_expr,
85 PREC_assign,
86 PREC_cond,
87 PREC_oror,
88 PREC_andand,
89 PREC_or,
90 PREC_xor,
91 PREC_and,
92 PREC_equal,
93 PREC_rel,
94 PREC_shift,
95 PREC_add,
96 PREC_mul,
97 PREC_unary,
98 PREC_primary,
99 };
100
101 enum PREC precedence[TOKMAX];
102
103 void initPrecedence()
104 {
105 precedence[TOKdotvar] = PREC_primary;
106 precedence[TOKimport] = PREC_primary;
107 precedence[TOKidentifier] = PREC_primary;
108 precedence[TOKthis] = PREC_primary;
109 precedence[TOKsuper] = PREC_primary;
110 precedence[TOKint64] = PREC_primary;
111 precedence[TOKfloat64] = PREC_primary;
112 precedence[TOKnull] = PREC_primary;
113 precedence[TOKstring] = PREC_primary;
114 precedence[TOKarrayliteral] = PREC_primary;
115 precedence[TOKtypedot] = PREC_primary;
116 precedence[TOKtypeid] = PREC_primary;
117 precedence[TOKis] = PREC_primary;
118 precedence[TOKassert] = PREC_primary;
119 precedence[TOKfunction] = PREC_primary;
120 precedence[TOKvar] = PREC_primary;
121 #if DMDV2
122 precedence[TOKdefault] = PREC_primary;
123 #endif
124
125 // post
126 precedence[TOKdotti] = PREC_primary;
127 precedence[TOKdot] = PREC_primary;
128 // precedence[TOKarrow] = PREC_primary;
129 precedence[TOKplusplus] = PREC_primary;
130 precedence[TOKminusminus] = PREC_primary;
131 precedence[TOKcall] = PREC_primary;
132 precedence[TOKslice] = PREC_primary;
133 precedence[TOKarray] = PREC_primary;
134
135 precedence[TOKaddress] = PREC_unary;
136 precedence[TOKstar] = PREC_unary;
137 precedence[TOKneg] = PREC_unary;
138 precedence[TOKuadd] = PREC_unary;
139 precedence[TOKnot] = PREC_unary;
140 precedence[TOKtobool] = PREC_add;
141 precedence[TOKtilde] = PREC_unary;
142 precedence[TOKdelete] = PREC_unary;
143 precedence[TOKnew] = PREC_unary;
144 precedence[TOKcast] = PREC_unary;
145
146 precedence[TOKmul] = PREC_mul;
147 precedence[TOKdiv] = PREC_mul;
148 precedence[TOKmod] = PREC_mul;
149
150 precedence[TOKadd] = PREC_add;
151 precedence[TOKmin] = PREC_add;
152 precedence[TOKcat] = PREC_add;
153
154 precedence[TOKshl] = PREC_shift;
155 precedence[TOKshr] = PREC_shift;
156 precedence[TOKushr] = PREC_shift;
157
158 precedence[TOKlt] = PREC_rel;
159 precedence[TOKle] = PREC_rel;
160 precedence[TOKgt] = PREC_rel;
161 precedence[TOKge] = PREC_rel;
162 precedence[TOKunord] = PREC_rel;
163 precedence[TOKlg] = PREC_rel;
164 precedence[TOKleg] = PREC_rel;
165 precedence[TOKule] = PREC_rel;
166 precedence[TOKul] = PREC_rel;
167 precedence[TOKuge] = PREC_rel;
168 precedence[TOKug] = PREC_rel;
169 precedence[TOKue] = PREC_rel;
170 precedence[TOKin] = PREC_rel;
171
172 precedence[TOKequal] = PREC_equal;
173 precedence[TOKnotequal] = PREC_equal;
174 precedence[TOKidentity] = PREC_equal;
175 precedence[TOKnotidentity] = PREC_equal;
176
177 precedence[TOKand] = PREC_and;
178
179 precedence[TOKxor] = PREC_xor;
180
181 precedence[TOKor] = PREC_or;
182
183 precedence[TOKandand] = PREC_andand;
184
185 precedence[TOKoror] = PREC_oror;
186
187 precedence[TOKquestion] = PREC_cond;
188
189 precedence[TOKassign] = PREC_assign;
190 precedence[TOKconstruct] = PREC_assign;
191 precedence[TOKblit] = PREC_assign;
192 precedence[TOKaddass] = PREC_assign;
193 precedence[TOKminass] = PREC_assign;
194 precedence[TOKcatass] = PREC_assign;
195 precedence[TOKmulass] = PREC_assign;
196 precedence[TOKdivass] = PREC_assign;
197 precedence[TOKmodass] = PREC_assign;
198 precedence[TOKshlass] = PREC_assign;
199 precedence[TOKshrass] = PREC_assign;
200 precedence[TOKushrass] = PREC_assign;
201 precedence[TOKandass] = PREC_assign;
202 precedence[TOKorass] = PREC_assign;
203 precedence[TOKxorass] = PREC_assign;
204
205 precedence[TOKcomma] = PREC_expr;
206 }
207
208 /*************************************************************
209 * Given var, we need to get the
210 * right 'this' pointer if var is in an outer class, but our
211 * existing 'this' pointer is in an inner class.
212 * Input:
213 * e1 existing 'this'
214 * ad struct or class we need the correct 'this' for
215 * var the specific member of ad we're accessing
216 */
217
218 Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
219 Expression *e1, Declaration *var)
220 {
221 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
222 L1:
223 Type *t = e1->type->toBasetype();
224 //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
225
226 /* If e1 is not the 'this' pointer for ad
227 */
228 if (ad &&
229 !(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
230 ((TypeStruct *)t->nextOf())->sym == ad)
231 &&
232 !(t->ty == Tstruct &&
233 ((TypeStruct *)t)->sym == ad)
234 )
235 {
236 ClassDeclaration *cd = ad->isClassDeclaration();
237 ClassDeclaration *tcd = t->isClassHandle();
238
239 /* e1 is the right this if ad is a base class of e1
240 */
241 if (!cd || !tcd ||
242 !(tcd == cd || cd->isBaseOf(tcd, NULL))
243 )
244 {
245 /* Only classes can be inner classes with an 'outer'
246 * member pointing to the enclosing class instance
247 */
248 if (tcd && tcd->isNested())
249 { /* e1 is the 'this' pointer for an inner class: tcd.
250 * Rewrite it as the 'this' pointer for the outer class.
251 */
252
253 e1 = new DotVarExp(loc, e1, tcd->vthis);
254 e1->type = tcd->vthis->type;
255 // Do not call checkNestedRef()
256 //e1 = e1->semantic(sc);
257
258 // Skip up over nested functions, and get the enclosing
259 // class type.
260 int n = 0;
261 Dsymbol *s;
262 for (s = tcd->toParent();
263 s && s->isFuncDeclaration();
264 s = s->toParent())
265 { FuncDeclaration *f = s->isFuncDeclaration();
266 if (f->vthis)
267 {
268 //printf("rewriting e1 to %s's this\n", f->toChars());
269 n++;
270
271 // LDC seems dmd misses it sometimes here :/
272 #if DMDV2
273 // FIXME!!!!
274 #else
275 f->vthis->nestedref = 1;
276 #endif
277
278 e1 = new VarExp(loc, f->vthis);
279 }
280 }
281 if (s && s->isClassDeclaration())
282 { e1->type = s->isClassDeclaration()->type;
283 if (n > 1)
284 e1 = e1->semantic(sc);
285 }
286 else
287 e1 = e1->semantic(sc);
288 goto L1;
289 }
290 /* Can't find a path from e1 to ad
291 */
292 e1->error("this for %s needs to be type %s not type %s",
293 var->toChars(), ad->toChars(), t->toChars());
294 }
295 }
296 return e1;
297 }
298
299 /*****************************************
300 * Determine if 'this' is available.
301 * If it is, return the FuncDeclaration that has it.
302 */
303
304 FuncDeclaration *hasThis(Scope *sc)
305 { FuncDeclaration *fd;
306 FuncDeclaration *fdthis;
307
308 //printf("hasThis()\n");
309 fdthis = sc->parent->isFuncDeclaration();
310 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : "");
311
312 // Go upwards until we find the enclosing member function
313 fd = fdthis;
314 while (1)
315 {
316 if (!fd)
317 {
318 goto Lno;
319 }
320 if (!fd->isNested())
321 break;
322
323 Dsymbol *parent = fd->parent;
324 while (parent)
325 {
326 TemplateInstance *ti = parent->isTemplateInstance();
327 if (ti)
328 parent = ti->parent;
329 else
330 break;
331 }
332
333 fd = fd->parent->isFuncDeclaration();
334 }
335
336 if (!fd->isThis())
337 { //printf("test '%s'\n", fd->toChars());
338 goto Lno;
339 }
340
341 assert(fd->vthis);
342 return fd;
343
344 Lno:
345 return NULL; // don't have 'this' available
346 }
347
348
349 /***************************************
350 * Pull out any properties.
351 */
352
353 Expression *resolveProperties(Scope *sc, Expression *e)
354 {
355 //printf("resolveProperties(%s)\n", e->toChars());
356 if (e->type)
357 {
358 Type *t = e->type->toBasetype();
359
360 if (t->ty == Tfunction || e->op == TOKoverloadset)
361 {
362 e = new CallExp(e->loc, e);
363 e = e->semantic(sc);
364 }
365
366 /* Look for e being a lazy parameter; rewrite as delegate call
367 */
368 else if (e->op == TOKvar)
369 { VarExp *ve = (VarExp *)e;
370
371 if (ve->var->storage_class & STClazy)
372 {
373 e = new CallExp(e->loc, e);
374 e = e->semantic(sc);
375 }
376 }
377
378 else if (e->op == TOKdotexp)
379 {
380 e->error("expression has no value");
381 }
382
383 }
384 return e;
385 }
386
387 /******************************
388 * Perform semantic() on an array of Expressions.
389 */
390
391 void arrayExpressionSemantic(Expressions *exps, Scope *sc)
392 {
393 if (exps)
394 {
395 for (size_t i = 0; i < exps->dim; i++)
396 { Expression *e = (Expression *)exps->data[i];
397
398 e = e->semantic(sc);
399 exps->data[i] = (void *)e;
400 }
401 }
402 }
403
404
405 /******************************
406 * Perform canThrow() on an array of Expressions.
407 */
408
409 #if DMDV2
410 int arrayExpressionCanThrow(Expressions *exps)
411 {
412 if (exps)
413 {
414 for (size_t i = 0; i < exps->dim; i++)
415 { Expression *e = (Expression *)exps->data[i];
416 if (e && e->canThrow())
417 return 1;
418 }
419 }
420 return 0;
421 }
422 #endif
423
424 /****************************************
425 * Expand tuples.
426 */
427
428 void expandTuples(Expressions *exps)
429 {
430 //printf("expandTuples()\n");
431 if (exps)
432 {
433 for (size_t i = 0; i < exps->dim; i++)
434 { Expression *arg = (Expression *)exps->data[i];
435 if (!arg)
436 continue;
437
438 // Look for tuple with 0 members
439 if (arg->op == TOKtype)
440 { TypeExp *e = (TypeExp *)arg;
441 if (e->type->toBasetype()->ty == Ttuple)
442 { TypeTuple *tt = (TypeTuple *)e->type->toBasetype();
443
444 if (!tt->arguments || tt->arguments->dim == 0)
445 {
446 exps->remove(i);
447 if (i == exps->dim)
448 return;
449 i--;
450 continue;
451 }
452 }
453 }
454
455 // Inline expand all the tuples
456 while (arg->op == TOKtuple)
457 { TupleExp *te = (TupleExp *)arg;
458
459 exps->remove(i); // remove arg
460 exps->insert(i, te->exps); // replace with tuple contents
461 if (i == exps->dim)
462 return; // empty tuple, no more arguments
463 arg = (Expression *)exps->data[i];
464 }
465 }
466 }
467 }
468
469 /****************************************
470 * Preprocess arguments to function.
471 */
472
473 void preFunctionArguments(Loc loc, Scope *sc, Expressions *exps)
474 {
475 if (exps)
476 {
477 expandTuples(exps);
478
479 for (size_t i = 0; i < exps->dim; i++)
480 { Expression *arg = (Expression *)exps->data[i];
481
482 if (!arg->type)
483 {
484 #ifdef DEBUG
485 if (!global.gag)
486 printf("1: \n");
487 #endif
488 arg->error("%s is not an expression", arg->toChars());
489 arg = new IntegerExp(arg->loc, 0, Type::tint32);
490 }
491
492 arg = resolveProperties(sc, arg);
493 exps->data[i] = (void *) arg;
494
495 //arg->rvalue();
496 #if 0
497 if (arg->type->ty == Tfunction)
498 {
499 arg = new AddrExp(arg->loc, arg);
500 arg = arg->semantic(sc);
501 exps->data[i] = (void *) arg;
502 }
503 #endif
504 }
505 }
506 }
507
508 /*********************************************
509 * Call copy constructor for struct value argument.
510 */
511 #if DMDV2
512 Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
513 {
514 Type *tb = e->type->toBasetype();
515 assert(tb->ty == Tstruct);
516 StructDeclaration *sd = ((TypeStruct *)tb)->sym;
517 if (sd->cpctor)
518 {
519 /* Create a variable tmp, and replace the argument e with:
520 * (tmp = e),tmp
521 * and let AssignExp() handle the construction.
522 * This is not the most efficent, ideally tmp would be constructed
523 * directly onto the stack.
524 */
525 Identifier *idtmp = Lexer::uniqueId("__tmp");
526 VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e));
527 Expression *ae = new DeclarationExp(loc, tmp);
528 e = new CommaExp(loc, ae, new VarExp(loc, tmp));
529 e = e->semantic(sc);
530 }
531 return e;
532 }
533 #endif
534
535 /****************************************
536 * Now that we know the exact type of the function we're calling,
537 * the arguments[] need to be adjusted:
538 * 1. implicitly convert argument to the corresponding parameter type
539 * 2. add default arguments for any missing arguments
540 * 3. do default promotions on arguments corresponding to ...
541 * 4. add hidden _arguments[] argument
542 * 5. call copy constructor for struct value arguments
543 */
544
545 void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments)
546 {
547 unsigned n;
548
549 //printf("functionArguments()\n");
550 assert(arguments);
551 size_t nargs = arguments ? arguments->dim : 0;
552 size_t nparams = Argument::dim(tf->parameters);
553
554 if (nargs > nparams && tf->varargs == 0)
555 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
556
557 n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
558
559 int done = 0;
560 for (size_t i = 0; i < n; i++)
561 {
562 Expression *arg;
563
564 if (i < nargs)
565 arg = (Expression *)arguments->data[i];
566 else
567 arg = NULL;
568 Type *tb;
569
570 if (i < nparams)
571 {
572 Argument *p = Argument::getNth(tf->parameters, i);
573
574 if (!arg)
575 {
576 if (!p->defaultArg)
577 {
578 if (tf->varargs == 2 && i + 1 == nparams)
579 goto L2;
580 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
581 break;
582 }
583 arg = p->defaultArg;
584 #if DMDV2
585 if (arg->op == TOKdefault)
586 { DefaultInitExp *de = (DefaultInitExp *)arg;
587 arg = de->resolve(loc, sc);
588 }
589 else
590 #endif
591 arg = arg->copy();
592 arguments->push(arg);
593 nargs++;
594 }
595
596 if (tf->varargs == 2 && i + 1 == nparams)
597 {
598 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
599 if (arg->implicitConvTo(p->type))
600 {
601 if (nargs != nparams)
602 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
603 goto L1;
604 }
605 L2:
606 Type *tb = p->type->toBasetype();
607 Type *tret = p->isLazyArray();
608 switch (tb->ty)
609 {
610 case Tsarray:
611 case Tarray:
612 { // Create a static array variable v of type arg->type
613 #ifdef IN_GCC
614 /* GCC 4.0 does not like zero length arrays used like
615 this; pass a null array value instead. Could also
616 just make a one-element array. */
617 if (nargs - i == 0)
618 {
619 arg = new NullExp(loc);
620 break;
621 }
622 #endif
623 Identifier *id = Lexer::uniqueId("__arrayArg");
624 Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i));
625 t = t->semantic(loc, sc);
626 VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc));
627 v->semantic(sc);
628 v->parent = sc->parent;
629 //sc->insert(v);
630
631 Expression *c = new DeclarationExp(0, v);
632 c->type = v->type;
633
634 for (size_t u = i; u < nargs; u++)
635 { Expression *a = (Expression *)arguments->data[u];
636 if (tret && !((TypeArray *)tb)->next->equals(a->type))
637 a = a->toDelegate(sc, tret);
638
639 Expression *e = new VarExp(loc, v);
640 e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
641 AssignExp *ae = new AssignExp(loc, e, a);
642 ae->op = TOKconstruct;
643 if (c)
644 c = new CommaExp(loc, c, ae);
645 else
646 c = ae;
647 }
648 arg = new VarExp(loc, v);
649 if (c)
650 arg = new CommaExp(loc, c, arg);
651 break;
652 }
653 case Tclass:
654 { /* Set arg to be:
655 * new Tclass(arg0, arg1, ..., argn)
656 */
657 Expressions *args = new Expressions();
658 args->setDim(nargs - i);
659 for (size_t u = i; u < nargs; u++)
660 args->data[u - i] = arguments->data[u];
661 arg = new NewExp(loc, NULL, NULL, p->type, args);
662 break;
663 }
664 default:
665 if (!arg)
666 { error(loc, "not enough arguments");
667 return;
668 }
669 break;
670 }
671 arg = arg->semantic(sc);
672 //printf("\targ = '%s'\n", arg->toChars());
673 arguments->setDim(i + 1);
674 done = 1;
675 }
676
677 L1:
678 if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
679 {
680 if (p->type != arg->type)
681 {
682 //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
683 arg = arg->implicitCastTo(sc, p->type);
684 arg = arg->optimize(WANTvalue);
685 }
686 }
687 if (p->storageClass & STCref)
688 {
689 arg = arg->toLvalue(sc, arg);
690 }
691 else if (p->storageClass & STCout)
692 {
693 arg = arg->modifiableLvalue(sc, arg);
694 }
695
696 tb = arg->type->toBasetype();
697
698 // LDC we don't want this!
699 #if !IN_LLVM
700 // Convert static arrays to pointers
701 if (tb->ty == Tsarray)
702 {
703 arg = arg->checkToPointer();
704 }
705 #endif
706
707
708 if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
709 {
710 arg = callCpCtor(loc, sc, arg);
711 }
712
713 // Convert lazy argument to a delegate
714 if (p->storageClass & STClazy)
715 {
716 arg = arg->toDelegate(sc, p->type);
717 }
718 }
719 else
720 {
721
722 // If not D linkage, do promotions
723 // LDC: don't do promotions on intrinsics
724 if (tf->linkage != LINKd && tf->linkage != LINKintrinsic)
725 {
726 // Promote bytes, words, etc., to ints
727 arg = arg->integralPromotions(sc);
728
729 // Promote floats to doubles
730 switch (arg->type->ty)
731 {
732 case Tfloat32:
733 arg = arg->castTo(sc, Type::tfloat64);
734 break;
735
736 case Timaginary32:
737 arg = arg->castTo(sc, Type::timaginary64);
738 break;
739 }
740 }
741
742 // Convert static arrays to dynamic arrays
743 tb = arg->type->toBasetype();
744 if (tb->ty == Tsarray)
745 { TypeSArray *ts = (TypeSArray *)tb;
746 Type *ta = ts->next->arrayOf();
747 if (ts->size(arg->loc) == 0)
748 { arg = new NullExp(arg->loc);
749 arg->type = ta;
750 }
751 else
752 arg = arg->castTo(sc, ta);
753 }
754 #if DMDV2
755 if (tb->ty == Tstruct)
756 {
757 arg = callCpCtor(loc, sc, arg);
758 }
759
760 // Give error for overloaded function addresses
761 if (arg->op == TOKsymoff)
762 { SymOffExp *se = (SymOffExp *)arg;
763 if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
764 arg->error("function %s is overloaded", arg->toChars());
765 }
766 #endif
767 arg->rvalue();
768 }
769 arg = arg->optimize(WANTvalue);
770 arguments->data[i] = (void *) arg;
771 if (done)
772 break;
773 }
774
775 #if !IN_LLVM
776 // If D linkage and variadic, add _arguments[] as first argument
777 if (tf->linkage == LINKd && tf->varargs == 1)
778 {
779 Expression *e;
780
781 e = createTypeInfoArray(sc, (Expression **)&arguments->data[nparams],
782 arguments->dim - nparams);
783 arguments->insert(0, e);
784 }
785 #endif
786 }
787
788 /**************************************************
789 * Write expression out to buf, but wrap it
790 * in ( ) if its precedence is less than pr.
791 */
792
793 void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr)
794 {
795 //if (precedence[e->op] == 0) e->dump(0);
796 if (precedence[e->op] < pr)
797 {
798 buf->writeByte('(');
799 e->toCBuffer(buf, hgs);
800 buf->writeByte(')');
801 }
802 else
803 e->toCBuffer(buf, hgs);
804 }
805
806 /**************************************************
807 * Write out argument list to buf.
808 */
809
810 void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
811 {
812 if (arguments)
813 {
814 for (size_t i = 0; i < arguments->dim; i++)
815 { Expression *arg = (Expression *)arguments->data[i];
816
817 if (arg)
818 { if (i)
819 buf->writeByte(',');
820 expToCBuffer(buf, hgs, arg, PREC_assign);
821 }
822 }
823 }
824 }
825
826 /**************************************************
827 * Write out argument types to buf.
828 */
829
830 void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
831 {
832 if (arguments)
833 { OutBuffer argbuf;
834
835 for (size_t i = 0; i < arguments->dim; i++)
836 { Expression *arg = (Expression *)arguments->data[i];
837
838 if (i)
839 buf->writeByte(',');
840 argbuf.reset();
841 arg->type->toCBuffer2(&argbuf, hgs, 0);
842 buf->write(&argbuf);
843 }
844 }
845 }
846
847 /******************************** Expression **************************/
848
849 Expression::Expression(Loc loc, enum TOK op, int size)
850 : loc(loc)
851 {
852 //printf("Expression::Expression(op = %d) this = %p\n", op, this);
853 this->loc = loc;
854 this->op = op;
855 this->size = size;
856 type = NULL;
857 }
858
859 Expression *Expression::syntaxCopy()
860 {
861 //printf("Expression::syntaxCopy()\n");
862 //dump(0);
863 return copy();
864 }
865
866 /*********************************
867 * Does *not* do a deep copy.
868 */
869
870 Expression *Expression::copy()
871 {
872 Expression *e;
873 if (!size)
874 {
875 #ifdef DEBUG
876 fprintf(stdmsg, "No expression copy for: %s\n", toChars());
877 printf("op = %d\n", op);
878 dump(0);
879 #endif
880 assert(0);
881 }
882 e = (Expression *)mem.malloc(size);
883 //printf("Expression::copy(op = %d) e = %p\n", op, e);
884 return (Expression *)memcpy(e, this, size);
885 }
886
887 /**************************
888 * Semantically analyze Expression.
889 * Determine types, fold constants, etc.
890 */
891
892 Expression *Expression::semantic(Scope *sc)
893 {
894 #if LOGSEMANTIC
895 printf("Expression::semantic() %s\n", toChars());
896 #endif
897 if (type)
898 type = type->semantic(loc, sc);
899 else
900 type = Type::tvoid;
901 return this;
902 }
903
904 void Expression::print()
905 {
906 fprintf(stdmsg, "%s\n", toChars());
907 fflush(stdmsg);
908 }
909
910 char *Expression::toChars()
911 { OutBuffer *buf;
912 HdrGenState hgs;
913
914 memset(&hgs, 0, sizeof(hgs));
915 buf = new OutBuffer();
916 toCBuffer(buf, &hgs);
917 return buf->toChars();
918 }
919
920 void Expression::error(const char *format, ...)
921 {
922 va_list ap;
923 va_start(ap, format);
924 ::verror(loc, format, ap);
925 va_end( ap );
926 }
927
928 void Expression::rvalue()
929 {
930 if (type && type->toBasetype()->ty == Tvoid)
931 { error("expression %s is void and has no value", toChars());
932 #if 0
933 dump(0);
934 halt();
935 #endif
936 type = Type::tint32;
937 }
938 }
939
940 Expression *Expression::combine(Expression *e1, Expression *e2)
941 {
942 if (e1)
943 {
944 if (e2)
945 {
946 e1 = new CommaExp(e1->loc, e1, e2);
947 e1->type = e2->type;
948 }
949 }
950 else
951 e1 = e2;
952 return e1;
953 }
954
955 integer_t Expression::toInteger()
956 {
957 //printf("Expression %s\n", Token::toChars(op));
958 error("Integer constant expression expected instead of %s", toChars());
959 return 0;
960 }
961
962 uinteger_t Expression::toUInteger()
963 {
964 //printf("Expression %s\n", Token::toChars(op));
965 return (uinteger_t)toInteger();
966 }
967
968 real_t Expression::toReal()
969 {
970 error("Floating point constant expression expected instead of %s", toChars());
971 return 0;
972 }
973
974 real_t Expression::toImaginary()
975 {
976 error("Floating point constant expression expected instead of %s", toChars());
977 return 0;
978 }
979
980 complex_t Expression::toComplex()
981 {
982 error("Floating point constant expression expected instead of %s", toChars());
983 #ifdef IN_GCC
984 return complex_t(real_t(0)); // %% nicer
985 #else
986 return 0;
987 #endif
988 }
989
990 void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
991 {
992 buf->writestring(Token::toChars(op));
993 }
994
995 void Expression::toMangleBuffer(OutBuffer *buf)
996 {
997 error("expression %s is not a valid template value argument", toChars());
998 }
999
1000 /***************************************
1001 * Return !=0 if expression is an lvalue.
1002 */
1003
1004 int Expression::isLvalue()
1005 {
1006 return 0;
1007 }
1008
1009 /*******************************
1010 * Give error if we're not an lvalue.
1011 * If we can, convert expression to be an lvalue.
1012 */
1013
1014 Expression *Expression::toLvalue(Scope *sc, Expression *e)
1015 {
1016 if (!e)
1017 e = this;
1018 else if (!loc.filename)
1019 loc = e->loc;
1020 error("%s is not an lvalue", e->toChars());
1021 return this;
1022 }
1023
1024 Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
1025 {
1026 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
1027
1028 // See if this expression is a modifiable lvalue (i.e. not const)
1029 if (type && (!type->isMutable() || !type->isAssignable()))
1030 error("%s is not mutable", e->toChars());
1031
1032 return toLvalue(sc, e);
1033 }
1034
1035 /************************************
1036 * Detect cases where pointers to the stack can 'escape' the
1037 * lifetime of the stack frame.
1038 */
1039
1040 void Expression::checkEscape()
1041 {
1042 }
1043
1044 void Expression::checkScalar()
1045 {
1046 if (!type->isscalar())
1047 error("'%s' is not a scalar, it is a %s", toChars(), type->toChars());
1048 }
1049
1050 void Expression::checkNoBool()
1051 {
1052 if (type->toBasetype()->ty == Tbool)
1053 error("operation not allowed on bool '%s'", toChars());
1054 }
1055
1056 Expression *Expression::checkIntegral()
1057 {
1058 if (!type->isintegral())
1059 { error("'%s' is not of integral type, it is a %s", toChars(), type->toChars());
1060 return new IntegerExp(0);
1061 }
1062 return this;
1063 }
1064
1065 Expression *Expression::checkArithmetic()
1066 {
1067 if (!type->isintegral() && !type->isfloating())
1068 { error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
1069 return new IntegerExp(0);
1070 }
1071 return this;
1072 }
1073
1074 void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
1075 {
1076 s->checkDeprecated(loc, sc);
1077 }
1078
1079 /********************************
1080 * Check for expressions that have no use.
1081 * Input:
1082 * flag 0 not going to use the result, so issue error message if no
1083 * side effects
1084 * 1 the result of the expression is used, but still check
1085 * for useless subexpressions
1086 * 2 do not issue error messages, just return !=0 if expression
1087 * has side effects
1088 */
1089
1090 int Expression::checkSideEffect(int flag)
1091 {
1092 if (flag == 0)
1093 { if (op == TOKimport)
1094 {
1095 error("%s has no effect", toChars());
1096 }
1097 else
1098 error("%s has no effect in expression (%s)",
1099 Token::toChars(op), toChars());
1100 }
1101 return 0;
1102 }
1103
1104 /*****************************
1105 * Check that expression can be tested for true or false.
1106 */
1107
1108 Expression *Expression::checkToBoolean()
1109 {
1110 // Default is 'yes' - do nothing
1111
1112 #ifdef DEBUG
1113 if (!type)
1114 dump(0);
1115 #endif
1116
1117 if (!type->checkBoolean())
1118 {
1119 error("expression %s of type %s does not have a boolean value", toChars(), type->toChars());
1120 }
1121 return this;
1122 }
1123
1124 /****************************
1125 */
1126
1127 Expression *Expression::checkToPointer()
1128 {
1129 Expression *e;
1130 Type *tb;
1131
1132 //printf("Expression::checkToPointer()\n");
1133 e = this;
1134
1135 // If C static array, convert to pointer
1136 tb = type->toBasetype();
1137 if (tb->ty == Tsarray)
1138 { TypeSArray *ts = (TypeSArray *)tb;
1139 if (ts->size(loc) == 0)
1140 e = new NullExp(loc);
1141 else
1142 e = new AddrExp(loc, this);
1143 e->type = ts->next->pointerTo();
1144 }
1145 return e;
1146 }
1147
1148 /******************************
1149 * Take address of expression.
1150 */
1151
1152 Expression *Expression::addressOf(Scope *sc)
1153 {
1154 Expression *e;
1155
1156 //printf("Expression::addressOf()\n");
1157 e = toLvalue(sc, NULL);
1158 e = new AddrExp(loc, e);
1159 e->type = type->pointerTo();
1160 return e;
1161 }
1162
1163 /******************************
1164 * If this is a reference, dereference it.
1165 */
1166
1167 Expression *Expression::deref()
1168 {
1169 //printf("Expression::deref()\n");
1170 if (type->ty == Treference)
1171 { Expression *e;
1172
1173 e = new PtrExp(loc, this);
1174 e->type = ((TypeReference *)type)->next;
1175 return e;
1176 }
1177 return this;
1178 }
1179
1180 /********************************
1181 * Does this expression statically evaluate to a boolean TRUE or FALSE?
1182 */
1183
1184 int Expression::isBool(int result)
1185 {
1186 return FALSE;
1187 }
1188
1189 /********************************
1190 * Does this expression result in either a 1 or a 0?
1191 */
1192
1193 int Expression::isBit()
1194 {
1195 return FALSE;
1196 }
1197
1198 /********************************
1199 * Can this expression throw an exception?
1200 * Valid only after semantic() pass.
1201 */
1202
1203 int Expression::canThrow()
1204 {
1205 return FALSE;
1206 }
1207
1208
1209
1210 Expressions *Expression::arraySyntaxCopy(Expressions *exps)
1211 { Expressions *a = NULL;
1212
1213 if (exps)
1214 {
1215 a = new Expressions();
1216 a->setDim(exps->dim);
1217 for (int i = 0; i < a->dim; i++)
1218 { Expression *e = (Expression *)exps->data[i];
1219
1220 e = e->syntaxCopy();
1221 a->data[i] = e;
1222 }
1223 }
1224 return a;
1225 }
1226
1227 /******************************** IntegerExp **************************/
1228
1229 IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type)
1230 : Expression(loc, TOKint64, sizeof(IntegerExp))
1231 {
1232 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
1233 if (type && !type->isscalar())
1234 {
1235 //printf("%s, loc = %d\n", toChars(), loc.linnum);
1236 error("integral constant must be scalar type, not %s", type->toChars());
1237 type = Type::terror;
1238 }
1239 this->type = type;
1240 this->value = value;
1241 }
1242
1243 IntegerExp::IntegerExp(integer_t value)
1244 : Expression(0, TOKint64, sizeof(IntegerExp))
1245 {
1246 this->type = Type::tint32;
1247 this->value = value;
1248 }
1249
1250 int IntegerExp::equals(Object *o)
1251 { IntegerExp *ne;
1252
1253 if (this == o ||
1254 (((Expression *)o)->op == TOKint64 &&
1255 ((ne = (IntegerExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
1256 value == ne->value))
1257 return 1;
1258 return 0;
1259 }
1260
1261 char *IntegerExp::toChars()
1262 {
1263 #if 1
1264 return Expression::toChars();
1265 #else
1266 static char buffer[sizeof(value) * 3 + 1];
1267 sprintf(buffer, "%lld", value);
1268 return buffer;
1269 #endif
1270 }
1271
1272 integer_t IntegerExp::toInteger()
1273 { Type *t;
1274
1275 t = type;
1276 while (t)
1277 {
1278 switch (t->ty)
1279 {
1280 case Tbit:
1281 case Tbool: value = (value != 0); break;
1282 case Tint8: value = (d_int8) value; break;
1283 case Tchar:
1284 case Tuns8: value = (d_uns8) value; break;
1285 case Tint16: value = (d_int16) value; break;
1286 case Twchar:
1287 case Tuns16: value = (d_uns16) value; break;
1288 case Tint32: value = (d_int32) value; break;
1289 case Tpointer:
1290 case Tdchar:
1291 case Tuns32: value = (d_uns32) value; break;
1292 case Tint64: value = (d_int64) value; break;
1293 case Tuns64: value = (d_uns64) value; break;
1294
1295 case Tenum:
1296 {
1297 TypeEnum *te = (TypeEnum *)t;
1298 t = te->sym->memtype;
1299 continue;
1300 }
1301
1302 case Ttypedef:
1303 {
1304 TypeTypedef *tt = (TypeTypedef *)t;
1305 t = tt->sym->basetype;
1306 continue;
1307 }
1308
1309 default:
1310 /* This can happen if errors, such as
1311 * the type is painted on like in fromConstInitializer().
1312 */
1313 if (!global.errors)
1314 { type->print();
1315 assert(0);
1316 }
1317 break;
1318 }
1319 break;
1320 }
1321 return value;
1322 }
1323
1324 real_t IntegerExp::toReal()
1325 {
1326 Type *t;
1327
1328 toInteger();
1329 t = type->toBasetype();
1330 if (t->ty == Tuns64)
1331 return (real_t)(d_uns64)value;
1332 else
1333 return (real_t)(d_int64)value;
1334 }
1335
1336 real_t IntegerExp::toImaginary()
1337 {
1338 return (real_t) 0;
1339 }
1340
1341 complex_t IntegerExp::toComplex()
1342 {
1343 return toReal();
1344 }
1345
1346 int IntegerExp::isBool(int result)
1347 {
1348 return result ? value != 0 : value == 0;
1349 }
1350
1351 Expression *IntegerExp::semantic(Scope *sc)
1352 {
1353 if (!type)
1354 {
1355 // Determine what the type of this number is
1356 integer_t number = value;
1357
1358 if (number & 0x8000000000000000LL)
1359 type = Type::tuns64;
1360 else if (number & 0xFFFFFFFF80000000LL)
1361 type = Type::tint64;
1362 else
1363 type = Type::tint32;
1364 }
1365 else
1366 { if (!type->deco)
1367 type = type->semantic(loc, sc);
1368 }
1369 return this;
1370 }
1371
1372 Expression *IntegerExp::toLvalue(Scope *sc, Expression *e)
1373 {
1374 if (!e)
1375 e = this;
1376 else if (!loc.filename)
1377 loc = e->loc;
1378 e->error("constant %s is not an lvalue", e->toChars());
1379 return this;
1380 }
1381
1382 void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1383 {
1384 integer_t v = toInteger();
1385
1386 if (type)
1387 { Type *t = type;
1388
1389 L1:
1390 switch (t->ty)
1391 {
1392 case Tenum:
1393 { TypeEnum *te = (TypeEnum *)t;
1394 buf->printf("cast(%s)", te->sym->toChars());
1395 t = te->sym->memtype;
1396 goto L1;
1397 }
1398
1399 case Ttypedef:
1400 { TypeTypedef *tt = (TypeTypedef *)t;
1401 buf->printf("cast(%s)", tt->sym->toChars());
1402 t = tt->sym->basetype;
1403 goto L1;
1404 }
1405
1406 case Twchar: // BUG: need to cast(wchar)
1407 case Tdchar: // BUG: need to cast(dchar)
1408 if ((uinteger_t)v > 0xFF)
1409 {
1410 buf->printf("'\\U%08x'", v);
1411 break;
1412 }
1413 case Tchar:
1414 if (v == '\'')
1415 buf->writestring("'\\''");
1416 else if (isprint(v) && v != '\\')
1417 buf->printf("'%c'", (int)v);
1418 else
1419 buf->printf("'\\x%02x'", (int)v);
1420 break;
1421
1422 case Tint8:
1423 buf->writestring("cast(byte)");
1424 goto L2;
1425
1426 case Tint16:
1427 buf->writestring("cast(short)");
1428 goto L2;
1429
1430 case Tint32:
1431 L2:
1432 buf->printf("%d", (int)v);
1433 break;
1434
1435 case Tuns8:
1436 buf->writestring("cast(ubyte)");
1437 goto L3;
1438
1439 case Tuns16:
1440 buf->writestring("cast(ushort)");
1441 goto L3;
1442
1443 case Tuns32:
1444 L3:
1445 buf->printf("%du", (unsigned)v);
1446 break;
1447
1448 case Tint64:
1449 buf->printf("%lldL", v);
1450 break;
1451
1452 case Tuns64:
1453 buf->printf("%lluLU", v);
1454 break;
1455
1456 case Tbit:
1457 case Tbool:
1458 buf->writestring((char *)(v ? "true" : "false"));
1459 break;
1460
1461 case Tpointer:
1462 buf->writestring("cast(");
1463 buf->writestring(t->toChars());
1464 buf->writeByte(')');
1465 goto L3;
1466
1467 default:
1468 /* This can happen if errors, such as
1469 * the type is painted on like in fromConstInitializer().
1470 */
1471 if (!global.errors)
1472 {
1473 #ifdef DEBUG
1474 t->print();
1475 #endif
1476 assert(0);
1477 }
1478 break;
1479 }
1480 }
1481 else if (v & 0x8000000000000000LL)
1482 buf->printf("0x%llx", v);
1483 else
1484 buf->printf("%lld", v);
1485 }
1486
1487 void IntegerExp::toMangleBuffer(OutBuffer *buf)
1488 {
1489 if ((sinteger_t)value < 0)
1490 buf->printf("N%lld", -value);
1491 else
1492 buf->printf("%lld", value);
1493 }
1494
1495 /******************************** RealExp **************************/
1496
1497 RealExp::RealExp(Loc loc, real_t value, Type *type)
1498 : Expression(loc, TOKfloat64, sizeof(RealExp))
1499 {
1500 //printf("RealExp::RealExp(%Lg)\n", value);
1501 this->value = value;
1502 this->type = type;
1503 }
1504
1505 char *RealExp::toChars()
1506 {
1507 char buffer[sizeof(value) * 3 + 8 + 1 + 1];
1508
1509 #ifdef IN_GCC
1510 value.format(buffer, sizeof(buffer));
1511 if (type->isimaginary())
1512 strcat(buffer, "i");
1513 #else
1514 sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value);
1515 #endif
1516 assert(strlen(buffer) < sizeof(buffer));
1517 return mem.strdup(buffer);
1518 }
1519
1520 integer_t RealExp::toInteger()
1521 {
1522 #ifdef IN_GCC
1523 return toReal().toInt();
1524 #else
1525 return (sinteger_t) toReal();
1526 #endif
1527 }
1528
1529 uinteger_t RealExp::toUInteger()
1530 {
1531 #ifdef IN_GCC
1532 return (uinteger_t) toReal().toInt();
1533 #else
1534 return (uinteger_t) toReal();
1535 #endif
1536 }
1537
1538 real_t RealExp::toReal()
1539 {
1540 return type->isreal() ? value : 0;
1541 }
1542
1543 real_t RealExp::toImaginary()
1544 {
1545 return type->isreal() ? 0 : value;
1546 }
1547
1548 complex_t RealExp::toComplex()
1549 {
1550 #ifdef __DMC__
1551 return toReal() + toImaginary() * I;
1552 #else
1553 return complex_t(toReal(), toImaginary());
1554 #endif
1555 }
1556
1557 /********************************
1558 * Test to see if two reals are the same.
1559 * Regard NaN's as equivalent.
1560 * Regard +0 and -0 as different.
1561 */
1562
1563 int RealEquals(real_t x1, real_t x2)
1564 {
1565 return // special case nans
1566 (isnan(x1) && isnan(x2)) ||
1567 // and zero, in order to distinguish +0 from -0
1568 (x1 == 0 && x2 == 0 && 1./x1 == 1./x2) ||
1569 // otherwise just compare
1570 (x1 != 0. && x1 == x2);
1571 }
1572
1573 int RealExp::equals(Object *o)
1574 { RealExp *ne;
1575
1576 if (this == o ||
1577 (((Expression *)o)->op == TOKfloat64 &&
1578 ((ne = (RealExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
1579 RealEquals(value, ne->value)
1580 )
1581 )
1582 return 1;
1583 return 0;
1584 }
1585
1586 Expression *RealExp::semantic(Scope *sc)
1587 {
1588 if (!type)
1589 type = Type::tfloat64;
1590 else
1591 type = type->semantic(loc, sc);
1592 return this;
1593 }
1594
1595 int RealExp::isBool(int result)
1596 {
1597 #ifdef IN_GCC
1598 return result ? (! value.isZero()) : (value.isZero());
1599 #else
1600 return result ? (value != 0)
1601 : (value == 0);
1602 #endif
1603 }
1604
1605 void floatToBuffer(OutBuffer *buf, Type *type, real_t value)
1606 {
1607 /* In order to get an exact representation, try converting it
1608 * to decimal then back again. If it matches, use it.
1609 * If it doesn't, fall back to hex, which is
1610 * always exact.
1611 */
1612 char buffer[25];
1613 sprintf(buffer, "%Lg", value);
1614 assert(strlen(buffer) < sizeof(buffer));
1615 #if _WIN32 && __DMC__
1616 char *save = __locale_decpoint;
1617 __locale_decpoint = ".";
1618 real_t r = strtold(buffer, NULL);
1619 __locale_decpoint = save;
1620 #else
1621 real_t r = strtold(buffer, NULL);
1622 #endif
1623 if (r == value) // if exact duplication
1624 buf->writestring(buffer);
1625 else
1626 buf->printf("%La", value); // ensure exact duplication
1627
1628 if (type)
1629 {
1630 Type *t = type->toBasetype();
1631 switch (t->ty)
1632 {
1633 case Tfloat32:
1634 case Timaginary32:
1635 case Tcomplex32:
1636 buf->writeByte('F');
1637 break;
1638
1639 case Tfloat80:
1640 case Timaginary80:
1641 case Tcomplex80:
1642 buf->writeByte('L');
1643 break;
1644
1645 default:
1646 break;
1647 }
1648 if (t->isimaginary())
1649 buf->writeByte('i');
1650 }
1651 }
1652
1653 void RealExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1654 {
1655 floatToBuffer(buf, type, value);
1656 }
1657
1658 void realToMangleBuffer(OutBuffer *buf, real_t value)
1659 {
1660 /* Rely on %A to get portable mangling.
1661 * Must munge result to get only identifier characters.
1662 *
1663 * Possible values from %A => mangled result
1664 * NAN => NAN
1665 * -INF => NINF
1666 * INF => INF
1667 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79
1668 * 0X1.9P+2 => 19P2
1669 */
1670
1671 if (isnan(value))
1672 buf->writestring("NAN"); // no -NAN bugs
1673 else
1674 {
1675 char buffer[32];
1676 int n = sprintf(buffer, "%LA", value);
1677 assert(n > 0 && n < sizeof(buffer));
1678 for (int i = 0; i < n; i++)
1679 { char c = buffer[i];
1680
1681 switch (c)
1682 {
1683 case '-':
1684 buf->writeByte('N');
1685 break;
1686
1687 case '+':
1688 case 'X':
1689 case '.':
1690 break;
1691
1692 case '0':
1693 if (i < 2)
1694 break; // skip leading 0X
1695 default:
1696 buf->writeByte(c);
1697 break;
1698 }
1699 }
1700 }
1701 }
1702
1703 void RealExp::toMangleBuffer(OutBuffer *buf)
1704 {
1705 buf->writeByte('e');
1706 realToMangleBuffer(buf, value);
1707 }
1708
1709
1710 /******************************** ComplexExp **************************/
1711
1712 ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type)
1713 : Expression(loc, TOKcomplex80, sizeof(ComplexExp))
1714 {
1715 this->value = value;
1716 this->type = type;
1717 //printf("ComplexExp::ComplexExp(%s)\n", toChars());
1718 }
1719
1720 char *ComplexExp::toChars()
1721 {
1722 char buffer[sizeof(value) * 3 + 8 + 1];
1723
1724 #ifdef IN_GCC
1725 char buf1[sizeof(value) * 3 + 8 + 1];
1726 char buf2[sizeof(value) * 3 + 8 + 1];
1727 creall(value).format(buf1, sizeof(buf1));
1728 cimagl(value).format(buf2, sizeof(buf2));
1729 sprintf(buffer, "(%s+%si)", buf1, buf2);
1730 #else
1731 sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value));
1732 assert(strlen(buffer) < sizeof(buffer));
1733 #endif
1734 return mem.strdup(buffer);
1735 }
1736
1737 integer_t ComplexExp::toInteger()
1738 {
1739 #ifdef IN_GCC
1740 return (sinteger_t) toReal().toInt();
1741 #else
1742 return (sinteger_t) toReal();
1743 #endif
1744 }
1745
1746 uinteger_t ComplexExp::toUInteger()
1747 {
1748 #ifdef IN_GCC
1749 return (uinteger_t) toReal().toInt();
1750 #else
1751 return (uinteger_t) toReal();
1752 #endif
1753 }
1754
1755 real_t ComplexExp::toReal()
1756 {
1757 return creall(value);
1758 }
1759
1760 real_t ComplexExp::toImaginary()
1761 {
1762 return cimagl(value);
1763 }
1764
1765 complex_t ComplexExp::toComplex()
1766 {
1767 return value;
1768 }
1769
1770 int ComplexExp::equals(Object *o)
1771 { ComplexExp *ne;
1772
1773 if (this == o ||
1774 (((Expression *)o)->op == TOKcomplex80 &&
1775 ((ne = (ComplexExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
1776 RealEquals(creall(value), creall(ne->value)) &&
1777 RealEquals(cimagl(value), cimagl(ne->value))
1778 )
1779 )
1780 return 1;
1781 return 0;
1782 }
1783
1784 Expression *ComplexExp::semantic(Scope *sc)
1785 {
1786 if (!type)
1787 type = Type::tcomplex80;
1788 else
1789 type = type->semantic(loc, sc);
1790 return this;
1791 }
1792
1793 int ComplexExp::isBool(int result)
1794 {
1795 if (result)
1796 return (bool)(value);
1797 else
1798 return !value;
1799 }
1800
1801 void ComplexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1802 {
1803 /* Print as:
1804 * (re+imi)
1805 */
1806 #ifdef IN_GCC
1807 char buf1[sizeof(value) * 3 + 8 + 1];
1808 char buf2[sizeof(value) * 3 + 8 + 1];
1809 creall(value).format(buf1, sizeof(buf1));
1810 cimagl(value).format(buf2, sizeof(buf2));
1811 buf->printf("(%s+%si)", buf1, buf2);
1812 #else
1813 buf->writeByte('(');
1814 floatToBuffer(buf, type, creall(value));
1815 buf->writeByte('+');
1816 floatToBuffer(buf, type, cimagl(value));
1817 buf->writestring("i)");
1818 #endif
1819 }
1820
1821 void ComplexExp::toMangleBuffer(OutBuffer *buf)
1822 {
1823 buf->writeByte('c');
1824 real_t r = toReal();
1825 realToMangleBuffer(buf, r);
1826 buf->writeByte('c'); // separate the two
1827 r = toImaginary();
1828 realToMangleBuffer(buf, r);
1829 }
1830
1831 /******************************** IdentifierExp **************************/
1832
1833 IdentifierExp::IdentifierExp(Loc loc, Identifier *ident)
1834 : Expression(loc, TOKidentifier, sizeof(IdentifierExp))
1835 {
1836 this->ident = ident;
1837 }
1838
1839 Expression *IdentifierExp::semantic(Scope *sc)
1840 {
1841 Dsymbol *s;
1842 Dsymbol *scopesym;
1843
1844 #if LOGSEMANTIC
1845 printf("IdentifierExp::semantic('%s')\n", ident->toChars());
1846 #endif
1847 s = sc->search(loc, ident, &scopesym);
1848 if (s)
1849 { Expression *e;
1850 WithScopeSymbol *withsym;
1851
1852 /* See if the symbol was a member of an enclosing 'with'
1853 */
1854 withsym = scopesym->isWithScopeSymbol();
1855 if (withsym)
1856 {
1857 s = s->toAlias();
1858
1859 // Same as wthis.ident
1860 if (s->needThis() || s->isTemplateDeclaration())
1861 {
1862 e = new VarExp(loc, withsym->withstate->wthis);
1863 e = new DotIdExp(loc, e, ident);
1864 }
1865 else
1866 { Type *t = withsym->withstate->wthis->type;
1867 if (t->ty == Tpointer)
1868 t = ((TypePointer *)t)->next;
1869 e = new TypeDotIdExp(loc, t, ident);
1870 }
1871 }
1872 else
1873 {
1874 /* If f is really a function template,
1875 * then replace f with the function template declaration.
1876 */
1877 FuncDeclaration *f = s->isFuncDeclaration();
1878 if (f && f->parent)
1879 { TemplateInstance *ti = f->parent->isTemplateInstance();
1880
1881 if (ti &&
1882 !ti->isTemplateMixin() &&
1883 (ti->name == f->ident ||
1884 ti->toAlias()->ident == f->ident)
1885 &&
1886 ti->tempdecl && ti->tempdecl->onemember)
1887 {
1888 TemplateDeclaration *tempdecl = ti->tempdecl;
1889 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's
1890 tempdecl = tempdecl->overroot; // then get the start
1891 e = new TemplateExp(loc, tempdecl);
1892 e = e->semantic(sc);
1893 return e;
1894 }
1895 }
1896 // Haven't done overload resolution yet, so pass 1
1897 e = new DsymbolExp(loc, s, 1);
1898 }
1899 return e->semantic(sc);
1900 }
1901 error("undefined identifier %s", ident->toChars());
1902 type = Type::terror;
1903 return this;
1904 }
1905
1906 char *IdentifierExp::toChars()
1907 {
1908 return ident->toChars();
1909 }
1910
1911 void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1912 {
1913 if (hgs->hdrgen)
1914 buf->writestring(ident->toHChars2());
1915 else
1916 buf->writestring(ident->toChars());
1917 }
1918
1919 int IdentifierExp::isLvalue()
1920 {
1921 return 1;
1922 }
1923
1924 Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e)
1925 {
1926 #if 0
1927 tym = tybasic(e1->ET->Tty);
1928 if (!(tyscalar(tym) ||
1929 tym == TYstruct ||
1930 tym == TYarray && e->Eoper == TOKaddr))
1931 synerr(EM_lvalue); // lvalue expected
1932 #endif
1933 return this;
1934 }
1935
1936 /******************************** DollarExp **************************/
1937
1938 DollarExp::DollarExp(Loc loc)
1939 : IdentifierExp(loc, Id::dollar)
1940 {
1941 }
1942
1943 /******************************** DsymbolExp **************************/
1944
1945 DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, int hasOverloads)
1946 : Expression(loc, TOKdsymbol, sizeof(DsymbolExp))
1947 {
1948 this->s = s;
1949 this->hasOverloads = hasOverloads;
1950 }
1951
1952 Expression *DsymbolExp::semantic(Scope *sc)
1953 {
1954 #if LOGSEMANTIC
1955 printf("DsymbolExp::semantic('%s')\n", s->toChars());
1956 #endif
1957
1958 Lagain:
1959 EnumMember *em;
1960 Expression *e;
1961 VarDeclaration *v;
1962 FuncDeclaration *f;
1963 FuncLiteralDeclaration *fld;
1964 OverloadSet *o;
1965 Declaration *d;
1966 ClassDeclaration *cd;
1967 ClassDeclaration *thiscd = NULL;
1968 Import *imp;
1969 Package *pkg;
1970 Type *t;
1971
1972 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
1973 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
1974 if (type)
1975 return this;
1976 if (!s->isFuncDeclaration()) // functions are checked after overloading
1977 checkDeprecated(sc, s);
1978 s = s->toAlias();
1979 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
1980 if (!s->isFuncDeclaration())
1981 checkDeprecated(sc, s);
1982
1983 if (sc->func)
1984 thiscd = sc->func->parent->isClassDeclaration();
1985
1986 // BUG: This should happen after overload resolution for functions, not before
1987 if (s->needThis())
1988 {
1989 if (hasThis(sc) && !s->isFuncDeclaration())
1990 {
1991 // Supply an implicit 'this', as in
1992 // this.ident
1993
1994 DotVarExp *de;
1995
1996 de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration());
1997 return de->semantic(sc);
1998 }
1999 }
2000
2001 em = s->isEnumMember();
2002 if (em)
2003 {
2004 e = em->value;
2005 e = e->semantic(sc);
2006 return e;
2007 }
2008 v = s->isVarDeclaration();
2009 if (v)
2010 {
2011 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
2012 if (!type)
2013 { type = v->type;
2014 if (!v->type)
2015 { error("forward reference of %s", v->toChars());
2016 type = Type::terror;
2017 }
2018 }
2019 e = new VarExp(loc, v);
2020 e->type = type;
2021 e = e->semantic(sc);
2022 return e->deref();
2023 }
2024 fld = s->isFuncLiteralDeclaration();
2025 if (fld)
2026 { //printf("'%s' is a function literal\n", fld->toChars());
2027 e = new FuncExp(loc, fld);
2028 return e->semantic(sc);
2029 }
2030 f = s->isFuncDeclaration();
2031 if (f)
2032 { //printf("'%s' is a function\n", f->toChars());
2033 return new VarExp(loc, f, hasOverloads);
2034 }
2035 o = s->isOverloadSet();
2036 if (o)
2037 { //printf("'%s' is an overload set\n", o->toChars());
2038 return new OverExp(o);
2039 }
2040 cd = s->isClassDeclaration();
2041 if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis())
2042 {
2043 // We need to add an implicit 'this' if cd is this class or a base class.
2044 DotTypeExp *dte;
2045
2046 dte = new DotTypeExp(loc, new ThisExp(loc), s);
2047 return dte->semantic(sc);
2048 }
2049 imp = s->isImport();
2050 if (imp)
2051 {
2052 ScopeExp *ie;
2053
2054 ie = new ScopeExp(loc, imp->pkg);
2055 return ie->semantic(sc);
2056 }
2057 pkg = s->isPackage();
2058 if (pkg)
2059 {
2060 ScopeExp *ie;
2061
2062 ie = new ScopeExp(loc, pkg);
2063 return ie->semantic(sc);
2064 }
2065 Module *mod = s->isModule();
2066 if (mod)
2067 {
2068 ScopeExp *ie;
2069
2070 ie = new ScopeExp(loc, mod);
2071 return ie->semantic(sc);
2072 }
2073
2074 t = s->getType();
2075 if (t)
2076 {
2077 return new TypeExp(loc, t);
2078 }
2079
2080 TupleDeclaration *tup = s->isTupleDeclaration();
2081 if (tup)
2082 {
2083 e = new TupleExp(loc, tup);
2084 e = e->semantic(sc);
2085 return e;
2086 }
2087
2088 TemplateInstance *ti = s->isTemplateInstance();
2089 if (ti && !global.errors)
2090 { if (!ti->semanticdone)
2091 ti->semantic(sc);
2092 s = ti->inst->toAlias();
2093 if (!s->isTemplateInstance())
2094 goto Lagain;
2095 e = new ScopeExp(loc, ti);
2096 e = e->semantic(sc);
2097 return e;
2098 }
2099
2100 TemplateDeclaration *td = s->isTemplateDeclaration();
2101 if (td)
2102 {
2103 e = new TemplateExp(loc, td);
2104 e = e->semantic(sc);
2105 return e;
2106 }
2107
2108 Lerr:
2109 error("%s '%s' is not a variable", s->kind(), s->toChars());
2110 type = Type::terror;
2111 return this;
2112 }
2113
2114 char *DsymbolExp::toChars()
2115 {
2116 return s->toChars();
2117 }
2118
2119 void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2120 {
2121 buf->writestring(s->toChars());
2122 }
2123
2124 int DsymbolExp::isLvalue()
2125 {
2126 return 1;
2127 }
2128
2129 Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e)
2130 {
2131 #if 0
2132 tym = tybasic(e1->ET->Tty);
2133 if (!(tyscalar(tym) ||
2134 tym == TYstruct ||
2135 tym == TYarray && e->Eoper == TOKaddr))
2136 synerr(EM_lvalue); // lvalue expected
2137 #endif
2138 return this;
2139 }
2140
2141 /******************************** ThisExp **************************/
2142
2143 ThisExp::ThisExp(Loc loc)
2144 : Expression(loc, TOKthis, sizeof(ThisExp))
2145 {
2146 var = NULL;
2147 }
2148
2149 Expression *ThisExp::semantic(Scope *sc)
2150 { FuncDeclaration *fd;
2151 FuncDeclaration *fdthis;
2152 int nested = 0;
2153
2154 #if LOGSEMANTIC
2155 printf("ThisExp::semantic()\n");
2156 #endif
2157 if (type)
2158 { //assert(global.errors || var);
2159 return this;
2160 }
2161
2162 /* Special case for typeof(this) and typeof(super) since both
2163 * should work even if they are not inside a non-static member function
2164 */
2165 if (sc->intypeof)
2166 {
2167 // Find enclosing struct or class
2168 for (Dsymbol *s = sc->parent; 1; s = s->parent)
2169 {
2170 ClassDeclaration *cd;
2171 StructDeclaration *sd;
2172
2173 if (!s)
2174 {
2175 error("%s is not in a struct or class scope", toChars());
2176 goto Lerr;
2177 }
2178 cd = s->isClassDeclaration();
2179 if (cd)
2180 {
2181 type = cd->type;
2182 return this;
2183 }
2184 sd = s->isStructDeclaration();
2185 if (sd)
2186 {
2187 type = sd->type->pointerTo();
2188 return this;
2189 }
2190 }
2191 }
2192
2193 fdthis = sc->parent->isFuncDeclaration();
2194 fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2195 if (!fd)
2196 goto Lerr;
2197
2198 assert(fd->vthis);
2199 var = fd->vthis;
2200 assert(var->parent);
2201 type = var->type;
2202 var->isVarDeclaration()->checkNestedReference(sc, loc);
2203 if (!sc->intypeof)
2204 sc->callSuper |= CSXthis;
2205 return this;
2206
2207 Lerr:
2208 error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars());
2209 type = Type::terror;
2210 return this;
2211 }
2212
2213 int ThisExp::isBool(int result)
2214 {
2215 return result ? TRUE : FALSE;
2216 }
2217
2218 void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2219 {
2220 buf->writestring("this");
2221 }
2222
2223 int ThisExp::isLvalue()
2224 {
2225 return 1;
2226 }
2227
2228 Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
2229 {
2230 return this;
2231 }
2232
2233 /******************************** SuperExp **************************/
2234
2235 SuperExp::SuperExp(Loc loc)
2236 : ThisExp(loc)
2237 {
2238 op = TOKsuper;
2239 }
2240
2241 Expression *SuperExp::semantic(Scope *sc)
2242 { FuncDeclaration *fd;
2243 FuncDeclaration *fdthis;
2244 ClassDeclaration *cd;
2245 Dsymbol *s;
2246
2247 #if LOGSEMANTIC
2248 printf("SuperExp::semantic('%s')\n", toChars());
2249 #endif
2250 if (type)
2251 return this;
2252
2253 /* Special case for typeof(this) and typeof(super) since both
2254 * should work even if they are not inside a non-static member function
2255 */
2256 if (sc->intypeof)
2257 {
2258 // Find enclosing class
2259 for (Dsymbol *s = sc->parent; 1; s = s->parent)
2260 {
2261 ClassDeclaration *cd;
2262
2263 if (!s)
2264 {
2265 error("%s is not in a class scope", toChars());
2266 goto Lerr;
2267 }
2268 cd = s->isClassDeclaration();
2269 if (cd)
2270 {
2271 cd = cd->baseClass;
2272 if (!cd)
2273 { error("class %s has no 'super'", s->toChars());
2274 goto Lerr;
2275 }
2276 type = cd->type;
2277 return this;
2278 }
2279 }
2280 }
2281
2282 fdthis = sc->parent->isFuncDeclaration();
2283 fd = hasThis(sc);
2284 if (!fd)
2285 goto Lerr;
2286 assert(fd->vthis);
2287 var = fd->vthis;
2288 assert(var->parent);
2289
2290 s = fd->toParent();
2291 while (s && s->isTemplateInstance())
2292 s = s->toParent();
2293 assert(s);
2294 cd = s->isClassDeclaration();
2295 //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
2296 if (!cd)
2297 goto Lerr;
2298 if (!cd->baseClass)
2299 {
2300 error("no base class for %s", cd->toChars());
2301 type = fd->vthis->type;
2302 }
2303 else
2304 {
2305 type = cd->baseClass->type;
2306 }
2307
2308 var->isVarDeclaration()->checkNestedReference(sc, loc);
2309
2310 if (!sc->intypeof)
2311 sc->callSuper |= CSXsuper;
2312 return this;
2313
2314
2315 Lerr:
2316 error("'super' is only allowed in non-static class member functions");
2317 type = Type::tint32;
2318 return this;
2319 }
2320
2321 void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2322 {
2323 buf->writestring("super");
2324 }
2325
2326
2327 /******************************** NullExp **************************/
2328
2329 NullExp::NullExp(Loc loc)
2330 : Expression(loc, TOKnull, sizeof(NullExp))
2331 {
2332 committed = 0;
2333 }
2334
2335 Expression *NullExp::semantic(Scope *sc)
2336 {
2337 #if LOGSEMANTIC
2338 printf("NullExp::semantic('%s')\n", toChars());
2339 #endif
2340 // NULL is the same as (void *)0
2341 if (!type)
2342 type = Type::tvoid->pointerTo();
2343 return this;
2344 }
2345
2346 int NullExp::isBool(int result)
2347 {
2348 return result ? FALSE : TRUE;
2349 }
2350
2351 void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2352 {
2353 buf->writestring("null");
2354 }
2355
2356 void NullExp::toMangleBuffer(OutBuffer *buf)
2357 {
2358 buf->writeByte('n');
2359 }
2360
2361 /******************************** StringExp **************************/
2362
2363 StringExp::StringExp(Loc loc, char *string)
2364 : Expression(loc, TOKstring, sizeof(StringExp))
2365 {
2366 this->string = string;
2367 this->len = strlen(string);
2368 this->sz = 1;
2369 this->committed = 0;
2370 this->postfix = 0;
2371 }
2372
2373 StringExp::StringExp(Loc loc, void *string, size_t len)
2374 : Expression(loc, TOKstring, sizeof(StringExp))
2375 {
2376 this->string = string;
2377 this->len = len;
2378 this->sz = 1;
2379 this->committed = 0;
2380 this->postfix = 0;
2381 }
2382
2383 StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix)
2384 : Expression(loc, TOKstring, sizeof(StringExp))
2385 {
2386 this->string = string;
2387 this->len = len;
2388 this->sz = 1;
2389 this->committed = 0;
2390 this->postfix = postfix;
2391 }
2392
2393 #if 0
2394 Expression *StringExp::syntaxCopy()
2395 {
2396 printf("StringExp::syntaxCopy() %s\n", toChars());
2397 return copy();
2398 }
2399 #endif
2400
2401 int StringExp::equals(Object *o)
2402 {
2403 //printf("StringExp::equals('%s')\n", o->toChars());
2404 if (o && o->dyncast() == DYNCAST_EXPRESSION)
2405 { Expression *e = (Expression *)o;
2406
2407 if (e->op == TOKstring)
2408 {
2409 return compare(o) == 0;
2410 }
2411 }
2412 return FALSE;
2413 }
2414
2415 char *StringExp::toChars()
2416 {
2417 OutBuffer buf;
2418 HdrGenState hgs;
2419 char *p;
2420
2421 memset(&hgs, 0, sizeof(hgs));
2422 toCBuffer(&buf, &hgs);
2423 buf.writeByte(0);
2424 p = (char *)buf.data;
2425 buf.data = NULL;
2426 return p;
2427 }
2428
2429 Expression *StringExp::semantic(Scope *sc)
2430 {
2431 #if LOGSEMANTIC
2432 printf("StringExp::semantic() %s\n", toChars());
2433 #endif
2434 if (!type)
2435 { OutBuffer buffer;
2436 size_t newlen = 0;
2437 const char *p;
2438 size_t u;
2439 unsigned c;
2440
2441 switch (postfix)
2442 {
2443 case 'd':
2444 for (u = 0; u < len;)
2445 {
2446 p = utf_decodeChar((unsigned char *)string, len, &u, &c);
2447 if (p)
2448 { error("%s", p);
2449 break;
2450 }
2451 else
2452 { buffer.write4(c);
2453 newlen++;
2454 }
2455 }
2456 buffer.write4(0);
2457 string = buffer.extractData();
2458 len = newlen;
2459 sz = 4;
2460 type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex));
2461 committed = 1;
2462 break;
2463
2464 case 'w':
2465 for (u = 0; u < len;)
2466 {
2467 p = utf_decodeChar((unsigned char *)string, len, &u, &c);
2468 if (p)
2469 { error("%s", p);
2470 break;
2471 }
2472 else
2473 { buffer.writeUTF16(c);
2474 newlen++;
2475 if (c >= 0x10000)
2476 newlen++;
2477 }
2478 }
2479 buffer.writeUTF16(0);
2480 string = buffer.extractData();
2481 len = newlen;
2482 sz = 2;
2483 type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex));
2484 committed = 1;
2485 break;
2486
2487 case 'c':
2488 committed = 1;
2489 default:
2490 type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex));
2491 break;
2492 }
2493 type = type->semantic(loc, sc);
2494 type = type->invariantOf();
2495 //printf("type = %s\n", type->toChars());
2496 }
2497 return this;
2498 }
2499
2500 /****************************************
2501 * Convert string to char[].
2502 */
2503
2504 StringExp *StringExp::toUTF8(Scope *sc)
2505 {
2506 if (sz != 1)
2507 { // Convert to UTF-8 string
2508 committed = 0;
2509 Expression *e = castTo(sc, Type::tchar->arrayOf());
2510 e = e->optimize(WANTvalue);
2511 assert(e->op == TOKstring);
2512 StringExp *se = (StringExp *)e;
2513 assert(se->sz == 1);
2514 return se;
2515 }
2516 return this;
2517 }
2518
2519 int StringExp::compare(Object *obj)
2520 {
2521 // Used to sort case statement expressions so we can do an efficient lookup
2522 StringExp *se2 = (StringExp *)(obj);
2523
2524 // This is a kludge so isExpression() in template.c will return 5
2525 // for StringExp's.
2526 if (!se2)
2527 return 5;
2528
2529 assert(se2->op == TOKstring);
2530
2531 int len1 = len;
2532 int len2 = se2->len;
2533
2534 if (len1 == len2)
2535 {
2536 switch (sz)
2537 {
2538 case 1:
2539 return strcmp((char *)string, (char *)se2->string);
2540
2541 case 2:
2542 { unsigned u;
2543 d_wchar *s1 = (d_wchar *)string;
2544 d_wchar *s2 = (d_wchar *)se2->string;
2545
2546 for (u = 0; u < len; u++)
2547 {
2548 if (s1[u] != s2[u])
2549 return s1[u] - s2[u];
2550 }
2551 }
2552
2553 case 4:
2554 { unsigned u;
2555 d_dchar *s1 = (d_dchar *)string;
2556 d_dchar *s2 = (d_dchar *)se2->string;
2557
2558 for (u = 0; u < len; u++)
2559 {
2560 if (s1[u] != s2[u])
2561 return s1[u] - s2[u];
2562 }
2563 }
2564 break;
2565
2566 default:
2567 assert(0);
2568 }
2569 }
2570 return len1 - len2;
2571 }
2572
2573 int StringExp::isBool(int result)
2574 {
2575 return result ? TRUE : FALSE;
2576 }
2577
2578 unsigned StringExp::charAt(size_t i)
2579 { unsigned value;
2580
2581 switch (sz)
2582 {
2583 case 1:
2584 value = ((unsigned char *)string)[i];
2585 break;
2586
2587 case 2:
2588 value = ((unsigned short *)string)[i];
2589 break;
2590
2591 case 4:
2592 value = ((unsigned int *)string)[i];
2593 break;
2594
2595 default:
2596 assert(0);
2597 break;
2598 }
2599 return value;
2600 }
2601
2602 void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2603 {
2604 buf->writeByte('"');
2605 for (size_t i = 0; i < len; i++)
2606 { unsigned c = charAt(i);
2607
2608 switch (c)
2609 {
2610 case '"':
2611 case '\\':
2612 if (!hgs->console)
2613 buf->writeByte('\\');
2614 default:
2615 if (c <= 0xFF)
2616 { if (c <= 0x7F && (isprint(c) || hgs->console))
2617 buf->writeByte(c);
2618 else
2619 buf->printf("\\x%02x", c);
2620 }
2621 else if (c <= 0xFFFF)
2622 buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8);
2623 else
2624 buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
2625 c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24);
2626 break;
2627 }
2628 }
2629 buf->writeByte('"');
2630 if (postfix)
2631 buf->writeByte(postfix);
2632 }
2633
2634 void StringExp::toMangleBuffer(OutBuffer *buf)
2635 { char m;
2636 OutBuffer tmp;
2637 const char *p;
2638 unsigned c;
2639 size_t u;
2640 unsigned char *q;
2641 unsigned qlen;
2642
2643 /* Write string in UTF-8 format
2644 */
2645 switch (sz)
2646 { case 1:
2647 m = 'a';
2648 q = (unsigned char *)string;
2649 qlen = len;
2650 break;
2651 case 2:
2652 m = 'w';
2653 for (u = 0; u < len; )
2654 {
2655 p = utf_decodeWchar((unsigned short *)string, len, &u, &c);
2656 if (p)
2657 error("%s", p);
2658 else
2659 tmp.writeUTF8(c);
2660 }
2661 q = tmp.data;
2662 qlen = tmp.offset;
2663 break;
2664 case 4:
2665 m = 'd';
2666 for (u = 0; u < len; u++)
2667 {
2668 c = ((unsigned *)string)[u];
2669 if (!utf_isValidDchar(c))
2670 error("invalid UCS-32 char \\U%08x", c);
2671 else
2672 tmp.writeUTF8(c);
2673 }
2674 q = tmp.data;
2675 qlen = tmp.offset;
2676 break;
2677 default:
2678 assert(0);
2679 }
2680 buf->writeByte(m);
2681 buf->printf("%d_", qlen);
2682 for (size_t i = 0; i < qlen; i++)
2683 buf->printf("%02x", q[i]);
2684 }
2685
2686 /************************ ArrayLiteralExp ************************************/
2687
2688 // [ e1, e2, e3, ... ]
2689
2690 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements)
2691 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
2692 {
2693 this->elements = elements;
2694 }
2695
2696 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e)
2697 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
2698 {
2699 elements = new Expressions;
2700 elements->push(e);
2701 }
2702
2703 Expression *ArrayLiteralExp::syntaxCopy()
2704 {
2705 return new ArrayLiteralExp(loc, arraySyntaxCopy(elements));
2706 }
2707
2708 Expression *ArrayLiteralExp::semantic(Scope *sc)
2709 { Expression *e;
2710 Type *t0 = NULL;
2711
2712 #if LOGSEMANTIC
2713 printf("ArrayLiteralExp::semantic('%s')\n", toChars());
2714 #endif
2715 if (type)
2716 return this;
2717
2718 // Run semantic() on each element
2719 for (int i = 0; i < elements->dim; i++)
2720 { e = (Expression *)elements->data[i];
2721 e = e->semantic(sc);
2722 elements->data[i] = (void *)e;
2723 }
2724 expandTuples(elements);
2725 for (int i = 0; i < elements->dim; i++)
2726 { e = (Expression *)elements->data[i];
2727
2728 if (!e->type)
2729 error("%s has no value", e->toChars());
2730 e = resolveProperties(sc, e);
2731
2732 unsigned char committed = 1;
2733 if (e->op == TOKstring)
2734 committed = ((StringExp *)e)->committed;
2735
2736 if (!t0)
2737 { t0 = e->type;
2738 // Convert any static arrays to dynamic arrays
2739 if (t0->ty == Tsarray)
2740 {
2741 t0 = ((TypeSArray *)t0)->next->arrayOf();
2742 e = e->implicitCastTo(sc, t0);
2743 }
2744 }
2745 else
2746 e = e->implicitCastTo(sc, t0);
2747 if (!committed && e->op == TOKstring)
2748 { StringExp *se = (StringExp *)e;
2749 se->committed = 0;
2750 }
2751 elements->data[i] = (void *)e;
2752 }
2753
2754 if (!t0)
2755 t0 = Type::tvoid;
2756 type = new TypeSArray(t0, new IntegerExp(elements->dim));
2757 type = type->semantic(loc, sc);
2758 return this;
2759 }
2760
2761 int ArrayLiteralExp::checkSideEffect(int flag)
2762 { int f = 0;
2763
2764 for (size_t i = 0; i < elements->dim; i++)
2765 { Expression *e = (Expression *)elements->data[i];
2766
2767 f |= e->checkSideEffect(2);
2768 }
2769 if (flag == 0 && f == 0)
2770 Expression::checkSideEffect(0);
2771 return f;
2772 }
2773
2774 int ArrayLiteralExp::isBool(int result)
2775 {
2776 size_t dim = elements ? elements->dim : 0;
2777 return result ? (dim != 0) : (dim == 0);
2778 }
2779
2780 int ArrayLiteralExp::canThrow()
2781 {
2782 return 1; // because it can fail allocating memory
2783 }
2784
2785 void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2786 {
2787 buf->writeByte('[');
2788 argsToCBuffer(buf, elements, hgs);
2789 buf->writeByte(']');
2790 }
2791
2792 void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
2793 {
2794 size_t dim = elements ? elements->dim : 0;
2795 buf->printf("A%u", dim);
2796 for (size_t i = 0; i < dim; i++)
2797 { Expression *e = (Expression *)elements->data[i];
2798 e->toMangleBuffer(buf);
2799 }
2800 }
2801
2802 /************************ AssocArrayLiteralExp ************************************/
2803
2804 // [ key0 : value0, key1 : value1, ... ]
2805
2806 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc,
2807 Expressions *keys, Expressions *values)
2808 : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp))
2809 {
2810 assert(keys->dim == values->dim);
2811 this->keys = keys;
2812 this->values = values;
2813 }
2814
2815 Expression *AssocArrayLiteralExp::syntaxCopy()
2816 {
2817 return new AssocArrayLiteralExp(loc,
2818 arraySyntaxCopy(keys), arraySyntaxCopy(values));
2819 }
2820
2821 Expression *AssocArrayLiteralExp::semantic(Scope *sc)
2822 { Expression *e;
2823 Type *tkey = NULL;
2824 Type *tvalue = NULL;
2825
2826 #if LOGSEMANTIC
2827 printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
2828 #endif
2829
2830 // Run semantic() on each element
2831 for (size_t i = 0; i < keys->dim; i++)
2832 { Expression *key = (Expression *)keys->data[i];
2833 Expression *value = (Expression *)values->data[i];
2834
2835 key = key->semantic(sc);
2836 value = value->semantic(sc);
2837
2838 keys->data[i] = (void *)key;
2839 values->data[i] = (void *)value;
2840 }
2841 expandTuples(keys);
2842 expandTuples(values);
2843 if (keys->dim != values->dim)
2844 {
2845 error("number of keys is %u, must match number of values %u", keys->dim, values->dim);
2846 keys->setDim(0);
2847 values->setDim(0);
2848 }
2849 for (size_t i = 0; i < keys->dim; i++)
2850 { Expression *key = (Expression *)keys->data[i];
2851 Expression *value = (Expression *)values->data[i];
2852
2853 if (!key->type)
2854 error("%s has no value", key->toChars());
2855 if (!value->type)
2856 error("%s has no value", value->toChars());
2857 key = resolveProperties(sc, key);
2858 value = resolveProperties(sc, value);
2859
2860 if (!tkey)
2861 tkey = key->type;
2862 else
2863 key = key->implicitCastTo(sc, tkey);
2864 keys->data[i] = (void *)key;
2865
2866 if (!tvalue)
2867 tvalue = value->type;
2868 else
2869 value = value->implicitCastTo(sc, tvalue);
2870 values->data[i] = (void *)value;
2871 }
2872
2873 if (!tkey)
2874 tkey = Type::tvoid;
2875 if (!tvalue)
2876 tvalue = Type::tvoid;
2877 type = new TypeAArray(tvalue, tkey);
2878 type = type->semantic(loc, sc);
2879 return this;
2880 }
2881
2882 int AssocArrayLiteralExp::checkSideEffect(int flag)
2883 { int f = 0;
2884
2885 for (size_t i = 0; i < keys->dim; i++)
2886 { Expression *key = (Expression *)keys->data[i];
2887 Expression *value = (Expression *)values->data[i];
2888
2889 f |= key->checkSideEffect(2);
2890 f |= value->checkSideEffect(2);
2891 }
2892 if (flag == 0 && f == 0)
2893 Expression::checkSideEffect(0);
2894 return f;
2895 }
2896
2897 int AssocArrayLiteralExp::isBool(int result)
2898 {
2899 size_t dim = keys->dim;
2900 return result ? (dim != 0) : (dim == 0);
2901 }
2902
2903 int AssocArrayLiteralExp::canThrow()
2904 {
2905 return 1;
2906 }
2907
2908 void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2909 {
2910 buf->writeByte('[');
2911 for (size_t i = 0; i < keys->dim; i++)
2912 { Expression *key = (Expression *)keys->data[i];
2913 Expression *value = (Expression *)values->data[i];
2914
2915 if (i)
2916 buf->writeByte(',');
2917 expToCBuffer(buf, hgs, key, PREC_assign);
2918 buf->writeByte(':');
2919 expToCBuffer(buf, hgs, value, PREC_assign);
2920 }
2921 buf->writeByte(']');
2922 }
2923
2924 void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
2925 {
2926 size_t dim = keys->dim;
2927 buf->printf("A%u", dim);
2928 for (size_t i = 0; i < dim; i++)
2929 { Expression *key = (Expression *)keys->data[i];
2930 Expression *value = (Expression *)values->data[i];
2931
2932 key->toMangleBuffer(buf);
2933 value->toMangleBuffer(buf);
2934 }
2935 }
2936
2937 /************************ StructLiteralExp ************************************/
2938
2939 // sd( e1, e2, e3, ... )
2940
2941 StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements)
2942 : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp))
2943 {
2944 this->sd = sd;
2945 this->elements = elements;
2946 this->sym = NULL;
2947 this->soffset = 0;
2948 this->fillHoles = 1;
2949 }
2950
2951 Expression *StructLiteralExp::syntaxCopy()
2952 {
2953 return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements));
2954 }
2955
2956 Expression *StructLiteralExp::semantic(Scope *sc)
2957 { Expression *e;
2958
2959 #if LOGSEMANTIC
2960 printf("StructLiteralExp::semantic('%s')\n", toChars());
2961 #endif
2962 if (type)
2963 return this;
2964
2965 // Run semantic() on each element
2966 for (size_t i = 0; i < elements->dim; i++)
2967 { e = (Expression *)elements->data[i];
2968 if (!e)
2969 continue;
2970 e = e->semantic(sc);
2971 elements->data[i] = (void *)e;
2972 }
2973 expandTuples(elements);
2974 size_t offset = 0;
2975 for (size_t i = 0; i < elements->dim; i++)
2976 { e = (Expression *)elements->data[i];
2977 if (!e)
2978 continue;
2979
2980 if (!e->type)
2981 error("%s has no value", e->toChars());
2982 e = resolveProperties(sc, e);
2983 if (i >= sd->fields.dim)
2984 { error("more initializers than fields of %s", sd->toChars());
2985 break;
2986 }
2987 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
2988 VarDeclaration *v = s->isVarDeclaration();
2989 assert(v);
2990 if (v->offset < offset)
2991 error("overlapping initialization for %s", v->toChars());
2992 offset = v->offset + v->type->size();
2993
2994 Type *telem = v->type;
2995 while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray)
2996 { /* Static array initialization, as in:
2997 * T[3][5] = e;
2998 */
2999 telem = telem->toBasetype()->nextOf();
3000 }
3001
3002 e = e->implicitCastTo(sc, telem);
3003
3004 elements->data[i] = (void *)e;
3005 }
3006
3007 /* Fill out remainder of elements[] with default initializers for fields[]
3008 */
3009 for (size_t i = elements->dim; i < sd->fields.dim; i++)
3010 { Dsymbol *s = (Dsymbol *)sd->fields.data[i];
3011 VarDeclaration *v = s->isVarDeclaration();
3012 assert(v);
3013
3014 if (v->offset < offset)
3015 { e = NULL;
3016 sd->hasUnions = 1;
3017 }
3018 else
3019 {
3020 if (v->init)
3021 { e = v->init->toExpression();
3022 if (!e)
3023 error("cannot make expression out of initializer for %s", v->toChars());
3024 }
3025 else
3026 { e = v->type->defaultInit();
3027 e->loc = loc;
3028 }
3029 offset = v->offset + v->type->size();
3030 }
3031 elements->push(e);
3032 }
3033
3034 type = sd->type;
3035 return this;
3036 }
3037
3038 /**************************************
3039 * Gets expression at offset of type.
3040 * Returns NULL if not found.
3041 */
3042
3043 Expression *StructLiteralExp::getField(Type *type, unsigned offset)
3044 {
3045 //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
3046 // /*toChars()*/"", type->toChars(), offset);
3047 Expression *e = NULL;
3048 int i = getFieldIndex(type, offset);
3049
3050 if (i != -1)
3051 {
3052 //printf("\ti = %d\n", i);
3053 assert(i < elements->dim);
3054 e = (Expression *)elements->data[i];
3055 if (e)
3056 {
3057 e = e->copy();
3058 e->type = type;
3059 }
3060 }
3061 return e;
3062 }
3063
3064 /************************************
3065 * Get index of field.
3066 * Returns -1 if not found.
3067 */
3068
3069 int StructLiteralExp::getFieldIndex(Type *type, unsigned offset)
3070 {
3071 /* Find which field offset is by looking at the field offsets
3072 */
3073 for (size_t i = 0; i < sd->fields.dim; i++)
3074 {
3075 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
3076 VarDeclaration *v = s->isVarDeclaration();
3077 assert(v);
3078
3079 if (offset == v->offset &&
3080 type->size() == v->type->size())
3081 { Expression *e = (Expression *)elements->data[i];
3082 if (e)
3083 {
3084 return i;
3085 }
3086 break;
3087 }
3088 }
3089 return -1;
3090 }
3091
3092 int StructLiteralExp::isLvalue()
3093 {
3094 return 1;
3095 }
3096
3097 Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e)
3098 {
3099 return this;
3100 }
3101
3102
3103 int StructLiteralExp::checkSideEffect(int flag)
3104 { int f = 0;
3105
3106 for (size_t i = 0; i < elements->dim; i++)
3107 { Expression *e = (Expression *)elements->data[i];
3108 if (!e)
3109 continue;
3110
3111 f |= e->checkSideEffect(2);
3112 }
3113 if (flag == 0 && f == 0)
3114 Expression::checkSideEffect(0);
3115 return f;
3116 }
3117
3118 int StructLiteralExp::canThrow()
3119 {
3120 return arrayExpressionCanThrow(elements);
3121 }
3122
3123 void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3124 {
3125 buf->writestring(sd->toChars());
3126 buf->writeByte('(');
3127 argsToCBuffer(buf, elements, hgs);
3128 buf->writeByte(')');
3129 }
3130
3131 void StructLiteralExp::toMangleBuffer(OutBuffer *buf)
3132 {
3133 size_t dim = elements ? elements->dim : 0;
3134 buf->printf("S%u", dim);
3135 for (size_t i = 0; i < dim; i++)
3136 { Expression *e = (Expression *)elements->data[i];
3137 if (e)
3138 e->toMangleBuffer(buf);
3139 else
3140 buf->writeByte('v'); // 'v' for void
3141 }
3142 }
3143
3144 /************************ TypeDotIdExp ************************************/
3145
3146 /* Things like:
3147 * int.size
3148 * foo.size
3149 * (foo).size
3150 * cast(foo).size
3151 */
3152
3153 TypeDotIdExp::TypeDotIdExp(Loc loc, Type *type, Identifier *ident)
3154 : Expression(loc, TOKtypedot, sizeof(TypeDotIdExp))
3155 {
3156 this->type = type;
3157 this->ident = ident;
3158 }
3159
3160 Expression *TypeDotIdExp::syntaxCopy()
3161 {
3162 TypeDotIdExp *te = new TypeDotIdExp(loc, type->syntaxCopy(), ident);
3163 return te;
3164 }
3165
3166 Expression *TypeDotIdExp::semantic(Scope *sc)
3167 { Expression *e;
3168
3169 #if LOGSEMANTIC
3170 printf("TypeDotIdExp::semantic()\n");
3171 #endif
3172 e = new DotIdExp(loc, new TypeExp(loc, type), ident);
3173 e = e->semantic(sc);
3174 return e;
3175 }
3176
3177 void TypeDotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3178 {
3179 buf->writeByte('(');
3180 type->toCBuffer(buf, NULL, hgs);
3181 buf->writeByte(')');
3182 buf->writeByte('.');
3183 buf->writestring(ident->toChars());
3184 }
3185
3186 /************************************************************/
3187
3188 // Mainly just a placeholder
3189
3190 TypeExp::TypeExp(Loc loc, Type *type)
3191 : Expression(loc, TOKtype, sizeof(TypeExp))
3192 {
3193 //printf("TypeExp::TypeExp(%s)\n", type->toChars());
3194 this->type = type;
3195 }
3196
3197 Expression *TypeExp::semantic(Scope *sc)
3198 {
3199 //printf("TypeExp::semantic(%s)\n", type->toChars());
3200 type = type->semantic(loc, sc);
3201 return this;
3202 }
3203
3204 void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3205 {
3206 type->toCBuffer(buf, NULL, hgs);
3207 }
3208
3209 /************************************************************/
3210
3211 // Mainly just a placeholder
3212
3213 ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg)
3214 : Expression(loc, TOKimport, sizeof(ScopeExp))
3215 {
3216 //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars());
3217 //static int count; if (++count == 38) *(char*)0=0;
3218 this->sds = pkg;
3219 }
3220
3221 Expression *ScopeExp::syntaxCopy()
3222 {
3223 ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL));
3224 return se;
3225 }
3226
3227 Expression *ScopeExp::semantic(Scope *sc)
3228 {
3229 TemplateInstance *ti;
3230 ScopeDsymbol *sds2;
3231
3232 #if LOGSEMANTIC
3233 printf("+ScopeExp::semantic('%s')\n", toChars());
3234 #endif
3235 Lagain:
3236 ti = sds->isTemplateInstance();
3237 if (ti && !global.errors)
3238 { Dsymbol *s;
3239 if (!ti->semanticdone)
3240 ti->semantic(sc);
3241 s = ti->inst->toAlias();
3242 sds2 = s->isScopeDsymbol();
3243 if (!sds2)
3244 { Expression *e;
3245
3246 //printf("s = %s, '%s'\n", s->kind(), s->toChars());
3247 if (ti->withsym)
3248 {
3249 // Same as wthis.s
3250 e = new VarExp(loc, ti->withsym->withstate->wthis);
3251 e = new DotVarExp(loc, e, s->isDeclaration());
3252 }
3253 else
3254 e = new DsymbolExp(loc, s);
3255 e = e->semantic(sc);
3256 //printf("-1ScopeExp::semantic()\n");
3257 return e;
3258 }
3259 if (sds2 != sds)
3260 {
3261 sds = sds2;
3262 goto Lagain;
3263 }
3264 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3265 }
3266 else
3267 {
3268 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3269 //printf("\tparent = '%s'\n", sds->parent->toChars());
3270 sds->semantic(sc);
3271 }
3272 type = Type::tvoid;
3273 //printf("-2ScopeExp::semantic() %s\n", toChars());
3274 return this;
3275 }
3276
3277 void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3278 {
3279 if (sds->isTemplateInstance())
3280 {
3281 sds->toCBuffer(buf, hgs);
3282 }
3283 else
3284 {
3285 buf->writestring(sds->kind());
3286 buf->writestring(" ");
3287 buf->writestring(sds->toChars());
3288 }
3289 }
3290
3291 /********************** TemplateExp **************************************/
3292
3293 // Mainly just a placeholder
3294
3295 TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td)
3296 : Expression(loc, TOKtemplate, sizeof(TemplateExp))
3297 {
3298 //printf("TemplateExp(): %s\n", td->toChars());
3299 this->td = td;
3300 }
3301
3302 void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3303 {
3304 buf->writestring(td->toChars());
3305 }
3306
3307 void TemplateExp::rvalue()
3308 {
3309 error("template %s has no value", toChars());
3310 }
3311
3312 /********************** NewExp **************************************/
3313
3314 /* thisexp.new(newargs) newtype(arguments) */
3315
3316 NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
3317 Type *newtype, Expressions *arguments)
3318 : Expression(loc, TOKnew, sizeof(NewExp))
3319 {
3320 this->thisexp = thisexp;
3321 this->newargs = newargs;
3322 this->newtype = newtype;
3323 this->arguments = arguments;
3324 member = NULL;
3325 allocator = NULL;
3326 onstack = 0;
3327 }
3328
3329 Expression *NewExp::syntaxCopy()
3330 {
3331 return new NewExp(loc,
3332 thisexp ? thisexp->syntaxCopy() : NULL,
3333 arraySyntaxCopy(newargs),
3334 newtype->syntaxCopy(), arraySyntaxCopy(arguments));
3335 }
3336
3337
3338 Expression *NewExp::semantic(Scope *sc)
3339 { int i;
3340 Type *tb;
3341 ClassDeclaration *cdthis = NULL;
3342
3343 #if LOGSEMANTIC
3344 printf("NewExp::semantic() %s\n", toChars());
3345 if (thisexp)
3346 printf("\tthisexp = %s\n", thisexp->toChars());
3347 printf("\tnewtype: %s\n", newtype->toChars());
3348 #endif
3349 if (type) // if semantic() already run
3350 return this;
3351
3352 Lagain:
3353 if (thisexp)
3354 { thisexp = thisexp->semantic(sc);
3355 cdthis = thisexp->type->isClassHandle();
3356 if (cdthis)
3357 {
3358 sc = sc->push(cdthis);
3359 type = newtype->semantic(loc, sc);
3360 sc = sc->pop();
3361 }
3362 else
3363 {
3364 error("'this' for nested class must be a class type, not %s", thisexp->type->toChars());
3365 type = newtype->semantic(loc, sc);
3366 }
3367 }
3368 else
3369 type = newtype->semantic(loc, sc);
3370 newtype = type; // in case type gets cast to something else
3371 tb = type->toBasetype();
3372 //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco);
3373
3374 arrayExpressionSemantic(newargs, sc);
3375 preFunctionArguments(loc, sc, newargs);
3376 arrayExpressionSemantic(arguments, sc);
3377 preFunctionArguments(loc, sc, arguments);
3378
3379 if (thisexp && tb->ty != Tclass)
3380 error("e.new is only for allocating nested classes, not %s", tb->toChars());
3381
3382 if (tb->ty == Tclass)
3383 { TypeFunction *tf;
3384
3385 TypeClass *tc = (TypeClass *)(tb);
3386 ClassDeclaration *cd = tc->sym->isClassDeclaration();
3387 if (cd->isInterfaceDeclaration())
3388 error("cannot create instance of interface %s", cd->toChars());
3389 else if (cd->isAbstract())
3390 { error("cannot create instance of abstract class %s", cd->toChars());
3391 for (int i = 0; i < cd->vtbl.dim; i++)
3392 { FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration();
3393 if (fd && fd->isAbstract())
3394 error("function %s is abstract", fd->toChars());
3395 }
3396 }
3397 checkDeprecated(sc, cd);
3398 if (cd->isNested())
3399 { /* We need a 'this' pointer for the nested class.
3400 * Ensure we have the right one.
3401 */
3402 Dsymbol *s = cd->toParent2();
3403 ClassDeclaration *cdn = s->isClassDeclaration();
3404 FuncDeclaration *fdn = s->isFuncDeclaration();
3405
3406 //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
3407 if (cdn)
3408 {
3409 if (!cdthis)
3410 {
3411 // Supply an implicit 'this' and try again
3412 thisexp = new ThisExp(loc);
3413 for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
3414 { if (!sp)
3415 {
3416 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
3417 break;
3418 }
3419 ClassDeclaration *cdp = sp->isClassDeclaration();
3420 if (!cdp)
3421 continue;
3422 if (cdp == cdn || cdn->isBaseOf(cdp, NULL))
3423 break;
3424 // Add a '.outer' and try again
3425 thisexp = new DotIdExp(loc, thisexp, Id::outer);
3426 }
3427 if (!global.errors)
3428 goto Lagain;
3429 }
3430 if (cdthis)
3431 {
3432 //printf("cdthis = %s\n", cdthis->toChars());
3433 if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL))
3434 error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars());
3435 }
3436 #if 0
3437 else
3438 {
3439 for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration())
3440 {
3441 if (!sf)
3442 {
3443 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
3444 break;
3445 }
3446 printf("sf = %s\n", sf->toChars());
3447 AggregateDeclaration *ad = sf->isThis();
3448 if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL)))
3449 break;
3450 }
3451 }
3452 #endif
3453 }
3454 // LDC , check if reachable
3455 else if (fdn)
3456 {
3457 // make sure the parent context fdn of cd is reachable from sc
3458 for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
3459 {
3460 if (fdn == sp)
3461 break;
3462 FuncDeclaration *fsp = sp ? sp->isFuncDeclaration() : NULL;
3463 if (!sp || (fsp && fsp->isStatic()))
3464 {
3465 error("outer function context of %s is needed to 'new' nested class %s", fdn->toPrettyChars(), cd->toPrettyChars());
3466 break;
3467 }
3468 }
3469
3470 }
3471 else
3472 assert(0);
3473 }
3474 else if (thisexp)
3475 error("e.new is only for allocating nested classes");
3476
3477 FuncDeclaration *f = cd->ctor;
3478 if (f)
3479 {
3480 assert(f);
3481 f = f->overloadResolve(loc, NULL, arguments);
3482 checkDeprecated(sc, f);
3483 member = f->isCtorDeclaration();
3484 assert(member);
3485
3486 cd->accessCheck(loc, sc, member);
3487
3488 tf = (TypeFunction *)f->type;
3489 // type = tf->next;
3490
3491 if (!arguments)
3492 arguments = new Expressions();
3493 functionArguments(loc, sc, tf, arguments);
3494 }
3495 else
3496 {
3497 if (arguments && arguments->dim)
3498 error("no constructor for %s", cd->toChars());
3499 }
3500
3501 if (cd->aggNew)
3502 {
3503 // Prepend the uint size argument to newargs[]
3504 Expression *e = new IntegerExp(loc, cd->size(loc), Type::tuns32);
3505 if (!newargs)
3506 newargs = new Expressions();
3507 newargs->shift(e);
3508
3509 f = cd->aggNew->overloadResolve(loc, NULL, newargs);
3510 allocator = f->isNewDeclaration();
3511 assert(allocator);
3512
3513 tf = (TypeFunction *)f->type;
3514 functionArguments(loc, sc, tf, newargs);
3515 }
3516 else
3517 {
3518 if (newargs && newargs->dim)
3519 error("no allocator for %s", cd->toChars());
3520 }
3521 }
3522 else if (tb->ty == Tstruct)
3523 {
3524 TypeStruct *ts = (TypeStruct *)tb;
3525 StructDeclaration *sd = ts->sym;
3526 TypeFunction *tf;
3527
3528 FuncDeclaration *f = sd->ctor;
3529 if (f && arguments && arguments->dim)
3530 {
3531 assert(f);
3532 f = f->overloadResolve(loc, NULL, arguments);
3533 checkDeprecated(sc, f);
3534 member = f->isCtorDeclaration();
3535 assert(member);
3536
3537 sd->accessCheck(loc, sc, member);
3538
3539 tf = (TypeFunction *)f->type;
3540 // type = tf->next;
3541
3542 if (!arguments)
3543 arguments = new Expressions();
3544 functionArguments(loc, sc, tf, arguments);
3545 }
3546 else
3547 {
3548 if (arguments && arguments->dim)
3549 error("no constructor for %s", sd->toChars());
3550 }
3551
3552
3553 if (sd->aggNew)
3554 {
3555 // Prepend the uint size argument to newargs[]
3556 Expression *e = new IntegerExp(loc, sd->size(loc), Type::tuns32);
3557 if (!newargs)
3558 newargs = new Expressions();
3559 newargs->shift(e);
3560
3561 f = sd->aggNew->overloadResolve(loc, NULL, newargs);
3562 allocator = f->isNewDeclaration();
3563 assert(allocator);
3564
3565 tf = (TypeFunction *)f->type;
3566 functionArguments(loc, sc, tf, newargs);
3567 #if 0
3568 e = new VarExp(loc, f);
3569 e = new CallExp(loc, e, newargs);
3570 e = e->semantic(sc);
3571 e->type = type->pointerTo();
3572 return e;
3573 #endif
3574 }
3575 else
3576 {
3577 if (newargs && newargs->dim)
3578 error("no allocator for %s", sd->toChars());
3579 }
3580
3581 type = type->pointerTo();
3582 }
3583 else if (tb->ty == Tarray && (arguments && arguments->dim))
3584 {
3585 for (size_t i = 0; i < arguments->dim; i++)
3586 {
3587 if (tb->ty != Tarray)
3588 { error("too many arguments for array");
3589 arguments->dim = i;
3590 break;
3591 }
3592
3593 Expression *arg = (Expression *)arguments->data[i];
3594 arg = resolveProperties(sc, arg);
3595 arg = arg->implicitCastTo(sc, Type::tsize_t);
3596 arg = arg->optimize(WANTvalue);
3597 if (arg->op == TOKint64 && (long long)arg->toInteger() < 0)
3598 error("negative array index %s", arg->toChars());
3599 arguments->data[i] = (void *) arg;
3600 tb = ((TypeDArray *)tb)->next->toBasetype();
3601 }
3602 }
3603 else if (tb->isscalar())
3604 {
3605 if (arguments && arguments->dim)
3606 error("no constructor for %s", type->toChars());
3607
3608 type = type->pointerTo();
3609 }
3610 else
3611 {
3612 error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars());
3613 type = type->pointerTo();
3614 }
3615
3616 //printf("NewExp: '%s'\n", toChars());
3617 //printf("NewExp:type '%s'\n", type->toChars());
3618
3619 return this;
3620 }
3621
3622 int NewExp::checkSideEffect(int flag)
3623 {
3624 return 1;
3625 }
3626
3627 int NewExp::canThrow()
3628 {
3629 return 1;
3630 }
3631
3632 void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3633 { int i;
3634
3635 if (thisexp)
3636 { expToCBuffer(buf, hgs, thisexp, PREC_primary);
3637 buf->writeByte('.');
3638 }
3639 buf->writestring("new ");
3640 if (newargs && newargs->dim)
3641 {
3642 buf->writeByte('(');
3643 argsToCBuffer(buf, newargs, hgs);
3644 buf->writeByte(')');
3645 }
3646 newtype->toCBuffer(buf, NULL, hgs);
3647 if (arguments && arguments->dim)
3648 {
3649 buf->writeByte('(');
3650 argsToCBuffer(buf, arguments, hgs);
3651 buf->writeByte(')');
3652 }
3653 }
3654
3655 /********************** NewAnonClassExp **************************************/
3656
3657 NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp,
3658 Expressions *newargs, ClassDeclaration *cd, Expressions *arguments)
3659 : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp))
3660 {
3661 this->thisexp = thisexp;
3662 this->newargs = newargs;
3663 this->cd = cd;
3664 this->arguments = arguments;
3665 }
3666
3667 Expression *NewAnonClassExp::syntaxCopy()
3668 {
3669 return new NewAnonClassExp(loc,
3670 thisexp ? thisexp->syntaxCopy() : NULL,
3671 arraySyntaxCopy(newargs),
3672 (ClassDeclaration *)cd->syntaxCopy(NULL),
3673 arraySyntaxCopy(arguments));
3674 }
3675
3676
3677 Expression *NewAnonClassExp::semantic(Scope *sc)
3678 {
3679 #if LOGSEMANTIC
3680 printf("NewAnonClassExp::semantic() %s\n", toChars());
3681 //printf("thisexp = %p\n", thisexp);
3682 //printf("type: %s\n", type->toChars());
3683 #endif
3684
3685 Expression *d = new DeclarationExp(loc, cd);
3686 d = d->semantic(sc);
3687
3688 Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments);
3689
3690 Expression *c = new CommaExp(loc, d, n);
3691 return c->semantic(sc);
3692 }
3693
3694 int NewAnonClassExp::checkSideEffect(int flag)
3695 {
3696 return 1;
3697 }
3698
3699 int NewAnonClassExp::canThrow()
3700 {
3701 return 1;
3702 }
3703
3704 void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3705 { int i;
3706
3707 if (thisexp)
3708 { expToCBuffer(buf, hgs, thisexp, PREC_primary);
3709 buf->writeByte('.');
3710 }
3711 buf->writestring("new");
3712 if (newargs && newargs->dim)
3713 {
3714 buf->writeByte('(');
3715 argsToCBuffer(buf, newargs, hgs);
3716 buf->writeByte(')');
3717 }
3718 buf->writestring(" class ");
3719 if (arguments && arguments->dim)
3720 {
3721 buf->writeByte('(');
3722 argsToCBuffer(buf, arguments, hgs);
3723 buf->writeByte(')');
3724 }
3725 //buf->writestring(" { }");
3726 if (cd)
3727 {
3728 cd->toCBuffer(buf, hgs);
3729 }
3730 }
3731
3732 /********************** SymbolExp **************************************/
3733
3734 SymbolExp::SymbolExp(Loc loc, enum TOK op, int size, Declaration *var, int hasOverloads)
3735 : Expression(loc, op, size)
3736 {
3737 assert(var);
3738 this->var = var;
3739 this->hasOverloads = hasOverloads;
3740 }
3741
3742 /********************** SymOffExp **************************************/
3743
3744 SymOffExp::SymOffExp(Loc loc, Declaration *var, unsigned offset, int hasOverloads)
3745 : SymbolExp(loc, TOKsymoff, sizeof(SymOffExp), var, hasOverloads)
3746 {
3747 this->offset = offset;
3748
3749 VarDeclaration *v = var->isVarDeclaration();
3750 if (v && v->needThis())
3751 error("need 'this' for address of %s", v->toChars());
3752 }
3753
3754 Expression *SymOffExp::semantic(Scope *sc)
3755 {
3756 #if LOGSEMANTIC
3757 printf("SymOffExp::semantic('%s')\n", toChars());
3758 #endif
3759 //var->semantic(sc);
3760 if (!type)
3761 type = var->type->pointerTo();
3762 VarDeclaration *v = var->isVarDeclaration();
3763 if (v)
3764 {
3765 v->checkNestedReference(sc, loc);
3766 }
3767 return this;
3768 }
3769
3770 int SymOffExp::isBool(int result)
3771 {
3772 return result ? TRUE : FALSE;
3773 }
3774
3775 void SymOffExp::checkEscape()
3776 {
3777 VarDeclaration *v = var->isVarDeclaration();
3778 if (v)
3779 {
3780 if (!v->isDataseg())
3781 error("escaping reference to local variable %s", v->toChars());
3782 }
3783 }
3784
3785 void SymOffExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3786 {
3787 if (offset)
3788 buf->printf("(& %s+%u)", var->toChars(), offset);
3789 else
3790 buf->printf("& %s", var->toChars());
3791 }
3792
3793 /******************************** VarExp **************************/
3794
3795 VarExp::VarExp(Loc loc, Declaration *var, int hasOverloads)
3796 : SymbolExp(loc, TOKvar, sizeof(VarExp), var, hasOverloads)
3797 {
3798 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
3799 //if (strcmp(var->ident->toChars(), "func") == 0) halt();
3800 this->type = var->type;
3801 }
3802
3803 int VarExp::equals(Object *o)
3804 { VarExp *ne;
3805
3806 if (this == o ||
3807 (((Expression *)o)->op == TOKvar &&
3808 ((ne = (VarExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
3809 var == ne->var))
3810 return 1;
3811 return 0;
3812 }
3813
3814 Expression *VarExp::semantic(Scope *sc)
3815 { FuncLiteralDeclaration *fd;
3816
3817 #if LOGSEMANTIC
3818 printf("VarExp::semantic(%s)\n", toChars());
3819 #endif
3820 if (!type)
3821 { type = var->type;
3822 #if 0
3823 if (var->storage_class & STClazy)
3824 {
3825 TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd);
3826 type = new TypeDelegate(tf);
3827 type = type->semantic(loc, sc);
3828 }
3829 #endif
3830 }
3831
3832 // LDC: Fixes bug 1161, http://d.puremagic.com/issues/show_bug.cgi?id=1161
3833 // check access to VarDeclaration
3834 accessCheck(loc, sc, NULL, var);
3835
3836 VarDeclaration *v = var->isVarDeclaration();
3837 if (v)
3838 {
3839 #if 0
3840 if ((v->isConst() || v->isInvariant()) &&
3841 type->toBasetype()->ty != Tsarray && v->init)
3842 {
3843 ExpInitializer *ei = v->init->isExpInitializer();
3844 if (ei)
3845 {
3846 //ei->exp->implicitCastTo(sc, type)->print();
3847 return ei->exp->implicitCastTo(sc, type);
3848 }
3849 }
3850 #endif
3851 v->checkNestedReference(sc, loc);
3852 }
3853 #if 0
3854 else if ((fd = var->isFuncLiteralDeclaration()) != NULL)
3855 { Expression *e;
3856 e = new FuncExp(loc, fd);
3857 e->type = type;
3858 return e;
3859 }
3860 #endif
3861 return this;
3862 }
3863
3864 char *VarExp::toChars()
3865 {
3866 return var->toChars();
3867 }
3868
3869 void VarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3870 {
3871 buf->writestring(var->toChars());
3872 }
3873
3874 void VarExp::checkEscape()
3875 {
3876 VarDeclaration *v = var->isVarDeclaration();
3877 if (v)
3878 { Type *tb = v->type->toBasetype();
3879 // if reference type
3880 if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass)
3881 {
3882 if ((v->isAuto() || v->isScope()) && !v->noauto)
3883 error("escaping reference to auto local %s", v->toChars());
3884 else if (v->storage_class & STCvariadic)
3885 error("escaping reference to variadic parameter %s", v->toChars());
3886 }
3887 }
3888 }
3889
3890 int VarExp::isLvalue()
3891 {
3892 if (var->storage_class & STClazy)
3893 return 0;
3894 return 1;
3895 }
3896
3897 Expression *VarExp::toLvalue(Scope *sc, Expression *e)
3898 {
3899 #if 0
3900 tym = tybasic(e1->ET->Tty);
3901 if (!(tyscalar(tym) ||
3902 tym == TYstruct ||
3903 tym == TYarray && e->Eoper == TOKaddr))
3904 synerr(EM_lvalue); // lvalue expected
3905 #endif
3906 if (var->storage_class & STClazy)
3907 error("lazy variables cannot be lvalues");
3908 return this;
3909 }
3910
3911 Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
3912 {
3913 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
3914 if (type && type->toBasetype()->ty == Tsarray)
3915 error("cannot change reference to static array '%s'", var->toChars());
3916
3917 var->checkModify(loc, sc, type);
3918
3919 // See if this expression is a modifiable lvalue (i.e. not const)
3920 return toLvalue(sc, e);
3921 }
3922
3923
3924 /******************************** OverExp **************************/
3925
3926 #if DMDV2
3927 OverExp::OverExp(OverloadSet *s)
3928 : Expression(loc, TOKoverloadset, sizeof(OverExp))
3929 {
3930 //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
3931 vars = s;
3932 type = Type::tvoid;
3933 }
3934
3935 int OverExp::isLvalue()
3936 {
3937 return 1;
3938 }
3939
3940 Expression *OverExp::toLvalue(Scope *sc, Expression *e)
3941 {
3942 return this;
3943 }
3944 #endif
3945
3946
3947 /******************************** TupleExp **************************/
3948
3949 TupleExp::TupleExp(Loc loc, Expressions *exps)
3950 : Expression(loc, TOKtuple, sizeof(TupleExp))
3951 {
3952 //printf("TupleExp(this = %p)\n", this);
3953 this->exps = exps;
3954 this->type = NULL;
3955 }
3956
3957
3958 TupleExp::TupleExp(Loc loc, TupleDeclaration *tup)
3959 : Expression(loc, TOKtuple, sizeof(TupleExp))
3960 {
3961 exps = new Expressions();
3962 type = NULL;
3963
3964 exps->reserve(tup->objects->dim);
3965 for (size_t i = 0; i < tup->objects->dim; i++)
3966 { Object *o = (Object *)tup->objects->data[i];
3967 if (o->dyncast() == DYNCAST_EXPRESSION)
3968 {
3969 Expression *e = (Expression *)o;
3970 e = e->syntaxCopy();
3971 exps->push(e);
3972 }
3973 else if (o->dyncast() == DYNCAST_DSYMBOL)
3974 {
3975 Dsymbol *s = (Dsymbol *)o;
3976 Expression *e = new DsymbolExp(loc, s);
3977 exps->push(e);
3978 }
3979 else if (o->dyncast() == DYNCAST_TYPE)
3980 {
3981 Type *t = (Type *)o;
3982 Expression *e = new TypeExp(loc, t);
3983 exps->push(e);
3984 }
3985 else
3986 {
3987 error("%s is not an expression", o->toChars());
3988 }
3989 }
3990 }
3991
3992 int TupleExp::equals(Object *o)
3993 { TupleExp *ne;
3994
3995 if (this == o)
3996 return 1;
3997 if (((Expression *)o)->op == TOKtuple)
3998 {
3999 TupleExp *te = (TupleExp *)o;
4000 if (exps->dim != te->exps->dim)
4001 return 0;
4002 for (size_t i = 0; i < exps->dim; i++)
4003 { Expression *e1 = (Expression *)exps->data[i];
4004 Expression *e2 = (Expression *)te->exps->data[i];
4005
4006 if (!e1->equals(e2))
4007 return 0;
4008 }
4009 return 1;
4010 }
4011 return 0;
4012 }
4013
4014 Expression *TupleExp::syntaxCopy()
4015 {
4016 return new TupleExp(loc, arraySyntaxCopy(exps));
4017 }
4018
4019 Expression *TupleExp::semantic(Scope *sc)
4020 {
4021 #if LOGSEMANTIC
4022 printf("+TupleExp::semantic(%s)\n", toChars());
4023 #endif
4024 if (type)
4025 return this;
4026
4027 // Run semantic() on each argument
4028 for (size_t i = 0; i < exps->dim; i++)
4029 { Expression *e = (Expression *)exps->data[i];
4030
4031 e = e->semantic(sc);
4032 if (!e->type)
4033 { error("%s has no value", e->toChars());
4034 e->type = Type::terror;
4035 }
4036 exps->data[i] = (void *)e;
4037 }
4038
4039 expandTuples(exps);
4040 if (0 && exps->dim == 1)
4041 {
4042 return (Expression *)exps->data[0];
4043 }
4044 type = new TypeTuple(exps);
4045 //printf("-TupleExp::semantic(%s)\n", toChars());
4046 return this;
4047 }
4048
4049 void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4050 {
4051 buf->writestring("tuple(");
4052 argsToCBuffer(buf, exps, hgs);
4053 buf->writeByte(')');
4054 }
4055
4056 int TupleExp::checkSideEffect(int flag)
4057 { int f = 0;
4058
4059 for (int i = 0; i < exps->dim; i++)
4060 { Expression *e = (Expression *)exps->data[i];
4061
4062 f |= e->checkSideEffect(2);
4063 }
4064 if (flag == 0 && f == 0)
4065 Expression::checkSideEffect(0);
4066 return f;
4067 }
4068
4069 int TupleExp::canThrow()
4070 {
4071 return arrayExpressionCanThrow(exps);
4072 }
4073
4074 void TupleExp::checkEscape()
4075 {
4076 for (size_t i = 0; i < exps->dim; i++)
4077 { Expression *e = (Expression *)exps->data[i];
4078 e->checkEscape();
4079 }
4080 }
4081
4082 /******************************** FuncExp *********************************/
4083
4084 FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd)
4085 : Expression(loc, TOKfunction, sizeof(FuncExp))
4086 {
4087 this->fd = fd;
4088 }
4089
4090 Expression *FuncExp::syntaxCopy()
4091 {
4092 return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL));
4093 }
4094
4095 Expression *FuncExp::semantic(Scope *sc)
4096 {
4097 #if LOGSEMANTIC
4098 printf("FuncExp::semantic(%s)\n", toChars());
4099 #endif
4100 if (!type)
4101 {
4102 fd->semantic(sc);
4103 fd->parent = sc->parent;
4104 if (global.errors)
4105 {
4106 }
4107 else
4108 {
4109 fd->semantic2(sc);
4110 if (!global.errors)
4111 {
4112 fd->semantic3(sc);
4113
4114 if (!global.errors && global.params.useInline)
4115 fd->inlineScan();
4116 }
4117 }
4118
4119 // Type is a "delegate to" or "pointer to" the function literal
4120 if (fd->isNested())
4121 {
4122 type = new TypeDelegate(fd->type);
4123 type = type->semantic(loc, sc);
4124 }
4125 else
4126 {
4127 type = fd->type->pointerTo();
4128 }
4129 fd->tookAddressOf++;
4130 }
4131 return this;
4132 }
4133
4134 char *FuncExp::toChars()
4135 {
4136 return fd->toChars();
4137 }
4138
4139 void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4140 {
4141 buf->writestring(fd->toChars());
4142 }
4143
4144
4145 /******************************** DeclarationExp **************************/
4146
4147 DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration)
4148 : Expression(loc, TOKdeclaration, sizeof(DeclarationExp))
4149 {
4150 this->declaration = declaration;
4151 }
4152
4153 Expression *DeclarationExp::syntaxCopy()
4154 {
4155 return new DeclarationExp(loc, declaration->syntaxCopy(NULL));
4156 }
4157
4158 Expression *DeclarationExp::semantic(Scope *sc)
4159 {
4160 if (type)
4161 return this;
4162
4163 #if LOGSEMANTIC
4164 printf("DeclarationExp::semantic() %s\n", toChars());
4165 #endif
4166
4167 /* This is here to support extern(linkage) declaration,
4168 * where the extern(linkage) winds up being an AttribDeclaration
4169 * wrapper.
4170 */
4171 Dsymbol *s = declaration;
4172
4173 AttribDeclaration *ad = declaration->isAttribDeclaration();
4174 if (ad)
4175 {
4176 if (ad->decl && ad->decl->dim == 1)
4177 s = (Dsymbol *)ad->decl->data[0];
4178 }
4179
4180 if (s->isVarDeclaration())
4181 { // Do semantic() on initializer first, so:
4182 // int a = a;
4183 // will be illegal.
4184 declaration->semantic(sc);
4185 s->parent = sc->parent;
4186 }
4187
4188 //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc);
4189 // Insert into both local scope and function scope.
4190 // Must be unique in both.
4191 if (s->ident)
4192 {
4193 if (!sc->insert(s))
4194 error("declaration %s is already defined", s->toPrettyChars());
4195 else if (sc->func)
4196 { VarDeclaration *v = s->isVarDeclaration();
4197 if (s->isFuncDeclaration() &&
4198 !sc->func->localsymtab->insert(s))
4199 error("declaration %s is already defined in another scope in %s", s->toPrettyChars(), sc->func->toChars());
4200 else if (!global.params.useDeprecated)
4201 { // Disallow shadowing
4202
4203 for (Scope *scx = sc->enclosing; scx && scx->func == sc->func; scx = scx->enclosing)
4204 { Dsymbol *s2;
4205
4206 if (scx->scopesym && scx->scopesym->symtab &&
4207 (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL &&
4208 s != s2)
4209 {
4210 error("shadowing declaration %s is deprecated", s->toPrettyChars());
4211 }
4212 }
4213 }
4214 }
4215 }
4216 if (!s->isVarDeclaration())
4217 {
4218 declaration->semantic(sc);
4219 s->parent = sc->parent;
4220 }
4221 if (!global.errors)
4222 {
4223 declaration->semantic2(sc);
4224 if (!global.errors)
4225 {
4226 declaration->semantic3(sc);
4227
4228 if (!global.errors && global.params.useInline)
4229 declaration->inlineScan();
4230 }
4231 }
4232
4233 type = Type::tvoid;
4234 return this;
4235 }
4236
4237 int DeclarationExp::checkSideEffect(int flag)
4238 {
4239 return 1;
4240 }
4241
4242 int DeclarationExp::canThrow()
4243 {
4244 VarDeclaration *v = declaration->isVarDeclaration();
4245 if (v && v->init)
4246 { ExpInitializer *ie = v->init->isExpInitializer();
4247 return ie && ie->exp->canThrow();
4248 }
4249 return 0;
4250 }
4251
4252 void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4253 {
4254 declaration->toCBuffer(buf, hgs);
4255 }
4256
4257
4258 /************************ TypeidExp ************************************/
4259
4260 /*
4261 * typeid(int)
4262 */
4263
4264 TypeidExp::TypeidExp(Loc loc, Type *typeidType)
4265 : Expression(loc, TOKtypeid, sizeof(TypeidExp))
4266 {
4267 this->typeidType = typeidType;
4268 }
4269
4270
4271 Expression *TypeidExp::syntaxCopy()
4272 {
4273 return new TypeidExp(loc, typeidType->syntaxCopy());
4274 }
4275
4276
4277 Expression *TypeidExp::semantic(Scope *sc)
4278 { Expression *e;
4279
4280 #if LOGSEMANTIC
4281 printf("TypeidExp::semantic()\n");
4282 #endif
4283 typeidType = typeidType->semantic(loc, sc);
4284 e = typeidType->getTypeInfo(sc);
4285 if (e->loc.linnum == 0)
4286 e->loc = loc; // so there's at least some line number info
4287 return e;
4288 }
4289
4290 void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4291 {
4292 buf->writestring("typeid(");
4293 typeidType->toCBuffer(buf, NULL, hgs);
4294 buf->writeByte(')');
4295 }
4296
4297 /************************ TraitsExp ************************************/
4298 #if DMDV2
4299 /*
4300 * __traits(identifier, args...)
4301 */
4302
4303 TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args)
4304 : Expression(loc, TOKtraits, sizeof(TraitsExp))
4305 {
4306 this->ident = ident;
4307 this->args = args;
4308 }
4309
4310
4311 Expression *TraitsExp::syntaxCopy()
4312 {
4313 return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args));
4314 }
4315
4316
4317 void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4318 {
4319 buf->writestring("__traits(");
4320 buf->writestring(ident->toChars());
4321 if (args)
4322 {
4323 for (int i = 0; i < args->dim; i++)
4324 {
4325 buf->writeByte(',');
4326 Object *oarg = (Object *)args->data[i];
4327 ObjectToCBuffer(buf, hgs, oarg);
4328 }
4329 }
4330 buf->writeByte(')');
4331 }
4332 #endif
4333
4334 /************************************************************/
4335
4336 HaltExp::HaltExp(Loc loc)
4337 : Expression(loc, TOKhalt, sizeof(HaltExp))
4338 {
4339 }
4340
4341 Expression *HaltExp::semantic(Scope *sc)
4342 {
4343 #if LOGSEMANTIC
4344 printf("HaltExp::semantic()\n");
4345 #endif
4346 type = Type::tvoid;
4347 return this;
4348 }
4349
4350 int HaltExp::checkSideEffect(int flag)
4351 {
4352 return 1;
4353 }
4354
4355 void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4356 {
4357 buf->writestring("halt");
4358 }
4359
4360 /************************************************************/
4361
4362 IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
4363 Type *tspec, enum TOK tok2, TemplateParameters *parameters)
4364 : Expression(loc, TOKis, sizeof(IsExp))
4365 {
4366 this->targ = targ;
4367 this->id = id;
4368 this->tok = tok;
4369 this->tspec = tspec;
4370 this->tok2 = tok2;
4371 this->parameters = parameters;
4372 }
4373
4374 Expression *IsExp::syntaxCopy()
4375 {
4376 // This section is identical to that in TemplateDeclaration::syntaxCopy()
4377 TemplateParameters *p = NULL;
4378 if (parameters)
4379 {
4380 p = new TemplateParameters();
4381 p->setDim(parameters->dim);
4382 for (int i = 0; i < p->dim; i++)
4383 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
4384 p->data[i] = (void *)tp->syntaxCopy();
4385 }
4386 }
4387
4388 return new IsExp(loc,
4389 targ->syntaxCopy(),
4390 id,
4391 tok,
4392 tspec ? tspec->syntaxCopy() : NULL,
4393 tok2,
4394 p);
4395 }
4396
4397 Expression *IsExp::semantic(Scope *sc)
4398 { Type *tded;
4399
4400 /* is(targ id tok tspec)
4401 * is(targ id == tok2)
4402 */
4403
4404 //printf("IsExp::semantic(%s)\n", toChars());
4405 if (id && !(sc->flags & SCOPEstaticif))
4406 error("can only declare type aliases within static if conditionals");
4407
4408 unsigned errors_save = global.errors;
4409 global.errors = 0;
4410 global.gag++; // suppress printing of error messages
4411 targ = targ->semantic(loc, sc);
4412 global.gag--;
4413 unsigned gerrors = global.errors;
4414 global.errors = errors_save;
4415
4416 if (gerrors) // if any errors happened
4417 { // then condition is false
4418 goto Lno;
4419 }
4420 else if (tok2 != TOKreserved)
4421 {
4422 switch (tok2)
4423 {
4424 case TOKtypedef:
4425 if (targ->ty != Ttypedef)
4426 goto Lno;
4427 tded = ((TypeTypedef *)targ)->sym->basetype;
4428 break;
4429
4430 case TOKstruct:
4431 if (targ->ty != Tstruct)
4432 goto Lno;
4433 if (((TypeStruct *)targ)->sym->isUnionDeclaration())
4434 goto Lno;
4435 tded = targ;
4436 break;
4437
4438 case TOKunion:
4439 if (targ->ty != Tstruct)
4440 goto Lno;
4441 if (!((TypeStruct *)targ)->sym->isUnionDeclaration())
4442 goto Lno;
4443 tded = targ;
4444 break;
4445
4446 case TOKclass:
4447 if (targ->ty != Tclass)
4448 goto Lno;
4449 if (((TypeClass *)targ)->sym->isInterfaceDeclaration())
4450 goto Lno;
4451 tded = targ;
4452 break;
4453
4454 case TOKinterface:
4455 if (targ->ty != Tclass)
4456 goto Lno;
4457 if (!((TypeClass *)targ)->sym->isInterfaceDeclaration())
4458 goto Lno;
4459 tded = targ;
4460 break;
4461 #if DMDV2
4462 case TOKconst:
4463 if (!targ->isConst())
4464 goto Lno;
4465 tded = targ;
4466 break;
4467
4468 case TOKinvariant:
4469 case TOKimmutable:
4470 if (!targ->isInvariant())
4471 goto Lno;
4472 tded = targ;
4473 break;
4474 #endif
4475
4476 case TOKsuper:
4477 // If class or interface, get the base class and interfaces
4478 if (targ->ty != Tclass)
4479 goto Lno;
4480 else
4481 { ClassDeclaration *cd = ((TypeClass *)targ)->sym;
4482 Arguments *args = new Arguments;
4483 args->reserve(cd->baseclasses.dim);
4484 for (size_t i = 0; i < cd->baseclasses.dim; i++)
4485 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
4486 args->push(new Argument(STCin, b->type, NULL, NULL));
4487 }
4488 tded = new TypeTuple(args);
4489 }
4490 break;
4491
4492 case TOKenum:
4493 if (targ->ty != Tenum)
4494 goto Lno;
4495 tded = ((TypeEnum *)targ)->sym->memtype;
4496 break;
4497
4498 case TOKdelegate:
4499 if (targ->ty != Tdelegate)
4500 goto Lno;
4501 tded = ((TypeDelegate *)targ)->next; // the underlying function type
4502 break;
4503
4504 case TOKfunction:
4505 {
4506 if (targ->ty != Tfunction)
4507 goto Lno;
4508 tded = targ;
4509
4510 /* Generate tuple from function parameter types.
4511 */
4512 assert(tded->ty == Tfunction);
4513 Arguments *params = ((TypeFunction *)tded)->parameters;
4514 size_t dim = Argument::dim(params);
4515 Arguments *args = new Arguments;
4516 args->reserve(dim);
4517 for (size_t i = 0; i < dim; i++)
4518 { Argument *arg = Argument::getNth(params, i);
4519 assert(arg && arg->type);
4520 args->push(new Argument(arg->storageClass, arg->type, NULL, NULL));
4521 }
4522 tded = new TypeTuple(args);
4523 break;
4524 }
4525 case TOKreturn:
4526 /* Get the 'return type' for the function,
4527 * delegate, or pointer to function.
4528 */
4529 if (targ->ty == Tfunction)
4530 tded = ((TypeFunction *)targ)->next;
4531 else if (targ->ty == Tdelegate)
4532 { tded = ((TypeDelegate *)targ)->next;
4533 tded = ((TypeFunction *)tded)->next;
4534 }
4535 else if (targ->ty == Tpointer &&
4536 ((TypePointer *)targ)->next->ty == Tfunction)
4537 { tded = ((TypePointer *)targ)->next;
4538 tded = ((TypeFunction *)tded)->next;
4539 }
4540 else
4541 goto Lno;
4542 break;
4543
4544 default:
4545 assert(0);
4546 }
4547 goto Lyes;
4548 }
4549 else if (id && tspec)
4550 {
4551 /* Evaluate to TRUE if targ matches tspec.
4552 * If TRUE, declare id as an alias for the specialized type.
4553 */
4554
4555 MATCH m;
4556 assert(parameters && parameters->dim);
4557
4558 Objects dedtypes;
4559 dedtypes.setDim(parameters->dim);
4560 dedtypes.zero();
4561
4562 m = targ->deduceType(NULL, tspec, parameters, &dedtypes);
4563 if (m == MATCHnomatch ||
4564 (m != MATCHexact && tok == TOKequal))
4565 goto Lno;
4566 else
4567 {
4568 tded = (Type *)dedtypes.data[0];
4569 if (!tded)
4570 tded = targ;
4571
4572 Objects tiargs;
4573 tiargs.setDim(1);
4574 tiargs.data[0] = (void *)targ;
4575
4576 for (int i = 1; i < parameters->dim; i++)
4577 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
4578 Declaration *s;
4579
4580 m = tp->matchArg(sc, &tiargs, i, parameters, &dedtypes, &s);
4581 if (m == MATCHnomatch)
4582 goto Lno;
4583 s->semantic(sc);
4584 if (!sc->insert(s))
4585 error("declaration %s is already defined", s->toChars());
4586 #if 0
4587 Object *o = (Object *)dedtypes.data[i];
4588 Dsymbol *s = TemplateDeclaration::declareParameter(loc, sc, tp, o);
4589 #endif
4590 if (sc->sd)
4591 s->addMember(sc, sc->sd, 1);
4592 }
4593
4594 goto Lyes;
4595 }
4596 }
4597 else if (id)
4598 {
4599 /* Declare id as an alias for type targ. Evaluate to TRUE
4600 */
4601 tded = targ;
4602 goto Lyes;
4603 }
4604 else if (tspec)
4605 {
4606 /* Evaluate to TRUE if targ matches tspec
4607 */
4608 tspec = tspec->semantic(loc, sc);
4609 //printf("targ = %s\n", targ->toChars());
4610 //printf("tspec = %s\n", tspec->toChars());
4611 if (tok == TOKcolon)
4612 { if (targ->implicitConvTo(tspec))
4613 goto Lyes;
4614 else
4615 goto Lno;
4616 }
4617 else /* == */
4618 { if (targ->equals(tspec))
4619 goto Lyes;
4620 else
4621 goto Lno;
4622 }
4623 }
4624
4625 Lyes:
4626 if (id)
4627 {
4628 Dsymbol *s = new AliasDeclaration(loc, id, tded);
4629 s->semantic(sc);
4630 if (!sc->insert(s))
4631 error("declaration %s is already defined", s->toChars());
4632 if (sc->sd)
4633 s->addMember(sc, sc->sd, 1);
4634 }
4635 //printf("Lyes\n");
4636 return new IntegerExp(loc, 1, Type::tbool);
4637
4638 Lno:
4639 //printf("Lno\n");
4640 return new IntegerExp(loc, 0, Type::tbool);
4641 }
4642
4643 void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4644 {
4645 buf->writestring("is(");
4646 targ->toCBuffer(buf, id, hgs);
4647 if (tok2 != TOKreserved)
4648 {
4649 buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2));
4650 }
4651 else if (tspec)
4652 {
4653 if (tok == TOKcolon)
4654 buf->writestring(" : ");
4655 else
4656 buf->writestring(" == ");
4657 tspec->toCBuffer(buf, NULL, hgs);
4658 }
4659 #if DMDV2
4660 if (parameters)
4661 { // First parameter is already output, so start with second
4662 for (int i = 1; i < parameters->dim; i++)
4663 {
4664 buf->writeByte(',');
4665 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
4666 tp->toCBuffer(buf, hgs);
4667 }
4668 }
4669 #endif
4670 buf->writeByte(')');
4671 }
4672
4673
4674 /************************************************************/
4675
4676 UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1)
4677 : Expression(loc, op, size)
4678 {
4679 this->e1 = e1;
4680 }
4681
4682 Expression *UnaExp::syntaxCopy()
4683 { UnaExp *e;
4684
4685 e = (UnaExp *)copy();
4686 e->type = NULL;
4687 e->e1 = e->e1->syntaxCopy();
4688 return e;
4689 }
4690
4691 Expression *UnaExp::semantic(Scope *sc)
4692 {
4693 #if LOGSEMANTIC
4694 printf("UnaExp::semantic('%s')\n", toChars());
4695 #endif
4696 e1 = e1->semantic(sc);
4697 // if (!e1->type)
4698 // error("%s has no value", e1->toChars());
4699 return this;
4700 }
4701
4702 int UnaExp::canThrow()
4703 {
4704 return e1->canThrow();
4705 }
4706
4707 void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4708 {
4709 buf->writestring(Token::toChars(op));
4710 expToCBuffer(buf, hgs, e1, precedence[op]);
4711 }
4712
4713 /************************************************************/
4714
4715 BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2)
4716 : Expression(loc, op, size)
4717 {
4718 this->e1 = e1;
4719 this->e2 = e2;
4720 }
4721
4722 Expression *BinExp::syntaxCopy()
4723 { BinExp *e;
4724
4725 e = (BinExp *)copy();
4726 e->type = NULL;
4727 e->e1 = e->e1->syntaxCopy();
4728 e->e2 = e->e2->syntaxCopy();
4729 return e;
4730 }
4731
4732 Expression *BinExp::semantic(Scope *sc)
4733 {
4734 #if LOGSEMANTIC
4735 printf("BinExp::semantic('%s')\n", toChars());
4736 #endif
4737 e1 = e1->semantic(sc);
4738 if (!e1->type &&
4739 !(op == TOKassign && e1->op == TOKdottd)) // a.template = e2
4740 {
4741 error("%s has no value", e1->toChars());
4742 e1->type = Type::terror;
4743 }
4744 e2 = e2->semantic(sc);
4745 if (!e2->type)
4746 {
4747 error("%s has no value", e2->toChars());
4748 e2->type = Type::terror;
4749 }
4750 return this;
4751 }
4752
4753 Expression *BinExp::semanticp(Scope *sc)
4754 {
4755 BinExp::semantic(sc);
4756 e1 = resolveProperties(sc, e1);
4757 e2 = resolveProperties(sc, e2);
4758 return this;
4759 }
4760
4761 /***************************
4762 * Common semantic routine for some xxxAssignExp's.
4763 */
4764
4765 Expression *BinExp::commonSemanticAssign(Scope *sc)
4766 { Expression *e;
4767
4768 if (!type)
4769 {
4770 BinExp::semantic(sc);
4771 e2 = resolveProperties(sc, e2);
4772
4773 e = op_overload(sc);
4774 if (e)
4775 return e;
4776
4777 if (e1->op == TOKslice)
4778 { // T[] op= ...
4779 typeCombine(sc);
4780 type = e1->type;
4781 return arrayOp(sc);
4782 }
4783
4784 e1 = e1->modifiableLvalue(sc, e1);
4785 e1->checkScalar();
4786 type = e1->type;
4787 if (type->toBasetype()->ty == Tbool)
4788 {
4789 error("operator not allowed on bool expression %s", toChars());
4790 }
4791 typeCombine(sc);
4792 e1->checkArithmetic();
4793 e2->checkArithmetic();
4794
4795 if (op == TOKmodass && e2->type->iscomplex())
4796 { error("cannot perform modulo complex arithmetic");
4797 return new IntegerExp(0);
4798 }
4799 }
4800 return this;
4801 }
4802
4803 Expression *BinExp::commonSemanticAssignIntegral(Scope *sc)
4804 { Expression *e;
4805
4806 if (!type)
4807 {
4808 BinExp::semantic(sc);
4809 e2 = resolveProperties(sc, e2);
4810
4811 e = op_overload(sc);
4812 if (e)
4813 return e;
4814
4815 if (e1->op == TOKslice)
4816 { // T[] op= ...
4817 typeCombine(sc);
4818 type = e1->type;
4819 return arrayOp(sc);
4820 }
4821
4822 e1 = e1->modifiableLvalue(sc, e1);
4823 e1->checkScalar();
4824 type = e1->type;
4825 if (type->toBasetype()->ty == Tbool)
4826 {
4827 e2 = e2->implicitCastTo(sc, type);
4828 }
4829
4830 typeCombine(sc);
4831 e1->checkIntegral();
4832 e2->checkIntegral();
4833 }
4834 return this;
4835 }
4836
4837 int BinExp::checkSideEffect(int flag)
4838 {
4839 if (op == TOKplusplus ||
4840 op == TOKminusminus ||
4841 op == TOKassign ||
4842 op == TOKconstruct ||
4843 op == TOKblit ||
4844 op == TOKaddass ||
4845 op == TOKminass ||
4846 op == TOKcatass ||
4847 op == TOKmulass ||
4848 op == TOKdivass ||
4849 op == TOKmodass ||
4850 op == TOKshlass ||
4851 op == TOKshrass ||
4852 op == TOKushrass ||
4853 op == TOKandass ||
4854 op == TOKorass ||
4855 op == TOKxorass ||
4856 op == TOKin ||
4857 op == TOKremove)
4858 return 1;
4859 return Expression::checkSideEffect(flag);
4860 }
4861
4862 void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4863 {
4864 expToCBuffer(buf, hgs, e1, precedence[op]);
4865 buf->writeByte(' ');
4866 buf->writestring(Token::toChars(op));
4867 buf->writeByte(' ');
4868 expToCBuffer(buf, hgs, e2, (enum PREC)(precedence[op] + 1));
4869 }
4870
4871 int BinExp::isunsigned()
4872 {
4873 return e1->type->isunsigned() || e2->type->isunsigned();
4874 }
4875
4876 int BinExp::canThrow()
4877 {
4878 return e1->canThrow() || e2->canThrow();
4879 }
4880
4881 void BinExp::incompatibleTypes()
4882 {
4883 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
4884 e1->toChars(), Token::toChars(op), e2->toChars(),
4885 e1->type->toChars(), e2->type->toChars());
4886 }
4887
4888 /************************************************************/
4889
4890 CompileExp::CompileExp(Loc loc, Expression *e)
4891 : UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
4892 {
4893 }
4894
4895 Expression *CompileExp::semantic(Scope *sc)
4896 {
4897 #if LOGSEMANTIC
4898 printf("CompileExp::semantic('%s')\n", toChars());
4899 #endif
4900 UnaExp::semantic(sc);
4901 e1 = resolveProperties(sc, e1);
4902 e1 = e1->optimize(WANTvalue | WANTinterpret);
4903 if (e1->op != TOKstring)
4904 { error("argument to mixin must be a string, not (%s)", e1->toChars());
4905 type = Type::terror;
4906 return this;
4907 }
4908 StringExp *se = (StringExp *)e1;
4909 se = se->toUTF8(sc);
4910 Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
4911 p.loc = loc;
4912 p.nextToken();
4913 //printf("p.loc.linnum = %d\n", p.loc.linnum);
4914 Expression *e = p.parseExpression();
4915 if (p.token.value != TOKeof)
4916 error("incomplete mixin expression (%s)", se->toChars());
4917 return e->semantic(sc);
4918 }
4919
4920 void CompileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4921 {
4922 buf->writestring("mixin(");
4923 expToCBuffer(buf, hgs, e1, PREC_assign);
4924 buf->writeByte(')');
4925 }
4926
4927 /************************************************************/
4928
4929 FileExp::FileExp(Loc loc, Expression *e)
4930 : UnaExp(loc, TOKmixin, sizeof(FileExp), e)
4931 {
4932 }
4933
4934 Expression *FileExp::semantic(Scope *sc)
4935 { char *name;
4936 StringExp *se;
4937
4938 #if LOGSEMANTIC
4939 printf("FileExp::semantic('%s')\n", toChars());
4940 #endif
4941 UnaExp::semantic(sc);
4942 e1 = resolveProperties(sc, e1);
4943 e1 = e1->optimize(WANTvalue);
4944 if (e1->op != TOKstring)
4945 { error("file name argument must be a string, not (%s)", e1->toChars());
4946 goto Lerror;
4947 }
4948 se = (StringExp *)e1;
4949 se = se->toUTF8(sc);
4950 name = (char *)se->string;
4951
4952 if (!global.params.fileImppath)
4953 { error("need -Jpath switch to import text file %s", name);
4954 goto Lerror;
4955 }
4956
4957 if (name != FileName::name(name))
4958 { error("use -Jpath switch to provide path for filename %s", name);
4959 goto Lerror;
4960 }
4961
4962 name = FileName::searchPath(global.filePath, name, 0);
4963 if (!name)
4964 { error("file %s cannot be found, check -Jpath", se->toChars());
4965 goto Lerror;
4966 }
4967
4968 if (global.params.verbose)
4969 printf("file %s\t(%s)\n", se->string, name);
4970
4971 { File f(name);
4972 if (f.read())
4973 { error("cannot read file %s", f.toChars());
4974 goto Lerror;
4975 }
4976 else
4977 {
4978 f.ref = 1;
4979 se = new StringExp(loc, f.buffer, f.len);
4980 }
4981 }
4982 Lret:
4983 return se->semantic(sc);
4984
4985 Lerror:
4986 se = new StringExp(loc, (char *)"");
4987 goto Lret;
4988 }
4989
4990 void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4991 {
4992 buf->writestring("import(");
4993 expToCBuffer(buf, hgs, e1, PREC_assign);
4994 buf->writeByte(')');
4995 }
4996
4997 /************************************************************/
4998
4999 AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg)
5000 : UnaExp(loc, TOKassert, sizeof(AssertExp), e)
5001 {
5002 this->msg = msg;
5003 }
5004
5005 Expression *AssertExp::syntaxCopy()
5006 {
5007 AssertExp *ae = new AssertExp(loc, e1->syntaxCopy(),
5008 msg ? msg->syntaxCopy() : NULL);
5009 return ae;
5010 }
5011
5012 Expression *AssertExp::semantic(Scope *sc)
5013 {
5014 #if LOGSEMANTIC
5015 printf("AssertExp::semantic('%s')\n", toChars());
5016 #endif
5017 UnaExp::semantic(sc);
5018 e1 = resolveProperties(sc, e1);
5019 // BUG: see if we can do compile time elimination of the Assert
5020 e1 = e1->optimize(WANTvalue);
5021 e1 = e1->checkToBoolean();
5022 if (msg)
5023 {
5024 msg = msg->semantic(sc);
5025 msg = resolveProperties(sc, msg);
5026 msg = msg->implicitCastTo(sc, Type::tchar->constOf()->arrayOf());
5027 msg = msg->optimize(WANTvalue);
5028 }
5029 if (e1->isBool(FALSE))
5030 {
5031 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
5032 fd->hasReturnExp |= 4;
5033
5034 if (!global.params.useAssert)
5035 { Expression *e = new HaltExp(loc);
5036 e = e->semantic(sc);
5037 return e;
5038 }
5039 }
5040 type = Type::tvoid;
5041 return this;
5042 }
5043
5044 int AssertExp::checkSideEffect(int flag)
5045 {
5046 return 1;
5047 }
5048
5049 int AssertExp::canThrow()
5050 {
5051 return (global.params.useAssert != 0);
5052 }
5053
5054 void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5055 {
5056 buf->writestring("assert(");
5057 expToCBuffer(buf, hgs, e1, PREC_assign);
5058 if (msg)
5059 {
5060 buf->writeByte(',');
5061 expToCBuffer(buf, hgs, msg, PREC_assign);
5062 }
5063 buf->writeByte(')');
5064 }
5065
5066 /************************************************************/
5067
5068 DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident)
5069 : UnaExp(loc, TOKdot, sizeof(DotIdExp), e)
5070 {
5071 this->ident = ident;
5072 }
5073
5074 Expression *DotIdExp::semantic(Scope *sc)
5075 { Expression *e;
5076 Expression *eleft;
5077 Expression *eright;
5078
5079 #if LOGSEMANTIC
5080 printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars());
5081 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
5082 #endif
5083
5084 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
5085
5086 #if 0
5087 /* Don't do semantic analysis if we'll be converting
5088 * it to a string.
5089 */
5090 if (ident == Id::stringof)
5091 { char *s = e1->toChars();
5092 e = new StringExp(loc, s, strlen(s), 'c');
5093 e = e->semantic(sc);
5094 return e;
5095 }
5096 #endif
5097
5098 /* Special case: rewrite this.id and super.id
5099 * to be classtype.id and baseclasstype.id
5100 * if we have no this pointer.
5101 */
5102 if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc))
5103 { ClassDeclaration *cd;
5104 StructDeclaration *sd;
5105 AggregateDeclaration *ad;
5106
5107 ad = sc->getStructClassScope();
5108 if (ad)
5109 {
5110 cd = ad->isClassDeclaration();
5111 if (cd)
5112 {
5113 if (e1->op == TOKthis)
5114 {
5115 e = new TypeDotIdExp(loc, cd->type, ident);
5116 return e->semantic(sc);
5117 }
5118 else if (cd->baseClass && e1->op == TOKsuper)
5119 {
5120 e = new TypeDotIdExp(loc, cd->baseClass->type, ident);
5121 return e->semantic(sc);
5122 }
5123 }
5124 else
5125 {
5126 sd = ad->isStructDeclaration();
5127 if (sd)
5128 {
5129 if (e1->op == TOKthis)
5130 {
5131 e = new TypeDotIdExp(loc, sd->type, ident);
5132 return e->semantic(sc);
5133 }
5134 }
5135 }
5136 }
5137 }
5138
5139 UnaExp::semantic(sc);
5140
5141 if (e1->op == TOKdotexp)
5142 {
5143 DotExp *de = (DotExp *)e1;
5144 eleft = de->e1;
5145 eright = de->e2;
5146 }
5147 else
5148 {
5149 e1 = resolveProperties(sc, e1);
5150 eleft = NULL;
5151 eright = e1;
5152 }
5153 #if DMDV2
5154 if (e1->op == TOKtuple && ident == Id::offsetof)
5155 { /* 'distribute' the .offsetof to each of the tuple elements.
5156 */
5157 TupleExp *te = (TupleExp *)e1;
5158 Expressions *exps = new Expressions();
5159 exps->setDim(te->exps->dim);
5160 for (int i = 0; i < exps->dim; i++)
5161 { Expression *e = (Expression *)te->exps->data[i];
5162 e = e->semantic(sc);
5163 e = new DotIdExp(e->loc, e, Id::offsetof);
5164 exps->data[i] = (void *)e;
5165 }
5166 e = new TupleExp(loc, exps);
5167 e = e->semantic(sc);
5168 return e;
5169 }
5170 #endif
5171
5172 if (e1->op == TOKtuple && ident == Id::length)
5173 {
5174 TupleExp *te = (TupleExp *)e1;
5175 e = new IntegerExp(loc, te->exps->dim, Type::tsize_t);
5176 return e;
5177 }
5178
5179 Type *t1b = e1->type->toBasetype();
5180
5181 if (eright->op == TOKimport) // also used for template alias's
5182 {
5183 Dsymbol *s;
5184 ScopeExp *ie = (ScopeExp *)eright;
5185
5186 s = ie->sds->search(loc, ident, 0);
5187 if (s)
5188 {
5189 s = s->toAlias();
5190 checkDeprecated(sc, s);
5191
5192 EnumMember *em = s->isEnumMember();
5193 if (em)
5194 {
5195 e = em->value;
5196 e = e->semantic(sc);
5197 return e;
5198 }
5199
5200 VarDeclaration *v = s->isVarDeclaration();
5201 if (v)
5202 {
5203 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
5204 if (v->inuse)
5205 {
5206 error("circular reference to '%s'", v->toChars());
5207 type = Type::tint32;
5208 return this;
5209 }
5210 type = v->type;
5211 #if 0
5212 if (v->isConst() || v->isInvariant())
5213 {
5214 if (v->init)
5215 {
5216 ExpInitializer *ei = v->init->isExpInitializer();
5217 if (ei)
5218 {
5219 //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars());
5220 //ei->exp = ei->exp->semantic(sc);
5221 if (ei->exp->type == type)
5222 {
5223 e = ei->exp->copy(); // make copy so we can change loc
5224 e->loc = loc;
5225 return e;
5226 }
5227 }
5228 }
5229 else if (type->isscalar())
5230 {
5231 e = type->defaultInit();
5232 e->loc = loc;
5233 return e;
5234 }
5235 }
5236 #endif
5237 if (v->needThis())
5238 {
5239 if (!eleft)
5240 eleft = new ThisExp(loc);
5241 e = new DotVarExp(loc, eleft, v);
5242 e = e->semantic(sc);
5243 }
5244 else
5245 {
5246 e = new VarExp(loc, v);
5247 if (eleft)
5248 { e = new CommaExp(loc, eleft, e);
5249 e->type = v->type;
5250 }
5251 }
5252 return e->deref();
5253 }
5254
5255 FuncDeclaration *f = s->isFuncDeclaration();
5256 if (f)
5257 {
5258 //printf("it's a function\n");
5259 if (f->needThis())
5260 {
5261 if (!eleft)
5262 eleft = new ThisExp(loc);
5263 e = new DotVarExp(loc, eleft, f);
5264 e = e->semantic(sc);
5265 }
5266 else
5267 {
5268 e = new VarExp(loc, f, 1);
5269 if (eleft)
5270 { e = new CommaExp(loc, eleft, e);
5271 e->type = f->type;
5272 }
5273 }
5274 return e;
5275 }
5276
5277 OverloadSet *o = s->isOverloadSet();
5278 if (o)
5279 { //printf("'%s' is an overload set\n", o->toChars());
5280 return new OverExp(o);
5281 }
5282
5283 Type *t = s->getType();
5284 if (t)
5285 {
5286 return new TypeExp(loc, t);
5287 }
5288
5289 TupleDeclaration *tup = s->isTupleDeclaration();
5290 if (tup)
5291 {
5292 if (eleft)
5293 error("cannot have e.tuple");
5294 e = new TupleExp(loc, tup);
5295 e = e->semantic(sc);
5296 return e;
5297 }
5298
5299 ScopeDsymbol *sds = s->isScopeDsymbol();
5300 if (sds)
5301 {
5302 //printf("it's a ScopeDsymbol\n");
5303 e = new ScopeExp(loc, sds);
5304 e = e->semantic(sc);
5305 if (eleft)
5306 e = new DotExp(loc, eleft, e);
5307 return e;
5308 }
5309
5310 Import *imp = s->isImport();
5311 if (imp)
5312 {
5313 ScopeExp *ie;
5314
5315 ie = new ScopeExp(loc, imp->pkg);
5316 return ie->semantic(sc);
5317 }
5318
5319 // BUG: handle other cases like in IdentifierExp::semantic()
5320 #ifdef DEBUG
5321 printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind());
5322 #endif
5323 assert(0);
5324 }
5325 else if (ident == Id::stringof)
5326 { char *s = ie->toChars();
5327 e = new StringExp(loc, s, strlen(s), 'c');
5328 e = e->semantic(sc);
5329 return e;
5330 }
5331 error("undefined identifier %s", toChars());
5332 type = Type::tvoid;
5333 return this;
5334 }
5335 else if (t1b->ty == Tpointer &&
5336 ident != Id::init && ident != Id::__sizeof &&
5337 ident != Id::alignof && ident != Id::offsetof &&
5338 ident != Id::mangleof && ident != Id::stringof)
5339 { /* Rewrite:
5340 * p.ident
5341 * as:
5342 * (*p).ident
5343 */
5344 e = new PtrExp(loc, e1);
5345 e->type = ((TypePointer *)t1b)->next;
5346 return e->type->dotExp(sc, e, ident);
5347 }
5348 else if (t1b->ty == Tarray ||
5349 t1b->ty == Tsarray ||
5350 t1b->ty == Taarray)
5351 { /* If ident is not a valid property, rewrite:
5352 * e1.ident
5353 * as:
5354 * .ident(e1)
5355 */
5356 unsigned errors = global.errors;
5357 global.gag++;
5358 e = e1->type->dotExp(sc, e1, ident);
5359 global.gag--;
5360 if (errors != global.errors) // if failed to find the property
5361 {
5362 global.errors = errors;
5363 e = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), ident);
5364 e = new CallExp(loc, e, e1);
5365 }
5366 e = e->semantic(sc);
5367 return e;
5368 }
5369 else
5370 {
5371 e = e1->type->dotExp(sc, e1, ident);
5372 e = e->semantic(sc);
5373 return e;
5374 }
5375 }
5376
5377 void DotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5378 {
5379 //printf("DotIdExp::toCBuffer()\n");
5380 expToCBuffer(buf, hgs, e1, PREC_primary);
5381 buf->writeByte('.');
5382 buf->writestring(ident->toChars());
5383 }
5384
5385 /********************** DotTemplateExp ***********************************/
5386
5387 // Mainly just a placeholder
5388
5389 DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td)
5390 : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e)
5391
5392 {
5393 this->td = td;
5394 }
5395
5396 void DotTemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5397 {
5398 expToCBuffer(buf, hgs, e1, PREC_primary);
5399 buf->writeByte('.');
5400 buf->writestring(td->toChars());
5401 }
5402
5403
5404 /************************************************************/
5405
5406 DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v, int hasOverloads)
5407 : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e)
5408 {
5409 //printf("DotVarExp()\n");
5410 this->var = v;
5411 this->hasOverloads = hasOverloads;
5412 }
5413
5414 Expression *DotVarExp::semantic(Scope *sc)
5415 {
5416 #if LOGSEMANTIC
5417 printf("DotVarExp::semantic('%s')\n", toChars());
5418 #endif
5419 if (!type)
5420 {
5421 var = var->toAlias()->isDeclaration();
5422
5423 TupleDeclaration *tup = var->isTupleDeclaration();
5424 if (tup)
5425 { /* Replace:
5426 * e1.tuple(a, b, c)
5427 * with:
5428 * tuple(e1.a, e1.b, e1.c)
5429 */
5430 Expressions *exps = new Expressions;
5431
5432 exps->reserve(tup->objects->dim);
5433 for (size_t i = 0; i < tup->objects->dim; i++)
5434 { Object *o = (Object *)tup->objects->data[i];
5435 if (o->dyncast() != DYNCAST_EXPRESSION)
5436 {
5437 error("%s is not an expression", o->toChars());
5438 }
5439 else
5440 {
5441 Expression *e = (Expression *)o;
5442 if (e->op != TOKdsymbol)
5443 error("%s is not a member", e->toChars());
5444 else
5445 { DsymbolExp *ve = (DsymbolExp *)e;
5446
5447 e = new DotVarExp(loc, e1, ve->s->isDeclaration());
5448 exps->push(e);
5449 }
5450 }
5451 }
5452 Expression *e = new TupleExp(loc, exps);
5453 e = e->semantic(sc);
5454 return e;
5455 }
5456
5457 e1 = e1->semantic(sc);
5458 type = var->type;
5459 if (!type && global.errors)
5460 { // var is goofed up, just return 0
5461 return new IntegerExp(0);
5462 }
5463 assert(type);
5464
5465 if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution
5466 {
5467 Type *t1 = e1->type;
5468 if (t1->ty == Tpointer)
5469 t1 = t1->nextOf();
5470 if (t1->isConst())
5471 type = type->constOf();
5472 else if (t1->isInvariant())
5473 type = type->invariantOf();
5474
5475 AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration();
5476 e1 = getRightThis(loc, sc, ad, e1, var);
5477 if (!sc->noaccesscheck)
5478 accessCheck(loc, sc, e1, var);
5479
5480 VarDeclaration *v = var->isVarDeclaration();
5481 Expression *e = expandVar(WANTvalue, v);
5482 if (e)
5483 return e;
5484 }
5485 }
5486 //printf("-DotVarExp::semantic('%s')\n", toChars());
5487 return this;
5488 }
5489
5490 int DotVarExp::isLvalue()
5491 {
5492 return 1;
5493 }
5494
5495 Expression *DotVarExp::toLvalue(Scope *sc, Expression *e)
5496 {
5497 //printf("DotVarExp::toLvalue(%s)\n", toChars());
5498 return this;
5499 }
5500
5501 Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
5502 {
5503 #if 0
5504 printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
5505 printf("e1->type = %s\n", e1->type->toChars());
5506 printf("var->type = %s\n", var->type->toChars());
5507 #endif
5508
5509 if (var->isCtorinit())
5510 { // It's only modifiable if inside the right constructor
5511 Dsymbol *s = sc->func;
5512 while (1)
5513 {
5514 FuncDeclaration *fd = NULL;
5515 if (s)
5516 fd = s->isFuncDeclaration();
5517 if (fd &&
5518 ((fd->isCtorDeclaration() && var->storage_class & STCfield) ||
5519 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) &&
5520 fd->toParent() == var->toParent() &&
5521 e1->op == TOKthis
5522 )
5523 {
5524 VarDeclaration *v = var->isVarDeclaration();
5525 assert(v);
5526 v->ctorinit = 1;
5527 //printf("setting ctorinit\n");
5528 }
5529 else
5530 {
5531 if (s)
5532 { s = s->toParent2();
5533 continue;
5534 }
5535 else
5536 {
5537 const char *p = var->isStatic() ? "static " : "";
5538 error("can only initialize %sconst member %s inside %sconstructor",
5539 p, var->toChars(), p);
5540 }
5541 }
5542 break;
5543 }
5544 }
5545 else
5546 {
5547 Type *t1 = e1->type->toBasetype();
5548
5549 if (!t1->isMutable() ||
5550 (t1->ty == Tpointer && !t1->nextOf()->isMutable()) ||
5551 !var->type->isMutable() ||
5552 !var->type->isAssignable() ||
5553 var->storage_class & STCmanifest
5554 )
5555 error("cannot modify const/invariant %s", toChars());
5556 }
5557 return this;
5558 }
5559
5560 void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5561 {
5562 expToCBuffer(buf, hgs, e1, PREC_primary);
5563 buf->writeByte('.');
5564 buf->writestring(var->toChars());
5565 }
5566
5567 /************************************************************/
5568
5569 /* Things like:
5570 * foo.bar!(args)
5571 */
5572
5573 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti)
5574 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e)
5575 {
5576 //printf("DotTemplateInstanceExp()\n");
5577 this->ti = ti;
5578 }
5579
5580 Expression *DotTemplateInstanceExp::syntaxCopy()
5581 {
5582 DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc,
5583 e1->syntaxCopy(),
5584 (TemplateInstance *)ti->syntaxCopy(NULL));
5585 return de;
5586 }
5587
5588 Expression *DotTemplateInstanceExp::semantic(Scope *sc)
5589 { Dsymbol *s;
5590 Dsymbol *s2;
5591 TemplateDeclaration *td;
5592 Expression *e;
5593 Identifier *id;
5594 Type *t1;
5595 Expression *eleft = NULL;
5596 Expression *eright;
5597
5598 #if LOGSEMANTIC
5599 printf("DotTemplateInstanceExp::semantic('%s')\n", toChars());
5600 #endif
5601 //e1->print();
5602 //print();
5603 e1 = e1->semantic(sc);
5604 t1 = e1->type;
5605 if (t1)
5606 t1 = t1->toBasetype();
5607 //t1->print();
5608
5609 /* Extract the following from e1:
5610 * s: the symbol which ti should be a member of
5611 * eleft: if not NULL, it is the 'this' pointer for ti
5612 */
5613
5614 if (e1->op == TOKdotexp)
5615 { DotExp *de = (DotExp *)e1;
5616 eleft = de->e1;
5617 eright = de->e2;
5618 }
5619 else
5620 { eleft = NULL;
5621 eright = e1;
5622 }
5623 if (eright->op == TOKimport)
5624 {
5625 s = ((ScopeExp *)eright)->sds;
5626 }
5627 else if (e1->op == TOKtype)
5628 {
5629 s = t1->isClassHandle();
5630 if (!s)
5631 { if (t1->ty == Tstruct)
5632 s = ((TypeStruct *)t1)->sym;
5633 else
5634 goto L1;
5635 }
5636 }
5637 else if (t1 && (t1->ty == Tstruct || t1->ty == Tclass))
5638 {
5639 s = t1->toDsymbol(sc);
5640 eleft = e1;
5641 }
5642 else if (t1 && t1->ty == Tpointer)
5643 {
5644 t1 = ((TypePointer *)t1)->next->toBasetype();
5645 if (t1->ty != Tstruct)
5646 goto L1;
5647 s = t1->toDsymbol(sc);
5648 eleft = e1;
5649 }
5650 else
5651 {
5652 L1:
5653 error("template %s is not a member of %s", ti->toChars(), e1->toChars());
5654 goto Lerr;
5655 }
5656
5657 assert(s);
5658 id = ti->name;
5659 s2 = s->search(loc, id, 0);
5660 if (!s2)
5661 { error("template identifier %s is not a member of %s %s", id->toChars(), s->kind(), s->ident->toChars());
5662 goto Lerr;
5663 }
5664 s = s2;
5665 s->semantic(sc);
5666 s = s->toAlias();
5667 td = s->isTemplateDeclaration();
5668 if (!td)
5669 {
5670 error("%s is not a template", id->toChars());
5671 goto Lerr;
5672 }
5673 if (global.errors)
5674 goto Lerr;
5675
5676 ti->tempdecl = td;
5677
5678 if (eleft)
5679 { Declaration *v;
5680
5681 ti->semantic(sc);
5682 s = ti->inst->toAlias();
5683 v = s->isDeclaration();
5684 if (v)
5685 { e = new DotVarExp(loc, eleft, v);
5686 e = e->semantic(sc);
5687 return e;
5688 }
5689 }
5690
5691 e = new ScopeExp(loc, ti);
5692 if (eleft)
5693 {
5694 e = new DotExp(loc, eleft, e);
5695 }
5696 e = e->semantic(sc);
5697 return e;
5698
5699 Lerr:
5700 return new IntegerExp(loc, 0, Type::tint32);
5701 }
5702
5703 void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5704 {
5705 expToCBuffer(buf, hgs, e1, PREC_primary);
5706 buf->writeByte('.');
5707 ti->toCBuffer(buf, hgs);
5708 }
5709
5710 /************************************************************/
5711
5712 DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f, int hasOverloads)
5713 : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
5714 {
5715 this->func = f;
5716 this->hasOverloads = hasOverloads;
5717 }
5718
5719 Expression *DelegateExp::semantic(Scope *sc)
5720 {
5721 #if LOGSEMANTIC
5722 printf("DelegateExp::semantic('%s')\n", toChars());
5723 #endif
5724 if (!type)
5725 {
5726 e1 = e1->semantic(sc);
5727 // LDC we need a copy as we store the LLVM tpye in TypeFunction, and delegate/members have different types for 'this'
5728 type = new TypeDelegate(func->type->syntaxCopy());
5729 type = type->semantic(loc, sc);
5730 AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration();
5731 if (func->needThis())
5732 e1 = getRightThis(loc, sc, ad, e1, func);
5733 }
5734 return this;
5735 }
5736
5737 void DelegateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5738 {
5739 buf->writeByte('&');
5740 if (!func->isNested())
5741 {
5742 expToCBuffer(buf, hgs, e1, PREC_primary);
5743 buf->writeByte('.');
5744 }
5745 buf->writestring(func->toChars());
5746 }
5747
5748 /************************************************************/
5749
5750 DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s)
5751 : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e)
5752 {
5753 this->sym = s;
5754 this->type = s->getType();
5755 }
5756
5757 Expression *DotTypeExp::semantic(Scope *sc)
5758 {
5759 #if LOGSEMANTIC
5760 printf("DotTypeExp::semantic('%s')\n", toChars());
5761 #endif
5762 UnaExp::semantic(sc);
5763 return this;
5764 }
5765
5766 void DotTypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5767 {
5768 expToCBuffer(buf, hgs, e1, PREC_primary);
5769 buf->writeByte('.');
5770 buf->writestring(sym->toChars());
5771 }
5772
5773 /************************************************************/
5774
5775 CallExp::CallExp(Loc loc, Expression *e, Expressions *exps)
5776 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5777 {
5778 this->arguments = exps;
5779 }
5780
5781 CallExp::CallExp(Loc loc, Expression *e)
5782 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5783 {
5784 this->arguments = NULL;
5785 }
5786
5787 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1)
5788 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5789 {
5790 Expressions *arguments = new Expressions();
5791 arguments->setDim(1);
5792 arguments->data[0] = (void *)earg1;
5793
5794 this->arguments = arguments;
5795 }
5796
5797 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2)
5798 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5799 {
5800 Expressions *arguments = new Expressions();
5801 arguments->setDim(2);
5802 arguments->data[0] = (void *)earg1;
5803 arguments->data[1] = (void *)earg2;
5804
5805 this->arguments = arguments;
5806 }
5807
5808 Expression *CallExp::syntaxCopy()
5809 {
5810 return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
5811 }
5812
5813
5814 Expression *CallExp::semantic(Scope *sc)
5815 {
5816 TypeFunction *tf;
5817 FuncDeclaration *f;
5818 int i;
5819 Type *t1;
5820 int istemp;
5821 Objects *targsi = NULL; // initial list of template arguments
5822
5823 #if LOGSEMANTIC
5824 printf("CallExp::semantic() %s\n", toChars());
5825 #endif
5826 if (type)
5827 return this; // semantic() already run
5828 #if 0
5829 if (arguments && arguments->dim)
5830 {
5831 Expression *earg = (Expression *)arguments->data[0];
5832 earg->print();
5833 if (earg->type) earg->type->print();
5834 }
5835 #endif
5836
5837 if (e1->op == TOKdelegate)
5838 { DelegateExp *de = (DelegateExp *)e1;
5839
5840 e1 = new DotVarExp(de->loc, de->e1, de->func);
5841 return semantic(sc);
5842 }
5843
5844 /* Transform:
5845 * array.id(args) into .id(array,args)
5846 * aa.remove(arg) into delete aa[arg]
5847 */
5848 if (e1->op == TOKdot)
5849 {
5850 // BUG: we should handle array.a.b.c.e(args) too
5851
5852 DotIdExp *dotid = (DotIdExp *)(e1);
5853 dotid->e1 = dotid->e1->semantic(sc);
5854 assert(dotid->e1);
5855 if (dotid->e1->type)
5856 {
5857 TY e1ty = dotid->e1->type->toBasetype()->ty;
5858 if (e1ty == Taarray && dotid->ident == Id::remove)
5859 {
5860 if (!arguments || arguments->dim != 1)
5861 { error("expected key as argument to aa.remove()");
5862 goto Lagain;
5863 }
5864 Expression *key = (Expression *)arguments->data[0];
5865 key = key->semantic(sc);
5866 key = resolveProperties(sc, key);
5867 key->rvalue();
5868
5869 TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype();
5870 key = key->implicitCastTo(sc, taa->index);
5871
5872 return new RemoveExp(loc, dotid->e1, key);
5873 }
5874 else if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray)
5875 {
5876 if (!arguments)
5877 arguments = new Expressions();
5878 arguments->shift(dotid->e1);
5879 e1 = new DotIdExp(dotid->loc, new IdentifierExp(dotid->loc, Id::empty), dotid->ident);
5880 }
5881 }
5882 }
5883
5884 #if DMDV2
5885 /* This recognizes:
5886 * foo!(tiargs)(funcargs)
5887 */
5888 if (e1->op == TOKimport && !e1->type)
5889 { ScopeExp *se = (ScopeExp *)e1;
5890 TemplateInstance *ti = se->sds->isTemplateInstance();
5891 if (ti && !ti->semanticdone)
5892 {
5893 /* Attempt to instantiate ti. If that works, go with it.
5894 * If not, go with partial explicit specialization.
5895 */
5896 ti->semanticTiargs(sc);
5897 unsigned errors = global.errors;
5898 global.gag++;
5899 ti->semantic(sc);
5900 global.gag--;
5901 if (errors != global.errors)
5902 {
5903 /* Didn't work, go with partial explicit specialization
5904 */
5905 global.errors = errors;
5906 targsi = ti->tiargs;
5907 e1 = new IdentifierExp(loc, ti->name);
5908 }
5909 }
5910 }
5911
5912 /* This recognizes:
5913 * expr.foo!(tiargs)(funcargs)
5914 */
5915 if (e1->op == TOKdotti && !e1->type)
5916 { DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1;
5917 TemplateInstance *ti = se->ti;
5918 if (!ti->semanticdone)
5919 {
5920 /* Attempt to instantiate ti. If that works, go with it.
5921 * If not, go with partial explicit specialization.
5922 */
5923 ti->semanticTiargs(sc);
5924 Expression *etmp;
5925 unsigned errors = global.errors;
5926 global.gag++;
5927 etmp = e1->semantic(sc);
5928 global.gag--;
5929 if (errors != global.errors)
5930 {
5931 global.errors = errors;
5932 targsi = ti->tiargs;
5933 e1 = new DotIdExp(loc, se->e1, ti->name);
5934 }
5935 else
5936 e1 = etmp;
5937 }
5938 }
5939 #endif
5940
5941 istemp = 0;
5942 Lagain:
5943 //printf("Lagain: %s\n", toChars());
5944 f = NULL;
5945 if (e1->op == TOKthis || e1->op == TOKsuper)
5946 {
5947 // semantic() run later for these
5948 }
5949 else
5950 {
5951 UnaExp::semantic(sc);
5952
5953 /* Look for e1 being a lazy parameter
5954 */
5955 if (e1->op == TOKvar)
5956 { VarExp *ve = (VarExp *)e1;
5957
5958 if (ve->var->storage_class & STClazy)
5959 {
5960 TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd);
5961 TypeDelegate *t = new TypeDelegate(tf);
5962 ve->type = t->semantic(loc, sc);
5963 }
5964 }
5965
5966 if (e1->op == TOKimport)
5967 { // Perhaps this should be moved to ScopeExp::semantic()
5968 ScopeExp *se = (ScopeExp *)e1;
5969 e1 = new DsymbolExp(loc, se->sds);
5970 e1 = e1->semantic(sc);
5971 }
5972 #if 1 // patch for #540 by Oskar Linde
5973 else if (e1->op == TOKdotexp)
5974 {
5975 DotExp *de = (DotExp *) e1;
5976
5977 if (de->e2->op == TOKimport)
5978 { // This should *really* be moved to ScopeExp::semantic()
5979 ScopeExp *se = (ScopeExp *)de->e2;
5980 de->e2 = new DsymbolExp(loc, se->sds);
5981 de->e2 = de->e2->semantic(sc);
5982 }
5983
5984 if (de->e2->op == TOKtemplate)
5985 { TemplateExp *te = (TemplateExp *) de->e2;
5986 e1 = new DotTemplateExp(loc,de->e1,te->td);
5987 }
5988 }
5989 #endif
5990 }
5991
5992 if (e1->op == TOKcomma)
5993 {
5994 CommaExp *ce = (CommaExp *)e1;
5995
5996 e1 = ce->e2;
5997 e1->type = ce->type;
5998 ce->e2 = this;
5999 ce->type = NULL;
6000 return ce->semantic(sc);
6001 }
6002
6003 t1 = NULL;
6004 if (e1->type)
6005 t1 = e1->type->toBasetype();
6006
6007 // Check for call operator overload
6008 if (t1)
6009 { AggregateDeclaration *ad;
6010
6011 if (t1->ty == Tstruct)
6012 {
6013 ad = ((TypeStruct *)t1)->sym;
6014
6015 // First look for constructor
6016 if (ad->ctor && arguments && arguments->dim)
6017 {
6018 // Create variable that will get constructed
6019 Identifier *idtmp = Lexer::uniqueId("__ctmp");
6020 VarDeclaration *tmp = new VarDeclaration(loc, t1, idtmp, NULL);
6021 Expression *av = new DeclarationExp(loc, tmp);
6022 av = new CommaExp(loc, av, new VarExp(loc, tmp));
6023
6024 Expression *e = new DotVarExp(loc, av, ad->ctor, 1);
6025 e = new CallExp(loc, e, arguments);
6026 e = new PtrExp(loc, e);
6027 e = e->semantic(sc);
6028 return e;
6029 }
6030
6031 // No constructor, look for overload of opCall
6032 if (search_function(ad, Id::call))
6033 goto L1; // overload of opCall, therefore it's a call
6034
6035 if (e1->op != TOKtype)
6036 error("%s %s does not overload ()", ad->kind(), ad->toChars());
6037 /* It's a struct literal
6038 */
6039 Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments);
6040 e = e->semantic(sc);
6041 e->type = e1->type; // in case e1->type was a typedef
6042 return e;
6043 }
6044 else if (t1->ty == Tclass)
6045 {
6046 ad = ((TypeClass *)t1)->sym;
6047 goto L1;
6048 L1:
6049 // Rewrite as e1.call(arguments)
6050 Expression *e = new DotIdExp(loc, e1, Id::call);
6051 e = new CallExp(loc, e, arguments);
6052 e = e->semantic(sc);
6053 return e;
6054 }
6055 }
6056
6057 arrayExpressionSemantic(arguments, sc);
6058 preFunctionArguments(loc, sc, arguments);
6059
6060 if (e1->op == TOKdotvar && t1->ty == Tfunction ||
6061 e1->op == TOKdottd)
6062 {
6063 DotVarExp *dve;
6064 DotTemplateExp *dte;
6065 AggregateDeclaration *ad;
6066 UnaExp *ue = (UnaExp *)(e1);
6067
6068 if (e1->op == TOKdotvar)
6069 { // Do overload resolution
6070 dve = (DotVarExp *)(e1);
6071
6072 f = dve->var->isFuncDeclaration();
6073 assert(f);
6074 f = f->overloadResolve(loc, ue->e1, arguments);
6075
6076 ad = f->toParent()->isAggregateDeclaration();
6077 }
6078 else
6079 { dte = (DotTemplateExp *)(e1);
6080 TemplateDeclaration *td = dte->td;
6081 assert(td);
6082 if (!arguments)
6083 // Should fix deduceFunctionTemplate() so it works on NULL argument
6084 arguments = new Expressions();
6085 f = td->deduceFunctionTemplate(sc, loc, targsi, ue->e1, arguments);
6086 if (!f)
6087 { type = Type::terror;
6088 return this;
6089 }
6090 ad = td->toParent()->isAggregateDeclaration();
6091 }
6092 if (f->needThis())
6093 {
6094 ue->e1 = getRightThis(loc, sc, ad, ue->e1, f);
6095 }
6096
6097 /* Cannot call public functions from inside invariant
6098 * (because then the invariant would have infinite recursion)
6099 */
6100 if (sc->func && sc->func->isInvariantDeclaration() &&
6101 ue->e1->op == TOKthis &&
6102 f->addPostInvariant()
6103 )
6104 {
6105 error("cannot call public/export function %s from invariant", f->toChars());
6106 }
6107
6108 checkDeprecated(sc, f);
6109 accessCheck(loc, sc, ue->e1, f);
6110 if (!f->needThis())
6111 {
6112 VarExp *ve = new VarExp(loc, f);
6113 e1 = new CommaExp(loc, ue->e1, ve);
6114 e1->type = f->type;
6115 }
6116 else
6117 {
6118 if (e1->op == TOKdotvar)
6119 dve->var = f;
6120 else
6121 e1 = new DotVarExp(loc, dte->e1, f);
6122 e1->type = f->type;
6123 #if 0
6124 printf("ue->e1 = %s\n", ue->e1->toChars());
6125 printf("f = %s\n", f->toChars());
6126 printf("t = %s\n", t->toChars());
6127 printf("e1 = %s\n", e1->toChars());
6128 printf("e1->type = %s\n", e1->type->toChars());
6129 #endif
6130 // Const member function can take const/invariant/mutable this
6131 if (!(f->type->isConst()))
6132 {
6133 // Check for const/invariant compatibility
6134 Type *tthis = ue->e1->type->toBasetype();
6135 if (tthis->ty == Tpointer)
6136 tthis = tthis->nextOf()->toBasetype();
6137 if (f->type->isInvariant())
6138 {
6139 if (tthis->mod != MODinvariant)
6140 error("%s can only be called on an invariant object", e1->toChars());
6141 }
6142 else
6143 {
6144 if (tthis->mod != 0)
6145 { //printf("mod = %x\n", tthis->mod);
6146 error("%s can only be called on a mutable object, not %s", e1->toChars(), tthis->toChars());
6147 }
6148 }
6149
6150 /* Cannot call mutable method on a final struct
6151 */
6152 if (tthis->ty == Tstruct &&
6153 ue->e1->op == TOKvar)
6154 { VarExp *v = (VarExp *)ue->e1;
6155 if (v->var->storage_class & STCfinal)
6156 error("cannot call mutable method on final struct");
6157 }
6158 }
6159
6160 // See if we need to adjust the 'this' pointer
6161 AggregateDeclaration *ad = f->isThis();
6162 ClassDeclaration *cd = ue->e1->type->isClassHandle();
6163 if (ad && cd && ad->isClassDeclaration() && ad != cd &&
6164 ue->e1->op != TOKsuper)
6165 {
6166 ue->e1 = ue->e1->castTo(sc, ad->type); //new CastExp(loc, ue->e1, ad->type);
6167 ue->e1 = ue->e1->semantic(sc);
6168 }
6169 }
6170 t1 = e1->type;
6171 }
6172 else if (e1->op == TOKsuper)
6173 {
6174 // Base class constructor call
6175 ClassDeclaration *cd = NULL;
6176
6177 if (sc->func)
6178 cd = sc->func->toParent()->isClassDeclaration();
6179 if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration())
6180 {
6181 error("super class constructor call must be in a constructor");
6182 type = Type::terror;
6183 return this;
6184 }
6185 else
6186 {
6187 f = cd->baseClass->ctor;
6188 if (!f)
6189 { error("no super class constructor for %s", cd->baseClass->toChars());
6190 type = Type::terror;
6191 return this;
6192 }
6193 else
6194 {
6195 if (!sc->intypeof)
6196 {
6197 #if 0
6198 if (sc->callSuper & (CSXthis | CSXsuper))
6199 error("reference to this before super()");
6200 #endif
6201 if (sc->noctor || sc->callSuper & CSXlabel)
6202 error("constructor calls not allowed in loops or after labels");
6203 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
6204 error("multiple constructor calls");
6205 sc->callSuper |= CSXany_ctor | CSXsuper_ctor;
6206 }
6207
6208 f = f->overloadResolve(loc, NULL, arguments);
6209 checkDeprecated(sc, f);
6210 e1 = new DotVarExp(e1->loc, e1, f);
6211 e1 = e1->semantic(sc);
6212 t1 = e1->type;
6213 }
6214 }
6215 }
6216 else if (e1->op == TOKthis)
6217 {
6218 // same class constructor call
6219 ClassDeclaration *cd = NULL;
6220
6221 if (sc->func)
6222 cd = sc->func->toParent()->isClassDeclaration();
6223 if (!cd || !sc->func->isCtorDeclaration())
6224 {
6225 error("class constructor call must be in a constructor");
6226 type = Type::terror;
6227 return this;
6228 }
6229 else
6230 {
6231 if (!sc->intypeof)
6232 {
6233 #if 0
6234 if (sc->callSuper & (CSXthis | CSXsuper))
6235 error("reference to this before super()");
6236 #endif
6237 if (sc->noctor || sc->callSuper & CSXlabel)
6238 error("constructor calls not allowed in loops or after labels");
6239 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
6240 error("multiple constructor calls");
6241 sc->callSuper |= CSXany_ctor | CSXthis_ctor;
6242 }
6243
6244 f = cd->ctor;
6245 f = f->overloadResolve(loc, NULL, arguments);
6246 checkDeprecated(sc, f);
6247 e1 = new DotVarExp(e1->loc, e1, f);
6248 e1 = e1->semantic(sc);
6249 t1 = e1->type;
6250
6251 // BUG: this should really be done by checking the static
6252 // call graph
6253 if (f == sc->func)
6254 error("cyclic constructor call");
6255 }
6256 }
6257 else if (e1->op == TOKoverloadset)
6258 {
6259 OverExp *eo = (OverExp *)e1;
6260 FuncDeclaration *f = NULL;
6261 for (int i = 0; i < eo->vars->a.dim; i++)
6262 { Dsymbol *s = (Dsymbol *)eo->vars->a.data[i];
6263 FuncDeclaration *f2 = s->isFuncDeclaration();
6264 if (f2)
6265 {
6266 f2 = f2->overloadResolve(loc, NULL, arguments, 1);
6267 }
6268 else
6269 { TemplateDeclaration *td = s->isTemplateDeclaration();
6270 assert(td);
6271 f2 = td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments, 1);
6272 }
6273 if (f2)
6274 { if (f)
6275 /* Error if match in more than one overload set,
6276 * even if one is a 'better' match than the other.
6277 */
6278 ScopeDsymbol::multiplyDefined(loc, f, f2);
6279 else
6280 f = f2;
6281 }
6282 }
6283 if (!f)
6284 { /* No overload matches, just set f and rely on error
6285 * message being generated later.
6286 */
6287 f = (FuncDeclaration *)eo->vars->a.data[0];
6288 }
6289 e1 = new VarExp(loc, f);
6290 goto Lagain;
6291 }
6292 else if (!t1)
6293 {
6294 error("function expected before (), not '%s'", e1->toChars());
6295 type = Type::terror;
6296 return this;
6297 }
6298 else if (t1->ty != Tfunction)
6299 {
6300 if (t1->ty == Tdelegate)
6301 { TypeDelegate *td = (TypeDelegate *)t1;
6302 assert(td->next->ty == Tfunction);
6303 tf = (TypeFunction *)(td->next);
6304 goto Lcheckargs;
6305 }
6306 else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction)
6307 { Expression *e;
6308
6309 e = new PtrExp(loc, e1);
6310 t1 = ((TypePointer *)t1)->next;
6311 e->type = t1;
6312 e1 = e;
6313 }
6314 else if (e1->op == TOKtemplate)
6315 {
6316 TemplateExp *te = (TemplateExp *)e1;
6317 f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments);
6318 if (!f)
6319 { type = Type::terror;
6320 return this;
6321 }
6322 if (f->needThis() && hasThis(sc))
6323 {
6324 // Supply an implicit 'this', as in
6325 // this.ident
6326
6327 e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td);
6328 goto Lagain;
6329 }
6330
6331 e1 = new VarExp(loc, f);
6332 goto Lagain;
6333 }
6334 else
6335 { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars());
6336 type = Type::terror;
6337 return this;
6338 }
6339 }
6340 else if (e1->op == TOKvar)
6341 {
6342 // Do overload resolution
6343 VarExp *ve = (VarExp *)e1;
6344
6345 f = ve->var->isFuncDeclaration();
6346 assert(f);
6347
6348 if (ve->hasOverloads)
6349 f = f->overloadResolve(loc, NULL, arguments);
6350 checkDeprecated(sc, f);
6351
6352 if (f->needThis() && hasThis(sc))
6353 {
6354 // Supply an implicit 'this', as in
6355 // this.ident
6356
6357 e1 = new DotVarExp(loc, new ThisExp(loc), f);
6358 goto Lagain;
6359 }
6360
6361 accessCheck(loc, sc, NULL, f);
6362
6363 ve->var = f;
6364 // ve->hasOverloads = 0;
6365 ve->type = f->type;
6366 t1 = f->type;
6367 }
6368 assert(t1->ty == Tfunction);
6369 tf = (TypeFunction *)(t1);
6370
6371 Lcheckargs:
6372 assert(tf->ty == Tfunction);
6373 type = tf->next;
6374
6375 if (!arguments)
6376 arguments = new Expressions();
6377 functionArguments(loc, sc, tf, arguments);
6378
6379 assert(type);
6380
6381 if (f && f->tintro)
6382 {
6383 Type *t = type;
6384 int offset = 0;
6385 TypeFunction *tf = (TypeFunction *)f->tintro;
6386
6387 if (tf->next->isBaseOf(t, &offset) && offset)
6388 {
6389 type = tf->next;
6390 return castTo(sc, t);
6391 }
6392 }
6393
6394 return this;
6395 }
6396
6397 int CallExp::checkSideEffect(int flag)
6398 {
6399 return 1;
6400 }
6401
6402 int CallExp::canThrow()
6403 {
6404 return 1;
6405 }
6406
6407 int CallExp::isLvalue()
6408 {
6409 if (type->toBasetype()->ty == Tstruct)
6410 return 1;
6411 Type *tb = e1->type->toBasetype();
6412 if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref)
6413 return 1; // function returns a reference
6414 return 0;
6415 }
6416
6417 Expression *CallExp::toLvalue(Scope *sc, Expression *e)
6418 {
6419 if (isLvalue())
6420 return this;
6421 return Expression::toLvalue(sc, e);
6422 }
6423
6424 void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6425 { int i;
6426
6427 expToCBuffer(buf, hgs, e1, precedence[op]);
6428 buf->writeByte('(');
6429 argsToCBuffer(buf, arguments, hgs);
6430 buf->writeByte(')');
6431 }
6432
6433
6434 /************************************************************/
6435
6436 AddrExp::AddrExp(Loc loc, Expression *e)
6437 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e)
6438 {
6439 }
6440
6441 Expression *AddrExp::semantic(Scope *sc)
6442 {
6443 #if LOGSEMANTIC
6444 printf("AddrExp::semantic('%s')\n", toChars());
6445 #endif
6446 if (!type)
6447 {
6448 UnaExp::semantic(sc);
6449 e1 = e1->toLvalue(sc, NULL);
6450 if (!e1->type)
6451 {
6452 error("cannot take address of %s", e1->toChars());
6453 type = Type::tint32;
6454 return this;
6455 }
6456 type = e1->type->pointerTo();
6457
6458 // See if this should really be a delegate
6459 if (e1->op == TOKdotvar)
6460 {
6461 DotVarExp *dve = (DotVarExp *)e1;
6462 FuncDeclaration *f = dve->var->isFuncDeclaration();
6463
6464 if (f)
6465 {
6466 if (!dve->hasOverloads)
6467 f->tookAddressOf = 1;
6468 Expression *e = new DelegateExp(loc, dve->e1, f, dve->hasOverloads);
6469 e = e->semantic(sc);
6470 return e;
6471 }
6472 }
6473 else if (e1->op == TOKvar)
6474 {
6475 VarExp *ve = (VarExp *)e1;
6476
6477 VarDeclaration *v = ve->var->isVarDeclaration();
6478 if (v && !v->canTakeAddressOf())
6479 error("cannot take address of %s", e1->toChars());
6480
6481 FuncDeclaration *f = ve->var->isFuncDeclaration();
6482
6483 if (f)
6484 {
6485 if (!ve->hasOverloads)
6486 f->tookAddressOf = 1;
6487
6488 // LDC
6489 if (f && f->isIntrinsic())
6490 {
6491 error("cannot take the address of intrinsic function %s", e1->toChars());
6492 return this;
6493 }
6494
6495 if (f->isNested())
6496 {
6497 Expression *e = new DelegateExp(loc, e1, f, ve->hasOverloads);
6498 e = e->semantic(sc);
6499 return e;
6500 }
6501 if (f->needThis() && hasThis(sc))
6502 {
6503 /* Should probably supply 'this' after overload resolution,
6504 * not before.
6505 */
6506 Expression *ethis = new ThisExp(loc);
6507 Expression *e = new DelegateExp(loc, ethis, f, ve->hasOverloads);
6508 e = e->semantic(sc);
6509 return e;
6510 }
6511 }
6512 }
6513 return optimize(WANTvalue);
6514 }
6515 return this;
6516 }
6517
6518 /************************************************************/
6519
6520 PtrExp::PtrExp(Loc loc, Expression *e)
6521 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
6522 {
6523 if (e->type)
6524 type = ((TypePointer *)e->type)->next;
6525 }
6526
6527 PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
6528 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
6529 {
6530 type = t;
6531 }
6532
6533 Expression *PtrExp::semantic(Scope *sc)
6534 { Type *tb;
6535
6536 #if LOGSEMANTIC
6537 printf("PtrExp::semantic('%s')\n", toChars());
6538 #endif
6539 if (!type)
6540 {
6541 UnaExp::semantic(sc);
6542 e1 = resolveProperties(sc, e1);
6543 if (!e1->type)
6544 printf("PtrExp::semantic('%s')\n", toChars());
6545 Expression *e = op_overload(sc);
6546 if (e)
6547 return e;
6548 tb = e1->type->toBasetype();
6549 switch (tb->ty)
6550 {
6551 case Tpointer:
6552 type = ((TypePointer *)tb)->next;
6553 break;
6554
6555 case Tsarray:
6556 case Tarray:
6557 type = ((TypeArray *)tb)->next;
6558 e1 = e1->castTo(sc, type->pointerTo());
6559 break;
6560
6561 default:
6562 error("can only * a pointer, not a '%s'", e1->type->toChars());
6563 type = Type::tint32;
6564 break;
6565 }
6566 rvalue();
6567 }
6568 return this;
6569 }
6570
6571 int PtrExp::isLvalue()
6572 {
6573 return 1;
6574 }
6575
6576 Expression *PtrExp::toLvalue(Scope *sc, Expression *e)
6577 {
6578 #if 0
6579 tym = tybasic(e1->ET->Tty);
6580 if (!(tyscalar(tym) ||
6581 tym == TYstruct ||
6582 tym == TYarray && e->Eoper == TOKaddr))
6583 synerr(EM_lvalue); // lvalue expected
6584 #endif
6585 return this;
6586 }
6587
6588 Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e)
6589 {
6590 //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
6591
6592 if (e1->op == TOKsymoff)
6593 { SymOffExp *se = (SymOffExp *)e1;
6594 se->var->checkModify(loc, sc, type);
6595 //return toLvalue(sc, e);
6596 }
6597
6598 return Expression::modifiableLvalue(sc, e);
6599 }
6600
6601
6602 void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6603 {
6604 buf->writeByte('*');
6605 expToCBuffer(buf, hgs, e1, precedence[op]);
6606 }
6607
6608 /************************************************************/
6609
6610 NegExp::NegExp(Loc loc, Expression *e)
6611 : UnaExp(loc, TOKneg, sizeof(NegExp), e)
6612 {
6613 }
6614
6615 Expression *NegExp::semantic(Scope *sc)
6616 { Expression *e;
6617
6618 #if LOGSEMANTIC
6619 printf("NegExp::semantic('%s')\n", toChars());
6620 #endif
6621 if (!type)
6622 {
6623 UnaExp::semantic(sc);
6624 e1 = resolveProperties(sc, e1);
6625 e = op_overload(sc);
6626 if (e)
6627 return e;
6628
6629 e1->checkNoBool();
6630 if (e1->op != TOKslice)
6631 e1->checkArithmetic();
6632 type = e1->type;
6633 }
6634 return this;
6635 }
6636
6637 /************************************************************/
6638
6639 UAddExp::UAddExp(Loc loc, Expression *e)
6640 : UnaExp(loc, TOKuadd, sizeof(UAddExp), e)
6641 {
6642 }
6643
6644 Expression *UAddExp::semantic(Scope *sc)
6645 { Expression *e;
6646
6647 #if LOGSEMANTIC
6648 printf("UAddExp::semantic('%s')\n", toChars());
6649 #endif
6650 assert(!type);
6651 UnaExp::semantic(sc);
6652 e1 = resolveProperties(sc, e1);
6653 e = op_overload(sc);
6654 if (e)
6655 return e;
6656 e1->checkNoBool();
6657 e1->checkArithmetic();
6658 return e1;
6659 }
6660
6661 /************************************************************/
6662
6663 ComExp::ComExp(Loc loc, Expression *e)
6664 : UnaExp(loc, TOKtilde, sizeof(ComExp), e)
6665 {
6666 }
6667
6668 Expression *ComExp::semantic(Scope *sc)
6669 { Expression *e;
6670
6671 if (!type)
6672 {
6673 UnaExp::semantic(sc);
6674 e1 = resolveProperties(sc, e1);
6675 e = op_overload(sc);
6676 if (e)
6677 return e;
6678
6679 e1->checkNoBool();
6680 if (e1->op != TOKslice)
6681 e1 = e1->checkIntegral();
6682 type = e1->type;
6683 }
6684 return this;
6685 }
6686
6687 /************************************************************/
6688
6689 NotExp::NotExp(Loc loc, Expression *e)
6690 : UnaExp(loc, TOKnot, sizeof(NotExp), e)
6691 {
6692 }
6693
6694 Expression *NotExp::semantic(Scope *sc)
6695 {
6696 UnaExp::semantic(sc);
6697 e1 = resolveProperties(sc, e1);
6698 e1 = e1->checkToBoolean();
6699 type = Type::tboolean;
6700 return this;
6701 }
6702
6703 int NotExp::isBit()
6704 {
6705 return TRUE;
6706 }
6707
6708
6709
6710 /************************************************************/
6711
6712 BoolExp::BoolExp(Loc loc, Expression *e, Type *t)
6713 : UnaExp(loc, TOKtobool, sizeof(BoolExp), e)
6714 {
6715 type = t;
6716 }
6717
6718 Expression *BoolExp::semantic(Scope *sc)
6719 {
6720 UnaExp::semantic(sc);
6721 e1 = resolveProperties(sc, e1);
6722 e1 = e1->checkToBoolean();
6723 type = Type::tboolean;
6724 return this;
6725 }
6726
6727 int BoolExp::isBit()
6728 {
6729 return TRUE;
6730 }
6731
6732 /************************************************************/
6733
6734 DeleteExp::DeleteExp(Loc loc, Expression *e)
6735 : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e)
6736 {
6737 }
6738
6739 Expression *DeleteExp::semantic(Scope *sc)
6740 {
6741 Type *tb;
6742
6743 UnaExp::semantic(sc);
6744 e1 = resolveProperties(sc, e1);
6745 e1 = e1->toLvalue(sc, NULL);
6746 type = Type::tvoid;
6747
6748 tb = e1->type->toBasetype();
6749 switch (tb->ty)
6750 { case Tclass:
6751 { TypeClass *tc = (TypeClass *)tb;
6752 ClassDeclaration *cd = tc->sym;
6753
6754 if (cd->isCOMinterface())
6755 { /* Because COM classes are deleted by IUnknown.Release()
6756 */
6757 error("cannot delete instance of COM interface %s", cd->toChars());
6758 }
6759 break;
6760 }
6761 case Tpointer:
6762 tb = ((TypePointer *)tb)->next->toBasetype();
6763 if (tb->ty == Tstruct)
6764 {
6765 TypeStruct *ts = (TypeStruct *)tb;
6766 StructDeclaration *sd = ts->sym;
6767 FuncDeclaration *f = sd->aggDelete;
6768 FuncDeclaration *fd = sd->dtor;
6769
6770 if (!f && !fd)
6771 break;
6772
6773 /* Construct:
6774 * ea = copy e1 to a tmp to do side effects only once
6775 * eb = call destructor
6776 * ec = call deallocator
6777 */
6778 Expression *ea = NULL;
6779 Expression *eb = NULL;
6780 Expression *ec = NULL;
6781 VarDeclaration *v;
6782
6783 if (fd && f)
6784 { Identifier *id = Lexer::idPool("__tmp");
6785 v = new VarDeclaration(loc, e1->type, id, new ExpInitializer(loc, e1));
6786 v->semantic(sc);
6787 v->parent = sc->parent;
6788 ea = new DeclarationExp(loc, v);
6789 ea->type = v->type;
6790 }
6791
6792 if (fd)
6793 { Expression *e = ea ? new VarExp(loc, v) : e1;
6794 e = new DotVarExp(0, e, fd, 0);
6795 eb = new CallExp(loc, e);
6796 eb = eb->semantic(sc);
6797 }
6798
6799 if (f)
6800 {
6801 Type *tpv = Type::tvoid->pointerTo();
6802 Expression *e = ea ? new VarExp(loc, v) : e1->castTo(sc, tpv);
6803 e = new CallExp(loc, new VarExp(loc, f), e);
6804 ec = e->semantic(sc);
6805 }
6806 ea = combine(ea, eb);
6807 ea = combine(ea, ec);
6808 assert(ea);
6809 return ea;
6810 }
6811 break;
6812
6813 case Tarray:
6814 /* BUG: look for deleting arrays of structs with dtors.
6815 */
6816 break;
6817
6818 default:
6819 if (e1->op == TOKindex)
6820 {
6821 IndexExp *ae = (IndexExp *)(e1);
6822 Type *tb1 = ae->e1->type->toBasetype();
6823 if (tb1->ty == Taarray)
6824 break;
6825 }
6826 error("cannot delete type %s", e1->type->toChars());
6827 break;
6828 }
6829
6830 if (e1->op == TOKindex)
6831 {
6832 IndexExp *ae = (IndexExp *)(e1);
6833 Type *tb1 = ae->e1->type->toBasetype();
6834 if (tb1->ty == Taarray)
6835 { if (!global.params.useDeprecated)
6836 error("delete aa[key] deprecated, use aa.remove(key)");
6837 }
6838 }
6839
6840 return this;
6841 }
6842
6843 int DeleteExp::checkSideEffect(int flag)
6844 {
6845 return 1;
6846 }
6847
6848 Expression *DeleteExp::checkToBoolean()
6849 {
6850 error("delete does not give a boolean result");
6851 return this;
6852 }
6853
6854 void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6855 {
6856 buf->writestring("delete ");
6857 expToCBuffer(buf, hgs, e1, precedence[op]);
6858 }
6859
6860 /************************************************************/
6861
6862 CastExp::CastExp(Loc loc, Expression *e, Type *t)
6863 : UnaExp(loc, TOKcast, sizeof(CastExp), e)
6864 {
6865 to = t;
6866 this->tok = TOKreserved;
6867 }
6868
6869 /* For cast(const) and cast(invariant)
6870 */
6871 CastExp::CastExp(Loc loc, Expression *e, enum TOK tok)
6872 : UnaExp(loc, TOKcast, sizeof(CastExp), e)
6873 {
6874 to = NULL;
6875 this->tok = tok;
6876 }
6877
6878 Expression *CastExp::syntaxCopy()
6879 {
6880 return to ? new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy())
6881 : new CastExp(loc, e1->syntaxCopy(), tok);
6882 }
6883
6884
6885 Expression *CastExp::semantic(Scope *sc)
6886 { Expression *e;
6887 BinExp *b;
6888 UnaExp *u;
6889
6890 #if LOGSEMANTIC
6891 printf("CastExp::semantic('%s')\n", toChars());
6892 #endif
6893
6894 //static int x; assert(++x < 10);
6895
6896 if (type)
6897 return this;
6898 UnaExp::semantic(sc);
6899 if (e1->type) // if not a tuple
6900 {
6901 e1 = resolveProperties(sc, e1);
6902
6903 /* Handle cast(const) and cast(invariant)
6904 */
6905 if (!to)
6906 { if (tok == TOKconst)
6907 to = e1->type->constOf();
6908 else if (tok == TOKinvariant || tok == TOKimmutable)
6909 to = e1->type->invariantOf();
6910 else
6911 assert(0);
6912 }
6913 else
6914 to = to->semantic(loc, sc);
6915
6916 e = op_overload(sc);
6917 if (e)
6918 {
6919 return e->implicitCastTo(sc, to);
6920 }
6921
6922 Type *tob = to->toBasetype();
6923 if (tob->ty == Tstruct &&
6924 !tob->equals(e1->type->toBasetype()) &&
6925 ((TypeStruct *)to)->sym->search(0, Id::call, 0)
6926 )
6927 {
6928 /* Look to replace:
6929 * cast(S)t
6930 * with:
6931 * S(t)
6932 */
6933
6934 // Rewrite as to.call(e1)
6935 e = new TypeExp(loc, to);
6936 e = new DotIdExp(loc, e, Id::call);
6937 e = new CallExp(loc, e, e1);
6938 e = e->semantic(sc);
6939 return e;
6940 }
6941 }
6942 else if (!to)
6943 { error("cannot cast tuple");
6944 to = Type::terror;
6945 }
6946 e = e1->castTo(sc, to);
6947 return e;
6948 }
6949
6950 int CastExp::checkSideEffect(int flag)
6951 {
6952 /* if not:
6953 * cast(void)
6954 * cast(classtype)func()
6955 */
6956 if (!to->equals(Type::tvoid) &&
6957 !(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass))
6958 return Expression::checkSideEffect(flag);
6959 return 1;
6960 }
6961
6962 void CastExp::checkEscape()
6963 { Type *tb = type->toBasetype();
6964 if (tb->ty == Tarray && e1->op == TOKvar &&
6965 e1->type->toBasetype()->ty == Tsarray)
6966 { VarExp *ve = (VarExp *)e1;
6967 VarDeclaration *v = ve->var->isVarDeclaration();
6968 if (v)
6969 {
6970 if (!v->isDataseg() && !v->isParameter())
6971 error("escaping reference to local %s", v->toChars());
6972 }
6973 }
6974 }
6975
6976 void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6977 {
6978 buf->writestring("cast(");
6979 if (to)
6980 to->toCBuffer(buf, NULL, hgs);
6981 else
6982 buf->writestring(Token::tochars[tok]);
6983 buf->writeByte(')');
6984 expToCBuffer(buf, hgs, e1, precedence[op]);
6985 }
6986
6987
6988 /************************************************************/
6989
6990 SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr)
6991 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1)
6992 {
6993 this->upr = upr;
6994 this->lwr = lwr;
6995 lengthVar = NULL;
6996 }
6997
6998 Expression *SliceExp::syntaxCopy()
6999 {
7000 Expression *lwr = NULL;
7001 if (this->lwr)
7002 lwr = this->lwr->syntaxCopy();
7003
7004 Expression *upr = NULL;
7005 if (this->upr)
7006 upr = this->upr->syntaxCopy();
7007
7008 return new SliceExp(loc, e1->syntaxCopy(), lwr, upr);
7009 }
7010
7011 Expression *SliceExp::semantic(Scope *sc)
7012 { Expression *e;
7013 AggregateDeclaration *ad;
7014 //FuncDeclaration *fd;
7015 ScopeDsymbol *sym;
7016
7017 #if LOGSEMANTIC
7018 printf("SliceExp::semantic('%s')\n", toChars());
7019 #endif
7020 if (type)
7021 return this;
7022
7023 UnaExp::semantic(sc);
7024 e1 = resolveProperties(sc, e1);
7025
7026 e = this;
7027
7028 Type *t = e1->type->toBasetype();
7029 if (t->ty == Tpointer)
7030 {
7031 if (!lwr || !upr)
7032 error("need upper and lower bound to slice pointer");
7033 }
7034 else if (t->ty == Tarray)
7035 {
7036 }
7037 else if (t->ty == Tsarray)
7038 {
7039 }
7040 else if (t->ty == Tclass)
7041 {
7042 ad = ((TypeClass *)t)->sym;
7043 goto L1;
7044 }
7045 else if (t->ty == Tstruct)
7046 {
7047 ad = ((TypeStruct *)t)->sym;
7048
7049 L1:
7050 if (search_function(ad, Id::slice))
7051 {
7052 // Rewrite as e1.slice(lwr, upr)
7053 e = new DotIdExp(loc, e1, Id::slice);
7054
7055 if (lwr)
7056 {
7057 assert(upr);
7058 e = new CallExp(loc, e, lwr, upr);
7059 }
7060 else
7061 { assert(!upr);
7062 e = new CallExp(loc, e);
7063 }
7064 e = e->semantic(sc);
7065 return e;
7066 }
7067 goto Lerror;
7068 }
7069 else if (t->ty == Ttuple)
7070 {
7071 if (!lwr && !upr)
7072 return e1;
7073 if (!lwr || !upr)
7074 { error("need upper and lower bound to slice tuple");
7075 goto Lerror;
7076 }
7077 }
7078 else
7079 goto Lerror;
7080
7081 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
7082 {
7083 sym = new ArrayScopeSymbol(sc, this);
7084 sym->loc = loc;
7085 sym->parent = sc->scopesym;
7086 sc = sc->push(sym);
7087 }
7088
7089 if (lwr)
7090 { lwr = lwr->semantic(sc);
7091 lwr = resolveProperties(sc, lwr);
7092 lwr = lwr->implicitCastTo(sc, Type::tsize_t);
7093 }
7094 if (upr)
7095 { upr = upr->semantic(sc);
7096 upr = resolveProperties(sc, upr);
7097 upr = upr->implicitCastTo(sc, Type::tsize_t);
7098 }
7099
7100 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
7101 sc->pop();
7102
7103 if (t->ty == Ttuple)
7104 {
7105 lwr = lwr->optimize(WANTvalue);
7106 upr = upr->optimize(WANTvalue);
7107 uinteger_t i1 = lwr->toUInteger();
7108 uinteger_t i2 = upr->toUInteger();
7109
7110 size_t length;
7111 TupleExp *te;
7112 TypeTuple *tup;
7113
7114 if (e1->op == TOKtuple) // slicing an expression tuple
7115 { te = (TupleExp *)e1;
7116 length = te->exps->dim;
7117 }
7118 else if (e1->op == TOKtype) // slicing a type tuple
7119 { tup = (TypeTuple *)t;
7120 length = Argument::dim(tup->arguments);
7121 }
7122 else
7123 assert(0);
7124
7125 if (i1 <= i2 && i2 <= length)
7126 { size_t j1 = (size_t) i1;
7127 size_t j2 = (size_t) i2;
7128
7129 if (e1->op == TOKtuple)
7130 { Expressions *exps = new Expressions;
7131 exps->setDim(j2 - j1);
7132 for (size_t i = 0; i < j2 - j1; i++)
7133 { Expression *e = (Expression *)te->exps->data[j1 + i];
7134 exps->data[i] = (void *)e;
7135 }
7136 e = new TupleExp(loc, exps);
7137 }
7138 else
7139 { Arguments *args = new Arguments;
7140 args->reserve(j2 - j1);
7141 for (size_t i = j1; i < j2; i++)
7142 { Argument *arg = Argument::getNth(tup->arguments, i);
7143 args->push(arg);
7144 }
7145 e = new TypeExp(e1->loc, new TypeTuple(args));
7146 }
7147 e = e->semantic(sc);
7148 }
7149 else
7150 {
7151 error("string slice [%llu .. %llu] is out of bounds", i1, i2);
7152 e = e1;
7153 }
7154 return e;
7155 }
7156
7157 type = t->nextOf()->arrayOf();
7158 return e;
7159
7160 Lerror:
7161 char *s;
7162 if (t->ty == Tvoid)
7163 s = e1->toChars();
7164 else
7165 s = t->toChars();
7166 error("%s cannot be sliced with []", s);
7167 type = Type::terror;
7168 return e;
7169 }
7170
7171 void SliceExp::checkEscape()
7172 {
7173 e1->checkEscape();
7174 }
7175
7176 int SliceExp::isLvalue()
7177 {
7178 return 1;
7179 }
7180
7181 Expression *SliceExp::toLvalue(Scope *sc, Expression *e)
7182 {
7183 return this;
7184 }
7185
7186 Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e)
7187 {
7188 error("slice expression %s is not a modifiable lvalue", toChars());
7189 return this;
7190 }
7191
7192 void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7193 {
7194 expToCBuffer(buf, hgs, e1, precedence[op]);
7195 buf->writeByte('[');
7196 if (upr || lwr)
7197 {
7198 if (lwr)
7199 expToCBuffer(buf, hgs, lwr, PREC_assign);
7200 else
7201 buf->writeByte('0');
7202 buf->writestring("..");
7203 if (upr)
7204 expToCBuffer(buf, hgs, upr, PREC_assign);
7205 else
7206 buf->writestring("length"); // BUG: should be array.length
7207 }
7208 buf->writeByte(']');
7209 }
7210
7211 /********************** ArrayLength **************************************/
7212
7213 ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1)
7214 : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1)
7215 {
7216 }
7217
7218 Expression *ArrayLengthExp::semantic(Scope *sc)
7219 { Expression *e;
7220
7221 #if LOGSEMANTIC
7222 printf("ArrayLengthExp::semantic('%s')\n", toChars());
7223 #endif
7224 if (!type)
7225 {
7226 UnaExp::semantic(sc);
7227 e1 = resolveProperties(sc, e1);
7228
7229 type = Type::tsize_t;
7230 }
7231 return this;
7232 }
7233
7234 void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7235 {
7236 expToCBuffer(buf, hgs, e1, PREC_primary);
7237 buf->writestring(".length");
7238 }
7239
7240 /*********************** ArrayExp *************************************/
7241
7242 // e1 [ i1, i2, i3, ... ]
7243
7244 ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args)
7245 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1)
7246 {
7247 arguments = args;
7248 }
7249
7250 Expression *ArrayExp::syntaxCopy()
7251 {
7252 return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
7253 }
7254
7255 Expression *ArrayExp::semantic(Scope *sc)
7256 { Expression *e;
7257 Type *t1;
7258
7259 #if LOGSEMANTIC
7260 printf("ArrayExp::semantic('%s')\n", toChars());
7261 #endif
7262 UnaExp::semantic(sc);
7263 e1 = resolveProperties(sc, e1);
7264
7265 t1 = e1->type->toBasetype();
7266 if (t1->ty != Tclass && t1->ty != Tstruct)
7267 { // Convert to IndexExp
7268 if (arguments->dim != 1)
7269 error("only one index allowed to index %s", t1->toChars());
7270 e = new IndexExp(loc, e1, (Expression *)arguments->data[0]);
7271 return e->semantic(sc);
7272 }
7273
7274 // Run semantic() on each argument
7275 for (size_t i = 0; i < arguments->dim; i++)
7276 { e = (Expression *)arguments->data[i];
7277
7278 e = e->semantic(sc);
7279 if (!e->type)
7280 error("%s has no value", e->toChars());
7281 arguments->data[i] = (void *)e;
7282 }
7283
7284 expandTuples(arguments);
7285 assert(arguments && arguments->dim);
7286
7287 e = op_overload(sc);
7288 if (!e)
7289 { error("no [] operator overload for type %s", e1->type->toChars());
7290 e = e1;
7291 }
7292 return e;
7293 }
7294
7295
7296 int ArrayExp::isLvalue()
7297 {
7298 if (type && type->toBasetype()->ty == Tvoid)
7299 return 0;
7300 return 1;
7301 }
7302
7303 Expression *ArrayExp::toLvalue(Scope *sc, Expression *e)
7304 {
7305 if (type && type->toBasetype()->ty == Tvoid)
7306 error("voids have no value");
7307 return this;
7308 }
7309
7310
7311 void ArrayExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7312 { int i;
7313
7314 expToCBuffer(buf, hgs, e1, PREC_primary);
7315 buf->writeByte('[');
7316 argsToCBuffer(buf, arguments, hgs);
7317 buf->writeByte(']');
7318 }
7319
7320 /************************* DotExp ***********************************/
7321
7322 DotExp::DotExp(Loc loc, Expression *e1, Expression *e2)
7323 : BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2)
7324 {
7325 }
7326
7327 Expression *DotExp::semantic(Scope *sc)
7328 {
7329 #if LOGSEMANTIC
7330 printf("DotExp::semantic('%s')\n", toChars());
7331 if (type) printf("\ttype = %s\n", type->toChars());
7332 #endif
7333 e1 = e1->semantic(sc);
7334 e2 = e2->semantic(sc);
7335 if (e2->op == TOKimport)
7336 {
7337 ScopeExp *se = (ScopeExp *)e2;
7338 TemplateDeclaration *td = se->sds->isTemplateDeclaration();
7339 if (td)
7340 { Expression *e = new DotTemplateExp(loc, e1, td);
7341 e = e->semantic(sc);
7342 return e;
7343 }
7344 }
7345 if (!type)
7346 type = e2->type;
7347 return this;
7348 }
7349
7350
7351 /************************* CommaExp ***********************************/
7352
7353 CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2)
7354 : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2)
7355 {
7356 }
7357
7358 Expression *CommaExp::semantic(Scope *sc)
7359 {
7360 if (!type)
7361 { BinExp::semanticp(sc);
7362 type = e2->type;
7363 }
7364 return this;
7365 }
7366
7367 void CommaExp::checkEscape()
7368 {
7369 e2->checkEscape();
7370 }
7371
7372 int CommaExp::isLvalue()
7373 {
7374 return e2->isLvalue();
7375 }
7376
7377 Expression *CommaExp::toLvalue(Scope *sc, Expression *e)
7378 {
7379 e2 = e2->toLvalue(sc, NULL);
7380 return this;
7381 }
7382
7383 Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e)
7384 {
7385 e2 = e2->modifiableLvalue(sc, e);
7386 return this;
7387 }
7388
7389 int CommaExp::isBool(int result)
7390 {
7391 return e2->isBool(result);
7392 }
7393
7394 int CommaExp::checkSideEffect(int flag)
7395 {
7396 if (flag == 2)
7397 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
7398 else
7399 {
7400 // Don't check e1 until we cast(void) the a,b code generation
7401 return e2->checkSideEffect(flag);
7402 }
7403 }
7404
7405 /************************** IndexExp **********************************/
7406
7407 // e1 [ e2 ]
7408
7409 IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2)
7410 : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2)
7411 {
7412 //printf("IndexExp::IndexExp('%s')\n", toChars());
7413 lengthVar = NULL;
7414 modifiable = 0; // assume it is an rvalue
7415 }
7416
7417 Expression *IndexExp::semantic(Scope *sc)
7418 { Expression *e;
7419 BinExp *b;
7420 UnaExp *u;
7421 Type *t1;
7422 ScopeDsymbol *sym;
7423
7424 #if LOGSEMANTIC
7425 printf("IndexExp::semantic('%s')\n", toChars());
7426 #endif
7427 if (type)
7428 return this;
7429 if (!e1->type)
7430 e1 = e1->semantic(sc);
7431 assert(e1->type); // semantic() should already be run on it
7432 e = this;
7433
7434 // Note that unlike C we do not implement the int[ptr]
7435
7436 t1 = e1->type->toBasetype();
7437
7438 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
7439 { // Create scope for 'length' variable
7440 sym = new ArrayScopeSymbol(sc, this);
7441 sym->loc = loc;
7442 sym->parent = sc->scopesym;
7443 sc = sc->push(sym);
7444 }
7445
7446 e2 = e2->semantic(sc);
7447 if (!e2->type)
7448 {
7449 error("%s has no value", e2->toChars());
7450 e2->type = Type::terror;
7451 }
7452 e2 = resolveProperties(sc, e2);
7453
7454 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
7455 sc = sc->pop();
7456
7457 switch (t1->ty)
7458 {
7459 case Tpointer:
7460 case Tarray:
7461 e2 = e2->implicitCastTo(sc, Type::tsize_t);
7462 e->type = ((TypeNext *)t1)->next;
7463 break;
7464
7465 case Tsarray:
7466 {
7467 e2 = e2->implicitCastTo(sc, Type::tsize_t);
7468
7469 TypeSArray *tsa = (TypeSArray *)t1;
7470
7471 #if 0 // Don't do now, because it might be short-circuit evaluated
7472 // Do compile time array bounds checking if possible
7473 e2 = e2->optimize(WANTvalue);
7474 if (e2->op == TOKint64)
7475 {
7476 integer_t index = e2->toInteger();
7477 integer_t length = tsa->dim->toInteger();
7478 if (index < 0 || index >= length)
7479 error("array index [%lld] is outside array bounds [0 .. %lld]",
7480 index, length);
7481 }
7482 #endif
7483 e->type = t1->nextOf();
7484 break;
7485 }
7486
7487 case Taarray:
7488 { TypeAArray *taa = (TypeAArray *)t1;
7489
7490 e2 = e2->implicitCastTo(sc, taa->index); // type checking
7491 type = taa->next;
7492 break;
7493 }
7494
7495 case Ttuple:
7496 {
7497 e2 = e2->implicitCastTo(sc, Type::tsize_t);
7498 e2 = e2->optimize(WANTvalue | WANTinterpret);
7499 uinteger_t index = e2->toUInteger();
7500 size_t length;
7501 TupleExp *te;
7502 TypeTuple *tup;
7503
7504 if (e1->op == TOKtuple)
7505 { te = (TupleExp *)e1;
7506 length = te->exps->dim;
7507 }
7508 else if (e1->op == TOKtype)
7509 {
7510 tup = (TypeTuple *)t1;
7511 length = Argument::dim(tup->arguments);
7512 }
7513 else
7514 assert(0);
7515
7516 if (index < length)
7517 {
7518
7519 if (e1->op == TOKtuple)
7520 e = (Expression *)te->exps->data[(size_t)index];
7521 else
7522 e = new TypeExp(e1->loc, Argument::getNth(tup->arguments, (size_t)index)->type);
7523 }
7524 else
7525 {
7526 error("array index [%llu] is outside array bounds [0 .. %"PRIuSIZE"]",
7527 index, length);
7528 e = e1;
7529 }
7530 break;
7531 }
7532
7533 default:
7534 error("%s must be an array or pointer type, not %s",
7535 e1->toChars(), e1->type->toChars());
7536 type = Type::tint32;
7537 break;
7538 }
7539 return e;
7540 }
7541
7542 int IndexExp::isLvalue()
7543 {
7544 return 1;
7545 }
7546
7547 Expression *IndexExp::toLvalue(Scope *sc, Expression *e)
7548 {
7549 // if (type && type->toBasetype()->ty == Tvoid)
7550 // error("voids have no value");
7551 return this;
7552 }
7553
7554 Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
7555 {
7556 //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
7557 modifiable = 1;
7558 if (e1->op == TOKstring)
7559 error("string literals are immutable");
7560 if (type && !type->isMutable())
7561 error("%s isn't mutable", e->toChars());
7562 if (e1->type->toBasetype()->ty == Taarray)
7563 e1 = e1->modifiableLvalue(sc, e1);
7564 return toLvalue(sc, e);
7565 }
7566
7567 void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7568 {
7569 expToCBuffer(buf, hgs, e1, PREC_primary);
7570 buf->writeByte('[');
7571 expToCBuffer(buf, hgs, e2, PREC_assign);
7572 buf->writeByte(']');
7573 }
7574
7575
7576 /************************* PostExp ***********************************/
7577
7578 PostExp::PostExp(enum TOK op, Loc loc, Expression *e)
7579 : BinExp(loc, op, sizeof(PostExp), e,
7580 new IntegerExp(loc, 1, Type::tint32))
7581 {
7582 }
7583
7584 Expression *PostExp::semantic(Scope *sc)
7585 { Expression *e = this;
7586
7587 if (!type)
7588 {
7589 BinExp::semantic(sc);
7590 e2 = resolveProperties(sc, e2);
7591
7592 e = op_overload(sc);
7593 if (e)
7594 return e;
7595
7596 e = this;
7597 e1 = e1->modifiableLvalue(sc, e1);
7598 e1->checkScalar();
7599 e1->checkNoBool();
7600 if (e1->type->ty == Tpointer)
7601 e = scaleFactor(sc);
7602 else
7603 e2 = e2->castTo(sc, e1->type);
7604 e->type = e1->type;
7605 }
7606 return e;
7607 }
7608
7609 void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7610 {
7611 expToCBuffer(buf, hgs, e1, precedence[op]);
7612 buf->writestring((op == TOKplusplus) ? (char *)"++" : (char *)"--");
7613 }
7614
7615 /************************************************************/
7616
7617 /* op can be TOKassign, TOKconstruct, or TOKblit */
7618
7619 AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2)
7620 : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2)
7621 {
7622 ismemset = 0;
7623 }
7624
7625 Expression *AssignExp::semantic(Scope *sc)
7626 {
7627 Expression *e1old = e1;
7628
7629 #if LOGSEMANTIC
7630 printf("AssignExp::semantic('%s')\n", toChars());
7631 #endif
7632 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
7633 //printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op));
7634
7635 if (type)
7636 return this;
7637
7638 if (e2->op == TOKcomma)
7639 { /* Rewrite to get rid of the comma from rvalue
7640 */
7641 AssignExp *ea = new AssignExp(loc, e1, ((CommaExp *)e2)->e2);
7642 ea->op = op;
7643 Expression *e = new CommaExp(loc, ((CommaExp *)e2)->e1, ea);
7644 return e->semantic(sc);
7645 }
7646
7647 /* Look for operator overloading of a[i]=value.
7648 * Do it before semantic() otherwise the a[i] will have been
7649 * converted to a.opIndex() already.
7650 */
7651 if (e1->op == TOKarray)
7652 {
7653 ArrayExp *ae = (ArrayExp *)e1;
7654 AggregateDeclaration *ad;
7655 Identifier *id = Id::index;
7656
7657 ae->e1 = ae->e1->semantic(sc);
7658 Type *t1 = ae->e1->type->toBasetype();
7659 if (t1->ty == Tstruct)
7660 {
7661 ad = ((TypeStruct *)t1)->sym;
7662 goto L1;
7663 }
7664 else if (t1->ty == Tclass)
7665 {
7666 ad = ((TypeClass *)t1)->sym;
7667 L1:
7668 // Rewrite (a[i] = value) to (a.opIndexAssign(value, i))
7669 if (search_function(ad, Id::indexass))
7670 { Expression *e = new DotIdExp(loc, ae->e1, Id::indexass);
7671 Expressions *a = (Expressions *)ae->arguments->copy();
7672
7673 a->insert(0, e2);
7674 e = new CallExp(loc, e, a);
7675 e = e->semantic(sc);
7676 return e;
7677 }
7678 else
7679 {
7680 // Rewrite (a[i] = value) to (a.opIndex(i, value))
7681 if (search_function(ad, id))
7682 { Expression *e = new DotIdExp(loc, ae->e1, id);
7683
7684 if (1 || !global.params.useDeprecated)
7685 error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
7686
7687 e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2);
7688 e = e->semantic(sc);
7689 return e;
7690 }
7691 }
7692 }
7693 }
7694 /* Look for operator overloading of a[i..j]=value.
7695 * Do it before semantic() otherwise the a[i..j] will have been
7696 * converted to a.opSlice() already.
7697 */
7698 if (e1->op == TOKslice)
7699 { Type *t1;
7700 SliceExp *ae = (SliceExp *)e1;
7701 AggregateDeclaration *ad;
7702 Identifier *id = Id::index;
7703
7704 ae->e1 = ae->e1->semantic(sc);
7705 ae->e1 = resolveProperties(sc, ae->e1);
7706 t1 = ae->e1->type->toBasetype();
7707 if (t1->ty == Tstruct)
7708 {
7709 ad = ((TypeStruct *)t1)->sym;
7710 goto L2;
7711 }
7712 else if (t1->ty == Tclass)
7713 {
7714 ad = ((TypeClass *)t1)->sym;
7715 L2:
7716 // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j))
7717 if (search_function(ad, Id::sliceass))
7718 { Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass);
7719 Expressions *a = new Expressions();
7720
7721 a->push(e2);
7722 if (ae->lwr)
7723 { a->push(ae->lwr);
7724 assert(ae->upr);
7725 a->push(ae->upr);
7726 }
7727 else
7728 assert(!ae->upr);
7729 e = new CallExp(loc, e, a);
7730 e = e->semantic(sc);
7731 return e;
7732 }
7733 }
7734 }
7735
7736 BinExp::semantic(sc);
7737
7738 if (e1->op == TOKdottd)
7739 { // Rewrite a.b=e2, when b is a template, as a.b(e2)
7740 Expression *e = new CallExp(loc, e1, e2);
7741 e = e->semantic(sc);
7742 return e;
7743 }
7744
7745 e2 = resolveProperties(sc, e2);
7746 assert(e1->type);
7747
7748 /* Rewrite tuple assignment as a tuple of assignments.
7749 */
7750 if (e1->op == TOKtuple && e2->op == TOKtuple)
7751 { TupleExp *tup1 = (TupleExp *)e1;
7752 TupleExp *tup2 = (TupleExp *)e2;
7753 size_t dim = tup1->exps->dim;
7754 if (dim != tup2->exps->dim)
7755 {
7756 error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim);
7757 }
7758 else
7759 { Expressions *exps = new Expressions;
7760 exps->setDim(dim);
7761
7762 for (int i = 0; i < dim; i++)
7763 { Expression *ex1 = (Expression *)tup1->exps->data[i];
7764 Expression *ex2 = (Expression *)tup2->exps->data[i];
7765 exps->data[i] = (void *) new AssignExp(loc, ex1, ex2);
7766 }
7767 Expression *e = new TupleExp(loc, exps);
7768 e = e->semantic(sc);
7769 return e;
7770 }
7771 }
7772
7773 Type *t1 = e1->type->toBasetype();
7774
7775 if (t1->ty == Tfunction)
7776 { // Rewrite f=value to f(value)
7777 Expression *e = new CallExp(loc, e1, e2);
7778 e = e->semantic(sc);
7779 return e;
7780 }
7781
7782 /* If it is an assignment from a 'foreign' type,
7783 * check for operator overloading.
7784 */
7785 if (t1->ty == Tstruct)
7786 {
7787 StructDeclaration *sd = ((TypeStruct *)t1)->sym;
7788 if (op == TOKassign)
7789 {
7790 Expression *e = op_overload(sc);
7791 if (e)
7792 return e;
7793 }
7794 else if (op == TOKconstruct)
7795 { Type *t2 = e2->type->toBasetype();
7796 if (t2->ty == Tstruct &&
7797 sd == ((TypeStruct *)t2)->sym &&
7798 sd->cpctor)
7799 { /* We have a copy constructor for this
7800 */
7801 if (e2->op == TOKvar || e2->op == TOKstar)
7802 { /* Write as:
7803 * e1.cpctor(e2);
7804 */
7805 Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0);
7806 e = new CallExp(loc, e, e2);
7807 return e->semantic(sc);
7808 }
7809 else if (e2->op == TOKquestion)
7810 { /* Write as:
7811 * a ? e1 = b : e1 = c;
7812 */
7813 CondExp *ec = (CondExp *)e2;
7814 AssignExp *ea1 = new AssignExp(ec->e1->loc, e1, ec->e1);
7815 ea1->op = op;
7816 AssignExp *ea2 = new AssignExp(ec->e1->loc, e1, ec->e2);
7817 ea2->op = op;
7818 Expression *e = new CondExp(loc, ec->econd, ea1, ea2);
7819 return e->semantic(sc);
7820 }
7821 }
7822 }
7823 }
7824 else if (t1->ty == Tclass)
7825 { // Disallow assignment operator overloads for same type
7826 if (!e2->type->implicitConvTo(e1->type))
7827 {
7828 Expression *e = op_overload(sc);
7829 if (e)
7830 return e;
7831 }
7832 }
7833
7834 if (t1->ty == Tsarray)
7835 { // Convert e1 to e1[]
7836 Expression *e = new SliceExp(e1->loc, e1, NULL, NULL);
7837 e1 = e->semantic(sc);
7838 t1 = e1->type->toBasetype();
7839 }
7840
7841 e2->rvalue();
7842
7843 if (e1->op == TOKarraylength)
7844 {
7845 // e1 is not an lvalue, but we let code generator handle it
7846 ArrayLengthExp *ale = (ArrayLengthExp *)e1;
7847
7848 ale->e1 = ale->e1->modifiableLvalue(sc, e1);
7849 }
7850 else if (e1->op == TOKslice)
7851 {
7852 Type *tn = e1->type->nextOf();
7853 if (tn && !tn->isMutable() && op != TOKconstruct)
7854 error("slice %s is not mutable", e1->toChars());
7855 }
7856 else
7857 { // Try to do a decent error message with the expression
7858 // before it got constant folded
7859 if (e1->op != TOKvar)
7860 e1 = e1->optimize(WANTvalue);
7861
7862 if (op != TOKconstruct)
7863 e1 = e1->modifiableLvalue(sc, e1old);
7864 }
7865
7866 Type *t2 = e2->type;
7867 if (e1->op == TOKslice &&
7868 t1->nextOf() &&
7869 e2->implicitConvTo(t1->nextOf())
7870 )
7871 { // memset
7872 ismemset = 1; // make it easy for back end to tell what this is
7873 e2 = e2->implicitCastTo(sc, t1->nextOf());
7874 }
7875 else if (t1->ty == Tsarray)
7876 {
7877 /* Should have already converted e1 => e1[]
7878 */
7879 assert(0);
7880 //error("cannot assign to static array %s", e1->toChars());
7881 }
7882 else if (e1->op == TOKslice)
7883 {
7884 e2 = e2->implicitCastTo(sc, e1->type->constOf());
7885 }
7886 else
7887 {
7888 e2 = e2->implicitCastTo(sc, e1->type);
7889 }
7890
7891 /* Look for array operations
7892 */
7893 if (e1->op == TOKslice && !ismemset &&
7894 (e2->op == TOKadd || e2->op == TOKmin ||
7895 e2->op == TOKmul || e2->op == TOKdiv ||
7896 e2->op == TOKmod || e2->op == TOKxor ||
7897 e2->op == TOKand || e2->op == TOKor ||
7898 e2->op == TOKtilde || e2->op == TOKneg))
7899 {
7900 type = e1->type;
7901 return arrayOp(sc);
7902 }
7903
7904 type = e1->type;
7905 assert(type);
7906 return this;
7907 }
7908
7909 Expression *AssignExp::checkToBoolean()
7910 {
7911 // Things like:
7912 // if (a = b) ...
7913 // are usually mistakes.
7914
7915 error("'=' does not give a boolean result");
7916 return this;
7917 }
7918
7919 /************************************************************/
7920
7921 AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
7922 : BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
7923 {
7924 }
7925
7926 Expression *AddAssignExp::semantic(Scope *sc)
7927 { Expression *e;
7928
7929 if (type)
7930 return this;
7931
7932 BinExp::semantic(sc);
7933 e2 = resolveProperties(sc, e2);
7934
7935 e = op_overload(sc);
7936 if (e)
7937 return e;
7938
7939 Type *tb1 = e1->type->toBasetype();
7940 Type *tb2 = e2->type->toBasetype();
7941
7942 if (e1->op == TOKslice)
7943 {
7944 typeCombine(sc);
7945 type = e1->type;
7946 return arrayOp(sc);
7947 }
7948 else
7949 {
7950 e1 = e1->modifiableLvalue(sc, e1);
7951 }
7952
7953 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
7954 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
7955 tb1->nextOf()->equals(tb2->nextOf())
7956 )
7957 {
7958 type = e1->type;
7959 typeCombine(sc);
7960 e = this;
7961 }
7962 else
7963 {
7964 e1->checkScalar();
7965 e1->checkNoBool();
7966 if (tb1->ty == Tpointer && tb2->isintegral())
7967 e = scaleFactor(sc);
7968 else if (tb1->ty == Tbit || tb1->ty == Tbool)
7969 {
7970 #if 0
7971 // Need to rethink this
7972 if (e1->op != TOKvar)
7973 { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2
7974 VarDeclaration *v;
7975 Expression *ea;
7976 Expression *ex;
7977
7978 Identifier *id = Lexer::uniqueId("__name");
7979
7980 v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL);
7981 v->semantic(sc);
7982 if (!sc->insert(v))
7983 assert(0);
7984 v->parent = sc->func;
7985
7986 ea = new AddrExp(loc, e1);
7987 ea = new AssignExp(loc, new VarExp(loc, v), ea);
7988
7989 ex = new VarExp(loc, v);
7990 ex = new PtrExp(loc, ex);
7991 e = new AddExp(loc, ex, e2);
7992 e = new CastExp(loc, e, e1->type);
7993 e = new AssignExp(loc, ex->syntaxCopy(), e);
7994
7995 e = new CommaExp(loc, ea, e);
7996 }
7997 else
7998 #endif
7999 { // Rewrite e1+=e2 to e1=e1+e2
8000 // BUG: doesn't account for side effects in e1
8001 // BUG: other assignment operators for bits aren't handled at all
8002 e = new AddExp(loc, e1, e2);
8003 e = new CastExp(loc, e, e1->type);
8004 e = new AssignExp(loc, e1->syntaxCopy(), e);
8005 }
8006 e = e->semantic(sc);
8007 }
8008 else
8009 {
8010 type = e1->type;
8011 typeCombine(sc);
8012 e1->checkArithmetic();
8013 e2->checkArithmetic();
8014 if (type->isreal() || type->isimaginary())
8015 {
8016 assert(global.errors || e2->type->isfloating());
8017 e2 = e2->castTo(sc, e1->type);
8018 }
8019 e = this;
8020 }
8021 }
8022 return e;
8023 }
8024
8025 /************************************************************/
8026
8027 MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
8028 : BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
8029 {
8030 }
8031
8032 Expression *MinAssignExp::semantic(Scope *sc)
8033 { Expression *e;
8034
8035 if (type)
8036 return this;
8037
8038 BinExp::semantic(sc);
8039 e2 = resolveProperties(sc, e2);
8040
8041 e = op_overload(sc);
8042 if (e)
8043 return e;
8044
8045 if (e1->op == TOKslice)
8046 { // T[] -= ...
8047 typeCombine(sc);
8048 type = e1->type;
8049 return arrayOp(sc);
8050 }
8051
8052 e1 = e1->modifiableLvalue(sc, e1);
8053 e1->checkScalar();
8054 e1->checkNoBool();
8055 if (e1->type->ty == Tpointer && e2->type->isintegral())
8056 e = scaleFactor(sc);
8057 else
8058 {
8059 e1 = e1->checkArithmetic();
8060 e2 = e2->checkArithmetic();
8061 type = e1->type;
8062 typeCombine(sc);
8063 if (type->isreal() || type->isimaginary())
8064 {
8065 assert(e2->type->isfloating());
8066 e2 = e2->castTo(sc, e1->type);
8067 }
8068 e = this;
8069 }
8070 return e;
8071 }
8072
8073 /************************************************************/
8074
8075 CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
8076 : BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
8077 {
8078 }
8079
8080 Expression *CatAssignExp::semantic(Scope *sc)
8081 { Expression *e;
8082
8083 BinExp::semantic(sc);
8084 e2 = resolveProperties(sc, e2);
8085
8086 e = op_overload(sc);
8087 if (e)
8088 return e;
8089
8090 if (e1->op == TOKslice)
8091 { SliceExp *se = (SliceExp *)e1;
8092
8093 if (se->e1->type->toBasetype()->ty == Tsarray)
8094 error("cannot append to static array %s", se->e1->type->toChars());
8095 }
8096
8097 e1 = e1->modifiableLvalue(sc, e1);
8098
8099 Type *tb1 = e1->type->toBasetype();
8100 Type *tb2 = e2->type->toBasetype();
8101
8102 e2->rvalue();
8103
8104 if ((tb1->ty == Tarray) &&
8105 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
8106 (e2->implicitConvTo(e1->type) ||
8107 tb2->nextOf()->implicitConvTo(tb1->nextOf()))
8108 )
8109 { // Append array
8110 e2 = e2->castTo(sc, e1->type);
8111 type = e1->type;
8112 e = this;
8113 }
8114 else if ((tb1->ty == Tarray) &&
8115 e2->implicitConvTo(tb1->nextOf())
8116 )
8117 { // Append element
8118 e2 = e2->castTo(sc, tb1->nextOf());
8119 type = e1->type;
8120 e = this;
8121 }
8122 else
8123 {
8124 error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars());
8125 type = Type::tint32;
8126 e = this;
8127 }
8128 return e;
8129 }
8130
8131 /************************************************************/
8132
8133 MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
8134 : BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
8135 {
8136 }
8137
8138 Expression *MulAssignExp::semantic(Scope *sc)
8139 { Expression *e;
8140
8141 BinExp::semantic(sc);
8142 e2 = resolveProperties(sc, e2);
8143
8144 e = op_overload(sc);
8145 if (e)
8146 return e;
8147
8148 if (e1->op == TOKslice)
8149 { // T[] -= ...
8150 typeCombine(sc);
8151 type = e1->type;
8152 return arrayOp(sc);
8153 }
8154
8155 e1 = e1->modifiableLvalue(sc, e1);
8156 e1->checkScalar();
8157 e1->checkNoBool();
8158 type = e1->type;
8159 typeCombine(sc);
8160 e1->checkArithmetic();
8161 e2->checkArithmetic();
8162 if (e2->type->isfloating())
8163 { Type *t1;
8164 Type *t2;
8165
8166 t1 = e1->type;
8167 t2 = e2->type;
8168 if (t1->isreal())
8169 {
8170 if (t2->isimaginary() || t2->iscomplex())
8171 {
8172 e2 = e2->castTo(sc, t1);
8173 }
8174 }
8175 else if (t1->isimaginary())
8176 {
8177 if (t2->isimaginary() || t2->iscomplex())
8178 {
8179 switch (t1->ty)
8180 {
8181 case Timaginary32: t2 = Type::tfloat32; break;
8182 case Timaginary64: t2 = Type::tfloat64; break;
8183 case Timaginary80: t2 = Type::tfloat80; break;
8184 default:
8185 assert(0);
8186 }
8187 e2 = e2->castTo(sc, t2);
8188 }
8189 }
8190 }
8191 return this;
8192 }
8193
8194 /************************************************************/
8195
8196 DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
8197 : BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
8198 {
8199 }
8200
8201 Expression *DivAssignExp::semantic(Scope *sc)
8202 { Expression *e;
8203
8204 BinExp::semantic(sc);
8205 e2 = resolveProperties(sc, e2);
8206
8207 e = op_overload(sc);
8208 if (e)
8209 return e;
8210
8211 if (e1->op == TOKslice)
8212 { // T[] -= ...
8213 typeCombine(sc);
8214 type = e1->type;
8215 return arrayOp(sc);
8216 }
8217
8218 e1 = e1->modifiableLvalue(sc, e1);
8219 e1->checkScalar();
8220 e1->checkNoBool();
8221 type = e1->type;
8222 typeCombine(sc);
8223 e1->checkArithmetic();
8224 e2->checkArithmetic();
8225 if (e2->type->isimaginary())
8226 { Type *t1;
8227 Type *t2;
8228
8229 t1 = e1->type;
8230 if (t1->isreal())
8231 { // x/iv = i(-x/v)
8232 // Therefore, the result is 0
8233 e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1));
8234 e2->type = t1;
8235 e = new AssignExp(loc, e1, e2);
8236 e->type = t1;
8237 return e;
8238 }
8239 else if (t1->isimaginary())
8240 { Expression *e;
8241
8242 switch (t1->ty)
8243 {
8244 case Timaginary32: t2 = Type::tfloat32; break;
8245 case Timaginary64: t2 = Type::tfloat64; break;
8246 case Timaginary80: t2 = Type::tfloat80; break;
8247 default:
8248 assert(0);
8249 }
8250 e2 = e2->castTo(sc, t2);
8251 e = new AssignExp(loc, e1, e2);
8252 e->type = t1;
8253 return e;
8254 }
8255 }
8256 return this;
8257 }
8258
8259 /************************************************************/
8260
8261 ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
8262 : BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
8263 {
8264 }
8265
8266 Expression *ModAssignExp::semantic(Scope *sc)
8267 {
8268 return commonSemanticAssign(sc);
8269 }
8270
8271 /************************************************************/
8272
8273 ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
8274 : BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
8275 {
8276 }
8277
8278 Expression *ShlAssignExp::semantic(Scope *sc)
8279 { Expression *e;
8280
8281 //printf("ShlAssignExp::semantic()\n");
8282 BinExp::semantic(sc);
8283 e2 = resolveProperties(sc, e2);
8284
8285 e = op_overload(sc);
8286 if (e)
8287 return e;
8288
8289 e1 = e1->modifiableLvalue(sc, e1);
8290 e1->checkScalar();
8291 e1->checkNoBool();
8292 type = e1->type;
8293 typeCombine(sc);
8294 e1->checkIntegral();
8295 e2 = e2->checkIntegral();
8296 //e2 = e2->castTo(sc, Type::tshiftcnt);
8297 e2 = e2->castTo(sc, e1->type); // LDC
8298 return this;
8299 }
8300
8301 /************************************************************/
8302
8303 ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
8304 : BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
8305 {
8306 }
8307
8308 Expression *ShrAssignExp::semantic(Scope *sc)
8309 { Expression *e;
8310
8311 BinExp::semantic(sc);
8312 e2 = resolveProperties(sc, e2);
8313
8314 e = op_overload(sc);
8315 if (e)
8316 return e;
8317
8318 e1 = e1->modifiableLvalue(sc, e1);
8319 e1->checkScalar();
8320 e1->checkNoBool();
8321 type = e1->type;
8322 typeCombine(sc);
8323 e1->checkIntegral();
8324 e2 = e2->checkIntegral();
8325 //e2 = e2->castTo(sc, Type::tshiftcnt);
8326 e2 = e2->castTo(sc, e1->type); // LDC
8327 return this;
8328 }
8329
8330 /************************************************************/
8331
8332 UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
8333 : BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
8334 {
8335 }
8336
8337 Expression *UshrAssignExp::semantic(Scope *sc)
8338 { Expression *e;
8339
8340 BinExp::semantic(sc);
8341 e2 = resolveProperties(sc, e2);
8342
8343 e = op_overload(sc);
8344 if (e)
8345 return e;
8346
8347 e1 = e1->modifiableLvalue(sc, e1);
8348 e1->checkScalar();
8349 e1->checkNoBool();
8350 type = e1->type;
8351 typeCombine(sc);
8352 e1->checkIntegral();
8353 e2 = e2->checkIntegral();
8354 //e2 = e2->castTo(sc, Type::tshiftcnt);
8355 e2 = e2->castTo(sc, e1->type); // LDC
8356 return this;
8357 }
8358
8359 /************************************************************/
8360
8361 AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
8362 : BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
8363 {
8364 }
8365
8366 Expression *AndAssignExp::semantic(Scope *sc)
8367 {
8368 return commonSemanticAssignIntegral(sc);
8369 }
8370
8371 /************************************************************/
8372
8373 OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
8374 : BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
8375 {
8376 }
8377
8378 Expression *OrAssignExp::semantic(Scope *sc)
8379 {
8380 return commonSemanticAssignIntegral(sc);
8381 }
8382
8383 /************************************************************/
8384
8385 XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
8386 : BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
8387 {
8388 }
8389
8390 Expression *XorAssignExp::semantic(Scope *sc)
8391 {
8392 return commonSemanticAssignIntegral(sc);
8393 }
8394
8395 /************************* AddExp *****************************/
8396
8397 AddExp::AddExp(Loc loc, Expression *e1, Expression *e2)
8398 : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2)
8399 {
8400 }
8401
8402 Expression *AddExp::semantic(Scope *sc)
8403 { Expression *e;
8404
8405 #if LOGSEMANTIC
8406 printf("AddExp::semantic('%s')\n", toChars());
8407 #endif
8408 if (!type)
8409 {
8410 BinExp::semanticp(sc);
8411
8412 e = op_overload(sc);
8413 if (e)
8414 return e;
8415
8416 Type *tb1 = e1->type->toBasetype();
8417 Type *tb2 = e2->type->toBasetype();
8418
8419 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
8420 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
8421 tb1->nextOf()->equals(tb2->nextOf())
8422 )
8423 {
8424 type = e1->type;
8425 e = this;
8426 }
8427 else if (tb1->ty == Tpointer && e2->type->isintegral() ||
8428 tb2->ty == Tpointer && e1->type->isintegral())
8429 e = scaleFactor(sc);
8430 else if (tb1->ty == Tpointer && tb2->ty == Tpointer)
8431 {
8432 incompatibleTypes();
8433 type = e1->type;
8434 e = this;
8435 }
8436 else
8437 {
8438 typeCombine(sc);
8439 if ((e1->type->isreal() && e2->type->isimaginary()) ||
8440 (e1->type->isimaginary() && e2->type->isreal()))
8441 {
8442 switch (type->toBasetype()->ty)
8443 {
8444 case Tfloat32:
8445 case Timaginary32:
8446 type = Type::tcomplex32;
8447 break;
8448
8449 case Tfloat64:
8450 case Timaginary64:
8451 type = Type::tcomplex64;
8452 break;
8453
8454 case Tfloat80:
8455 case Timaginary80:
8456 type = Type::tcomplex80;
8457 break;
8458
8459 default:
8460 assert(0);
8461 }
8462 }
8463 e = this;
8464 }
8465 return e;
8466 }
8467 return this;
8468 }
8469
8470 /************************************************************/
8471
8472 MinExp::MinExp(Loc loc, Expression *e1, Expression *e2)
8473 : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2)
8474 {
8475 }
8476
8477 Expression *MinExp::semantic(Scope *sc)
8478 { Expression *e;
8479 Type *t1;
8480 Type *t2;
8481
8482 #if LOGSEMANTIC
8483 printf("MinExp::semantic('%s')\n", toChars());
8484 #endif
8485 if (type)
8486 return this;
8487
8488 BinExp::semanticp(sc);
8489
8490 e = op_overload(sc);
8491 if (e)
8492 return e;
8493
8494 e = this;
8495 t1 = e1->type->toBasetype();
8496 t2 = e2->type->toBasetype();
8497 if (t1->ty == Tpointer)
8498 {
8499 if (t2->ty == Tpointer)
8500 { // Need to divide the result by the stride
8501 // Replace (ptr - ptr) with (ptr - ptr) / stride
8502 d_int64 stride;
8503 Expression *e;
8504
8505 typeCombine(sc); // make sure pointer types are compatible
8506 type = Type::tptrdiff_t;
8507 stride = t2->nextOf()->size();
8508 if (stride == 0)
8509 {
8510 e = new IntegerExp(loc, 0, Type::tptrdiff_t);
8511 }
8512 else
8513 {
8514 e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
8515 e->type = Type::tptrdiff_t;
8516 }
8517 return e;
8518 }
8519 else if (t2->isintegral())
8520 e = scaleFactor(sc);
8521 else
8522 { error("incompatible types for minus");
8523 return new IntegerExp(0);
8524 }
8525 }
8526 else if (t2->ty == Tpointer)
8527 {
8528 type = e2->type;
8529 error("can't subtract pointer from %s", e1->type->toChars());
8530 return new IntegerExp(0);
8531 }
8532 else
8533 {
8534 typeCombine(sc);
8535 t1 = e1->type->toBasetype();
8536 t2 = e2->type->toBasetype();
8537 if ((t1->isreal() && t2->isimaginary()) ||
8538 (t1->isimaginary() && t2->isreal()))
8539 {
8540 switch (type->ty)
8541 {
8542 case Tfloat32:
8543 case Timaginary32:
8544 type = Type::tcomplex32;
8545 break;
8546
8547 case Tfloat64:
8548 case Timaginary64:
8549 type = Type::tcomplex64;
8550 break;
8551
8552 case Tfloat80:
8553 case Timaginary80:
8554 type = Type::tcomplex80;
8555 break;
8556
8557 default:
8558 assert(0);
8559 }
8560 }
8561 }
8562 return e;
8563 }
8564
8565 /************************* CatExp *****************************/
8566
8567 CatExp::CatExp(Loc loc, Expression *e1, Expression *e2)
8568 : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2)
8569 {
8570 }
8571
8572 Expression *CatExp::semantic(Scope *sc)
8573 { Expression *e;
8574
8575 //printf("CatExp::semantic() %s\n", toChars());
8576 if (!type)
8577 {
8578 BinExp::semanticp(sc);
8579 e = op_overload(sc);
8580 if (e)
8581 return e;
8582
8583 Type *tb1 = e1->type->toBasetype();
8584 Type *tb2 = e2->type->toBasetype();
8585
8586
8587 /* BUG: Should handle things like:
8588 * char c;
8589 * c ~ ' '
8590 * ' ' ~ c;
8591 */
8592
8593 #if 0
8594 e1->type->print();
8595 e2->type->print();
8596 #endif
8597 if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
8598 e2->type->implicitConvTo(tb1->nextOf()) >= MATCHconst)
8599 {
8600 type = tb1->nextOf()->arrayOf();
8601 if (tb2->ty == Tarray)
8602 { // Make e2 into [e2]
8603 e2 = new ArrayLiteralExp(e2->loc, e2);
8604 e2->type = type;
8605 }
8606 return this;
8607 }
8608 else if ((tb2->ty == Tsarray || tb2->ty == Tarray) &&
8609 e1->type->implicitConvTo(tb2->nextOf()) >= MATCHconst)
8610 {
8611 type = tb2->nextOf()->arrayOf();
8612 if (tb1->ty == Tarray)
8613 { // Make e1 into [e1]
8614 e1 = new ArrayLiteralExp(e1->loc, e1);
8615 e1->type = type;
8616 }
8617 return this;
8618 }
8619
8620 if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
8621 (tb2->ty == Tsarray || tb2->ty == Tarray) &&
8622 (tb1->nextOf()->mod || tb2->nextOf()->mod) &&
8623 (tb1->nextOf()->mod != tb2->nextOf()->mod)
8624 )
8625 {
8626 Type *t1 = tb1->nextOf()->mutableOf()->constOf()->arrayOf();
8627 Type *t2 = tb2->nextOf()->mutableOf()->constOf()->arrayOf();
8628 if (e1->op == TOKstring && !((StringExp *)e1)->committed)
8629 e1->type = t1;
8630 else
8631 e1 = e1->castTo(sc, t1);
8632 if (e2->op == TOKstring && !((StringExp *)e2)->committed)
8633 e2->type = t2;
8634 else
8635 e2 = e2->castTo(sc, t2);
8636 }
8637
8638 typeCombine(sc);
8639 type = type->toHeadMutable();
8640
8641 Type *tb = type->toBasetype();
8642 if (tb->ty == Tsarray)
8643 type = tb->nextOf()->arrayOf();
8644 if (type->ty == Tarray && tb1->nextOf() && tb2->nextOf() &&
8645 tb1->nextOf()->mod != tb2->nextOf()->mod)
8646 {
8647 type = type->nextOf()->toHeadMutable()->arrayOf();
8648 }
8649 #if 0
8650 e1->type->print();
8651 e2->type->print();
8652 type->print();
8653 print();
8654 #endif
8655 Type *t1 = e1->type->toBasetype();
8656 Type *t2 = e2->type->toBasetype();
8657 if (e1->op == TOKstring && e2->op == TOKstring)
8658 e = optimize(WANTvalue);
8659 else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
8660 (t2->ty == Tarray || t2->ty == Tsarray))
8661 {
8662 e = this;
8663 }
8664 else
8665 {
8666 //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars());
8667 error("Can only concatenate arrays, not (%s ~ %s)",
8668 e1->type->toChars(), e2->type->toChars());
8669 type = Type::tint32;
8670 e = this;
8671 }
8672 e->type = e->type->semantic(loc, sc);
8673 return e;
8674 }
8675 return this;
8676 }
8677
8678 /************************************************************/
8679
8680 MulExp::MulExp(Loc loc, Expression *e1, Expression *e2)
8681 : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2)
8682 {
8683 }
8684
8685 Expression *MulExp::semantic(Scope *sc)
8686 { Expression *e;
8687
8688 #if 0
8689 printf("MulExp::semantic() %s\n", toChars());
8690 #endif
8691 if (type)
8692 {
8693 return this;
8694 }
8695
8696 BinExp::semanticp(sc);
8697 e = op_overload(sc);
8698 if (e)
8699 return e;
8700
8701 typeCombine(sc);
8702 if (e1->op != TOKslice && e2->op != TOKslice)
8703 { e1->checkArithmetic();
8704 e2->checkArithmetic();
8705 }
8706 if (type->isfloating())
8707 { Type *t1 = e1->type;
8708 Type *t2 = e2->type;
8709
8710 if (t1->isreal())
8711 {
8712 type = t2;
8713 }
8714 else if (t2->isreal())
8715 {
8716 type = t1;
8717 }
8718 else if (t1->isimaginary())
8719 {
8720 if (t2->isimaginary())
8721 { Expression *e;
8722
8723 switch (t1->ty)
8724 {
8725 case Timaginary32: type = Type::tfloat32; break;
8726 case Timaginary64: type = Type::tfloat64; break;
8727 case Timaginary80: type = Type::tfloat80; break;
8728 default: assert(0);
8729 }
8730
8731 // iy * iv = -yv
8732 e1->type = type;
8733 e2->type = type;
8734 e = new NegExp(loc, this);
8735 e = e->semantic(sc);
8736 return e;
8737 }
8738 else
8739 type = t2; // t2 is complex
8740 }
8741 else if (t2->isimaginary())
8742 {
8743 type = t1; // t1 is complex
8744 }
8745 }
8746 return this;
8747 }
8748
8749 /************************************************************/
8750
8751 DivExp::DivExp(Loc loc, Expression *e1, Expression *e2)
8752 : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2)
8753 {
8754 }
8755
8756 Expression *DivExp::semantic(Scope *sc)
8757 { Expression *e;
8758
8759 if (type)
8760 return this;
8761
8762 BinExp::semanticp(sc);
8763 e = op_overload(sc);
8764 if (e)
8765 return e;
8766
8767 typeCombine(sc);
8768 if (e1->op != TOKslice && e2->op != TOKslice)
8769 { e1->checkArithmetic();
8770 e2->checkArithmetic();
8771 }
8772 if (type->isfloating())
8773 { Type *t1 = e1->type;
8774 Type *t2 = e2->type;
8775
8776 if (t1->isreal())
8777 {
8778 type = t2;
8779 if (t2->isimaginary())
8780 { Expression *e;
8781
8782 // x/iv = i(-x/v)
8783 e2->type = t1;
8784 e = new NegExp(loc, this);
8785 e = e->semantic(sc);
8786 return e;
8787 }
8788 }
8789 else if (t2->isreal())
8790 {
8791 type = t1;
8792 }
8793 else if (t1->isimaginary())
8794 {
8795 if (t2->isimaginary())
8796 {
8797 switch (t1->ty)
8798 {
8799 case Timaginary32: type = Type::tfloat32; break;
8800 case Timaginary64: type = Type::tfloat64; break;
8801 case Timaginary80: type = Type::tfloat80; break;
8802 default: assert(0);
8803 }
8804 }
8805 else
8806 type = t2; // t2 is complex
8807 }
8808 else if (t2->isimaginary())
8809 {
8810 type = t1; // t1 is complex
8811 }
8812 }
8813 return this;
8814 }
8815
8816 /************************************************************/
8817
8818 ModExp::ModExp(Loc loc, Expression *e1, Expression *e2)
8819 : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2)
8820 {
8821 }
8822
8823 Expression *ModExp::semantic(Scope *sc)
8824 { Expression *e;
8825
8826 if (type)
8827 return this;
8828
8829 BinExp::semanticp(sc);
8830 e = op_overload(sc);
8831 if (e)
8832 return e;
8833
8834 typeCombine(sc);
8835 if (e1->op != TOKslice && e2->op != TOKslice)
8836 { e1->checkArithmetic();
8837 e2->checkArithmetic();
8838 }
8839 if (type->isfloating())
8840 { type = e1->type;
8841 if (e2->type->iscomplex())
8842 { error("cannot perform modulo complex arithmetic");
8843 return new IntegerExp(0);
8844 }
8845 }
8846 return this;
8847 }
8848
8849 /************************************************************/
8850
8851 ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2)
8852 : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2)
8853 {
8854 }
8855
8856 Expression *ShlExp::semantic(Scope *sc)
8857 { Expression *e;
8858
8859 //printf("ShlExp::semantic(), type = %p\n", type);
8860 if (!type)
8861 { BinExp::semanticp(sc);
8862 e = op_overload(sc);
8863 if (e)
8864 return e;
8865 e1 = e1->checkIntegral();
8866 e2 = e2->checkIntegral();
8867 e1 = e1->integralPromotions(sc);
8868 //e2 = e2->castTo(sc, Type::tshiftcnt);
8869 e2 = e2->castTo(sc, e1->type); // LDC
8870 type = e1->type;
8871 }
8872 return this;
8873 }
8874
8875 /************************************************************/
8876
8877 ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2)
8878 : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2)
8879 {
8880 }
8881
8882 Expression *ShrExp::semantic(Scope *sc)
8883 { Expression *e;
8884
8885 if (!type)
8886 { BinExp::semanticp(sc);
8887 e = op_overload(sc);
8888 if (e)
8889 return e;
8890 e1 = e1->checkIntegral();
8891 e2 = e2->checkIntegral();
8892 e1 = e1->integralPromotions(sc);
8893 //e2 = e2->castTo(sc, Type::tshiftcnt);
8894 e2 = e2->castTo(sc, e1->type); // LDC
8895 type = e1->type;
8896 }
8897 return this;
8898 }
8899
8900 /************************************************************/
8901
8902 UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2)
8903 : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2)
8904 {
8905 }
8906
8907 Expression *UshrExp::semantic(Scope *sc)
8908 { Expression *e;
8909
8910 if (!type)
8911 { BinExp::semanticp(sc);
8912 e = op_overload(sc);
8913 if (e)
8914 return e;
8915 e1 = e1->checkIntegral();
8916 e2 = e2->checkIntegral();
8917 e1 = e1->integralPromotions(sc);
8918 //e2 = e2->castTo(sc, Type::tshiftcnt);
8919 e2 = e2->castTo(sc, e1->type); // LDC
8920 type = e1->type;
8921 }
8922 return this;
8923 }
8924
8925 /************************************************************/
8926
8927 AndExp::AndExp(Loc loc, Expression *e1, Expression *e2)
8928 : BinExp(loc, TOKand, sizeof(AndExp), e1, e2)
8929 {
8930 }
8931
8932 Expression *AndExp::semantic(Scope *sc)
8933 { Expression *e;
8934
8935 if (!type)
8936 { BinExp::semanticp(sc);
8937 e = op_overload(sc);
8938 if (e)
8939 return e;
8940 if (e1->type->toBasetype()->ty == Tbool &&
8941 e2->type->toBasetype()->ty == Tbool)
8942 {
8943 type = e1->type;
8944 e = this;
8945 }
8946 else
8947 {
8948 typeCombine(sc);
8949 if (e1->op != TOKslice && e2->op != TOKslice)
8950 { e1->checkIntegral();
8951 e2->checkIntegral();
8952 }
8953 }
8954 }
8955 return this;
8956 }
8957
8958 /************************************************************/
8959
8960 OrExp::OrExp(Loc loc, Expression *e1, Expression *e2)
8961 : BinExp(loc, TOKor, sizeof(OrExp), e1, e2)
8962 {
8963 }
8964
8965 Expression *OrExp::semantic(Scope *sc)
8966 { Expression *e;
8967
8968 if (!type)
8969 { BinExp::semanticp(sc);
8970 e = op_overload(sc);
8971 if (e)
8972 return e;
8973 if (e1->type->toBasetype()->ty == Tbool &&
8974 e2->type->toBasetype()->ty == Tbool)
8975 {
8976 type = e1->type;
8977 e = this;
8978 }
8979 else
8980 {
8981 typeCombine(sc);
8982 if (e1->op != TOKslice && e2->op != TOKslice)
8983 { e1->checkIntegral();
8984 e2->checkIntegral();
8985 }
8986 }
8987 }
8988 return this;
8989 }
8990
8991 /************************************************************/
8992
8993 XorExp::XorExp(Loc loc, Expression *e1, Expression *e2)
8994 : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2)
8995 {
8996 }
8997
8998 Expression *XorExp::semantic(Scope *sc)
8999 { Expression *e;
9000
9001 if (!type)
9002 { BinExp::semanticp(sc);
9003 e = op_overload(sc);
9004 if (e)
9005 return e;
9006 if (e1->type->toBasetype()->ty == Tbool &&
9007 e2->type->toBasetype()->ty == Tbool)
9008 {
9009 type = e1->type;
9010 e = this;
9011 }
9012 else
9013 {
9014 typeCombine(sc);
9015 if (e1->op != TOKslice && e2->op != TOKslice)
9016 { e1->checkIntegral();
9017 e2->checkIntegral();
9018 }
9019 }
9020 }
9021 return this;
9022 }
9023
9024
9025 /************************************************************/
9026
9027 OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2)
9028 : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2)
9029 {
9030 }
9031
9032 Expression *OrOrExp::semantic(Scope *sc)
9033 {
9034 unsigned cs1;
9035
9036 // same as for AndAnd
9037 e1 = e1->semantic(sc);
9038 e1 = resolveProperties(sc, e1);
9039 e1 = e1->checkToPointer();
9040 e1 = e1->checkToBoolean();
9041 cs1 = sc->callSuper;
9042
9043 if (sc->flags & SCOPEstaticif)
9044 {
9045 /* If in static if, don't evaluate e2 if we don't have to.
9046 */
9047 e1 = e1->optimize(WANTflags);
9048 if (e1->isBool(TRUE))
9049 {
9050 return new IntegerExp(loc, 1, Type::tboolean);
9051 }
9052 }
9053
9054 e2 = e2->semantic(sc);
9055 sc->mergeCallSuper(loc, cs1);
9056 e2 = resolveProperties(sc, e2);
9057 e2 = e2->checkToPointer();
9058
9059 type = Type::tboolean;
9060 if (e1->type->ty == Tvoid)
9061 type = Type::tvoid;
9062 if (e2->op == TOKtype || e2->op == TOKimport)
9063 error("%s is not an expression", e2->toChars());
9064 return this;
9065 }
9066
9067 Expression *OrOrExp::checkToBoolean()
9068 {
9069 e2 = e2->checkToBoolean();
9070 return this;
9071 }
9072
9073 int OrOrExp::isBit()
9074 {
9075 return TRUE;
9076 }
9077
9078 int OrOrExp::checkSideEffect(int flag)
9079 {
9080 if (flag == 2)
9081 {
9082 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
9083 }
9084 else
9085 { e1->checkSideEffect(1);
9086 return e2->checkSideEffect(flag);
9087 }
9088 }
9089
9090 /************************************************************/
9091
9092 AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2)
9093 : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2)
9094 {
9095 }
9096
9097 Expression *AndAndExp::semantic(Scope *sc)
9098 {
9099 unsigned cs1;
9100
9101 // same as for OrOr
9102 e1 = e1->semantic(sc);
9103 e1 = resolveProperties(sc, e1);
9104 e1 = e1->checkToPointer();
9105 e1 = e1->checkToBoolean();
9106 cs1 = sc->callSuper;
9107
9108 if (sc->flags & SCOPEstaticif)
9109 {
9110 /* If in static if, don't evaluate e2 if we don't have to.
9111 */
9112 e1 = e1->optimize(WANTflags);
9113 if (e1->isBool(FALSE))
9114 {
9115 return new IntegerExp(loc, 0, Type::tboolean);
9116 }
9117 }
9118
9119 e2 = e2->semantic(sc);
9120 sc->mergeCallSuper(loc, cs1);
9121 e2 = resolveProperties(sc, e2);
9122 e2 = e2->checkToPointer();
9123
9124 type = Type::tboolean;
9125 if (e1->type->ty == Tvoid)
9126 type = Type::tvoid;
9127 if (e2->op == TOKtype || e2->op == TOKimport)
9128 error("%s is not an expression", e2->toChars());
9129 return this;
9130 }
9131
9132 Expression *AndAndExp::checkToBoolean()
9133 {
9134 e2 = e2->checkToBoolean();
9135 return this;
9136 }
9137
9138 int AndAndExp::isBit()
9139 {
9140 return TRUE;
9141 }
9142
9143 int AndAndExp::checkSideEffect(int flag)
9144 {
9145 if (flag == 2)
9146 {
9147 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
9148 }
9149 else
9150 {
9151 e1->checkSideEffect(1);
9152 return e2->checkSideEffect(flag);
9153 }
9154 }
9155
9156 /************************************************************/
9157
9158 InExp::InExp(Loc loc, Expression *e1, Expression *e2)
9159 : BinExp(loc, TOKin, sizeof(InExp), e1, e2)
9160 {
9161 }
9162
9163 Expression *InExp::semantic(Scope *sc)
9164 { Expression *e;
9165
9166 if (type)
9167 return this;
9168
9169 BinExp::semanticp(sc);
9170 e = op_overload(sc);
9171 if (e)
9172 return e;
9173
9174 //type = Type::tboolean;
9175 Type *t2b = e2->type->toBasetype();
9176 if (t2b->ty != Taarray)
9177 {
9178 error("rvalue of in expression must be an associative array, not %s", e2->type->toChars());
9179 type = Type::terror;
9180 }
9181 else
9182 {
9183 TypeAArray *ta = (TypeAArray *)t2b;
9184
9185 // Convert key to type of key
9186 e1 = e1->implicitCastTo(sc, ta->index);
9187
9188 // Return type is pointer to value
9189 type = ta->nextOf()->pointerTo();
9190 }
9191 return this;
9192 }
9193
9194 int InExp::isBit()
9195 {
9196 return FALSE;
9197 }
9198
9199
9200 /************************************************************/
9201
9202 /* This deletes the key e1 from the associative array e2
9203 */
9204
9205 RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2)
9206 : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2)
9207 {
9208 type = Type::tvoid;
9209 }
9210
9211 /************************************************************/
9212
9213 CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
9214 : BinExp(loc, op, sizeof(CmpExp), e1, e2)
9215 {
9216 }
9217
9218 Expression *CmpExp::semantic(Scope *sc)
9219 { Expression *e;
9220 Type *t1;
9221 Type *t2;
9222
9223 #if LOGSEMANTIC
9224 printf("CmpExp::semantic('%s')\n", toChars());
9225 #endif
9226 if (type)
9227 return this;
9228
9229 BinExp::semanticp(sc);
9230
9231 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
9232 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
9233 {
9234 error("do not use null when comparing class types");
9235 }
9236
9237 e = op_overload(sc);
9238 if (e)
9239 {
9240 e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32));
9241 e = e->semantic(sc);
9242 return e;
9243 }
9244
9245 typeCombine(sc);
9246 type = Type::tboolean;
9247
9248 // Special handling for array comparisons
9249 t1 = e1->type->toBasetype();
9250 t2 = e2->type->toBasetype();
9251 if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
9252 (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
9253 {
9254 if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
9255 t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
9256 (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
9257 error("array comparison type mismatch, %s vs %s", t1->nextOf()->toChars(), t2->nextOf()->toChars());
9258 e = this;
9259 }
9260 else if (t1->ty == Tstruct || t2->ty == Tstruct ||
9261 (t1->ty == Tclass && t2->ty == Tclass))
9262 {
9263 if (t2->ty == Tstruct)
9264 error("need member function opCmp() for %s %s to compare", t2->toDsymbol(sc)->kind(), t2->toChars());
9265 else
9266 error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars());
9267 e = this;
9268 }
9269 #if 1
9270 else if (t1->iscomplex() || t2->iscomplex())
9271 {
9272 error("compare not defined for complex operands");
9273 e = new IntegerExp(0);
9274 }
9275 #endif
9276 else
9277 e = this;
9278 //printf("CmpExp: %s\n", e->toChars());
9279 return e;
9280 }
9281
9282 int CmpExp::isBit()
9283 {
9284 return TRUE;
9285 }
9286
9287
9288 /************************************************************/
9289
9290 EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
9291 : BinExp(loc, op, sizeof(EqualExp), e1, e2)
9292 {
9293 assert(op == TOKequal || op == TOKnotequal);
9294 }
9295
9296 Expression *EqualExp::semantic(Scope *sc)
9297 { Expression *e;
9298 Type *t1;
9299 Type *t2;
9300
9301 //printf("EqualExp::semantic('%s')\n", toChars());
9302 if (type)
9303 return this;
9304
9305 BinExp::semanticp(sc);
9306
9307 /* Before checking for operator overloading, check to see if we're
9308 * comparing the addresses of two statics. If so, we can just see
9309 * if they are the same symbol.
9310 */
9311 if (e1->op == TOKaddress && e2->op == TOKaddress)
9312 { AddrExp *ae1 = (AddrExp *)e1;
9313 AddrExp *ae2 = (AddrExp *)e2;
9314
9315 if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar)
9316 { VarExp *ve1 = (VarExp *)ae1->e1;
9317 VarExp *ve2 = (VarExp *)ae2->e1;
9318
9319 if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/)
9320 {
9321 // They are the same, result is 'true' for ==, 'false' for !=
9322 e = new IntegerExp(loc, (op == TOKequal), Type::tboolean);
9323 return e;
9324 }
9325 }
9326 }
9327
9328 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
9329 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
9330 {
9331 error("use '%s' instead of '%s' when comparing with null",
9332 Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity),
9333 Token::toChars(op));
9334 }
9335
9336 //if (e2->op != TOKnull)
9337 {
9338 e = op_overload(sc);
9339 if (e)
9340 {
9341 if (op == TOKnotequal)
9342 {
9343 e = new NotExp(e->loc, e);
9344 e = e->semantic(sc);
9345 }
9346 return e;
9347 }
9348 }
9349
9350 e = typeCombine(sc);
9351 type = Type::tboolean;
9352
9353 // Special handling for array comparisons
9354 t1 = e1->type->toBasetype();
9355 t2 = e2->type->toBasetype();
9356
9357 if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
9358 (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
9359 {
9360 if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
9361 t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
9362 (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
9363 error("array equality comparison type mismatch, %s vs %s", t1->toChars(), t2->toChars());
9364 }
9365 else
9366 {
9367 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
9368 {
9369 // Cast both to complex
9370 e1 = e1->castTo(sc, Type::tcomplex80);
9371 e2 = e2->castTo(sc, Type::tcomplex80);
9372 }
9373 }
9374 return e;
9375 }
9376
9377 int EqualExp::isBit()
9378 {
9379 return TRUE;
9380 }
9381
9382
9383
9384 /************************************************************/
9385
9386 IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
9387 : BinExp(loc, op, sizeof(IdentityExp), e1, e2)
9388 {
9389 }
9390
9391 Expression *IdentityExp::semantic(Scope *sc)
9392 {
9393 if (type)
9394 return this;
9395
9396 BinExp::semanticp(sc);
9397 type = Type::tboolean;
9398 typeCombine(sc);
9399 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
9400 {
9401 // Cast both to complex
9402 e1 = e1->castTo(sc, Type::tcomplex80);
9403 e2 = e2->castTo(sc, Type::tcomplex80);
9404 }
9405 return this;
9406 }
9407
9408 int IdentityExp::isBit()
9409 {
9410 return TRUE;
9411 }
9412
9413
9414 /****************************************************************/
9415
9416 CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2)
9417 : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2)
9418 {
9419 this->econd = econd;
9420 }
9421
9422 Expression *CondExp::syntaxCopy()
9423 {
9424 return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy());
9425 }
9426
9427
9428 Expression *CondExp::semantic(Scope *sc)
9429 { Type *t1;
9430 Type *t2;
9431 unsigned cs0;
9432 unsigned cs1;
9433
9434 #if LOGSEMANTIC
9435 printf("CondExp::semantic('%s')\n", toChars());
9436 #endif
9437 if (type)
9438 return this;
9439
9440 econd = econd->semantic(sc);
9441 econd = resolveProperties(sc, econd);
9442 econd = econd->checkToPointer();
9443 econd = econd->checkToBoolean();
9444
9445 #if 0 /* this cannot work right because the types of e1 and e2
9446 * both contribute to the type of the result.
9447 */
9448 if (sc->flags & SCOPEstaticif)
9449 {
9450 /* If in static if, don't evaluate what we don't have to.
9451 */
9452 econd = econd->optimize(WANTflags);
9453 if (econd->isBool(TRUE))
9454 {
9455 e1 = e1->semantic(sc);
9456 e1 = resolveProperties(sc, e1);
9457 return e1;
9458 }
9459 else if (econd->isBool(FALSE))
9460 {
9461 e2 = e2->semantic(sc);
9462 e2 = resolveProperties(sc, e2);
9463 return e2;
9464 }
9465 }
9466 #endif
9467
9468
9469 cs0 = sc->callSuper;
9470 e1 = e1->semantic(sc);
9471 e1 = resolveProperties(sc, e1);
9472 cs1 = sc->callSuper;
9473 sc->callSuper = cs0;
9474 e2 = e2->semantic(sc);
9475 e2 = resolveProperties(sc, e2);
9476 sc->mergeCallSuper(loc, cs1);
9477
9478
9479 // If either operand is void, the result is void
9480 t1 = e1->type;
9481 t2 = e2->type;
9482 if (t1->ty == Tvoid || t2->ty == Tvoid)
9483 type = Type::tvoid;
9484 else if (t1 == t2)
9485 type = t1;
9486 else
9487 {
9488 typeCombine(sc);
9489 switch (e1->type->toBasetype()->ty)
9490 {
9491 case Tcomplex32:
9492 case Tcomplex64:
9493 case Tcomplex80:
9494 e2 = e2->castTo(sc, e1->type);
9495 break;
9496 }
9497 switch (e2->type->toBasetype()->ty)
9498 {
9499 case Tcomplex32:
9500 case Tcomplex64:
9501 case Tcomplex80:
9502 e1 = e1->castTo(sc, e2->type);
9503 break;
9504 }
9505 if (type->toBasetype()->ty == Tarray)
9506 {
9507 e1 = e1->castTo(sc, type);
9508 e2 = e2->castTo(sc, type);
9509 }
9510 }
9511 #if 0
9512 printf("res: %s\n", type->toChars());
9513 printf("e1 : %s\n", e1->type->toChars());
9514 printf("e2 : %s\n", e2->type->toChars());
9515 #endif
9516 return this;
9517 }
9518
9519 int CondExp::isLvalue()
9520 {
9521 return e1->isLvalue() && e2->isLvalue();
9522 }
9523
9524 Expression *CondExp::toLvalue(Scope *sc, Expression *ex)
9525 {
9526 PtrExp *e;
9527
9528 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
9529 e = new PtrExp(loc, this, type);
9530
9531 e1 = e1->addressOf(sc);
9532 //e1 = e1->toLvalue(sc, NULL);
9533
9534 e2 = e2->addressOf(sc);
9535 //e2 = e2->toLvalue(sc, NULL);
9536
9537 typeCombine(sc);
9538
9539 type = e2->type;
9540 return e;
9541 }
9542
9543 Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e)
9544 {
9545 error("conditional expression %s is not a modifiable lvalue", toChars());
9546 return this;
9547 }
9548
9549 void CondExp::checkEscape()
9550 {
9551 e1->checkEscape();
9552 e2->checkEscape();
9553 }
9554
9555
9556 Expression *CondExp::checkToBoolean()
9557 {
9558 e1 = e1->checkToBoolean();
9559 e2 = e2->checkToBoolean();
9560 return this;
9561 }
9562
9563 int CondExp::checkSideEffect(int flag)
9564 {
9565 if (flag == 2)
9566 {
9567 return econd->checkSideEffect(2) ||
9568 e1->checkSideEffect(2) ||
9569 e2->checkSideEffect(2);
9570 }
9571 else
9572 {
9573 econd->checkSideEffect(1);
9574 e1->checkSideEffect(flag);
9575 return e2->checkSideEffect(flag);
9576 }
9577 }
9578
9579 int CondExp::canThrow()
9580 {
9581 return econd->canThrow() || e1->canThrow() || e2->canThrow();
9582 }
9583
9584
9585 void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
9586 {
9587 expToCBuffer(buf, hgs, econd, PREC_oror);
9588 buf->writestring(" ? ");
9589 expToCBuffer(buf, hgs, e1, PREC_expr);
9590 buf->writestring(" : ");
9591 expToCBuffer(buf, hgs, e2, PREC_cond);
9592 }
9593
9594
9595 /****************************************************************/
9596
9597 DefaultInitExp::DefaultInitExp(Loc loc, enum TOK subop, int size)
9598 : Expression(loc, TOKdefault, size)
9599 {
9600 this->subop = subop;
9601 }
9602
9603 void DefaultInitExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
9604 {
9605 buf->writestring(Token::toChars(subop));
9606 }
9607
9608 /****************************************************************/
9609
9610 FileInitExp::FileInitExp(Loc loc)
9611 : DefaultInitExp(loc, TOKfile, sizeof(FileInitExp))
9612 {
9613 }
9614
9615 Expression *FileInitExp::semantic(Scope *sc)
9616 {
9617 //printf("FileInitExp::semantic()\n");
9618 type = Type::tchar->invariantOf()->arrayOf();
9619 return this;
9620 }
9621
9622 Expression *FileInitExp::resolve(Loc loc, Scope *sc)
9623 {
9624 //printf("FileInitExp::resolve() %s\n", toChars());
9625 char *s = loc.filename ? loc.filename : sc->module->ident->toChars();
9626 Expression *e = new StringExp(loc, s);
9627 e = e->semantic(sc);
9628 e = e->castTo(sc, type);
9629 return e;
9630 }
9631
9632 /****************************************************************/
9633
9634 LineInitExp::LineInitExp(Loc loc)
9635 : DefaultInitExp(loc, TOKline, sizeof(LineInitExp))
9636 {
9637 }
9638
9639 Expression *LineInitExp::semantic(Scope *sc)
9640 {
9641 type = Type::tint32;
9642 return this;
9643 }
9644
9645 Expression *LineInitExp::resolve(Loc loc, Scope *sc)
9646 {
9647 Expression *e = new IntegerExp(loc, loc.linnum, Type::tint32);
9648 e = e->castTo(sc, type);
9649 return e;
9650 }
9651
9652 /****************************************************************/
9653 /****************************************************************/
9654 /****************************************************************/
9655
9656 #if IN_LLVM
9657
9658 // Strictly LDC specific stuff
9659
9660 GEPExp::GEPExp(Loc loc, Expression* e, Identifier* id, unsigned idx)
9661 : UnaExp(loc, TOKgep, sizeof(GEPExp), e)
9662 {
9663 index = idx;
9664 ident = id;
9665 }
9666
9667 void GEPExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
9668 {
9669 expToCBuffer(buf, hgs, e1, PREC_primary);
9670 buf->writeByte('.');
9671 buf->writestring(ident->toChars());
9672 }
9673
9674 Expression* GEPExp::toLvalue(Scope* sc, Expression* e)
9675 {
9676 // GEP's are always lvalues, at least in the "LLVM sense" ...
9677 return this;
9678 }
9679
9680 #endif
9681
9682 /****************************************************************/
9683 /****************************************************************/
9684 /****************************************************************/