"cast(Foo) foo" has type "Foo?"
[delight/core.git] / dmd / expression.c
blob47eb6d32a35df2d2ad1bdafbf94825d23ae6a9c3
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.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, December 2006
17 // Issues with using -include total.h (defines integer_t) and then complex.h fails...
18 #undef integer_t
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <ctype.h>
23 #include <assert.h>
24 #include <complex.h>
25 #include <math.h>
27 #ifdef __APPLE__
28 #define integer_t dmd_integer_t
29 #endif
31 #if _WIN32 && __DMC__
32 extern "C" char * __cdecl __locale_decpoint;
33 #endif
35 #if IN_GCC
36 #include "mem.h"
37 #elif _WIN32
38 #include "..\root\mem.h"
39 #elif linux
40 #include "../root/mem.h"
41 #endif
42 //#include "port.h"
43 #include "mtype.h"
44 #include "init.h"
45 #include "expression.h"
46 #include "template.h"
47 #include "utf.h"
48 #include "enum.h"
49 #include "scope.h"
50 #include "statement.h"
51 #include "declaration.h"
52 #include "aggregate.h"
53 #include "import.h"
54 #include "id.h"
55 #include "dsymbol.h"
56 #include "module.h"
57 #include "attrib.h"
58 #include "hdrgen.h"
59 #include "parse.h"
61 Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim);
63 #define LOGSEMANTIC 0
65 /**********************************
66 * Set operator precedence for each operator.
69 // Operator precedence - greater values are higher precedence
71 enum PREC
73 PREC_zero,
74 PREC_expr,
75 PREC_assign,
76 PREC_cond,
77 PREC_oror,
78 PREC_andand,
79 PREC_or,
80 PREC_xor,
81 PREC_and,
82 PREC_equal,
83 PREC_rel,
84 PREC_shift,
85 PREC_add,
86 PREC_mul,
87 PREC_unary,
88 PREC_primary,
91 enum PREC precedence[TOKMAX];
93 void initPrecedence()
95 precedence[TOKdotvar] = PREC_primary;
96 precedence[TOKimport] = PREC_primary;
97 precedence[TOKidentifier] = PREC_primary;
98 precedence[TOKthis] = PREC_primary;
99 precedence[TOKsuper] = PREC_primary;
100 precedence[TOKint64] = PREC_primary;
101 precedence[TOKfloat64] = PREC_primary;
102 precedence[TOKnull] = PREC_primary;
103 precedence[TOKstring] = PREC_primary;
104 precedence[TOKarrayliteral] = PREC_primary;
105 precedence[TOKtypedot] = PREC_primary;
106 precedence[TOKtypeid] = PREC_primary;
107 precedence[TOKis] = PREC_primary;
108 precedence[TOKassert] = PREC_primary;
109 precedence[TOKfunction] = PREC_primary;
110 precedence[TOKvar] = PREC_primary;
112 // post
113 precedence[TOKdotti] = PREC_primary;
114 precedence[TOKdot] = PREC_primary;
115 // precedence[TOKarrow] = PREC_primary;
116 precedence[TOKplusplus] = PREC_primary;
117 precedence[TOKminusminus] = PREC_primary;
118 precedence[TOKcall] = PREC_primary;
119 precedence[TOKslice] = PREC_primary;
120 precedence[TOKarray] = PREC_primary;
122 precedence[TOKaddress] = PREC_unary;
123 precedence[TOKstar] = PREC_unary;
124 precedence[TOKneg] = PREC_unary;
125 precedence[TOKuadd] = PREC_unary;
126 precedence[TOKnot] = PREC_unary;
127 precedence[TOKtobool] = PREC_add;
128 precedence[TOKtilde] = PREC_unary;
129 precedence[TOKdelete] = PREC_unary;
130 precedence[TOKnew] = PREC_unary;
131 precedence[TOKcast] = PREC_unary;
133 precedence[TOKmul] = PREC_mul;
134 precedence[TOKdiv] = PREC_mul;
135 precedence[TOKmod] = PREC_mul;
137 precedence[TOKadd] = PREC_add;
138 precedence[TOKmin] = PREC_add;
139 precedence[TOKcat] = PREC_add;
141 precedence[TOKshl] = PREC_shift;
142 precedence[TOKshr] = PREC_shift;
143 precedence[TOKushr] = PREC_shift;
145 precedence[TOKlt] = PREC_rel;
146 precedence[TOKle] = PREC_rel;
147 precedence[TOKgt] = PREC_rel;
148 precedence[TOKge] = PREC_rel;
149 precedence[TOKunord] = PREC_rel;
150 precedence[TOKlg] = PREC_rel;
151 precedence[TOKleg] = PREC_rel;
152 precedence[TOKule] = PREC_rel;
153 precedence[TOKul] = PREC_rel;
154 precedence[TOKuge] = PREC_rel;
155 precedence[TOKug] = PREC_rel;
156 precedence[TOKue] = PREC_rel;
157 precedence[TOKin] = PREC_rel;
159 precedence[TOKequal] = PREC_equal;
160 precedence[TOKnotequal] = PREC_equal;
161 precedence[TOKidentity] = PREC_equal;
162 precedence[TOKnotidentity] = PREC_equal;
164 precedence[TOKand] = PREC_and;
166 precedence[TOKxor] = PREC_xor;
168 precedence[TOKor] = PREC_or;
170 precedence[TOKandand] = PREC_andand;
172 precedence[TOKoror] = PREC_oror;
174 precedence[TOKquestion] = PREC_cond;
176 precedence[TOKassign] = PREC_assign;
177 precedence[TOKconstruct] = PREC_assign;
178 precedence[TOKblit] = PREC_assign;
179 precedence[TOKaddass] = PREC_assign;
180 precedence[TOKminass] = PREC_assign;
181 precedence[TOKcatass] = PREC_assign;
182 precedence[TOKmulass] = PREC_assign;
183 precedence[TOKdivass] = PREC_assign;
184 precedence[TOKmodass] = PREC_assign;
185 precedence[TOKshlass] = PREC_assign;
186 precedence[TOKshrass] = PREC_assign;
187 precedence[TOKushrass] = PREC_assign;
188 precedence[TOKandass] = PREC_assign;
189 precedence[TOKorass] = PREC_assign;
190 precedence[TOKxorass] = PREC_assign;
192 precedence[TOKcomma] = PREC_expr;
195 /*************************************************************
196 * Now that we have the right function f, we need to get the
197 * right 'this' pointer if f is in an outer class, but our
198 * existing 'this' pointer is in an inner class.
199 * This code is analogous to that used for variables
200 * in DotVarExp::semantic().
203 Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad, Expression *e1, Declaration *var)
206 Type *t = e1->type->toBasetype();
208 if (ad &&
209 !(t->ty == Tpointer && t->next->ty == Tstruct &&
210 ((TypeStruct *)t->next)->sym == ad)
212 !(t->ty == Tstruct &&
213 ((TypeStruct *)t)->sym == ad)
216 ClassDeclaration *cd = ad->isClassDeclaration();
217 ClassDeclaration *tcd = t->isClassHandle();
219 if (!cd || !tcd ||
220 !(tcd == cd || cd->isBaseOf(tcd, NULL))
223 if (tcd && tcd->isNested())
224 { // Try again with outer scope
226 e1 = new DotVarExp(loc, e1, tcd->vthis);
227 e1 = e1->semantic(sc);
229 // Skip over nested functions, and get the enclosing
230 // class type.
231 Dsymbol *s = tcd->toParent();
232 while (s && s->isFuncDeclaration())
233 { FuncDeclaration *f = s->isFuncDeclaration();
234 if (f->vthis)
236 e1 = new VarExp(loc, f->vthis);
238 s = s->toParent();
240 if (s && s->isClassDeclaration())
241 e1->type = s->isClassDeclaration()->type;
242 e1 = e1->semantic(sc);
243 goto L1;
245 #ifdef DEBUG
246 printf("2: ");
247 #endif
248 error("this for %s needs to be type %s not type %s",
249 var->toChars(), ad->toChars(), t->toChars());
252 return e1;
255 /*****************************************
256 * Determine if 'this' is available.
257 * If it is, return the FuncDeclaration that has it.
260 FuncDeclaration *hasThis(Scope *sc)
261 { FuncDeclaration *fd;
262 FuncDeclaration *fdthis;
264 //printf("hasThis()\n");
265 fdthis = sc->parent->isFuncDeclaration();
266 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : "");
268 // Go upwards until we find the enclosing member function
269 fd = fdthis;
270 while (1)
272 if (!fd)
274 goto Lno;
276 if (!fd->isNested())
277 break;
279 Dsymbol *parent = fd->parent;
280 while (parent)
282 TemplateInstance *ti = parent->isTemplateInstance();
283 if (ti)
284 parent = ti->parent;
285 else
286 break;
289 fd = fd->parent->isFuncDeclaration();
292 if (!fd->isThis())
293 { //printf("test '%s'\n", fd->toChars());
294 goto Lno;
297 assert(fd->vthis);
298 return fd;
300 Lno:
301 return NULL; // don't have 'this' available
305 /***************************************
306 * Pull out any properties.
309 Expression *resolveProperties(Scope *sc, Expression *e)
311 //printf("resolveProperties(%s)\n", e->toChars());
312 if (e->type)
314 Type *t = e->type->toBasetype();
316 if (t->ty == Tfunction)
318 e = new CallExp(e->loc, e);
319 e = e->semantic(sc);
322 /* Look for e being a lazy parameter; rewrite as delegate call
324 else if (e->op == TOKvar)
325 { VarExp *ve = (VarExp *)e;
327 if (ve->var->storage_class & STClazy)
329 e = new CallExp(e->loc, e);
330 e = e->semantic(sc);
334 else if (e->op == TOKdotexp)
336 e->error("expression has no value");
339 return e;
342 /******************************
343 * Perform semantic() on an array of Expressions.
346 void arrayExpressionSemantic(Expressions *exps, Scope *sc)
348 if (exps)
350 for (size_t i = 0; i < exps->dim; i++)
351 { Expression *e = (Expression *)exps->data[i];
353 e = e->semantic(sc);
354 exps->data[i] = (void *)e;
359 /****************************************
360 * Expand tuples.
363 void expandTuples(Expressions *exps)
365 //printf("expandTuples()\n");
366 if (exps)
368 for (size_t i = 0; i < exps->dim; i++)
369 { Expression *arg = (Expression *)exps->data[i];
370 if (!arg)
371 continue;
373 // Look for tuple with 0 members
374 if (arg->op == TOKtype)
375 { TypeExp *e = (TypeExp *)arg;
376 if (e->type->toBasetype()->ty == Ttuple)
377 { TypeTuple *tt = (TypeTuple *)e->type->toBasetype();
379 if (!tt->arguments || tt->arguments->dim == 0)
381 exps->remove(i);
382 if (i == exps->dim)
383 return;
384 i--;
385 continue;
390 // Inline expand all the tuples
391 while (arg->op == TOKtuple)
392 { TupleExp *te = (TupleExp *)arg;
394 exps->remove(i); // remove arg
395 exps->insert(i, te->exps); // replace with tuple contents
396 if (i == exps->dim)
397 return; // empty tuple, no more arguments
398 arg = (Expression *)exps->data[i];
404 /****************************************
405 * Preprocess arguments to function.
408 void preFunctionArguments(Loc loc, Scope *sc, Expressions *exps)
410 if (exps)
412 expandTuples(exps);
414 for (size_t i = 0; i < exps->dim; i++)
415 { Expression *arg = (Expression *)exps->data[i];
417 if (!arg->type)
419 #ifdef DEBUG
420 if (!global.gag)
421 printf("1: \n");
422 #endif
423 arg->error("%s is not an expression", arg->toChars());
424 arg = new IntegerExp(arg->loc, 0, Type::tint32);
427 arg = resolveProperties(sc, arg);
428 exps->data[i] = (void *) arg;
430 //arg->rvalue();
431 #if 0
432 if (arg->type->ty == Tfunction)
434 arg = new AddrExp(arg->loc, arg);
435 arg = arg->semantic(sc);
436 exps->data[i] = (void *) arg;
438 #endif
444 /****************************************
445 * Now that we know the exact type of the function we're calling,
446 * the arguments[] need to be adjusted:
447 * 1) implicitly convert argument to the corresponding parameter type
448 * 2) add default arguments for any missing arguments
449 * 3) do default promotions on arguments corresponding to ...
450 * 4) add hidden _arguments[] argument
453 void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments)
455 unsigned n;
456 int done;
457 Type *tb;
459 //printf("functionArguments()\n");
460 assert(arguments);
461 size_t nargs = arguments ? arguments->dim : 0;
462 size_t nparams = Argument::dim(tf->parameters);
464 if (nargs > nparams && tf->varargs == 0)
465 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
467 n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
469 done = 0;
470 for (size_t i = 0; i < n; i++)
472 Expression *arg;
474 if (i < nargs)
475 arg = (Expression *)arguments->data[i];
476 else
477 arg = NULL;
479 if (i < nparams)
481 Argument *p = Argument::getNth(tf->parameters, i);
483 if (!arg)
485 if (!p->defaultArg)
487 if (tf->varargs == 2 && i + 1 == nparams)
488 goto L2;
489 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
490 break;
492 arg = p->defaultArg->copy();
493 arguments->push(arg);
494 nargs++;
497 if (tf->varargs == 2 && i + 1 == nparams)
499 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
500 if (arg->implicitConvTo(p->type))
502 if (nargs != nparams)
503 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
504 goto L1;
507 Type *tb = p->type->toBasetype();
508 Type *tret = p->isLazyArray();
509 switch (tb->ty)
511 case Tsarray:
512 case Tarray:
513 { // Create a static array variable v of type arg->type
514 #ifdef IN_GCC
515 /* GCC 4.0 does not like zero length arrays used like
516 this; pass a null array value instead. Could also
517 just make a one-element array. */
518 if (nargs - i == 0)
520 arg = new NullExp(loc);
521 break;
523 #endif
524 static int idn;
525 char name[10 + sizeof(idn)*3 + 1];
526 sprintf(name, "__arrayArg%d", ++idn);
527 Identifier *id = Lexer::idPool(name);
528 Type *t = new TypeSArray(tb->next, new IntegerExp(nargs - i));
529 t = t->semantic(loc, sc);
530 VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc));
531 v->semantic(sc);
532 v->parent = sc->parent;
533 //sc->insert(v);
535 Expression *c = new DeclarationExp(0, v);
536 c->type = v->type;
538 for (size_t u = i; u < nargs; u++)
539 { Expression *a = (Expression *)arguments->data[u];
540 if (tret && !tb->next->equals(a->type))
541 a = a->toDelegate(sc, tret);
543 Expression *e = new VarExp(loc, v);
544 e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
545 e = new AssignExp(loc, e, a);
546 if (c)
547 c = new CommaExp(loc, c, e);
548 else
549 c = e;
551 arg = new VarExp(loc, v);
552 if (c)
553 arg = new CommaExp(loc, c, arg);
554 break;
556 case Tclass:
557 { /* Set arg to be:
558 * new Tclass(arg0, arg1, ..., argn)
560 Expressions *args = new Expressions();
561 args->setDim(nargs - i);
562 for (size_t u = i; u < nargs; u++)
563 args->data[u - i] = arguments->data[u];
564 arg = new NewExp(loc, NULL, NULL, p->type, args);
565 break;
567 default:
568 if (!arg)
569 { error(loc, "not enough arguments");
570 return;
572 break;
574 arg = arg->semantic(sc);
575 //printf("\targ = '%s'\n", arg->toChars());
576 arguments->setDim(i + 1);
577 done = 1;
581 if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
582 arg = arg->implicitCastTo(sc, p->type);
583 if (p->storageClass & (STCout | STCref))
585 // BUG: should check that argument to ref is type 'invariant'
586 // BUG: assignments to ref should also be type 'invariant'
587 arg = arg->modifiableLvalue(sc, arg);
589 //if (arg->op == TOKslice)
590 //arg->error("cannot modify slice %s", arg->toChars());
593 // Convert static arrays to pointers
594 tb = arg->type->toBasetype();
595 if (tb->ty == Tsarray)
597 arg = arg->checkToPointer();
600 // Convert lazy argument to a delegate
601 if (p->storageClass & STClazy)
603 arg = arg->toDelegate(sc, p->type);
606 else
609 // If not D linkage, do promotions
610 if (tf->linkage != LINKd)
612 // Promote bytes, words, etc., to ints
613 arg = arg->integralPromotions(sc);
615 // Promote floats to doubles
616 switch (arg->type->ty)
618 case Tfloat32:
619 arg = arg->castTo(sc, Type::tfloat64);
620 break;
622 case Timaginary32:
623 arg = arg->castTo(sc, Type::timaginary64);
624 break;
628 // Convert static arrays to dynamic arrays
629 tb = arg->type->toBasetype();
630 if (tb->ty == Tsarray)
631 { TypeSArray *ts = (TypeSArray *)tb;
632 Type *ta = tb->next->arrayOf();
633 if (ts->size(arg->loc) == 0)
634 { arg = new NullExp(arg->loc);
635 arg->type = ta;
637 else
638 arg = arg->castTo(sc, ta);
641 arg->rvalue();
643 arg = arg->optimize(WANTvalue);
644 arguments->data[i] = (void *) arg;
645 if (done)
646 break;
649 // If D linkage and variadic, add _arguments[] as first argument
650 if (tf->linkage == LINKd && tf->varargs == 1)
652 Expression *e;
654 e = createTypeInfoArray(sc, (Expression **)&arguments->data[nparams],
655 arguments->dim - nparams);
656 arguments->insert(0, e);
660 /**************************************************
661 * Write expression out to buf, but wrap it
662 * in ( ) if its precedence is less than pr.
665 void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr)
667 if (precedence[e->op] < pr)
669 buf->writeByte('(');
670 e->toCBuffer(buf, hgs);
671 buf->writeByte(')');
673 else
674 e->toCBuffer(buf, hgs);
677 /**************************************************
678 * Write out argument list to buf.
681 void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
683 if (arguments)
685 for (size_t i = 0; i < arguments->dim; i++)
686 { Expression *arg = (Expression *)arguments->data[i];
688 if (arg)
689 { if (i)
690 buf->writeByte(',');
691 expToCBuffer(buf, hgs, arg, PREC_assign);
697 /**************************************************
698 * Write out argument types to buf.
701 void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
703 if (arguments)
704 { OutBuffer argbuf;
706 for (size_t i = 0; i < arguments->dim; i++)
707 { Expression *arg = (Expression *)arguments->data[i];
709 if (i)
710 buf->writeByte(',');
711 argbuf.reset();
712 arg->type->toCBuffer2(&argbuf, hgs, 0);
713 buf->write(&argbuf);
718 /******************************** Expression **************************/
720 Expression::Expression(Loc loc, enum TOK op, int size)
721 : loc(loc)
723 this->loc = loc;
724 this->op = op;
725 this->size = size;
726 type = NULL;
729 Expression *Expression::syntaxCopy()
731 //printf("Expression::syntaxCopy()\n");
732 //dump(0);
733 return copy();
736 /*********************************
737 * Does *not* do a deep copy.
740 Expression *Expression::copy()
742 Expression *e;
743 if (!size)
745 #ifdef DEBUG
746 fprintf(stdmsg, "No expression copy for: %s\n", toChars());
747 printf("op = %d\n", op);
748 dump(0);
749 #endif
750 assert(0);
752 e = (Expression *)mem.malloc(size);
753 return (Expression *)memcpy(e, this, size);
756 /**************************
757 * Semantically analyze Expression.
758 * Determine types, fold constants, etc.
761 Expression *Expression::semantic(Scope *sc)
763 #if LOGSEMANTIC
764 printf("Expression::semantic()\n");
765 #endif
766 if (type)
767 type = type->semantic(loc, sc);
768 else
769 type = Type::tvoid;
770 return this;
773 void Expression::print()
775 fprintf(stdmsg, "%s\n", toChars());
776 fflush(stdmsg);
779 char *Expression::toChars()
780 { OutBuffer *buf;
781 HdrGenState hgs;
783 memset(&hgs, 0, sizeof(hgs));
784 buf = new OutBuffer();
785 toCBuffer(buf, &hgs);
786 return buf->toChars();
789 void Expression::error(const char *format, ...)
791 va_list ap;
792 va_start(ap, format);
793 ::verror(loc, format, ap);
794 va_end( ap );
797 void Expression::rvalue()
799 if (type && type->toBasetype()->ty == Tvoid)
800 { error("expression %s is void and has no value", toChars());
801 #if 0
802 dump(0);
803 halt();
804 #endif
808 Expression *Expression::combine(Expression *e1, Expression *e2)
810 if (e1)
812 if (e2)
814 e1 = new CommaExp(e1->loc, e1, e2);
815 e1->type = e2->type;
818 else
819 e1 = e2;
820 return e1;
823 integer_t Expression::toInteger()
825 //printf("Expression %s\n", Token::toChars(op));
826 error("Integer constant expression expected instead of %s", toChars());
827 return 0;
830 uinteger_t Expression::toUInteger()
832 //printf("Expression %s\n", Token::toChars(op));
833 return (uinteger_t)toInteger();
836 real_t Expression::toReal()
838 error("Floating point constant expression expected instead of %s", toChars());
839 return 0;
842 real_t Expression::toImaginary()
844 error("Floating point constant expression expected instead of %s", toChars());
845 return 0;
848 complex_t Expression::toComplex()
850 error("Floating point constant expression expected instead of %s", toChars());
851 #ifdef IN_GCC
852 return complex_t(real_t(0)); // %% nicer
853 #else
854 return 0;
855 #endif
858 void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
860 buf->writestring(Token::toChars(op));
863 void Expression::toMangleBuffer(OutBuffer *buf)
865 error("expression %s is not a valid template value argument", toChars());
868 /*******************************
869 * Give error if we're not an lvalue.
870 * If we can, convert expression to be an lvalue.
873 Expression *Expression::toLvalue(Scope *sc, Expression *e)
875 if (!e)
876 e = this;
877 else if (!loc.filename)
878 loc = e->loc;
879 error("%s is not an lvalue", e->toChars());
880 return this;
883 Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
885 // See if this expression is a modifiable lvalue (i.e. not const)
886 return toLvalue(sc, e);
889 /************************************
890 * Detect cases where pointers to the stack can 'escape' the
891 * lifetime of the stack frame.
894 void Expression::checkEscape()
898 void Expression::checkScalar()
900 if (!type->isscalar())
901 error("'%s' is not a scalar, it is a %s", toChars(), type->toChars());
904 void Expression::checkNoBool()
906 if (type->toBasetype()->ty == Tbool)
907 error("operation not allowed on bool '%s'", toChars());
910 Expression *Expression::checkIntegral()
912 if (!type->isintegral())
913 { error("'%s' is not of integral type, it is a %s", toChars(), type->toChars());
914 return new IntegerExp(0);
916 return this;
919 Expression *Expression::checkArithmetic()
921 if (!type->isintegral() && !type->isfloating())
922 { error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
923 return new IntegerExp(0);
925 return this;
928 void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
930 s->checkDeprecated(loc, sc);
933 /********************************
934 * Check for expressions that have no use.
935 * Input:
936 * flag 0 not going to use the result, so issue error message if no
937 * side effects
938 * 1 the result of the expression is used, but still check
939 * for useless subexpressions
940 * 2 do not issue error messages, just return !=0 if expression
941 * has side effects
944 int Expression::checkSideEffect(int flag)
946 if (flag == 0)
947 { if (op == TOKimport)
949 error("%s has no effect", toChars());
951 else
952 error("%s has no effect in expression (%s)",
953 Token::toChars(op), toChars());
955 return 0;
958 /*****************************
959 * Check that expression can be tested for true or false.
962 Expression *Expression::checkToBoolean()
964 // Default is 'yes' - do nothing
966 #ifdef DEBUG
967 if (!type)
968 dump(0);
969 #endif
971 if (!type->checkBoolean())
973 error("expression %s of type %s does not have a boolean value", toChars(), type->toChars());
975 return this;
978 /****************************
981 Expression *Expression::checkToPointer()
983 Expression *e;
984 Type *tb;
986 //printf("Expression::checkToPointer()\n");
987 e = this;
989 // If C static array, convert to pointer
990 tb = type->toBasetype();
991 if (tb->ty == Tsarray)
992 { TypeSArray *ts = (TypeSArray *)tb;
993 if (ts->size(loc) == 0)
994 e = new NullExp(loc);
995 else
996 e = new AddrExp(loc, this);
997 e->type = tb->next->pointerTo();
999 return e;
1002 /******************************
1003 * Take address of expression.
1006 Expression *Expression::addressOf(Scope *sc)
1008 Expression *e;
1010 //printf("Expression::addressOf()\n");
1011 e = toLvalue(sc, NULL);
1012 e = new AddrExp(loc, e);
1013 e->type = type->pointerTo();
1014 return e;
1017 /******************************
1018 * If this is a reference, dereference it.
1021 Expression *Expression::deref()
1023 //printf("Expression::deref()\n");
1024 if (type->ty == Treference)
1025 { Expression *e;
1027 e = new PtrExp(loc, this);
1028 e->type = type->next;
1029 return e;
1031 return this;
1034 /********************************
1035 * Does this expression statically evaluate to a boolean TRUE or FALSE?
1038 int Expression::isBool(int result)
1040 return FALSE;
1043 /********************************
1044 * Does this expression result in either a 1 or a 0?
1047 int Expression::isBit()
1049 return FALSE;
1052 Expressions *Expression::arraySyntaxCopy(Expressions *exps)
1053 { Expressions *a = NULL;
1055 if (exps)
1057 a = new Expressions();
1058 a->setDim(exps->dim);
1059 for (int i = 0; i < a->dim; i++)
1060 { Expression *e = (Expression *)exps->data[i];
1062 e = e->syntaxCopy();
1063 a->data[i] = e;
1066 return a;
1069 /******************************** IntegerExp **************************/
1071 IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type)
1072 : Expression(loc, TOKint64, sizeof(IntegerExp))
1074 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
1075 if (type && !type->isscalar())
1077 error("integral constant must be scalar type, not %s", type->toChars());
1078 type = Type::terror;
1080 this->type = type;
1081 this->value = value;
1084 IntegerExp::IntegerExp(integer_t value)
1085 : Expression(0, TOKint64, sizeof(IntegerExp))
1087 this->type = Type::tint32;
1088 this->value = value;
1091 int IntegerExp::equals(Object *o)
1092 { IntegerExp *ne;
1094 if (this == o ||
1095 (((Expression *)o)->op == TOKint64 &&
1096 ((ne = (IntegerExp *)o), type->equals(ne->type)) &&
1097 value == ne->value))
1098 return 1;
1099 return 0;
1102 char *IntegerExp::toChars()
1104 #if 1
1105 return Expression::toChars();
1106 #else
1107 static char buffer[sizeof(value) * 3 + 1];
1109 sprintf(buffer, "%"PRIdMAX, value);
1110 return buffer;
1111 #endif
1114 integer_t IntegerExp::toInteger()
1115 { Type *t;
1117 t = type;
1118 while (t)
1120 switch (t->ty)
1122 case Tbit:
1123 case Tbool: value = (value != 0); break;
1124 case Tint8: value = (d_int8) value; break;
1125 case Tchar:
1126 case Tuns8: value = (d_uns8) value; break;
1127 case Tint16: value = (d_int16) value; break;
1128 case Twchar:
1129 case Tuns16: value = (d_uns16) value; break;
1130 case Tint32: value = (d_int32) value; break;
1131 case Tdchar:
1132 case Tuns32: value = (d_uns32) value; break;
1133 case Tint64: value = (d_int64) value; break;
1134 case Tuns64: value = (d_uns64) value; break;
1136 case Tpointer:
1137 switch (PTRSIZE)
1139 case 4: value = (d_uns32) value; break;
1140 case 8: value = (d_uns64) value; break;
1141 default:
1142 assert(PTRSIZE == 4 || PTRSIZE == 8);
1144 break;
1146 case Tenum:
1148 TypeEnum *te = (TypeEnum *)t;
1149 t = te->sym->memtype;
1150 continue;
1153 case Ttypedef:
1155 TypeTypedef *tt = (TypeTypedef *)t;
1156 t = tt->sym->basetype;
1157 continue;
1160 default:
1161 print();
1162 type->print();
1163 assert(0);
1164 break;
1166 break;
1168 return value;
1171 real_t IntegerExp::toReal()
1173 Type *t;
1175 toInteger();
1176 t = type->toBasetype();
1177 if (t->ty == Tuns64)
1178 return (real_t)(d_uns64)value;
1179 else
1180 return (real_t)(d_int64)value;
1183 real_t IntegerExp::toImaginary()
1185 return (real_t) 0;
1188 complex_t IntegerExp::toComplex()
1190 return toReal();
1193 int IntegerExp::isBool(int result)
1195 return result ? value != 0 : value == 0;
1198 Expression *IntegerExp::semantic(Scope *sc)
1200 if (!type)
1202 // Determine what the type of this number is
1203 integer_t number = value;
1205 if (number & 0x8000000000000000LL)
1206 type = Type::tuns64;
1207 else if (number & 0xFFFFFFFF80000000LL)
1208 type = Type::tint64;
1209 else
1210 type = Type::tint32;
1212 else
1213 { type = type->semantic(loc, sc);
1215 return this;
1218 Expression *IntegerExp::toLvalue(Scope *sc, Expression *e)
1220 if (!e)
1221 e = this;
1222 else if (!loc.filename)
1223 loc = e->loc;
1224 e->error("constant %s is not an lvalue", e->toChars());
1225 return this;
1228 void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1230 integer_t v = toInteger();
1232 if (type)
1233 { Type *t = type;
1236 switch (t->ty)
1238 case Tenum:
1239 { TypeEnum *te = (TypeEnum *)t;
1240 buf->printf("cast(%s)", te->sym->toChars());
1241 t = te->sym->memtype;
1242 goto L1;
1245 case Ttypedef:
1246 { TypeTypedef *tt = (TypeTypedef *)t;
1247 buf->printf("cast(%s)", tt->sym->toChars());
1248 t = tt->sym->basetype;
1249 goto L1;
1252 case Twchar: // BUG: need to cast(wchar)
1253 case Tdchar: // BUG: need to cast(dchar)
1254 if ((uinteger_t)v > 0xFF)
1256 buf->printf("'\\U%08x'", v);
1257 break;
1259 case Tchar:
1260 if (v == '\'')
1261 buf->writestring("'\\''");
1262 else if (isprint(v) && v != '\\')
1263 buf->printf("'%c'", (int)v);
1264 else
1265 buf->printf("'\\x%02x'", (int)v);
1266 break;
1268 case Tint8:
1269 buf->writestring("cast(byte)");
1270 goto L2;
1272 case Tint16:
1273 buf->writestring("cast(short)");
1274 goto L2;
1276 case Tint32:
1278 buf->printf("%d", (int)v);
1279 break;
1281 case Tuns8:
1282 buf->writestring("cast(ubyte)");
1283 goto L3;
1285 case Tuns16:
1286 buf->writestring("cast(ushort)");
1287 goto L3;
1289 case Tuns32:
1291 buf->printf("%du", (unsigned)v);
1292 break;
1294 case Tint64:
1295 buf->printf("%"PRIdMAX"L", v);
1296 break;
1298 case Tuns64:
1299 buf->printf("%"PRIuMAX"LU", v);
1300 break;
1302 case Tbit:
1303 case Tbool:
1304 buf->writestring((char *)(v ? "true" : "false"));
1305 break;
1307 case Tpointer:
1308 buf->writestring("cast(");
1309 buf->writestring(t->toChars());
1310 buf->writeByte(')');
1311 goto L3;
1313 default:
1314 #ifdef DEBUG
1315 t->print();
1316 #endif
1317 assert(0);
1320 else if (v & 0x8000000000000000LL)
1321 buf->printf("0x%"PRIxMAX, v);
1322 else
1323 buf->printf("%"PRIdMAX, v);
1326 void IntegerExp::toMangleBuffer(OutBuffer *buf)
1328 if ((sinteger_t)value < 0)
1329 buf->printf("N%"PRIdMAX, -value);
1330 else
1331 buf->printf("%"PRIdMAX, value);
1334 /******************************** RealExp **************************/
1336 RealExp::RealExp(Loc loc, real_t value, Type *type)
1337 : Expression(loc, TOKfloat64, sizeof(RealExp))
1339 //printf("RealExp::RealExp(%Lg)\n", value);
1340 this->value = value;
1341 this->type = type;
1344 char *RealExp::toChars()
1346 char buffer[sizeof(value) * 3 + 8 + 1 + 1];
1348 #ifdef IN_GCC
1349 value.format(buffer, sizeof(buffer));
1350 if (type->isimaginary())
1351 strcat(buffer, "i");
1352 #else
1353 sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value);
1354 #endif
1355 assert(strlen(buffer) < sizeof(buffer));
1356 return mem.strdup(buffer);
1359 integer_t RealExp::toInteger()
1361 #ifdef IN_GCC
1362 return (d_int64) toReal().toInt();
1363 #else
1364 return (sinteger_t) toReal();
1365 #endif
1368 uinteger_t RealExp::toUInteger()
1370 #ifdef IN_GCC
1371 return (uinteger_t) toReal().toInt();
1372 #else
1373 return (uinteger_t) toReal();
1374 #endif
1377 real_t RealExp::toReal()
1379 return type->isreal() ? value : 0;
1382 real_t RealExp::toImaginary()
1384 return type->isreal() ? 0 : value;
1387 complex_t RealExp::toComplex()
1389 #ifdef __DMC__
1390 return toReal() + toImaginary() * I;
1391 #else
1392 return complex_t(toReal(), toImaginary());
1393 #endif
1396 /********************************
1397 * Test to see if two reals are the same.
1398 * Regard NaN's as equivalent.
1399 * Regard +0 and -0 as different.
1402 int RealEquals(real_t x1, real_t x2)
1404 #ifndef IN_GCC
1405 return (isnan(x1) && isnan(x2)) ||
1406 /* In some cases, the REALPAD bytes get garbage in them,
1407 * so be sure and ignore them.
1409 memcmp(&x1, &x2, REALSIZE - REALPAD) == 0;
1410 #else
1411 return (x1.isNan() && x2.isNan()) || x1.isIdenticalTo(x2);
1412 #endif
1415 int RealExp::equals(Object *o)
1416 { RealExp *ne;
1418 if (this == o ||
1419 (((Expression *)o)->op == TOKfloat64 &&
1420 ((ne = (RealExp *)o), type->equals(ne->type)) &&
1421 RealEquals(value, ne->value)
1424 return 1;
1425 return 0;
1428 Expression *RealExp::semantic(Scope *sc)
1430 if (!type)
1431 type = Type::tfloat64;
1432 else
1433 type = type->semantic(loc, sc);
1434 return this;
1437 int RealExp::isBool(int result)
1439 #ifdef IN_GCC
1440 return result ? (! value.isZero()) : (value.isZero());
1441 #else
1442 return result ? (value != 0)
1443 : (value == 0);
1444 #endif
1447 void floatToBuffer(OutBuffer *buf, Type *type, const real_t & value)
1449 /* In order to get an exact representation, try converting it
1450 * to decimal then back again. If it matches, use it.
1451 * If it doesn't, fall back to hex, which is
1452 * always exact.
1454 char buffer[48];
1455 #ifdef IN_GCC
1456 real_t parsed_value;
1458 value.format(buffer, sizeof(buffer));
1459 parsed_value = real_t::parse(buffer, real_t::LongDouble);
1460 if (parsed_value.isIdenticalTo( value ))
1461 buf->writestring(buffer);
1462 else
1464 value.formatHex(buffer, sizeof(buffer));
1465 buf->writestring(buffer);
1467 #else
1468 sprintf(buffer, "%Lg", value);
1469 assert(strlen(buffer) < sizeof(buffer));
1470 #if _WIN32 && __DMC__
1471 char *save = __locale_decpoint;
1472 __locale_decpoint = ".";
1473 real_t r = strtold(buffer, NULL);
1474 __locale_decpoint = save;
1475 #else
1476 real_t r = strtold(buffer, NULL);
1477 #endif
1478 if (r == value) // if exact duplication
1479 buf->writestring(buffer);
1480 else
1481 buf->printf("%La", value); // ensure exact duplication
1482 #endif
1484 if (type)
1486 Type *t = type->toBasetype();
1487 switch (t->ty)
1489 case Tfloat32:
1490 case Timaginary32:
1491 case Tcomplex32:
1492 buf->writeByte('F');
1493 break;
1495 case Tfloat80:
1496 case Timaginary80:
1497 case Tcomplex80:
1498 buf->writeByte('L');
1499 break;
1501 default:
1502 break;
1504 if (t->isimaginary())
1505 buf->writeByte('i');
1509 void RealExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1511 floatToBuffer(buf, type, value);
1514 void realToMangleBuffer(OutBuffer *buf, real_t value)
1516 /* Rely on %A to get portable mangling.
1517 * Must munge result to get only identifier characters.
1519 * Possible values from %A => mangled result
1520 * NAN => NAN
1521 * -INF => NINF
1522 * INF => INF
1523 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79
1524 * 0X1.9P+2 => 19P2
1527 #ifdef IN_GCC
1528 if (value.isNan())
1529 buf->writestring("NAN"); // no -NAN bugs
1530 else if (value.isInf())
1531 buf->writestring(value.isNegative()?"NINF":"INF");
1532 #else
1533 if (isnan(value))
1534 buf->writestring("NAN"); // no -NAN bugs
1535 #endif
1536 else
1538 char buffer[64];
1539 #ifdef IN_GCC
1540 value.formatHex(buffer, sizeof(buffer));
1541 int n = strlen(buffer);
1542 #else
1543 int n = sprintf(buffer, "%LA", value);
1544 assert(n > 0 && n < sizeof(buffer));
1545 #endif
1546 for (int i = 0; i < n; i++)
1547 { char c = buffer[i];
1549 switch (c)
1551 case '-':
1552 buf->writeByte('N');
1553 break;
1555 case '+':
1556 case 'x':
1557 case 'X':
1558 case '.':
1559 break;
1561 case '0':
1562 if (i < 2)
1563 break; // skip leading 0X
1564 default:
1565 buf->writeByte(c);
1566 break;
1572 void RealExp::toMangleBuffer(OutBuffer *buf)
1574 buf->writeByte('e');
1575 realToMangleBuffer(buf, value);
1579 /******************************** ComplexExp **************************/
1581 ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type)
1582 : Expression(loc, TOKcomplex80, sizeof(ComplexExp))
1584 this->value = value;
1585 this->type = type;
1586 //printf("ComplexExp::ComplexExp(%s)\n", toChars());
1589 char *ComplexExp::toChars()
1591 char buffer[sizeof(value) * 3 + 8 + 1];
1593 #ifdef IN_GCC
1594 char buf1[sizeof(value) * 3 + 8 + 1];
1595 char buf2[sizeof(value) * 3 + 8 + 1];
1596 creall(value).format(buf1, sizeof(buf1));
1597 cimagl(value).format(buf2, sizeof(buf2));
1598 sprintf(buffer, "(%s+%si)", buf1, buf2);
1599 #else
1600 sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value));
1601 assert(strlen(buffer) < sizeof(buffer));
1602 #endif
1603 return mem.strdup(buffer);
1606 integer_t ComplexExp::toInteger()
1608 #ifdef IN_GCC
1609 return (d_int64) toReal().toInt();
1610 #else
1611 return (sinteger_t) toReal();
1612 #endif
1615 uinteger_t ComplexExp::toUInteger()
1617 #ifdef IN_GCC
1618 return (uinteger_t) toReal().toInt();
1619 #else
1620 return (uinteger_t) toReal();
1621 #endif
1624 real_t ComplexExp::toReal()
1626 return creall(value);
1629 real_t ComplexExp::toImaginary()
1631 return cimagl(value);
1634 complex_t ComplexExp::toComplex()
1636 return value;
1639 int ComplexExp::equals(Object *o)
1640 { ComplexExp *ne;
1642 if (this == o ||
1643 (((Expression *)o)->op == TOKcomplex80 &&
1644 ((ne = (ComplexExp *)o), type->equals(ne->type)) &&
1645 #ifndef IN_GCC
1646 RealEquals(creall(value), creall(ne->value)) &&
1647 RealEquals(cimagl(value), cimagl(ne->value))
1648 #else
1649 RealEquals(value.re, ne->value.re) &&
1650 RealEquals(value.im, ne->value.im)
1651 #endif
1654 return 1;
1655 return 0;
1658 Expression *ComplexExp::semantic(Scope *sc)
1660 if (!type)
1661 type = Type::tcomplex80;
1662 else
1663 type = type->semantic(loc, sc);
1664 return this;
1667 int ComplexExp::isBool(int result)
1669 if (result)
1670 return (bool)(value);
1671 else
1672 return !value;
1675 void ComplexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1677 /* Print as:
1678 * (re+imi)
1680 #ifdef IN_GCC
1681 char buf1[sizeof(value) * 3 + 8 + 1];
1682 char buf2[sizeof(value) * 3 + 8 + 1];
1683 creall(value).format(buf1, sizeof(buf1));
1684 cimagl(value).format(buf2, sizeof(buf2));
1685 buf->printf("(%s+%si)", buf1, buf2);
1686 #else
1687 buf->writeByte('(');
1688 floatToBuffer(buf, type, creall(value));
1689 buf->writeByte('+');
1690 floatToBuffer(buf, type, cimagl(value));
1691 buf->writestring("i)");
1692 #endif
1695 void ComplexExp::toMangleBuffer(OutBuffer *buf)
1697 buf->writeByte('c');
1698 real_t r = toReal();
1699 realToMangleBuffer(buf, r);
1700 buf->writeByte('c'); // separate the two
1701 r = toImaginary();
1702 realToMangleBuffer(buf, r);
1705 /******************************** IdentifierExp **************************/
1707 IdentifierExp::IdentifierExp(Loc loc, Identifier *ident)
1708 : Expression(loc, TOKidentifier, sizeof(IdentifierExp))
1710 this->ident = ident;
1713 Expression *IdentifierExp::semantic(Scope *sc)
1715 Dsymbol *s;
1716 Dsymbol *scopesym;
1718 #if LOGSEMANTIC
1719 printf("IdentifierExp::semantic('%s')\n", ident->toChars());
1720 #endif
1721 s = sc->search(loc, ident, &scopesym);
1722 if (s)
1723 { Expression *e;
1724 WithScopeSymbol *withsym;
1726 // See if it was a with class
1727 withsym = scopesym->isWithScopeSymbol();
1728 if (withsym)
1730 s = s->toAlias();
1732 // Same as wthis.ident
1733 if (s->needThis() || s->isTemplateDeclaration())
1735 e = new VarExp(loc, withsym->withstate->wthis);
1736 e = new DotIdExp(loc, e, ident);
1738 else
1739 { Type *t = withsym->withstate->wthis->type;
1740 if (t->ty == Tpointer)
1741 t = t->next;
1742 e = new TypeDotIdExp(loc, t, ident);
1745 else
1747 if (!s->parent && scopesym->isArrayScopeSymbol())
1748 { // Kludge to run semantic() here because
1749 // ArrayScopeSymbol::search() doesn't have access to sc.
1750 s->semantic(sc);
1752 // Look to see if f is really a function template
1753 FuncDeclaration *f = s->isFuncDeclaration();
1754 if (f && f->parent)
1755 { TemplateInstance *ti = f->parent->isTemplateInstance();
1757 if (ti &&
1758 !ti->isTemplateMixin() &&
1759 (ti->name == f->ident ||
1760 ti->toAlias()->ident == f->ident)
1762 ti->tempdecl && ti->tempdecl->onemember)
1764 TemplateDeclaration *tempdecl = ti->tempdecl;
1765 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's
1766 tempdecl = tempdecl->overroot; // then get the start
1767 e = new TemplateExp(loc, tempdecl);
1768 e = e->semantic(sc);
1769 return e;
1772 e = new DsymbolExp(loc, s);
1774 return e->semantic(sc);
1776 error("undefined identifier %s", ident->toChars());
1777 type = Type::terror;
1778 return this;
1781 char *IdentifierExp::toChars()
1783 return ident->toChars();
1786 void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1788 if (hgs->hdrgen)
1789 buf->writestring(ident->toHChars2());
1790 else
1791 buf->writestring(ident->toChars());
1794 Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e)
1796 #if 0
1797 tym = tybasic(e1->ET->Tty);
1798 if (!(tyscalar(tym) ||
1799 tym == TYstruct ||
1800 tym == TYarray && e->Eoper == TOKaddr))
1801 synerr(EM_lvalue); // lvalue expected
1802 #endif
1803 return this;
1806 /******************************** DollarExp **************************/
1808 DollarExp::DollarExp(Loc loc)
1809 : IdentifierExp(loc, Id::dollar)
1813 /******************************** DsymbolExp **************************/
1815 DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s)
1816 : Expression(loc, TOKdsymbol, sizeof(DsymbolExp))
1818 this->s = s;
1821 Expression *DsymbolExp::semantic(Scope *sc)
1823 #if LOGSEMANTIC
1824 printf("DsymbolExp::semantic('%s')\n", s->toChars());
1825 #endif
1827 Lagain:
1828 EnumMember *em;
1829 Expression *e;
1830 VarDeclaration *v;
1831 FuncDeclaration *f;
1832 FuncLiteralDeclaration *fld;
1833 Declaration *d;
1834 ClassDeclaration *cd;
1835 ClassDeclaration *thiscd = NULL;
1836 Import *imp;
1837 Package *pkg;
1838 Type *t;
1840 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
1841 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
1842 if (type)
1843 return this;
1844 if (!s->isFuncDeclaration()) // functions are checked after overloading
1845 checkDeprecated(sc, s);
1846 s = s->toAlias();
1847 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
1848 if (!s->isFuncDeclaration())
1849 checkDeprecated(sc, s);
1851 if (sc->func)
1852 thiscd = sc->func->parent->isClassDeclaration();
1854 // BUG: This should happen after overload resolution for functions, not before
1855 if (s->needThis())
1857 if (hasThis(sc) /*&& !s->isFuncDeclaration()*/)
1859 // Supply an implicit 'this', as in
1860 // this.ident
1862 DotVarExp *de;
1864 de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration());
1865 return de->semantic(sc);
1869 em = s->isEnumMember();
1870 if (em)
1872 e = em->value->copy();
1873 e = e->semantic(sc);
1874 return e;
1876 v = s->isVarDeclaration();
1877 if (v)
1879 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
1880 if (!type)
1881 { type = v->type;
1882 if (!v->type)
1883 { error("forward reference of %s", v->toChars());
1884 type = Type::terror;
1887 if (v->isConst() && type->toBasetype()->ty != Tsarray)
1889 if (v->init)
1891 if (v->inuse)
1893 error("circular reference to '%s'", v->toChars());
1894 type = Type::tint32;
1895 return this;
1897 ExpInitializer *ei = v->init->isExpInitializer();
1898 if (ei)
1900 e = ei->exp->copy(); // make copy so we can change loc
1901 if (e->op == TOKstring || !e->type)
1902 e = e->semantic(sc);
1903 e = e->implicitCastTo(sc, type);
1904 e->loc = loc;
1905 return e;
1908 else
1910 e = type->defaultInit();
1911 e->loc = loc;
1912 return e;
1915 e = new VarExp(loc, v);
1916 e->type = type;
1917 e = e->semantic(sc);
1918 return e->deref();
1920 fld = s->isFuncLiteralDeclaration();
1921 if (fld)
1922 { //printf("'%s' is a function literal\n", fld->toChars());
1923 e = new FuncExp(loc, fld);
1924 return e->semantic(sc);
1926 f = s->isFuncDeclaration();
1927 if (f)
1928 { //printf("'%s' is a function\n", f->toChars());
1929 return new VarExp(loc, f);
1931 cd = s->isClassDeclaration();
1932 if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis())
1934 // We need to add an implicit 'this' if cd is this class or a base class.
1935 DotTypeExp *dte;
1937 dte = new DotTypeExp(loc, new ThisExp(loc), s);
1938 return dte->semantic(sc);
1940 imp = s->isImport();
1941 if (imp)
1943 ScopeExp *ie;
1945 ie = new ScopeExp(loc, imp->pkg);
1946 return ie->semantic(sc);
1948 pkg = s->isPackage();
1949 if (pkg)
1951 ScopeExp *ie;
1953 ie = new ScopeExp(loc, pkg);
1954 return ie->semantic(sc);
1956 Module *mod = s->isModule();
1957 if (mod)
1959 ScopeExp *ie;
1961 ie = new ScopeExp(loc, mod);
1962 return ie->semantic(sc);
1965 t = s->getType();
1966 if (t)
1968 return new TypeExp(loc, t);
1971 TupleDeclaration *tup = s->isTupleDeclaration();
1972 if (tup)
1974 e = new TupleExp(loc, tup);
1975 e = e->semantic(sc);
1976 return e;
1979 TemplateInstance *ti = s->isTemplateInstance();
1980 if (ti && !global.errors)
1981 { if (!ti->semanticdone)
1982 ti->semantic(sc);
1983 s = ti->inst->toAlias();
1984 if (!s->isTemplateInstance())
1985 goto Lagain;
1986 e = new ScopeExp(loc, ti);
1987 e = e->semantic(sc);
1988 return e;
1991 TemplateDeclaration *td = s->isTemplateDeclaration();
1992 if (td)
1994 e = new TemplateExp(loc, td);
1995 e = e->semantic(sc);
1996 return e;
1999 Lerr:
2000 error("%s '%s' is not a variable", s->kind(), s->toChars());
2001 type = Type::terror;
2002 return this;
2005 char *DsymbolExp::toChars()
2007 return s->toChars();
2010 void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2012 buf->writestring(s->toChars());
2015 Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e)
2017 #if 0
2018 tym = tybasic(e1->ET->Tty);
2019 if (!(tyscalar(tym) ||
2020 tym == TYstruct ||
2021 tym == TYarray && e->Eoper == TOKaddr))
2022 synerr(EM_lvalue); // lvalue expected
2023 #endif
2024 return this;
2027 /******************************** GetLoggerExp **************************/
2029 GetLoggerExp::GetLoggerExp(Loc loc)
2030 : Expression(loc, TOKlogger, sizeof(GetLoggerExp))
2034 Expression *GetLoggerExp::semantic(Scope *sc)
2036 Expression *log = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), Id::__log);
2037 return log->semantic(sc);
2040 void GetLoggerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2042 buf->writestring("log");
2045 /******************************** ThisExp **************************/
2047 ThisExp::ThisExp(Loc loc)
2048 : Expression(loc, TOKthis, sizeof(ThisExp))
2050 var = NULL;
2053 Expression *ThisExp::semantic(Scope *sc)
2054 { FuncDeclaration *fd;
2055 FuncDeclaration *fdthis;
2056 int nested = 0;
2058 #if LOGSEMANTIC
2059 printf("ThisExp::semantic()\n");
2060 #endif
2061 if (type)
2062 { //assert(global.errors || var);
2063 return this;
2066 /* Special case for typeof(this) and typeof(super) since both
2067 * should work even if they are not inside a non-static member function
2069 if (sc->intypeof)
2071 // Find enclosing struct or class
2072 for (Dsymbol *s = sc->parent; 1; s = s->parent)
2074 ClassDeclaration *cd;
2075 StructDeclaration *sd;
2077 if (!s)
2079 error("%s is not in a struct or class scope", toChars());
2080 goto Lerr;
2082 cd = s->isClassDeclaration();
2083 if (cd)
2085 type = cd->type;
2086 return this;
2088 sd = s->isStructDeclaration();
2089 if (sd)
2091 type = sd->type->pointerTo();
2092 return this;
2097 fdthis = sc->parent->isFuncDeclaration();
2098 fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2099 if (!fd)
2100 goto Lerr;
2102 assert(fd->vthis);
2103 var = fd->vthis;
2104 assert(var->parent);
2105 type = var->type;
2106 var->isVarDeclaration()->checkNestedReference(sc, loc);
2107 #if 0
2108 if (fd != fdthis) // if nested
2110 fdthis->getLevel(loc, fd);
2111 fd->vthis->nestedref = 1;
2112 fd->nestedFrameRef = 1;
2114 #endif
2115 sc->callSuper |= CSXthis;
2116 return this;
2118 Lerr:
2119 error("'this' is only allowed in non-static member functions, not %s", sc->parent->toChars());
2120 type = Type::tint32;
2121 return this;
2124 int ThisExp::isBool(int result)
2126 return result ? TRUE : FALSE;
2129 void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2131 buf->writestring("this");
2134 Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
2136 return this;
2139 /******************************** SuperExp **************************/
2141 SuperExp::SuperExp(Loc loc)
2142 : ThisExp(loc)
2144 op = TOKsuper;
2147 Expression *SuperExp::semantic(Scope *sc)
2148 { FuncDeclaration *fd;
2149 FuncDeclaration *fdthis;
2150 ClassDeclaration *cd;
2151 Dsymbol *s;
2153 #if LOGSEMANTIC
2154 printf("SuperExp::semantic('%s')\n", toChars());
2155 #endif
2156 if (type)
2157 return this;
2159 /* Special case for typeof(this) and typeof(super) since both
2160 * should work even if they are not inside a non-static member function
2162 if (sc->intypeof)
2164 // Find enclosing class
2165 for (Dsymbol *s = sc->parent; 1; s = s->parent)
2167 ClassDeclaration *cd;
2169 if (!s)
2171 error("%s is not in a class scope", toChars());
2172 goto Lerr;
2174 cd = s->isClassDeclaration();
2175 if (cd)
2177 cd = cd->baseClass;
2178 if (!cd)
2179 { error("class %s has no 'super'", s->toChars());
2180 goto Lerr;
2182 type = cd->type;
2183 return this;
2188 fdthis = sc->parent->isFuncDeclaration();
2189 fd = hasThis(sc);
2190 if (!fd)
2191 goto Lerr;
2192 assert(fd->vthis);
2193 var = fd->vthis;
2194 assert(var->parent);
2196 s = fd->toParent();
2197 while (s && s->isTemplateInstance())
2198 s = s->toParent();
2199 assert(s);
2200 cd = s->isClassDeclaration();
2201 //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
2202 if (!cd)
2203 goto Lerr;
2204 if (!cd->baseClass)
2206 error("no base class for %s", cd->toChars());
2207 type = fd->vthis->type;
2209 else
2211 type = cd->baseClass->type;
2214 var->isVarDeclaration()->checkNestedReference(sc, loc);
2215 #if 0
2216 if (fd != fdthis)
2218 fdthis->getLevel(loc, fd);
2219 fd->vthis->nestedref = 1;
2220 fd->nestedFrameRef = 1;
2222 #endif
2224 sc->callSuper |= CSXsuper;
2225 return this;
2228 Lerr:
2229 error("'super' is only allowed in non-static class member functions");
2230 type = Type::tint32;
2231 return this;
2234 void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2236 buf->writestring("super");
2240 /******************************** NullExp **************************/
2242 NullExp::NullExp(Loc loc)
2243 : Expression(loc, TOKnull, sizeof(NullExp))
2245 committed = 0;
2248 Expression *NullExp::semantic(Scope *sc)
2250 #if LOGSEMANTIC
2251 printf("NullExp::semantic('%s')\n", toChars());
2252 #endif
2253 // NULL is the same as (void *)0
2254 if (!type)
2255 type = Type::tvoid->pointerTo();
2256 return this;
2259 int NullExp::isBool(int result)
2261 return result ? FALSE : TRUE;
2264 void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2266 buf->writestring("null");
2269 void NullExp::toMangleBuffer(OutBuffer *buf)
2271 buf->writeByte('n');
2274 /******************************** StringExp **************************/
2276 StringExp::StringExp(Loc loc, char *string)
2277 : Expression(loc, TOKstring, sizeof(StringExp))
2279 this->string = string;
2280 this->len = strlen(string);
2281 this->sz = 1;
2282 this->committed = 0;
2283 this->postfix = 0;
2286 StringExp::StringExp(Loc loc, void *string, size_t len)
2287 : Expression(loc, TOKstring, sizeof(StringExp))
2289 this->string = string;
2290 this->len = len;
2291 this->sz = 1;
2292 this->committed = 0;
2293 this->postfix = 0;
2296 StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix)
2297 : Expression(loc, TOKstring, sizeof(StringExp))
2299 this->string = string;
2300 this->len = len;
2301 this->sz = 1;
2302 this->committed = 0;
2303 this->postfix = postfix;
2306 #if 0
2307 Expression *StringExp::syntaxCopy()
2309 printf("StringExp::syntaxCopy() %s\n", toChars());
2310 return copy();
2312 #endif
2314 int StringExp::equals(Object *o)
2316 //printf("StringExp::equals('%s')\n", o->toChars());
2317 if (o && o->dyncast() == DYNCAST_EXPRESSION)
2318 { Expression *e = (Expression *)o;
2320 if (e->op == TOKstring)
2322 return compare(o) == 0;
2325 return FALSE;
2328 char *StringExp::toChars()
2330 OutBuffer buf;
2331 HdrGenState hgs;
2332 char *p;
2334 memset(&hgs, 0, sizeof(hgs));
2335 toCBuffer(&buf, &hgs);
2336 buf.writeByte(0);
2337 p = (char *)buf.data;
2338 buf.data = NULL;
2339 return p;
2342 Expression *StringExp::semantic(Scope *sc)
2344 #if LOGSEMANTIC
2345 printf("StringExp::semantic() %s\n", toChars());
2346 #endif
2347 if (!type)
2348 { OutBuffer buffer;
2349 size_t newlen = 0;
2350 char *p;
2351 size_t u;
2352 unsigned c;
2354 switch (postfix)
2356 case 'd':
2357 for (u = 0; u < len;)
2359 p = utf_decodeChar((unsigned char *)string, len, &u, &c);
2360 if (p)
2361 { error("%s", p);
2362 break;
2364 else
2365 { buffer.write4(c);
2366 newlen++;
2369 buffer.write4(0);
2370 string = buffer.extractData();
2371 len = newlen;
2372 sz = 4;
2373 type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex));
2374 committed = 1;
2375 break;
2377 case 'w':
2378 for (u = 0; u < len;)
2380 p = utf_decodeChar((unsigned char *)string, len, &u, &c);
2381 if (p)
2382 { error("%s", p);
2383 break;
2385 else
2386 { buffer.writeUTF16(c);
2387 newlen++;
2388 if (c >= 0x10000)
2389 newlen++;
2392 buffer.writeUTF16(0);
2393 string = buffer.extractData();
2394 len = newlen;
2395 sz = 2;
2396 type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex));
2397 committed = 1;
2398 break;
2400 case 'c':
2401 committed = 1;
2402 default:
2403 type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex));
2404 break;
2406 type = type->semantic(loc, sc);
2408 return this;
2411 /****************************************
2412 * Convert string to char[].
2415 StringExp *StringExp::toUTF8(Scope *sc)
2417 if (sz != 1)
2418 { // Convert to UTF-8 string
2419 committed = 0;
2420 Expression *e = castTo(sc, Type::tchar->arrayOf());
2421 e = e->optimize(WANTvalue);
2422 assert(e->op == TOKstring);
2423 StringExp *se = (StringExp *)e;
2424 assert(se->sz == 1);
2425 return se;
2427 return this;
2430 int StringExp::compare(Object *obj)
2432 // Used to sort case statement expressions so we can do an efficient lookup
2433 StringExp *se2 = (StringExp *)(obj);
2435 // This is a kludge so isExpression() in template.c will return 5
2436 // for StringExp's.
2437 if (!se2)
2438 return 5;
2440 assert(se2->op == TOKstring);
2442 int len1 = len;
2443 int len2 = se2->len;
2445 if (len1 == len2)
2447 switch (sz)
2449 case 1:
2450 return strcmp((char *)string, (char *)se2->string);
2452 case 2:
2453 { unsigned u;
2454 d_wchar *s1 = (d_wchar *)string;
2455 d_wchar *s2 = (d_wchar *)se2->string;
2457 for (u = 0; u < len; u++)
2459 if (s1[u] != s2[u])
2460 return s1[u] - s2[u];
2464 case 4:
2465 { unsigned u;
2466 d_dchar *s1 = (d_dchar *)string;
2467 d_dchar *s2 = (d_dchar *)se2->string;
2469 for (u = 0; u < len; u++)
2471 if (s1[u] != s2[u])
2472 return s1[u] - s2[u];
2475 break;
2477 default:
2478 assert(0);
2481 return len1 - len2;
2484 int StringExp::isBool(int result)
2486 return result ? TRUE : FALSE;
2489 unsigned StringExp::charAt(size_t i)
2490 { unsigned value;
2492 switch (sz)
2494 case 1:
2495 value = ((unsigned char *)string)[i];
2496 break;
2498 case 2:
2499 value = ((unsigned short *)string)[i];
2500 break;
2502 case 4:
2503 value = ((unsigned int *)string)[i];
2504 break;
2506 default:
2507 assert(0);
2508 break;
2510 return value;
2513 void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2515 buf->writeByte('"');
2516 for (size_t i = 0; i < len; i++)
2517 { unsigned c = charAt(i);
2519 switch (c)
2521 case '"':
2522 case '\\':
2523 if (!hgs->console)
2524 buf->writeByte('\\');
2525 default:
2526 if (c <= 0xFF)
2527 { if (c <= 0x7F && (isprint(c) || hgs->console))
2528 buf->writeByte(c);
2529 else
2530 buf->printf("\\x%02x", c);
2532 else if (c <= 0xFFFF)
2533 buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8);
2534 else
2535 buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
2536 c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24);
2537 break;
2540 buf->writeByte('"');
2541 if (postfix)
2542 buf->writeByte(postfix);
2545 void StringExp::toMangleBuffer(OutBuffer *buf)
2546 { char m;
2547 OutBuffer tmp;
2548 char *p;
2549 dchar_t c;
2550 size_t u;
2551 unsigned char *q;
2552 unsigned qlen;
2554 /* Write string in UTF-8 format
2556 switch (sz)
2557 { case 1:
2558 m = 'a';
2559 q = (unsigned char *)string;
2560 qlen = len;
2561 break;
2562 case 2:
2563 m = 'w';
2564 for (u = 0; u < len; )
2566 p = utf_decodeWchar((unsigned short *)string, len, &u, &c);
2567 if (p)
2568 error("%s", p);
2569 else
2570 tmp.writeUTF8(c);
2572 q = tmp.data;
2573 qlen = tmp.offset;
2574 break;
2575 case 4:
2576 m = 'd';
2577 for (u = 0; u < len; u++)
2579 c = ((unsigned *)string)[u];
2580 if (!utf_isValidDchar(c))
2581 error("invalid UCS-32 char \\U%08x", c);
2582 else
2583 tmp.writeUTF8(c);
2585 q = tmp.data;
2586 qlen = tmp.offset;
2587 break;
2588 default:
2589 assert(0);
2591 buf->writeByte(m);
2592 buf->printf("%d_", qlen);
2593 for (size_t i = 0; i < qlen; i++)
2594 buf->printf("%02x", q[i]);
2597 /************************ ArrayLiteralExp ************************************/
2599 // [ e1, e2, e3, ... ]
2601 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements)
2602 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
2604 this->elements = elements;
2607 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e)
2608 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
2610 elements = new Expressions;
2611 elements->push(e);
2614 Expression *ArrayLiteralExp::syntaxCopy()
2616 return new ArrayLiteralExp(loc, arraySyntaxCopy(elements));
2619 Expression *ArrayLiteralExp::semantic(Scope *sc)
2620 { Expression *e;
2621 Type *t0 = NULL;
2623 #if LOGSEMANTIC
2624 printf("ArrayLiteralExp::semantic('%s')\n", toChars());
2625 #endif
2626 if (type)
2627 return this;
2629 // Run semantic() on each element
2630 for (int i = 0; i < elements->dim; i++)
2631 { e = (Expression *)elements->data[i];
2632 e = e->semantic(sc);
2633 elements->data[i] = (void *)e;
2635 expandTuples(elements);
2636 for (int i = 0; i < elements->dim; i++)
2637 { e = (Expression *)elements->data[i];
2639 if (!e->type)
2640 error("%s has no value", e->toChars());
2641 e = resolveProperties(sc, e);
2643 unsigned char committed = 1;
2644 if (e->op == TOKstring)
2645 committed = ((StringExp *)e)->committed;
2647 if (!t0)
2648 { t0 = e->type;
2649 // Convert any static arrays to dynamic arrays
2650 if (t0->ty == Tsarray)
2652 t0 = t0->next->arrayOf();
2653 e = e->implicitCastTo(sc, t0);
2656 else
2657 e = e->implicitCastTo(sc, t0);
2658 if (!committed && e->op == TOKstring)
2659 { StringExp *se = (StringExp *)e;
2660 se->committed = 0;
2662 elements->data[i] = (void *)e;
2665 if (!t0)
2666 t0 = Type::tvoid;
2667 type = new TypeSArray(t0, new IntegerExp(elements->dim));
2668 type = type->semantic(loc, sc);
2669 return this;
2672 int ArrayLiteralExp::checkSideEffect(int flag)
2673 { int f = 0;
2675 for (size_t i = 0; i < elements->dim; i++)
2676 { Expression *e = (Expression *)elements->data[i];
2678 f |= e->checkSideEffect(2);
2680 if (flag == 0 && f == 0)
2681 Expression::checkSideEffect(0);
2682 return f;
2685 int ArrayLiteralExp::isBool(int result)
2687 size_t dim = elements ? elements->dim : 0;
2688 return result ? (dim != 0) : (dim == 0);
2691 void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2693 buf->writeByte('[');
2694 argsToCBuffer(buf, elements, hgs);
2695 buf->writeByte(']');
2698 void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
2700 size_t dim = elements ? elements->dim : 0;
2701 buf->printf("A%"PRIuSIZE, dim);
2702 for (size_t i = 0; i < dim; i++)
2703 { Expression *e = (Expression *)elements->data[i];
2704 e->toMangleBuffer(buf);
2708 /************************ AssocArrayLiteralExp ************************************/
2710 // [ key0 : value0, key1 : value1, ... ]
2712 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc,
2713 Expressions *keys, Expressions *values)
2714 : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp))
2716 assert(keys->dim == values->dim);
2717 this->keys = keys;
2718 this->values = values;
2721 Expression *AssocArrayLiteralExp::syntaxCopy()
2723 return new AssocArrayLiteralExp(loc,
2724 arraySyntaxCopy(keys), arraySyntaxCopy(values));
2727 Expression *AssocArrayLiteralExp::semantic(Scope *sc)
2728 { Expression *e;
2729 Type *tkey = NULL;
2730 Type *tvalue = NULL;
2732 #if LOGSEMANTIC
2733 printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
2734 #endif
2736 // Run semantic() on each element
2737 for (size_t i = 0; i < keys->dim; i++)
2738 { Expression *key = (Expression *)keys->data[i];
2739 Expression *value = (Expression *)values->data[i];
2741 key = key->semantic(sc);
2742 value = value->semantic(sc);
2744 keys->data[i] = (void *)key;
2745 values->data[i] = (void *)value;
2747 expandTuples(keys);
2748 expandTuples(values);
2749 if (keys->dim != values->dim)
2751 error("number of keys is %u, must match number of values %u", keys->dim, values->dim);
2752 keys->setDim(0);
2753 values->setDim(0);
2755 for (size_t i = 0; i < keys->dim; i++)
2756 { Expression *key = (Expression *)keys->data[i];
2757 Expression *value = (Expression *)values->data[i];
2759 if (!key->type)
2760 error("%s has no value", key->toChars());
2761 if (!value->type)
2762 error("%s has no value", value->toChars());
2763 key = resolveProperties(sc, key);
2764 value = resolveProperties(sc, value);
2766 if (!tkey)
2767 tkey = key->type;
2768 else
2769 key = key->implicitCastTo(sc, tkey);
2770 keys->data[i] = (void *)key;
2772 if (!tvalue)
2773 tvalue = value->type;
2774 else
2775 value = value->implicitCastTo(sc, tvalue);
2776 values->data[i] = (void *)value;
2779 if (!tkey)
2780 tkey = Type::tvoid;
2781 if (!tvalue)
2782 tvalue = Type::tvoid;
2783 type = new TypeAArray(tvalue, tkey);
2784 type = type->semantic(loc, sc);
2785 return this;
2788 int AssocArrayLiteralExp::checkSideEffect(int flag)
2789 { int f = 0;
2791 for (size_t i = 0; i < keys->dim; i++)
2792 { Expression *key = (Expression *)keys->data[i];
2793 Expression *value = (Expression *)values->data[i];
2795 f |= key->checkSideEffect(2);
2796 f |= value->checkSideEffect(2);
2798 if (flag == 0 && f == 0)
2799 Expression::checkSideEffect(0);
2800 return f;
2803 int AssocArrayLiteralExp::isBool(int result)
2805 size_t dim = keys->dim;
2806 return result ? (dim != 0) : (dim == 0);
2809 void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2811 buf->writeByte('[');
2812 for (size_t i = 0; i < keys->dim; i++)
2813 { Expression *key = (Expression *)keys->data[i];
2814 Expression *value = (Expression *)values->data[i];
2816 if (i)
2817 buf->writeByte(',');
2818 expToCBuffer(buf, hgs, key, PREC_assign);
2819 buf->writeByte(':');
2820 expToCBuffer(buf, hgs, value, PREC_assign);
2822 buf->writeByte(']');
2825 void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
2827 size_t dim = keys->dim;
2828 buf->printf("A%u", dim);
2829 for (size_t i = 0; i < dim; i++)
2830 { Expression *key = (Expression *)keys->data[i];
2831 Expression *value = (Expression *)values->data[i];
2833 key->toMangleBuffer(buf);
2834 value->toMangleBuffer(buf);
2838 /************************ StructLiteralExp ************************************/
2840 // sd( e1, e2, e3, ... )
2842 StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements)
2843 : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp))
2845 this->sd = sd;
2846 this->elements = elements;
2847 this->sym = NULL;
2848 this->soffset = 0;
2849 this->fillHoles = 1;
2852 Expression *StructLiteralExp::syntaxCopy()
2854 return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements));
2857 Expression *StructLiteralExp::semantic(Scope *sc)
2858 { Expression *e;
2860 #if LOGSEMANTIC
2861 printf("StructLiteralExp::semantic('%s')\n", toChars());
2862 #endif
2864 // Run semantic() on each element
2865 for (size_t i = 0; i < elements->dim; i++)
2866 { e = (Expression *)elements->data[i];
2867 if (!e)
2868 continue;
2869 e = e->semantic(sc);
2870 elements->data[i] = (void *)e;
2872 expandTuples(elements);
2873 size_t offset = 0;
2874 for (size_t i = 0; i < elements->dim; i++)
2875 { e = (Expression *)elements->data[i];
2876 if (!e)
2877 continue;
2879 if (!e->type)
2880 error("%s has no value", e->toChars());
2881 e = resolveProperties(sc, e);
2882 if (i >= sd->fields.dim)
2883 { error("more initializers than fields of %s", sd->toChars());
2884 break;
2886 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
2887 VarDeclaration *v = s->isVarDeclaration();
2888 assert(v);
2889 if (v->offset < offset)
2890 error("overlapping initialization for %s", v->toChars());
2891 offset = v->offset + v->type->size();
2893 Type *telem = v->type;
2894 while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray)
2895 { /* Static array initialization, as in:
2896 * T[3][5] = e;
2898 telem = telem->toBasetype()->nextOf();
2901 e = e->implicitCastTo(sc, telem);
2903 elements->data[i] = (void *)e;
2906 /* Fill out remainder of elements[] with default initializers for fields[]
2908 for (size_t i = elements->dim; i < sd->fields.dim; i++)
2909 { Dsymbol *s = (Dsymbol *)sd->fields.data[i];
2910 VarDeclaration *v = s->isVarDeclaration();
2911 assert(v);
2913 if (v->offset < offset)
2914 { e = NULL;
2915 sd->hasUnions = 1;
2917 else
2919 if (v->init)
2920 { e = v->init->toExpression();
2921 if (!e)
2922 error("cannot make expression out of initializer for %s", v->toChars());
2924 else
2925 { e = v->type->defaultInit();
2926 e->loc = loc;
2928 offset = v->offset + v->type->size();
2930 elements->push(e);
2933 type = sd->type;
2934 return this;
2937 /**************************************
2938 * Gets expression at offset of type.
2939 * Returns NULL if not found.
2942 Expression *StructLiteralExp::getField(Type *type, unsigned offset)
2943 { Expression *e = NULL;
2944 int i = getFieldIndex(type, offset);
2946 if (i != -1)
2947 { e = (Expression *)elements->data[i];
2948 if (e)
2950 e = e->copy();
2951 e->type = type;
2954 return e;
2957 /************************************
2958 * Get index of field.
2959 * Returns -1 if not found.
2962 int StructLiteralExp::getFieldIndex(Type *type, unsigned offset)
2964 /* Find which field offset is by looking at the field offsets
2966 for (size_t i = 0; i < sd->fields.dim; i++)
2968 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
2969 VarDeclaration *v = s->isVarDeclaration();
2970 assert(v);
2972 if (offset == v->offset &&
2973 type->size() == v->type->size())
2974 { Expression *e = (Expression *)elements->data[i];
2975 if (e)
2977 return i;
2979 break;
2982 return -1;
2986 Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e)
2988 return this;
2992 int StructLiteralExp::checkSideEffect(int flag)
2993 { int f = 0;
2995 for (size_t i = 0; i < elements->dim; i++)
2996 { Expression *e = (Expression *)elements->data[i];
2997 if (!e)
2998 continue;
3000 f |= e->checkSideEffect(2);
3002 if (flag == 0 && f == 0)
3003 Expression::checkSideEffect(0);
3004 return f;
3007 void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3009 buf->writestring(sd->toChars());
3010 buf->writeByte('(');
3011 argsToCBuffer(buf, elements, hgs);
3012 buf->writeByte(')');
3015 void StructLiteralExp::toMangleBuffer(OutBuffer *buf)
3017 size_t dim = elements ? elements->dim : 0;
3018 buf->printf("S%u", dim);
3019 for (size_t i = 0; i < dim; i++)
3020 { Expression *e = (Expression *)elements->data[i];
3021 if (e)
3022 e->toMangleBuffer(buf);
3023 else
3024 buf->writeByte('v'); // 'v' for void
3028 /************************ TypeDotIdExp ************************************/
3030 /* Things like:
3031 * int.size
3032 * foo.size
3033 * (foo).size
3034 * cast(foo).size
3037 TypeDotIdExp::TypeDotIdExp(Loc loc, Type *type, Identifier *ident)
3038 : Expression(loc, TOKtypedot, sizeof(TypeDotIdExp))
3040 this->type = type;
3041 this->ident = ident;
3044 Expression *TypeDotIdExp::syntaxCopy()
3046 TypeDotIdExp *te = new TypeDotIdExp(loc, type->syntaxCopy(), ident);
3047 return te;
3050 Expression *TypeDotIdExp::semantic(Scope *sc)
3051 { Expression *e;
3053 #if LOGSEMANTIC
3054 printf("TypeDotIdExp::semantic()\n");
3055 #endif
3056 e = new DotIdExp(loc, new TypeExp(loc, type), ident);
3057 e = e->semantic(sc);
3058 return e;
3061 void TypeDotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3063 buf->writeByte('(');
3064 type->toCBuffer(buf, NULL, hgs);
3065 buf->writeByte(')');
3066 buf->writeByte('.');
3067 buf->writestring(ident->toChars());
3070 /************************************************************/
3072 // Mainly just a placeholder
3074 TypeExp::TypeExp(Loc loc, Type *type)
3075 : Expression(loc, TOKtype, sizeof(TypeExp))
3077 //printf("TypeExp::TypeExp(%s)\n", type->toChars());
3078 this->type = type;
3081 Expression *TypeExp::semantic(Scope *sc)
3083 //printf("TypeExp::semantic(%s)\n", type->toChars());
3084 type = type->semantic(loc, sc);
3085 return this;
3088 void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3090 type->toCBuffer(buf, NULL, hgs);
3093 /************************************************************/
3095 // Mainly just a placeholder
3097 ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg)
3098 : Expression(loc, TOKimport, sizeof(ScopeExp))
3100 //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars());
3101 //static int count; if (++count == 38) *(char*)0=0;
3102 this->sds = pkg;
3105 Expression *ScopeExp::syntaxCopy()
3107 ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL));
3108 return se;
3111 Expression *ScopeExp::semantic(Scope *sc)
3113 TemplateInstance *ti;
3114 ScopeDsymbol *sds2;
3116 #if LOGSEMANTIC
3117 printf("+ScopeExp::semantic('%s')\n", toChars());
3118 #endif
3119 Lagain:
3120 ti = sds->isTemplateInstance();
3121 if (ti && !global.errors)
3122 { Dsymbol *s;
3123 if (!ti->semanticdone)
3124 ti->semantic(sc);
3125 s = ti->inst->toAlias();
3126 sds2 = s->isScopeDsymbol();
3127 if (!sds2)
3128 { Expression *e;
3130 //printf("s = %s, '%s'\n", s->kind(), s->toChars());
3131 if (ti->withsym)
3133 // Same as wthis.s
3134 e = new VarExp(loc, ti->withsym->withstate->wthis);
3135 e = new DotVarExp(loc, e, s->isDeclaration());
3137 else
3138 e = new DsymbolExp(loc, s);
3139 e = e->semantic(sc);
3140 //printf("-1ScopeExp::semantic()\n");
3141 return e;
3143 if (sds2 != sds)
3145 sds = sds2;
3146 goto Lagain;
3148 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3150 else
3152 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3153 //printf("\tparent = '%s'\n", sds->parent->toChars());
3154 sds->semantic(sc);
3156 type = Type::tvoid;
3157 //printf("-2ScopeExp::semantic() %s\n", toChars());
3158 return this;
3161 void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3163 if (sds->isTemplateInstance())
3165 sds->toCBuffer(buf, hgs);
3167 else
3169 buf->writestring(sds->kind());
3170 buf->writestring(" ");
3171 buf->writestring(sds->toChars());
3175 /********************** TemplateExp **************************************/
3177 // Mainly just a placeholder
3179 TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td)
3180 : Expression(loc, TOKtemplate, sizeof(TemplateExp))
3182 //printf("TemplateExp(): %s\n", td->toChars());
3183 this->td = td;
3186 void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3188 buf->writestring(td->toChars());
3191 void TemplateExp::rvalue()
3193 error("template %s has no value", toChars());
3196 /********************** NewExp **************************************/
3198 NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
3199 Type *newtype, Expressions *arguments)
3200 : Expression(loc, TOKnew, sizeof(NewExp))
3202 this->thisexp = thisexp;
3203 this->newargs = newargs;
3204 this->newtype = newtype;
3205 this->arguments = arguments;
3206 member = NULL;
3207 allocator = NULL;
3208 onstack = 0;
3211 Expression *NewExp::syntaxCopy()
3213 return new NewExp(loc,
3214 thisexp ? thisexp->syntaxCopy() : NULL,
3215 arraySyntaxCopy(newargs),
3216 newtype->syntaxCopy(), arraySyntaxCopy(arguments));
3220 Expression *NewExp::semantic(Scope *sc)
3221 { int i;
3222 Type *tb;
3223 ClassDeclaration *cdthis = NULL;
3225 #if LOGSEMANTIC
3226 printf("NewExp::semantic() %s\n", toChars());
3227 if (thisexp)
3228 printf("\tthisexp = %s\n", thisexp->toChars());
3229 printf("\tnewtype: %s\n", newtype->toChars());
3230 #endif
3231 if (type) // if semantic() already run
3232 return this;
3234 Lagain:
3235 if (thisexp)
3236 { thisexp = thisexp->semantic(sc);
3237 cdthis = thisexp->type->isClassHandle();
3238 if (cdthis)
3240 sc = sc->push(cdthis);
3241 type = newtype->semantic(loc, sc);
3242 sc = sc->pop();
3244 else
3246 error("'this' for nested class must be a class type, not %s", thisexp->type->toChars());
3247 type = newtype->semantic(loc, sc);
3250 else
3251 type = newtype->semantic(loc, sc);
3252 newtype = type; // in case type gets cast to something else
3253 tb = type->toBasetype();
3254 //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco);
3256 arrayExpressionSemantic(newargs, sc);
3257 preFunctionArguments(loc, sc, newargs);
3258 arrayExpressionSemantic(arguments, sc);
3259 preFunctionArguments(loc, sc, arguments);
3261 if (thisexp && tb->ty != Tclass)
3262 error("e.new is only for allocating nested classes, not %s", tb->toChars());
3264 if (tb->ty == Tclass)
3265 { TypeFunction *tf;
3267 TypeClass *tc = (TypeClass *)(tb);
3268 ClassDeclaration *cd = tc->sym->isClassDeclaration();
3269 if (cd->isInterfaceDeclaration())
3270 error("cannot create instance of interface %s", cd->toChars());
3271 else if (cd->isAbstract())
3272 { error("cannot create instance of abstract class %s", cd->toChars());
3273 for (int i = 0; i < cd->vtbl.dim; i++)
3274 { FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration();
3275 if (fd && fd->isAbstract())
3276 error("function %s is abstract", fd->toChars());
3279 checkDeprecated(sc, cd);
3280 if (cd->isNested())
3281 { /* We need a 'this' pointer for the nested class.
3282 * Ensure we have the right one.
3284 Dsymbol *s = cd->toParent2();
3285 ClassDeclaration *cdn = s->isClassDeclaration();
3287 //printf("isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
3288 if (cdn)
3290 if (!cdthis)
3292 // Supply an implicit 'this' and try again
3293 thisexp = new ThisExp(loc);
3294 for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
3295 { if (!sp)
3297 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
3298 break;
3300 ClassDeclaration *cdp = sp->isClassDeclaration();
3301 if (!cdp)
3302 continue;
3303 if (cdp == cdn || cdn->isBaseOf(cdp, NULL))
3304 break;
3305 // Add a '.outer' and try again
3306 thisexp = new DotIdExp(loc, thisexp, Id::outer);
3308 if (!global.errors)
3309 goto Lagain;
3311 if (cdthis)
3313 //printf("cdthis = %s\n", cdthis->toChars());
3314 if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL))
3315 error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars());
3317 #if 0
3318 else
3320 for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration())
3322 if (!sf)
3324 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
3325 break;
3327 printf("sf = %s\n", sf->toChars());
3328 AggregateDeclaration *ad = sf->isThis();
3329 if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL)))
3330 break;
3333 #endif
3335 else if (thisexp)
3336 error("e.new is only for allocating nested classes");
3338 else if (thisexp)
3339 error("e.new is only for allocating nested classes");
3341 FuncDeclaration *f = cd->ctor;
3342 if (f)
3344 assert(f);
3345 f = f->overloadResolve(loc, arguments);
3346 checkDeprecated(sc, f);
3347 member = f->isCtorDeclaration();
3348 assert(member);
3350 cd->accessCheck(loc, sc, member);
3352 tf = (TypeFunction *)f->type;
3353 type = tf->next;
3355 if (!arguments)
3356 arguments = new Expressions();
3357 functionArguments(loc, sc, tf, arguments);
3359 else
3361 if (arguments && arguments->dim)
3362 error("no constructor for %s", cd->toChars());
3365 if (cd->aggNew)
3366 { Expression *e;
3368 f = cd->aggNew;
3370 // Prepend the uint size argument to newargs[]
3371 e = new IntegerExp(loc, cd->size(loc), Type::tsize_t);
3372 if (!newargs)
3373 newargs = new Expressions();
3374 newargs->shift(e);
3376 f = f->overloadResolve(loc, newargs);
3377 allocator = f->isNewDeclaration();
3378 assert(allocator);
3380 tf = (TypeFunction *)f->type;
3381 functionArguments(loc, sc, tf, newargs);
3383 else
3385 if (newargs && newargs->dim)
3386 error("no allocator for %s", cd->toChars());
3390 else if (tb->ty == Tstruct)
3392 TypeStruct *ts = (TypeStruct *)tb;
3393 StructDeclaration *sd = ts->sym;
3394 FuncDeclaration *f = sd->aggNew;
3395 TypeFunction *tf;
3397 if (arguments && arguments->dim)
3398 error("no constructor for %s", type->toChars());
3400 if (f)
3402 Expression *e;
3404 // Prepend the uint size argument to newargs[]
3405 e = new IntegerExp(loc, sd->size(loc), Type::tsize_t);
3406 if (!newargs)
3407 newargs = new Expressions();
3408 newargs->shift(e);
3410 f = f->overloadResolve(loc, newargs);
3411 allocator = f->isNewDeclaration();
3412 assert(allocator);
3414 tf = (TypeFunction *)f->type;
3415 functionArguments(loc, sc, tf, newargs);
3417 e = new VarExp(loc, f);
3418 e = new CallExp(loc, e, newargs);
3419 e = e->semantic(sc);
3420 e->type = type->pointerTo();
3421 return e;
3424 type = type->pointerTo();
3426 else if (tb->ty == Tarray && (arguments && arguments->dim))
3428 for (size_t i = 0; i < arguments->dim; i++)
3430 if (tb->ty != Tarray)
3431 { error("too many arguments for array");
3432 arguments->dim = i;
3433 break;
3436 Expression *arg = (Expression *)arguments->data[i];
3437 arg = resolveProperties(sc, arg);
3438 arg = arg->implicitCastTo(sc, Type::tsize_t);
3439 if (arg->op == TOKint64 && (long long)arg->toInteger() < 0)
3440 error("negative array index %s", arg->toChars());
3441 arguments->data[i] = (void *) arg;
3442 tb = tb->next->toBasetype();
3445 else if (tb->isscalar())
3447 if (arguments && arguments->dim)
3448 error("no constructor for %s", type->toChars());
3450 type = type->pointerTo();
3452 else
3454 error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars());
3455 type = type->pointerTo();
3458 //printf("NewExp: '%s'\n", toChars());
3459 //printf("NewExp:type '%s'\n", type->toChars());
3461 return this;
3464 int NewExp::checkSideEffect(int flag)
3466 return 1;
3469 void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3470 { int i;
3472 if (thisexp)
3473 { expToCBuffer(buf, hgs, thisexp, PREC_primary);
3474 buf->writeByte('.');
3476 buf->writestring("new ");
3477 if (newargs && newargs->dim)
3479 buf->writeByte('(');
3480 argsToCBuffer(buf, newargs, hgs);
3481 buf->writeByte(')');
3483 newtype->toCBuffer(buf, NULL, hgs);
3484 if (arguments && arguments->dim)
3486 buf->writeByte('(');
3487 argsToCBuffer(buf, arguments, hgs);
3488 buf->writeByte(')');
3492 /********************** NewAnonClassExp **************************************/
3494 NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp,
3495 Expressions *newargs, ClassDeclaration *cd, Expressions *arguments)
3496 : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp))
3498 this->thisexp = thisexp;
3499 this->newargs = newargs;
3500 this->cd = cd;
3501 this->arguments = arguments;
3504 Expression *NewAnonClassExp::syntaxCopy()
3506 return new NewAnonClassExp(loc,
3507 thisexp ? thisexp->syntaxCopy() : NULL,
3508 arraySyntaxCopy(newargs),
3509 (ClassDeclaration *)cd->syntaxCopy(NULL),
3510 arraySyntaxCopy(arguments));
3514 Expression *NewAnonClassExp::semantic(Scope *sc)
3516 #if LOGSEMANTIC
3517 printf("NewAnonClassExp::semantic() %s\n", toChars());
3518 //printf("type: %s\n", type->toChars());
3519 #endif
3521 Expression *d = new DeclarationExp(loc, cd);
3522 d = d->semantic(sc);
3524 Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments);
3526 Expression *c = new CommaExp(loc, d, n);
3527 return c->semantic(sc);
3530 int NewAnonClassExp::checkSideEffect(int flag)
3532 return 1;
3535 void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3536 { int i;
3538 if (thisexp)
3539 { expToCBuffer(buf, hgs, thisexp, PREC_primary);
3540 buf->writeByte('.');
3542 buf->writestring("new");
3543 if (newargs && newargs->dim)
3545 buf->writeByte('(');
3546 argsToCBuffer(buf, newargs, hgs);
3547 buf->writeByte(')');
3549 buf->writestring(" class ");
3550 if (arguments && arguments->dim)
3552 buf->writeByte('(');
3553 argsToCBuffer(buf, arguments, hgs);
3554 buf->writeByte(')');
3556 //buf->writestring(" { }");
3557 if (cd)
3559 cd->toCBuffer(buf, hgs);
3563 /********************** SymOffExp **************************************/
3565 SymOffExp::SymOffExp(Loc loc, Declaration *var, target_size_t offset)
3566 : Expression(loc, TOKsymoff, sizeof(SymOffExp))
3568 assert(var);
3569 this->var = var;
3570 this->offset = offset;
3571 VarDeclaration *v = var->isVarDeclaration();
3572 if (v && v->needThis())
3573 error("need 'this' for address of %s", v->toChars());
3576 Expression *SymOffExp::semantic(Scope *sc)
3578 #if LOGSEMANTIC
3579 printf("SymOffExp::semantic('%s')\n", toChars());
3580 #endif
3581 //var->semantic(sc);
3582 if (!type)
3583 type = var->type->pointerTo();
3584 VarDeclaration *v = var->isVarDeclaration();
3585 if (v)
3586 v->checkNestedReference(sc, loc);
3587 return this;
3590 int SymOffExp::isBool(int result)
3592 return result ? TRUE : FALSE;
3595 void SymOffExp::checkEscape()
3597 VarDeclaration *v = var->isVarDeclaration();
3598 if (v)
3600 if (!v->isDataseg())
3601 error("escaping reference to local variable %s", v->toChars());
3605 void SymOffExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3607 if (offset)
3608 buf->printf("(& %s+%"PRIuTSIZE")", var->toChars(), offset);
3609 else
3610 buf->printf("& %s", var->toChars());
3613 /******************************** VarExp **************************/
3615 VarExp::VarExp(Loc loc, Declaration *var)
3616 : Expression(loc, TOKvar, sizeof(VarExp))
3618 //printf("VarExp(this = %p, '%s')\n", this, var->toChars());
3619 this->var = var;
3620 this->type = var->type;
3623 int VarExp::equals(Object *o)
3624 { VarExp *ne;
3626 if (this == o ||
3627 (((Expression *)o)->op == TOKvar &&
3628 ((ne = (VarExp *)o), type->equals(ne->type)) &&
3629 var == ne->var))
3630 return 1;
3631 return 0;
3634 Expression *VarExp::semantic(Scope *sc)
3635 { FuncLiteralDeclaration *fd;
3637 #if LOGSEMANTIC
3638 printf("VarExp::semantic(%s)\n", toChars());
3639 #endif
3640 if (!type)
3641 { type = var->type;
3642 #if 0
3643 if (var->storage_class & STClazy)
3645 TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd);
3646 type = new TypeDelegate(tf);
3647 type = type->semantic(loc, sc);
3649 #endif
3652 VarDeclaration *v = var->isVarDeclaration();
3653 if (v)
3655 if (v->isConst() && type->toBasetype()->ty != Tsarray && v->init)
3657 ExpInitializer *ei = v->init->isExpInitializer();
3658 if (ei)
3660 //ei->exp->implicitCastTo(sc, type)->print();
3661 return ei->exp->implicitCastTo(sc, type);
3664 v->checkNestedReference(sc, loc);
3666 #if 0
3667 else if ((fd = var->isFuncLiteralDeclaration()) != NULL)
3668 { Expression *e;
3669 e = new FuncExp(loc, fd);
3670 e->type = type;
3671 return e;
3673 #endif
3674 return this;
3677 char *VarExp::toChars()
3679 return var->toChars();
3682 void VarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3684 buf->writestring(var->toChars());
3687 void VarExp::checkEscape()
3689 VarDeclaration *v = var->isVarDeclaration();
3690 if (v)
3691 { Type *tb = v->type->toBasetype();
3692 // if reference type
3693 if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass)
3695 if ((v->isAuto() || v->isScope()) && !v->noauto)
3696 error("escaping reference to auto local %s", v->toChars());
3697 else if (v->storage_class & STCvariadic)
3698 error("escaping reference to variadic parameter %s", v->toChars());
3703 Expression *VarExp::toLvalue(Scope *sc, Expression *e)
3705 #if 0
3706 tym = tybasic(e1->ET->Tty);
3707 if (!(tyscalar(tym) ||
3708 tym == TYstruct ||
3709 tym == TYarray && e->Eoper == TOKaddr))
3710 synerr(EM_lvalue); // lvalue expected
3711 #endif
3712 if (var->storage_class & STClazy)
3713 error("lazy variables cannot be lvalues");
3714 return this;
3717 Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
3719 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
3720 if (sc->incontract && var->isParameter())
3721 error("cannot modify parameter '%s' in contract", var->toChars());
3723 if (type && type->toBasetype()->ty == Tsarray)
3724 error("cannot change reference to static array '%s'", var->toChars());
3726 VarDeclaration *v = var->isVarDeclaration();
3727 if (v && v->canassign == 0 &&
3728 (var->isConst() || (global.params.Dversion > 1 && var->isFinal())))
3729 error("cannot modify final variable '%s'", var->toChars());
3731 // Also need this for non-null fields.
3732 v->ctorinit = 1;
3734 if (var->isCtorinit())
3735 { // It's only modifiable if inside the right constructor
3736 Dsymbol *s = sc->func;
3737 while (1)
3739 FuncDeclaration *fd = NULL;
3740 if (s)
3741 fd = s->isFuncDeclaration();
3742 if (fd &&
3743 ((fd->isCtorDeclaration() && var->storage_class & STCfield) ||
3744 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) &&
3745 fd->toParent() == var->toParent()
3748 VarDeclaration *v = var->isVarDeclaration();
3749 assert(v);
3750 //v->ctorinit = 1;
3751 //printf("setting ctorinit\n");
3753 else
3755 if (s)
3756 { s = s->toParent2();
3757 continue;
3759 else
3761 const char *p = var->isStatic() ? "static " : "";
3762 error("can only initialize %sconst %s inside %sconstructor",
3763 p, var->toChars(), p);
3766 break;
3770 // See if this expression is a modifiable lvalue (i.e. not const)
3771 return toLvalue(sc, e);
3775 /******************************** TupleExp **************************/
3777 TupleExp::TupleExp(Loc loc, Expressions *exps)
3778 : Expression(loc, TOKtuple, sizeof(TupleExp))
3780 //printf("TupleExp(this = %p)\n", this);
3781 this->exps = exps;
3782 this->type = NULL;
3786 TupleExp::TupleExp(Loc loc, TupleDeclaration *tup)
3787 : Expression(loc, TOKtuple, sizeof(TupleExp))
3789 exps = new Expressions();
3790 type = NULL;
3792 exps->reserve(tup->objects->dim);
3793 for (size_t i = 0; i < tup->objects->dim; i++)
3794 { Object *o = (Object *)tup->objects->data[i];
3795 if (o->dyncast() == DYNCAST_EXPRESSION)
3797 Expression *e = (Expression *)o;
3798 e = e->syntaxCopy();
3799 exps->push(e);
3801 else if (o->dyncast() == DYNCAST_DSYMBOL)
3803 Dsymbol *s = (Dsymbol *)o;
3804 Expression *e = new DsymbolExp(loc, s);
3805 exps->push(e);
3807 else if (o->dyncast() == DYNCAST_TYPE)
3809 Type *t = (Type *)o;
3810 Expression *e = new TypeExp(loc, t);
3811 exps->push(e);
3813 else
3815 error("%s is not an expression", o->toChars());
3820 int TupleExp::equals(Object *o)
3821 { TupleExp *ne;
3823 if (this == o)
3824 return 1;
3825 if (((Expression *)o)->op == TOKtuple)
3827 TupleExp *te = (TupleExp *)o;
3828 if (exps->dim != te->exps->dim)
3829 return 0;
3830 for (size_t i = 0; i < exps->dim; i++)
3831 { Expression *e1 = (Expression *)exps->data[i];
3832 Expression *e2 = (Expression *)te->exps->data[i];
3834 if (!e1->equals(e2))
3835 return 0;
3837 return 1;
3839 return 0;
3842 Expression *TupleExp::syntaxCopy()
3844 return new TupleExp(loc, arraySyntaxCopy(exps));
3847 Expression *TupleExp::semantic(Scope *sc)
3849 #if LOGSEMANTIC
3850 printf("+TupleExp::semantic(%s)\n", toChars());
3851 #endif
3852 if (type)
3853 return this;
3855 // Run semantic() on each argument
3856 for (size_t i = 0; i < exps->dim; i++)
3857 { Expression *e = (Expression *)exps->data[i];
3859 e = e->semantic(sc);
3860 if (!e->type)
3861 { error("%s has no value", e->toChars());
3862 e->type = Type::terror;
3864 exps->data[i] = (void *)e;
3867 expandTuples(exps);
3868 if (0 && exps->dim == 1)
3870 return (Expression *)exps->data[0];
3872 type = new TypeTuple(exps);
3873 //printf("-TupleExp::semantic(%s)\n", toChars());
3874 return this;
3877 void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3879 buf->writestring("tuple(");
3880 argsToCBuffer(buf, exps, hgs);
3881 buf->writeByte(')');
3884 int TupleExp::checkSideEffect(int flag)
3885 { int f = 0;
3887 for (int i = 0; i < exps->dim; i++)
3888 { Expression *e = (Expression *)exps->data[i];
3890 f |= e->checkSideEffect(2);
3892 if (flag == 0 && f == 0)
3893 Expression::checkSideEffect(0);
3894 return f;
3897 void TupleExp::checkEscape()
3899 for (size_t i = 0; i < exps->dim; i++)
3900 { Expression *e = (Expression *)exps->data[i];
3901 e->checkEscape();
3905 /******************************** FuncExp *********************************/
3907 FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd)
3908 : Expression(loc, TOKfunction, sizeof(FuncExp))
3910 this->fd = fd;
3913 Expression *FuncExp::syntaxCopy()
3915 return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL));
3918 Expression *FuncExp::semantic(Scope *sc)
3920 #if LOGSEMANTIC
3921 printf("FuncExp::semantic(%s)\n", toChars());
3922 #endif
3923 if (!type)
3925 fd->semantic(sc);
3926 fd->parent = sc->parent;
3927 if (global.errors)
3929 if (!fd->type->next)
3930 fd->type->next = Type::terror;
3932 else
3934 fd->semantic2(sc);
3935 if (!global.errors)
3937 fd->semantic3(sc);
3939 if (!global.errors && global.params.useInline)
3940 fd->inlineScan();
3944 // Type is a "delegate to" or "pointer to" the function literal
3945 if (fd->isNested())
3947 type = new TypeDelegate(fd->type);
3948 type = type->semantic(loc, sc);
3950 else
3952 type = fd->type->pointerTo();
3955 return this;
3958 char *FuncExp::toChars()
3960 return fd->toChars();
3963 void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3965 buf->writestring(fd->toChars());
3969 /******************************** DeclarationExp **************************/
3971 DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration)
3972 : Expression(loc, TOKdeclaration, sizeof(DeclarationExp))
3974 this->declaration = declaration;
3977 Expression *DeclarationExp::syntaxCopy()
3979 return new DeclarationExp(loc, declaration->syntaxCopy(NULL));
3982 Expression *DeclarationExp::semantic(Scope *sc)
3984 if (type)
3985 return this;
3987 #if LOGSEMANTIC
3988 printf("DeclarationExp::semantic() %s\n", toChars());
3989 #endif
3991 /* This is here to support extern(linkage) declaration,
3992 * where the extern(linkage) winds up being an AttribDeclaration
3993 * wrapper.
3995 Dsymbol *s = declaration;
3997 AttribDeclaration *ad = declaration->isAttribDeclaration();
3998 if (ad)
4000 if (ad->decl && ad->decl->dim == 1)
4001 s = (Dsymbol *)ad->decl->data[0];
4004 if (s->isVarDeclaration())
4005 { // Do semantic() on initializer first, so:
4006 // int a = a;
4007 // will be illegal.
4008 declaration->semantic(sc);
4009 s->parent = sc->parent;
4012 //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc);
4013 // Insert into both local scope and function scope.
4014 // Must be unique in both.
4015 if (s->ident)
4017 if (!sc->insert(s))
4018 error("declaration %s is already defined", s->toPrettyChars());
4019 else if (sc->func)
4020 { VarDeclaration *v = s->isVarDeclaration();
4021 if ((s->isFuncDeclaration() /*|| v && v->storage_class & STCstatic*/) &&
4022 !sc->func->localsymtab->insert(s))
4023 error("declaration %s is already defined in another scope in %s", s->toPrettyChars(), sc->func->toChars());
4024 else if (!global.params.useDeprecated)
4025 { // Disallow shadowing
4027 for (Scope *scx = sc->enclosing; scx && scx->func == sc->func; scx = scx->enclosing)
4028 { Dsymbol *s2;
4030 if (scx->scopesym && scx->scopesym->symtab &&
4031 (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL &&
4032 s != s2)
4034 error("shadowing declaration %s is deprecated", s->toPrettyChars());
4040 if (!s->isVarDeclaration())
4042 declaration->semantic(sc);
4043 s->parent = sc->parent;
4045 if (!global.errors)
4047 declaration->semantic2(sc);
4048 if (!global.errors)
4050 declaration->semantic3(sc);
4052 if (!global.errors && global.params.useInline)
4053 declaration->inlineScan();
4057 type = Type::tvoid;
4058 return this;
4061 int DeclarationExp::checkSideEffect(int flag)
4063 return 1;
4066 void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4068 declaration->toCBuffer(buf, hgs);
4072 /************************ TypeidExp ************************************/
4075 * typeid(int)
4078 TypeidExp::TypeidExp(Loc loc, Type *typeidType)
4079 : Expression(loc, TOKtypeid, sizeof(TypeidExp))
4081 this->typeidType = typeidType;
4085 Expression *TypeidExp::syntaxCopy()
4087 return new TypeidExp(loc, typeidType->syntaxCopy());
4091 Expression *TypeidExp::semantic(Scope *sc)
4092 { Expression *e;
4094 #if LOGSEMANTIC
4095 printf("TypeidExp::semantic()\n");
4096 #endif
4097 typeidType = typeidType->semantic(loc, sc);
4098 e = typeidType->getTypeInfo(sc);
4099 return e;
4102 void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4104 buf->writestring("typeid(");
4105 typeidType->toCBuffer(buf, NULL, hgs);
4106 buf->writeByte(')');
4109 /************************************************************/
4111 HaltExp::HaltExp(Loc loc)
4112 : Expression(loc, TOKhalt, sizeof(HaltExp))
4116 Expression *HaltExp::semantic(Scope *sc)
4118 #if LOGSEMANTIC
4119 printf("HaltExp::semantic()\n");
4120 #endif
4121 type = Type::tvoid;
4122 return this;
4125 int HaltExp::checkSideEffect(int flag)
4127 return 1;
4130 void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4132 buf->writestring("halt");
4135 /************************************************************/
4137 IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
4138 Type *tspec, enum TOK tok2)
4139 : Expression(loc, TOKis, sizeof(IsExp))
4141 this->targ = targ;
4142 this->id = id;
4143 this->tok = tok;
4144 this->tspec = tspec;
4145 this->tok2 = tok2;
4148 Expression *IsExp::syntaxCopy()
4150 return new IsExp(loc,
4151 targ->syntaxCopy(),
4153 tok,
4154 tspec ? tspec->syntaxCopy() : NULL,
4155 tok2);
4158 Expression *IsExp::semantic(Scope *sc)
4159 { Type *tded;
4161 //printf("IsExp::semantic()\n");
4162 if (id && !(sc->flags & SCOPEstaticif))
4163 error("can only declare type aliases within static if conditionals");
4165 unsigned errors_save = global.errors;
4166 global.errors = 0;
4167 global.gag++; // suppress printing of error messages
4168 targ = targ->semantic(loc, sc);
4169 global.gag--;
4170 unsigned gerrors = global.errors;
4171 global.errors = errors_save;
4173 if (gerrors) // if any errors happened
4174 { // then condition is false
4175 goto Lno;
4177 else if (tok2 != TOKreserved)
4179 switch (tok2)
4181 case TOKtypedef:
4182 if (targ->ty != Ttypedef)
4183 goto Lno;
4184 tded = ((TypeTypedef *)targ)->sym->basetype;
4185 break;
4187 case TOKstruct:
4188 if (targ->ty != Tstruct)
4189 goto Lno;
4190 if (((TypeStruct *)targ)->sym->isUnionDeclaration())
4191 goto Lno;
4192 tded = targ;
4193 break;
4195 case TOKunion:
4196 if (targ->ty != Tstruct)
4197 goto Lno;
4198 if (!((TypeStruct *)targ)->sym->isUnionDeclaration())
4199 goto Lno;
4200 tded = targ;
4201 break;
4203 case TOKclass:
4204 if (targ->ty != Tclass)
4205 goto Lno;
4206 if (((TypeClass *)targ)->sym->isInterfaceDeclaration())
4207 goto Lno;
4208 tded = targ;
4209 break;
4211 case TOKinterface:
4212 if (targ->ty != Tclass)
4213 goto Lno;
4214 if (!((TypeClass *)targ)->sym->isInterfaceDeclaration())
4215 goto Lno;
4216 tded = targ;
4217 break;
4219 case TOKsuper:
4220 // If class or interface, get the base class and interfaces
4221 if (targ->ty != Tclass)
4222 goto Lno;
4223 else
4224 { ClassDeclaration *cd = ((TypeClass *)targ)->sym;
4225 Arguments *args = new Arguments;
4226 args->reserve(cd->baseclasses.dim);
4227 for (size_t i = 0; i < cd->baseclasses.dim; i++)
4228 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
4229 args->push(new Argument(STCin, b->type, NULL, NULL));
4231 tded = new TypeTuple(args);
4233 break;
4235 case TOKenum:
4236 if (targ->ty != Tenum)
4237 goto Lno;
4238 tded = ((TypeEnum *)targ)->sym->memtype;
4239 break;
4241 case TOKdelegate:
4242 if (targ->ty != Tdelegate)
4243 goto Lno;
4244 tded = targ->next; // the underlying function type
4245 break;
4247 case TOKfunction:
4248 { if (targ->ty != Tfunction)
4249 goto Lno;
4250 tded = targ;
4252 /* Generate tuple from function parameter types.
4254 assert(tded->ty == Tfunction);
4255 Arguments *params = ((TypeFunction *)tded)->parameters;
4256 size_t dim = Argument::dim(params);
4257 Arguments *args = new Arguments;
4258 args->reserve(dim);
4259 for (size_t i = 0; i < dim; i++)
4260 { Argument *arg = Argument::getNth(params, i);
4261 assert(arg && arg->type);
4262 args->push(new Argument(arg->storageClass, arg->type, NULL, NULL));
4264 tded = new TypeTuple(args);
4265 break;
4267 case TOKreturn:
4268 /* Get the 'return type' for the function,
4269 * delegate, or pointer to function.
4271 if (targ->ty == Tfunction)
4272 tded = targ->next;
4273 else if (targ->ty == Tdelegate)
4274 tded = targ->next->next;
4275 else if (targ->ty == Tpointer && targ->next->ty == Tfunction)
4276 tded = targ->next->next;
4277 else
4278 goto Lno;
4279 break;
4281 default:
4282 assert(0);
4284 goto Lyes;
4286 else if (id && tspec)
4288 /* Evaluate to TRUE if targ matches tspec.
4289 * If TRUE, declare id as an alias for the specialized type.
4292 MATCH m;
4293 TemplateTypeParameter tp(loc, id, NULL, NULL);
4295 TemplateParameters parameters;
4296 parameters.setDim(1);
4297 parameters.data[0] = (void *)&tp;
4299 Objects dedtypes;
4300 dedtypes.setDim(1);
4301 dedtypes.data[0] = NULL;
4303 m = targ->deduceType(NULL, tspec, &parameters, &dedtypes);
4304 if (m == MATCHnomatch ||
4305 (m != MATCHexact && tok == TOKequal))
4306 goto Lno;
4307 else
4309 assert(dedtypes.dim == 1);
4310 tded = (Type *)dedtypes.data[0];
4311 if (!tded)
4312 tded = targ;
4313 goto Lyes;
4316 else if (id)
4318 /* Declare id as an alias for type targ. Evaluate to TRUE
4320 tded = targ;
4321 goto Lyes;
4323 else if (tspec)
4325 /* Evaluate to TRUE if targ matches tspec
4327 tspec = tspec->semantic(loc, sc);
4328 //printf("targ = %s\n", targ->toChars());
4329 //printf("tspec = %s\n", tspec->toChars());
4330 if (tok == TOKcolon)
4331 { if (targ->implicitConvTo(tspec))
4332 goto Lyes;
4333 else
4334 goto Lno;
4336 else /* == */
4337 { if (targ->equals(tspec))
4338 goto Lyes;
4339 else
4340 goto Lno;
4344 Lyes:
4345 if (id)
4347 Dsymbol *s = new AliasDeclaration(loc, id, tded);
4348 s->semantic(sc);
4349 sc->insert(s);
4350 if (sc->sd)
4351 s->addMember(sc, sc->sd, 1);
4353 return new IntegerExp(1);
4355 Lno:
4356 return new IntegerExp(0);
4359 void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4361 buf->writestring("is(");
4362 targ->toCBuffer(buf, id, hgs);
4363 if (tok2 != TOKreserved)
4365 buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2));
4367 else if (tspec)
4369 if (tok == TOKcolon)
4370 buf->writestring(" : ");
4371 else
4372 buf->writestring(" == ");
4373 tspec->toCBuffer(buf, NULL, hgs);
4375 #if V2
4376 if (parameters)
4377 { // First parameter is already output, so start with second
4378 for (int i = 1; i < parameters->dim; i++)
4380 buf->writeByte(',');
4381 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
4382 tp->toCBuffer(buf, hgs);
4385 #endif
4386 buf->writeByte(')');
4390 /************************************************************/
4392 UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1)
4393 : Expression(loc, op, size)
4395 this->e1 = e1;
4398 Expression *UnaExp::syntaxCopy()
4399 { UnaExp *e;
4401 e = (UnaExp *)copy();
4402 e->type = NULL;
4403 e->e1 = e->e1->syntaxCopy();
4404 return e;
4407 Expression *UnaExp::semantic(Scope *sc)
4409 #if LOGSEMANTIC
4410 printf("UnaExp::semantic('%s')\n", toChars());
4411 #endif
4412 e1 = e1->semantic(sc);
4413 // if (!e1->type)
4414 // error("%s has no value", e1->toChars());
4415 return this;
4418 void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4420 buf->writestring(Token::toChars(op));
4421 expToCBuffer(buf, hgs, e1, precedence[op]);
4424 /************************************************************/
4426 BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2)
4427 : Expression(loc, op, size)
4429 this->e1 = e1;
4430 this->e2 = e2;
4433 Expression *BinExp::syntaxCopy()
4434 { BinExp *e;
4436 e = (BinExp *)copy();
4437 e->type = NULL;
4438 e->e1 = e->e1->syntaxCopy();
4439 e->e2 = e->e2->syntaxCopy();
4440 return e;
4443 Expression *BinExp::semantic(Scope *sc)
4445 #if LOGSEMANTIC
4446 printf("BinExp::semantic('%s')\n", toChars());
4447 #endif
4448 e1 = e1->semantic(sc);
4449 if (!e1->type)
4451 error("%s has no value", e1->toChars());
4452 e1->type = Type::terror;
4454 e2 = e2->semantic(sc);
4455 if (!e2->type)
4457 error("%s has no value", e2->toChars());
4458 e2->type = Type::terror;
4460 assert(e1->type);
4461 return this;
4464 Expression *BinExp::semanticp(Scope *sc)
4466 BinExp::semantic(sc);
4467 e1 = resolveProperties(sc, e1);
4468 e2 = resolveProperties(sc, e2);
4469 return this;
4472 /***************************
4473 * Common semantic routine for some xxxAssignExp's.
4476 Expression *BinExp::commonSemanticAssign(Scope *sc)
4477 { Expression *e;
4479 if (!type)
4481 BinExp::semantic(sc);
4482 e2 = resolveProperties(sc, e2);
4484 e = op_overload(sc);
4485 if (e)
4486 return e;
4488 e1 = e1->modifiableLvalue(sc, e1);
4489 e1->checkScalar();
4490 type = e1->type;
4491 if (type->toBasetype()->ty == Tbool)
4493 error("operator not allowed on bool expression %s", toChars());
4495 typeCombine(sc);
4496 e1->checkArithmetic();
4497 e2->checkArithmetic();
4499 if (op == TOKmodass && e2->type->iscomplex())
4500 { error("cannot perform modulo complex arithmetic");
4501 return new IntegerExp(0);
4504 return this;
4507 Expression *BinExp::commonSemanticAssignIntegral(Scope *sc)
4508 { Expression *e;
4510 if (!type)
4512 BinExp::semantic(sc);
4513 e2 = resolveProperties(sc, e2);
4515 e = op_overload(sc);
4516 if (e)
4517 return e;
4519 e1 = e1->modifiableLvalue(sc, e1);
4520 e1->checkScalar();
4521 type = e1->type;
4522 if (type->toBasetype()->ty == Tbool)
4524 e2 = e2->implicitCastTo(sc, type);
4527 typeCombine(sc);
4528 e1->checkIntegral();
4529 e2->checkIntegral();
4531 return this;
4534 int BinExp::checkSideEffect(int flag)
4536 if (op == TOKplusplus ||
4537 op == TOKminusminus ||
4538 op == TOKassign ||
4539 op == TOKconstruct ||
4540 op == TOKblit ||
4541 op == TOKaddass ||
4542 op == TOKminass ||
4543 op == TOKcatass ||
4544 op == TOKmulass ||
4545 op == TOKdivass ||
4546 op == TOKmodass ||
4547 op == TOKshlass ||
4548 op == TOKshrass ||
4549 op == TOKushrass ||
4550 op == TOKandass ||
4551 op == TOKorass ||
4552 op == TOKxorass ||
4553 op == TOKin ||
4554 op == TOKremove)
4555 return 1;
4556 return Expression::checkSideEffect(flag);
4559 void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4561 expToCBuffer(buf, hgs, e1, precedence[op]);
4562 buf->writeByte(' ');
4563 buf->writestring(Token::toChars(op));
4564 buf->writeByte(' ');
4565 expToCBuffer(buf, hgs, e2, (enum PREC)(precedence[op] + 1));
4568 int BinExp::isunsigned()
4570 return e1->type->isunsigned() || e2->type->isunsigned();
4573 void BinExp::incompatibleTypes()
4575 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
4576 e1->toChars(), Token::toChars(op), e2->toChars(),
4577 e1->type->toChars(), e2->type->toChars());
4580 /************************************************************/
4582 CompileExp::CompileExp(Loc loc, Expression *e)
4583 : UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
4587 Expression *CompileExp::semantic(Scope *sc)
4589 #if LOGSEMANTIC
4590 printf("CompileExp::semantic('%s')\n", toChars());
4591 #endif
4592 UnaExp::semantic(sc);
4593 e1 = resolveProperties(sc, e1);
4594 e1 = e1->optimize(WANTvalue | WANTinterpret);
4595 if (e1->op != TOKstring)
4596 { error("argument to mixin must be a string, not (%s)", e1->toChars());
4597 type = Type::terror;
4598 return this;
4600 StringExp *se = (StringExp *)e1;
4601 se = se->toUTF8(sc);
4602 Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
4603 p.loc = loc;
4604 p.nextToken();
4605 Expression *e = p.parseExpression();
4606 if (p.token.value != TOKeof)
4607 error("incomplete mixin expression (%s)", se->toChars());
4608 return e->semantic(sc);
4611 void CompileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4613 buf->writestring("mixin(");
4614 expToCBuffer(buf, hgs, e1, PREC_assign);
4615 buf->writeByte(')');
4618 /************************************************************/
4620 FileExp::FileExp(Loc loc, Expression *e)
4621 : UnaExp(loc, TOKmixin, sizeof(FileExp), e)
4625 Expression *FileExp::semantic(Scope *sc)
4626 { char *name;
4627 StringExp *se;
4629 #if LOGSEMANTIC
4630 printf("FileExp::semantic('%s')\n", toChars());
4631 #endif
4632 UnaExp::semantic(sc);
4633 e1 = resolveProperties(sc, e1);
4634 e1 = e1->optimize(WANTvalue);
4635 if (e1->op != TOKstring)
4636 { error("file name argument must be a string, not (%s)", e1->toChars());
4637 goto Lerror;
4639 se = (StringExp *)e1;
4640 se = se->toUTF8(sc);
4641 name = (char *)se->string;
4643 if (!global.params.fileImppath)
4644 { error("need -Jpath switch to import text file %s", name);
4645 goto Lerror;
4648 if (name != FileName::name(name))
4649 { error("use -Jpath switch to provide path for filename %s", name);
4650 goto Lerror;
4653 name = FileName::searchPath(global.filePath, name, 0);
4654 if (!name)
4655 { error("file %s cannot be found, check -Jpath", se->toChars());
4656 goto Lerror;
4659 if (global.params.verbose)
4660 printf("file %s\t(%s)\n", se->string, name);
4662 { File f(name);
4663 if (f.read())
4664 { error("cannot read file %s", f.toChars());
4665 goto Lerror;
4667 else
4669 f.ref = 1;
4670 se = new StringExp(loc, f.buffer, f.len);
4673 Lret:
4674 return se->semantic(sc);
4676 Lerror:
4677 se = new StringExp(loc, "");
4678 goto Lret;
4681 void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4683 buf->writestring("import(");
4684 expToCBuffer(buf, hgs, e1, PREC_assign);
4685 buf->writeByte(')');
4688 /************************************************************/
4690 AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg)
4691 : UnaExp(loc, TOKassert, sizeof(AssertExp), e)
4693 this->msg = msg;
4696 Expression *AssertExp::syntaxCopy()
4698 AssertExp *ae = new AssertExp(loc, e1->syntaxCopy(),
4699 msg ? msg->syntaxCopy() : NULL);
4700 return ae;
4703 Expression *AssertExp::semantic(Scope *sc)
4705 #if LOGSEMANTIC
4706 printf("AssertExp::semantic('%s')\n", toChars());
4707 #endif
4708 UnaExp::semantic(sc);
4709 e1 = resolveProperties(sc, e1);
4710 // BUG: see if we can do compile time elimination of the Assert
4711 e1 = e1->optimize(WANTvalue);
4712 e1 = e1->checkToBoolean();
4713 if (msg)
4715 msg = msg->semantic(sc);
4716 msg = resolveProperties(sc, msg);
4717 msg = msg->implicitCastTo(sc, Type::tchar->arrayOf());
4718 msg = msg->optimize(WANTvalue);
4720 if (e1->isBool(FALSE))
4722 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
4723 fd->hasReturnExp |= 4;
4725 if (!global.params.useAssert)
4726 { Expression *e = new HaltExp(loc);
4727 e = e->semantic(sc);
4728 return e;
4731 type = Type::tvoid;
4732 return this;
4735 int AssertExp::checkSideEffect(int flag)
4737 return 1;
4740 void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4742 buf->writestring("assert(");
4743 expToCBuffer(buf, hgs, e1, PREC_assign);
4744 if (msg)
4746 buf->writeByte(',');
4747 expToCBuffer(buf, hgs, msg, PREC_assign);
4749 buf->writeByte(')');
4752 /************************************************************/
4754 DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident)
4755 : UnaExp(loc, TOKdot, sizeof(DotIdExp), e)
4757 this->ident = ident;
4760 Expression *DotIdExp::semantic(Scope *sc)
4761 { Expression *e;
4762 Expression *eleft;
4763 Expression *eright;
4765 #if LOGSEMANTIC
4766 printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars());
4767 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
4768 #endif
4770 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
4772 #if 0
4773 /* Don't do semantic analysis if we'll be converting
4774 * it to a string.
4776 if (ident == Id::stringof)
4777 { char *s = e1->toChars();
4778 e = new StringExp(loc, s, strlen(s), 'c');
4779 e = e->semantic(sc);
4780 return e;
4782 #endif
4784 /* Special case: rewrite this.id and super.id
4785 * to be classtype.id and baseclasstype.id
4786 * if we have no this pointer.
4788 if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc))
4789 { ClassDeclaration *cd;
4790 StructDeclaration *sd;
4791 AggregateDeclaration *ad;
4793 ad = sc->getStructClassScope();
4794 if (ad)
4796 cd = ad->isClassDeclaration();
4797 if (cd)
4799 if (e1->op == TOKthis)
4801 e = new TypeDotIdExp(loc, cd->type, ident);
4802 return e->semantic(sc);
4804 else if (cd->baseClass && e1->op == TOKsuper)
4806 e = new TypeDotIdExp(loc, cd->baseClass->type, ident);
4807 return e->semantic(sc);
4810 else
4812 sd = ad->isStructDeclaration();
4813 if (sd)
4815 if (e1->op == TOKthis)
4817 e = new TypeDotIdExp(loc, sd->type, ident);
4818 return e->semantic(sc);
4825 UnaExp::semantic(sc);
4827 if (e1->op == TOKdotexp)
4829 DotExp *de = (DotExp *)e1;
4830 eleft = de->e1;
4831 eright = de->e2;
4833 else
4835 e1 = resolveProperties(sc, e1);
4836 eleft = NULL;
4837 eright = e1;
4840 if (e1->op == TOKtuple && ident == Id::length)
4842 TupleExp *te = (TupleExp *)e1;
4843 e = new IntegerExp(loc, te->exps->dim, Type::tsize_t);
4844 return e;
4847 if (eright->op == TOKimport) // also used for template alias's
4849 Dsymbol *s;
4850 ScopeExp *ie = (ScopeExp *)eright;
4852 s = ie->sds->search(loc, ident, 0);
4853 if (s)
4855 s = s->toAlias();
4856 checkDeprecated(sc, s);
4858 EnumMember *em = s->isEnumMember();
4859 if (em)
4861 e = em->value;
4862 e = e->semantic(sc);
4863 return e;
4866 VarDeclaration *v = s->isVarDeclaration();
4867 if (v)
4869 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
4870 if (v->inuse)
4872 error("circular reference to '%s'", v->toChars());
4873 type = Type::tint32;
4874 return this;
4876 type = v->type;
4877 if (v->isConst())
4879 if (v->init)
4881 ExpInitializer *ei = v->init->isExpInitializer();
4882 if (ei)
4884 //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars());
4885 //ei->exp = ei->exp->semantic(sc);
4886 if (ei->exp->type == type)
4888 e = ei->exp->copy(); // make copy so we can change loc
4889 e->loc = loc;
4890 return e;
4894 else if (type->isscalar())
4896 e = type->defaultInit();
4897 e->loc = loc;
4898 return e;
4901 if (v->needThis())
4903 if (!eleft)
4904 eleft = new ThisExp(loc);
4905 e = new DotVarExp(loc, eleft, v);
4906 e = e->semantic(sc);
4908 else
4910 e = new VarExp(loc, v);
4911 if (eleft)
4912 { e = new CommaExp(loc, eleft, e);
4913 e->type = v->type;
4916 return e->deref();
4919 FuncDeclaration *f = s->isFuncDeclaration();
4920 if (f)
4922 //printf("it's a function\n");
4923 if (f->needThis())
4925 if (!eleft)
4926 eleft = new ThisExp(loc);
4927 e = new DotVarExp(loc, eleft, f);
4928 e = e->semantic(sc);
4930 else
4932 e = new VarExp(loc, f);
4933 if (eleft)
4934 { e = new CommaExp(loc, eleft, e);
4935 e->type = f->type;
4938 return e;
4941 Type *t = s->getType();
4942 if (t)
4944 return new TypeExp(loc, t);
4947 TupleDeclaration *tup = s->isTupleDeclaration();
4948 if (tup)
4950 if (eleft)
4951 error("cannot have e.tuple");
4952 e = new TupleExp(loc, tup);
4953 e = e->semantic(sc);
4954 return e;
4957 ScopeDsymbol *sds = s->isScopeDsymbol();
4958 if (sds)
4960 //printf("it's a ScopeDsymbol\n");
4961 e = new ScopeExp(loc, sds);
4962 e = e->semantic(sc);
4963 if (eleft)
4964 e = new DotExp(loc, eleft, e);
4965 return e;
4968 Import *imp = s->isImport();
4969 if (imp)
4971 ScopeExp *ie;
4973 ie = new ScopeExp(loc, imp->pkg);
4974 return ie->semantic(sc);
4977 // BUG: handle other cases like in IdentifierExp::semantic()
4978 #ifdef DEBUG
4979 printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind());
4980 #endif
4981 assert(0);
4983 else if (ident == Id::stringof)
4984 { char *s = ie->toChars();
4985 e = new StringExp(loc, s, strlen(s), 'c');
4986 e = e->semantic(sc);
4987 return e;
4989 error("undefined identifier %s", toChars());
4990 type = Type::tvoid;
4991 return this;
4993 else if (e1->type->ty == Tpointer &&
4994 ident != Id::init && ident != Id::__sizeof &&
4995 ident != Id::alignof && ident != Id::offsetof &&
4996 ident != Id::mangleof && ident != Id::stringof)
4998 e = new PtrExp(loc, e1);
4999 e->type = e1->type->next;
5000 return e->type->dotExp(sc, e, ident);
5002 else
5004 e = e1->type->dotExp(sc, e1, ident);
5005 e = e->semantic(sc);
5006 return e;
5010 void DotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5012 //printf("DotIdExp::toCBuffer()\n");
5013 expToCBuffer(buf, hgs, e1, PREC_primary);
5014 buf->writeByte('.');
5015 buf->writestring(ident->toChars());
5018 /********************** DotTemplateExp ***********************************/
5020 // Mainly just a placeholder
5022 DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td)
5023 : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e)
5026 this->td = td;
5029 void DotTemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5031 expToCBuffer(buf, hgs, e1, PREC_primary);
5032 buf->writeByte('.');
5033 buf->writestring(td->toChars());
5037 /************************************************************/
5039 DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v)
5040 : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e)
5042 //printf("DotVarExp()\n");
5043 this->var = v;
5046 Expression *DotVarExp::semantic(Scope *sc)
5048 #if LOGSEMANTIC
5049 printf("DotVarExp::semantic('%s')\n", toChars());
5050 #endif
5051 if (!type)
5053 var = var->toAlias()->isDeclaration();
5055 TupleDeclaration *tup = var->isTupleDeclaration();
5056 if (tup)
5057 { /* Replace:
5058 * e1.tuple(a, b, c)
5059 * with:
5060 * tuple(e1.a, e1.b, e1.c)
5062 Expressions *exps = new Expressions;
5064 exps->reserve(tup->objects->dim);
5065 for (size_t i = 0; i < tup->objects->dim; i++)
5066 { Object *o = (Object *)tup->objects->data[i];
5067 if (o->dyncast() != DYNCAST_EXPRESSION)
5069 error("%s is not an expression", o->toChars());
5071 else
5073 Expression *e = (Expression *)o;
5074 if (e->op != TOKdsymbol)
5075 error("%s is not a member", e->toChars());
5076 else
5077 { DsymbolExp *ve = (DsymbolExp *)e;
5079 e = new DotVarExp(loc, e1, ve->s->isDeclaration());
5080 exps->push(e);
5084 Expression *e = new TupleExp(loc, exps);
5085 e = e->semantic(sc);
5086 return e;
5089 e1 = e1->semantic(sc);
5090 type = var->type;
5091 if (!type && global.errors)
5092 { // var is goofed up, just return 0
5093 return new IntegerExp(0);
5095 assert(type);
5097 if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution
5099 AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration();
5100 e1 = getRightThis(loc, sc, ad, e1, var);
5101 accessCheck(loc, sc, e1, var);
5104 //printf("-DotVarExp::semantic('%s')\n", toChars());
5105 return this;
5108 Expression *DotVarExp::toLvalue(Scope *sc, Expression *e)
5110 //printf("DotVarExp::toLvalue(%s)\n", toChars());
5111 return this;
5114 Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
5116 //printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
5118 // Also need this for non-null fields.
5119 VarDeclaration *v = var->isVarDeclaration();
5120 if (v) // When is it not a VarDeclaration?
5121 v->ctorinit = 1;
5122 else
5123 error("Just curious");
5125 if (var->isCtorinit())
5126 { // It's only modifiable if inside the right constructor
5127 Dsymbol *s = sc->func;
5128 while (1)
5130 FuncDeclaration *fd = NULL;
5131 if (s)
5132 fd = s->isFuncDeclaration();
5133 if (fd &&
5134 ((fd->isCtorDeclaration() && var->storage_class & STCfield) ||
5135 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) &&
5136 fd->toParent() == var->toParent() &&
5137 e1->op == TOKthis
5140 VarDeclaration *v = var->isVarDeclaration();
5141 assert(v);
5142 v->ctorinit = 1;
5143 //printf("setting ctorinit\n");
5145 else
5147 if (s)
5148 { s = s->toParent2();
5149 continue;
5151 else
5153 const char *p = var->isStatic() ? "static " : "";
5154 error("can only initialize %sconst member %s inside %sconstructor",
5155 p, var->toChars(), p);
5158 break;
5161 return this;
5164 void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5166 expToCBuffer(buf, hgs, e1, PREC_primary);
5167 buf->writeByte('.');
5168 buf->writestring(var->toChars());
5171 /************************************************************/
5173 /* Things like:
5174 * foo.bar!(args)
5177 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti)
5178 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e)
5180 //printf("DotTemplateInstanceExp()\n");
5181 this->ti = ti;
5184 Expression *DotTemplateInstanceExp::syntaxCopy()
5186 DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc,
5187 e1->syntaxCopy(),
5188 (TemplateInstance *)ti->syntaxCopy(NULL));
5189 return de;
5192 Expression *DotTemplateInstanceExp::semantic(Scope *sc)
5193 { Dsymbol *s;
5194 Dsymbol *s2;
5195 TemplateDeclaration *td;
5196 Expression *e;
5197 Identifier *id;
5198 Type *t1;
5199 Expression *eleft = NULL;
5200 Expression *eright;
5202 #if LOGSEMANTIC
5203 printf("DotTemplateInstanceExp::semantic('%s')\n", toChars());
5204 #endif
5205 //e1->print();
5206 //print();
5207 e1 = e1->semantic(sc);
5208 t1 = e1->type;
5209 if (t1)
5210 t1 = t1->toBasetype();
5211 //t1->print();
5212 if (e1->op == TOKdotexp)
5213 { DotExp *de = (DotExp *)e1;
5214 eleft = de->e1;
5215 eright = de->e2;
5217 else
5218 { eleft = NULL;
5219 eright = e1;
5221 if (eright->op == TOKimport)
5223 s = ((ScopeExp *)eright)->sds;
5225 else if (e1->op == TOKtype)
5227 s = t1->isClassHandle();
5228 if (!s)
5229 { if (t1->ty == Tstruct)
5230 s = ((TypeStruct *)t1)->sym;
5231 else
5232 goto L1;
5235 else if (t1 && (t1->ty == Tstruct || t1->ty == Tclass))
5237 s = t1->toDsymbol(sc);
5238 eleft = e1;
5240 else if (t1 && t1->ty == Tpointer)
5242 t1 = t1->next->toBasetype();
5243 if (t1->ty != Tstruct)
5244 goto L1;
5245 s = t1->toDsymbol(sc);
5246 eleft = e1;
5248 else
5251 error("template %s is not a member of %s", ti->toChars(), e1->toChars());
5252 goto Lerr;
5255 assert(s);
5256 id = ti->name;
5257 s2 = s->search(loc, id, 0);
5258 if (!s2)
5259 { error("template identifier %s is not a member of %s %s", id->toChars(), s->kind(), s->ident->toChars());
5260 goto Lerr;
5262 s = s2;
5263 s->semantic(sc);
5264 s = s->toAlias();
5265 td = s->isTemplateDeclaration();
5266 if (!td)
5268 error("%s is not a template", id->toChars());
5269 goto Lerr;
5271 if (global.errors)
5272 goto Lerr;
5274 ti->tempdecl = td;
5276 if (eleft)
5277 { Declaration *v;
5279 ti->semantic(sc);
5280 s = ti->inst->toAlias();
5281 v = s->isDeclaration();
5282 if (v)
5283 { e = new DotVarExp(loc, eleft, v);
5284 e = e->semantic(sc);
5285 return e;
5289 e = new ScopeExp(loc, ti);
5290 if (eleft)
5292 e = new DotExp(loc, eleft, e);
5294 e = e->semantic(sc);
5295 return e;
5297 Lerr:
5298 return new IntegerExp(0);
5301 void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5303 expToCBuffer(buf, hgs, e1, PREC_primary);
5304 buf->writeByte('.');
5305 ti->toCBuffer(buf, hgs);
5308 /************************************************************/
5310 DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f)
5311 : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
5313 this->func = f;
5316 Expression *DelegateExp::semantic(Scope *sc)
5318 #if LOGSEMANTIC
5319 printf("DelegateExp::semantic('%s')\n", toChars());
5320 #endif
5321 if (!type)
5323 e1 = e1->semantic(sc);
5324 type = new TypeDelegate(func->type);
5325 type = type->semantic(loc, sc);
5326 AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration();
5327 if (func->needThis())
5328 e1 = getRightThis(loc, sc, ad, e1, func);
5330 return this;
5333 void DelegateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5335 buf->writeByte('&');
5336 if (!func->isNested())
5338 expToCBuffer(buf, hgs, e1, PREC_primary);
5339 buf->writeByte('.');
5341 buf->writestring(func->toChars());
5344 /************************************************************/
5346 DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s)
5347 : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e)
5349 this->sym = s;
5350 this->type = s->getType();
5353 Expression *DotTypeExp::semantic(Scope *sc)
5355 #if LOGSEMANTIC
5356 printf("DotTypeExp::semantic('%s')\n", toChars());
5357 #endif
5358 UnaExp::semantic(sc);
5359 return this;
5362 void DotTypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5364 expToCBuffer(buf, hgs, e1, PREC_primary);
5365 buf->writeByte('.');
5366 buf->writestring(sym->toChars());
5369 /************************************************************/
5371 CallExp::CallExp(Loc loc, Expression *e, Expressions *exps)
5372 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5374 this->arguments = exps;
5377 CallExp::CallExp(Loc loc, Expression *e)
5378 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5380 this->arguments = NULL;
5383 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1)
5384 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5386 Expressions *arguments = new Expressions();
5387 arguments->setDim(1);
5388 arguments->data[0] = (void *)earg1;
5390 this->arguments = arguments;
5393 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2)
5394 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5396 Expressions *arguments = new Expressions();
5397 arguments->setDim(2);
5398 arguments->data[0] = (void *)earg1;
5399 arguments->data[1] = (void *)earg2;
5401 this->arguments = arguments;
5404 Expression *CallExp::syntaxCopy()
5406 return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
5410 Expression *CallExp::semantic(Scope *sc)
5412 TypeFunction *tf;
5413 FuncDeclaration *f;
5414 int i;
5415 Type *t1;
5416 int istemp;
5418 #if LOGSEMANTIC
5419 printf("CallExp::semantic() %s\n", toChars());
5420 #endif
5421 if (type)
5422 return this; // semantic() already run
5423 #if 0
5424 if (arguments && arguments->dim)
5426 Expression *earg = (Expression *)arguments->data[0];
5427 earg->print();
5428 if (earg->type) earg->type->print();
5430 #endif
5432 if (e1->op == TOKdelegate)
5433 { DelegateExp *de = (DelegateExp *)e1;
5435 e1 = new DotVarExp(de->loc, de->e1, de->func);
5436 return semantic(sc);
5439 /* Transform:
5440 * array.id(args) into id(array,args)
5441 * aa.remove(arg) into delete aa[arg]
5443 if (e1->op == TOKdot)
5445 // BUG: we should handle array.a.b.c.e(args) too
5447 DotIdExp *dotid = (DotIdExp *)(e1);
5448 dotid->e1 = dotid->e1->semantic(sc);
5449 assert(dotid->e1);
5450 if (dotid->e1->type)
5452 TY e1ty = dotid->e1->type->toBasetype()->ty;
5453 if (e1ty == Taarray && dotid->ident == Id::remove)
5455 if (!arguments || arguments->dim != 1)
5456 { error("expected key as argument to aa.remove()");
5457 goto Lagain;
5459 Expression *key = (Expression *)arguments->data[0];
5460 key = key->semantic(sc);
5461 key = resolveProperties(sc, key);
5462 key->rvalue();
5464 TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype();
5465 key = key->implicitCastTo(sc, taa->index);
5466 key = key->implicitCastTo(sc, taa->key);
5468 return new RemoveExp(loc, dotid->e1, key);
5470 else if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray)
5472 if (!arguments)
5473 arguments = new Expressions();
5474 arguments->shift(dotid->e1);
5475 e1 = new IdentifierExp(dotid->loc, dotid->ident);
5480 istemp = 0;
5481 Lagain:
5482 f = NULL;
5483 if (e1->op == TOKthis || e1->op == TOKsuper)
5485 // semantic() run later for these
5487 else
5489 UnaExp::semantic(sc);
5491 /* Look for e1 being a lazy parameter
5493 if (e1->op == TOKvar)
5494 { VarExp *ve = (VarExp *)e1;
5496 if (ve->var->storage_class & STClazy)
5498 TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd);
5499 TypeDelegate *t = new TypeDelegate(tf);
5500 ve->type = t->semantic(loc, sc);
5504 if (e1->op == TOKimport)
5505 { // Perhaps this should be moved to ScopeExp::semantic()
5506 ScopeExp *se = (ScopeExp *)e1;
5507 e1 = new DsymbolExp(loc, se->sds);
5508 e1 = e1->semantic(sc);
5510 #if 1 // patch for #540 by Oskar Linde
5511 else if (e1->op == TOKdotexp)
5513 DotExp *de = (DotExp *) e1;
5515 if (de->e2->op == TOKimport)
5516 { // This should *really* be moved to ScopeExp::semantic()
5517 ScopeExp *se = (ScopeExp *)de->e2;
5518 de->e2 = new DsymbolExp(loc, se->sds);
5519 de->e2 = de->e2->semantic(sc);
5522 if (de->e2->op == TOKtemplate)
5523 { TemplateExp *te = (TemplateExp *) de->e2;
5524 e1 = new DotTemplateExp(loc,de->e1,te->td);
5527 #endif
5530 if (e1->op == TOKcomma)
5532 CommaExp *ce = (CommaExp *)e1;
5534 e1 = ce->e2;
5535 e1->type = ce->type;
5536 ce->e2 = this;
5537 ce->type = NULL;
5538 return ce->semantic(sc);
5541 t1 = NULL;
5542 if (e1->type)
5543 t1 = e1->type->toBasetype();
5545 // Check for call operator overload
5546 if (t1)
5547 { AggregateDeclaration *ad;
5549 if (t1->ty == Tstruct)
5551 ad = ((TypeStruct *)t1)->sym;
5552 if (search_function(ad, Id::call))
5553 goto L1; // overload of opCall, therefore it's a call
5555 if (e1->op != TOKtype)
5556 error("%s %s does not overload ()", ad->kind(), ad->toChars());
5557 /* It's a struct literal
5559 Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments);
5560 e = e->semantic(sc);
5561 e->type = e1->type; // in case e1->type was a typedef
5562 return e;
5564 else if (t1->ty == Tclass)
5566 ad = ((TypeClass *)t1)->sym;
5567 goto L1;
5569 // Rewrite as e1.call(arguments)
5570 Expression *e = new DotIdExp(loc, e1, Id::call);
5571 e = new CallExp(loc, e, arguments);
5572 e = e->semantic(sc);
5573 return e;
5577 arrayExpressionSemantic(arguments, sc);
5578 preFunctionArguments(loc, sc, arguments);
5580 if (e1->op == TOKdotvar && t1->ty == Tfunction ||
5581 e1->op == TOKdottd)
5583 DotVarExp *dve;
5584 DotTemplateExp *dte;
5585 AggregateDeclaration *ad;
5586 UnaExp *ue = (UnaExp *)(e1);
5588 if (e1->op == TOKdotvar)
5589 { // Do overload resolution
5590 dve = (DotVarExp *)(e1);
5592 f = dve->var->isFuncDeclaration();
5593 assert(f);
5594 f = f->overloadResolve(loc, arguments);
5596 ad = f->toParent()->isAggregateDeclaration();
5598 else
5599 { dte = (DotTemplateExp *)(e1);
5600 TemplateDeclaration *td = dte->td;
5601 assert(td);
5602 if (!arguments)
5603 // Should fix deduceFunctionTemplate() so it works on NULL argument
5604 arguments = new Expressions();
5605 f = td->deduceFunctionTemplate(sc, loc, NULL, arguments);
5606 if (!f)
5607 { type = Type::terror;
5608 return this;
5610 ad = td->toParent()->isAggregateDeclaration();
5612 if (f->needThis())
5613 ue->e1 = getRightThis(loc, sc, ad, ue->e1, f);
5615 checkDeprecated(sc, f);
5616 accessCheck(loc, sc, ue->e1, f);
5617 if (!f->needThis())
5619 VarExp *ve = new VarExp(loc, f);
5620 e1 = new CommaExp(loc, ue->e1, ve);
5621 e1->type = f->type;
5623 else
5625 if (e1->op == TOKdotvar)
5626 dve->var = f;
5627 else
5628 e1 = new DotVarExp(loc, dte->e1, f);
5629 e1->type = f->type;
5631 // See if we need to adjust the 'this' pointer
5632 AggregateDeclaration *ad = f->isThis();
5633 ClassDeclaration *cd = ue->e1->type->isClassHandle();
5634 if (ad && cd && ad->isClassDeclaration() && ad != cd &&
5635 ue->e1->op != TOKsuper)
5637 ue->e1 = ue->e1->castTo(sc, ad->type); //new CastExp(loc, ue->e1, ad->type);
5638 ue->e1 = ue->e1->semantic(sc);
5641 t1 = e1->type;
5643 else if (e1->op == TOKsuper)
5645 // Base class constructor call
5646 ClassDeclaration *cd = NULL;
5648 if (sc->func)
5649 cd = sc->func->toParent()->isClassDeclaration();
5650 if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration())
5652 error("super class constructor call must be in a constructor");
5653 type = Type::terror;
5654 return this;
5656 else
5658 f = cd->baseClass->ctor;
5659 if (!f)
5660 { error("no super class constructor for %s", cd->baseClass->toChars());
5661 type = Type::terror;
5662 return this;
5664 else
5666 #if 0
5667 if (sc->callSuper & (CSXthis | CSXsuper))
5668 error("reference to this before super()");
5669 #endif
5670 if (sc->noctor || sc->callSuper & CSXlabel)
5671 error("constructor calls not allowed in loops or after labels");
5672 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
5673 error("multiple constructor calls");
5674 sc->callSuper |= CSXany_ctor | CSXsuper_ctor;
5676 f = f->overloadResolve(loc, arguments);
5677 checkDeprecated(sc, f);
5678 e1 = new DotVarExp(e1->loc, e1, f);
5679 e1 = e1->semantic(sc);
5680 t1 = e1->type;
5684 else if (e1->op == TOKthis)
5686 // same class constructor call
5687 ClassDeclaration *cd = NULL;
5689 if (sc->func)
5690 cd = sc->func->toParent()->isClassDeclaration();
5691 if (!cd || !sc->func->isCtorDeclaration())
5693 error("class constructor call must be in a constructor");
5694 type = Type::terror;
5695 return this;
5697 else
5699 #if 0
5700 if (sc->callSuper & (CSXthis | CSXsuper))
5701 error("reference to this before super()");
5702 #endif
5703 if (sc->noctor || sc->callSuper & CSXlabel)
5704 error("constructor calls not allowed in loops or after labels");
5705 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
5706 error("multiple constructor calls");
5707 sc->callSuper |= CSXany_ctor | CSXthis_ctor;
5709 f = cd->ctor;
5710 f = f->overloadResolve(loc, arguments);
5711 checkDeprecated(sc, f);
5712 e1 = new DotVarExp(e1->loc, e1, f);
5713 e1 = e1->semantic(sc);
5714 t1 = e1->type;
5716 // BUG: this should really be done by checking the static
5717 // call graph
5718 if (f == sc->func)
5719 error("cyclic constructor call");
5722 else if (!t1)
5724 error("function expected before (), not '%s'", e1->toChars());
5725 type = Type::terror;
5726 return this;
5728 else if (t1->ty != Tfunction)
5730 if (t1->ty == Tdelegate)
5732 assert(t1->next->ty == Tfunction);
5733 tf = (TypeFunction *)(t1->next);
5734 goto Lcheckargs;
5736 else if (t1->ty == Tpointer && t1->next->ty == Tfunction)
5737 { Expression *e;
5739 e = new PtrExp(loc, e1);
5740 t1 = t1->next;
5741 e->type = t1;
5742 e1 = e;
5744 else if (e1->op == TOKtemplate)
5746 TemplateExp *te = (TemplateExp *)e1;
5747 f = te->td->deduceFunctionTemplate(sc, loc, NULL, arguments);
5748 if (!f)
5749 { type = Type::terror;
5750 return this;
5752 if (f->needThis() && hasThis(sc))
5754 // Supply an implicit 'this', as in
5755 // this.ident
5757 e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td);
5758 goto Lagain;
5761 e1 = new VarExp(loc, f);
5762 goto Lagain;
5764 else
5765 { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars());
5766 type = Type::terror;
5767 return this;
5770 else if (e1->op == TOKvar)
5772 // Do overload resolution
5773 VarExp *ve = (VarExp *)e1;
5775 f = ve->var->isFuncDeclaration();
5776 assert(f);
5778 // Look to see if f is really a function template
5779 if (0 && !istemp && f->parent)
5780 { TemplateInstance *ti = f->parent->isTemplateInstance();
5782 if (ti &&
5783 (ti->name == f->ident ||
5784 ti->toAlias()->ident == f->ident)
5786 ti->tempdecl)
5788 /* This is so that one can refer to the enclosing
5789 * template, even if it has the same name as a member
5790 * of the template, if it has a !(arguments)
5792 TemplateDeclaration *tempdecl = ti->tempdecl;
5793 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's
5794 tempdecl = tempdecl->overroot; // then get the start
5795 e1 = new TemplateExp(loc, tempdecl);
5796 istemp = 1;
5797 goto Lagain;
5801 f = f->overloadResolve(loc, arguments);
5802 checkDeprecated(sc, f);
5804 if (f->needThis() && hasThis(sc))
5806 // Supply an implicit 'this', as in
5807 // this.ident
5809 e1 = new DotVarExp(loc, new ThisExp(loc), f);
5810 goto Lagain;
5813 accessCheck(loc, sc, NULL, f);
5815 ve->var = f;
5816 ve->type = f->type;
5817 t1 = f->type;
5819 assert(t1->ty == Tfunction);
5820 tf = (TypeFunction *)(t1);
5822 Lcheckargs:
5823 assert(tf->ty == Tfunction);
5824 type = tf->next;
5826 if (!arguments)
5827 arguments = new Expressions();
5828 functionArguments(loc, sc, tf, arguments);
5830 assert(type);
5832 if (f && f->tintro)
5834 Type *t = type;
5835 target_ptrdiff_t offset = 0;
5837 if (f->tintro->next->isBaseOf(t, &offset) && offset)
5839 type = f->tintro->next;
5840 return castTo(sc, t);
5844 return this;
5847 int CallExp::checkSideEffect(int flag)
5849 return 1;
5852 Expression *CallExp::toLvalue(Scope *sc, Expression *e)
5854 if (type->toBasetype()->ty == Tstruct)
5855 return this;
5856 else
5857 return Expression::toLvalue(sc, e);
5860 void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5861 { int i;
5863 expToCBuffer(buf, hgs, e1, precedence[op]);
5864 buf->writeByte('(');
5865 argsToCBuffer(buf, arguments, hgs);
5866 buf->writeByte(')');
5870 /************************************************************/
5872 AddrExp::AddrExp(Loc loc, Expression *e)
5873 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e)
5877 Expression *AddrExp::semantic(Scope *sc)
5879 #if LOGSEMANTIC
5880 printf("AddrExp::semantic('%s')\n", toChars());
5881 #endif
5882 if (!type)
5884 UnaExp::semantic(sc);
5885 e1 = e1->toLvalue(sc, NULL);
5886 if (!e1->type)
5888 error("cannot take address of %s", e1->toChars());
5889 type = Type::tint32;
5890 return this;
5892 type = e1->type->pointerTo();
5894 // See if this should really be a delegate
5895 if (e1->op == TOKdotvar)
5897 DotVarExp *dve = (DotVarExp *)e1;
5898 FuncDeclaration *f = dve->var->isFuncDeclaration();
5900 if (f)
5901 { Expression *e;
5903 e = new DelegateExp(loc, dve->e1, f);
5904 e = e->semantic(sc);
5905 return e;
5908 else if (e1->op == TOKvar)
5910 VarExp *dve = (VarExp *)e1;
5911 FuncDeclaration *f = dve->var->isFuncDeclaration();
5913 if (f && f->isNested())
5914 { Expression *e;
5916 e = new DelegateExp(loc, e1, f);
5917 e = e->semantic(sc);
5918 return e;
5921 else if (e1->op == TOKarray)
5923 if (e1->type->toBasetype()->ty == Tbit)
5924 error("cannot take address of bit in array");
5926 return optimize(WANTvalue);
5928 return this;
5931 /************************************************************/
5933 PtrExp::PtrExp(Loc loc, Expression *e)
5934 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
5936 if (e->type)
5937 type = e->type->next;
5940 PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
5941 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
5943 type = t;
5946 Expression *PtrExp::semantic(Scope *sc)
5947 { Type *tb;
5949 #if LOGSEMANTIC
5950 printf("PtrExp::semantic('%s')\n", toChars());
5951 #endif
5952 UnaExp::semantic(sc);
5953 e1 = resolveProperties(sc, e1);
5954 if (type)
5955 return this;
5956 if (!e1->type)
5957 printf("PtrExp::semantic('%s')\n", toChars());
5958 tb = e1->type->toBasetype();
5959 switch (tb->ty)
5961 case Tpointer:
5962 type = tb->next;
5963 if (type->isbit())
5964 { Expression *e;
5966 // Rewrite *p as p[0]
5967 e = new IndexExp(loc, e1, new IntegerExp(0));
5968 return e->semantic(sc);
5970 break;
5972 case Tsarray:
5973 case Tarray:
5974 type = tb->next;
5975 e1 = e1->castTo(sc, type->pointerTo());
5976 break;
5978 default:
5979 error("can only * a pointer, not a '%s'", e1->type->toChars());
5980 type = Type::tint32;
5981 break;
5983 rvalue();
5984 return this;
5987 Expression *PtrExp::toLvalue(Scope *sc, Expression *e)
5989 #if 0
5990 tym = tybasic(e1->ET->Tty);
5991 if (!(tyscalar(tym) ||
5992 tym == TYstruct ||
5993 tym == TYarray && e->Eoper == TOKaddr))
5994 synerr(EM_lvalue); // lvalue expected
5995 #endif
5996 return this;
5999 void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6001 buf->writeByte('*');
6002 expToCBuffer(buf, hgs, e1, precedence[op]);
6005 /************************************************************/
6007 NegExp::NegExp(Loc loc, Expression *e)
6008 : UnaExp(loc, TOKneg, sizeof(NegExp), e)
6012 Expression *NegExp::semantic(Scope *sc)
6013 { Expression *e;
6015 #if LOGSEMANTIC
6016 printf("NegExp::semantic('%s')\n", toChars());
6017 #endif
6018 if (!type)
6020 UnaExp::semantic(sc);
6021 e1 = resolveProperties(sc, e1);
6022 e = op_overload(sc);
6023 if (e)
6024 return e;
6026 e1->checkNoBool();
6027 e1->checkArithmetic();
6028 type = e1->type;
6030 return this;
6033 /************************************************************/
6035 UAddExp::UAddExp(Loc loc, Expression *e)
6036 : UnaExp(loc, TOKuadd, sizeof(UAddExp), e)
6040 Expression *UAddExp::semantic(Scope *sc)
6041 { Expression *e;
6043 #if LOGSEMANTIC
6044 printf("UAddExp::semantic('%s')\n", toChars());
6045 #endif
6046 assert(!type);
6047 UnaExp::semantic(sc);
6048 e1 = resolveProperties(sc, e1);
6049 e = op_overload(sc);
6050 if (e)
6051 return e;
6052 e1->checkNoBool();
6053 e1->checkArithmetic();
6054 return e1;
6057 /************************************************************/
6059 ComExp::ComExp(Loc loc, Expression *e)
6060 : UnaExp(loc, TOKtilde, sizeof(ComExp), e)
6064 Expression *ComExp::semantic(Scope *sc)
6065 { Expression *e;
6067 if (!type)
6069 UnaExp::semantic(sc);
6070 e1 = resolveProperties(sc, e1);
6071 e = op_overload(sc);
6072 if (e)
6073 return e;
6075 e1->checkNoBool();
6076 e1 = e1->checkIntegral();
6077 type = e1->type;
6079 return this;
6082 /************************************************************/
6084 NotExp::NotExp(Loc loc, Expression *e)
6085 : UnaExp(loc, TOKnot, sizeof(NotExp), e)
6089 Expression *NotExp::semantic(Scope *sc)
6091 UnaExp::semantic(sc);
6092 e1 = resolveProperties(sc, e1);
6093 e1 = e1->checkToBoolean();
6094 type = Type::tboolean;
6095 return this;
6098 int NotExp::isBit()
6100 return TRUE;
6105 /************************************************************/
6107 BoolExp::BoolExp(Loc loc, Expression *e, Type *t)
6108 : UnaExp(loc, TOKtobool, sizeof(BoolExp), e)
6110 type = t;
6113 Expression *BoolExp::semantic(Scope *sc)
6115 UnaExp::semantic(sc);
6116 e1 = resolveProperties(sc, e1);
6117 e1 = e1->checkToBoolean();
6118 type = Type::tboolean;
6119 return this;
6122 int BoolExp::isBit()
6124 return TRUE;
6127 /************************************************************/
6129 DeleteExp::DeleteExp(Loc loc, Expression *e)
6130 : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e)
6134 Expression *DeleteExp::semantic(Scope *sc)
6136 Type *tb;
6138 UnaExp::semantic(sc);
6139 e1 = resolveProperties(sc, e1);
6140 e1 = e1->toLvalue(sc, NULL);
6141 type = Type::tvoid;
6143 tb = e1->type->toBasetype();
6144 switch (tb->ty)
6145 { case Tclass:
6146 { TypeClass *tc = (TypeClass *)tb;
6147 ClassDeclaration *cd = tc->sym;
6149 if (cd->isCOMinterface())
6150 { /* Because COM classes are deleted by IUnknown.Release()
6152 error("cannot delete instance of COM interface %s", cd->toChars());
6154 break;
6156 case Tpointer:
6157 tb = tb->next->toBasetype();
6158 if (tb->ty == Tstruct)
6160 TypeStruct *ts = (TypeStruct *)tb;
6161 StructDeclaration *sd = ts->sym;
6162 FuncDeclaration *f = sd->aggDelete;
6164 if (f)
6166 Type *tpv = Type::tvoid->pointerTo();
6168 Expression *e = e1->castTo(sc, tpv);
6169 Expression *ec = new VarExp(loc, f);
6170 e = new CallExp(loc, ec, e);
6171 return e->semantic(sc);
6174 break;
6176 case Tarray:
6177 break;
6179 default:
6180 if (e1->op == TOKindex)
6182 IndexExp *ae = (IndexExp *)(e1);
6183 Type *tb1 = ae->e1->type->toBasetype();
6184 if (tb1->ty == Taarray)
6185 break;
6187 error("cannot delete type %s", e1->type->toChars());
6188 break;
6191 if (e1->op == TOKindex)
6193 IndexExp *ae = (IndexExp *)(e1);
6194 Type *tb1 = ae->e1->type->toBasetype();
6195 if (tb1->ty == Taarray)
6196 { if (!global.params.useDeprecated)
6197 error("delete aa[key] deprecated, use aa.remove(key)");
6201 return this;
6204 int DeleteExp::checkSideEffect(int flag)
6206 return 1;
6209 Expression *DeleteExp::checkToBoolean()
6211 error("delete does not give a boolean result");
6212 return this;
6215 void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6217 buf->writestring("delete ");
6218 expToCBuffer(buf, hgs, e1, precedence[op]);
6221 /************************************************************/
6223 CastExp::CastExp(Loc loc, Expression *e, Type *t)
6224 : UnaExp(loc, TOKcast, sizeof(CastExp), e)
6226 to = t;
6229 Expression *CastExp::syntaxCopy()
6231 return new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy());
6235 Expression *CastExp::semantic(Scope *sc)
6236 { Expression *e;
6237 BinExp *b;
6238 UnaExp *u;
6240 #if LOGSEMANTIC
6241 printf("CastExp::semantic('%s')\n", toChars());
6242 #endif
6244 //static int x; assert(++x < 10);
6246 if (type)
6247 return this;
6248 UnaExp::semantic(sc);
6249 if (e1->type) // if not a tuple
6251 e1 = resolveProperties(sc, e1);
6252 to = to->semantic(loc, sc);
6254 e = op_overload(sc);
6255 if (e)
6257 return e->implicitCastTo(sc, to);
6260 Type *tob = to->toBasetype();
6261 if (tob->ty == Tstruct &&
6262 !tob->equals(e1->type->toBasetype()) &&
6263 ((TypeStruct *)to)->sym->search(0, Id::call, 0)
6266 /* Look to replace:
6267 * cast(S)t
6268 * with:
6269 * S(t)
6272 // Rewrite as to.call(e1)
6273 e = new TypeExp(loc, to);
6274 e = new DotIdExp(loc, e, Id::call);
6275 e = new CallExp(loc, e, e1);
6276 e = e->semantic(sc);
6277 return e;
6280 e = e1->castTo(sc, to->maybe());
6281 return e;
6284 int CastExp::checkSideEffect(int flag)
6286 /* if not:
6287 * cast(void)
6288 * cast(classtype)func()
6290 if (!to->equals(Type::tvoid) &&
6291 !(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass))
6292 return Expression::checkSideEffect(flag);
6293 return 1;
6296 void CastExp::checkEscape()
6297 { Type *tb = type->toBasetype();
6298 if (tb->ty == Tarray && e1->op == TOKvar &&
6299 e1->type->toBasetype()->ty == Tsarray)
6300 { VarExp *ve = (VarExp *)e1;
6301 VarDeclaration *v = ve->var->isVarDeclaration();
6302 if (v)
6304 if (!v->isDataseg() && !v->isParameter())
6305 error("escaping reference to local %s", v->toChars());
6310 void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6312 buf->writestring("cast(");
6313 to->toCBuffer(buf, NULL, hgs);
6314 buf->writeByte(')');
6315 expToCBuffer(buf, hgs, e1, precedence[op]);
6319 /************************************************************/
6321 SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr)
6322 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1)
6324 this->upr = upr;
6325 this->lwr = lwr;
6326 lengthVar = NULL;
6329 Expression *SliceExp::syntaxCopy()
6331 Expression *lwr = NULL;
6332 if (this->lwr)
6333 lwr = this->lwr->syntaxCopy();
6335 Expression *upr = NULL;
6336 if (this->upr)
6337 upr = this->upr->syntaxCopy();
6339 return new SliceExp(loc, e1->syntaxCopy(), lwr, upr);
6342 Expression *SliceExp::semantic(Scope *sc)
6343 { Expression *e;
6344 AggregateDeclaration *ad;
6345 //FuncDeclaration *fd;
6346 ScopeDsymbol *sym;
6348 #if LOGSEMANTIC
6349 printf("SliceExp::semantic('%s')\n", toChars());
6350 #endif
6351 if (type)
6352 return this;
6354 UnaExp::semantic(sc);
6355 e1 = resolveProperties(sc, e1);
6357 e = this;
6359 Type *t = e1->type->toBasetype();
6360 if (t->ty == Tpointer)
6362 if (!lwr || !upr)
6363 error("need upper and lower bound to slice pointer");
6365 else if (t->ty == Tarray)
6368 else if (t->ty == Tsarray)
6371 else if (t->ty == Tclass)
6373 ad = ((TypeClass *)t)->sym;
6374 goto L1;
6376 else if (t->ty == Tstruct)
6378 ad = ((TypeStruct *)t)->sym;
6381 if (search_function(ad, Id::slice))
6383 // Rewrite as e1.slice(lwr, upr)
6384 e = new DotIdExp(loc, e1, Id::slice);
6386 if (lwr)
6388 assert(upr);
6389 e = new CallExp(loc, e, lwr, upr);
6391 else
6392 { assert(!upr);
6393 e = new CallExp(loc, e);
6395 e = e->semantic(sc);
6396 return e;
6398 goto Lerror;
6400 else if (t->ty == Ttuple)
6402 if (!lwr && !upr)
6403 return e1;
6404 if (!lwr || !upr)
6405 { error("need upper and lower bound to slice tuple");
6406 goto Lerror;
6409 else
6410 goto Lerror;
6412 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
6414 sym = new ArrayScopeSymbol(this);
6415 sym->loc = loc;
6416 sym->parent = sc->scopesym;
6417 sc = sc->push(sym);
6420 if (lwr)
6421 { lwr = lwr->semantic(sc);
6422 lwr = resolveProperties(sc, lwr);
6423 lwr = lwr->implicitCastTo(sc, Type::tsize_t);
6425 if (upr)
6426 { upr = upr->semantic(sc);
6427 upr = resolveProperties(sc, upr);
6428 upr = upr->implicitCastTo(sc, Type::tsize_t);
6431 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
6432 sc->pop();
6434 if (t->ty == Ttuple)
6436 lwr = lwr->optimize(WANTvalue);
6437 upr = upr->optimize(WANTvalue);
6438 uinteger_t i1 = lwr->toUInteger();
6439 uinteger_t i2 = upr->toUInteger();
6441 size_t length;
6442 TupleExp *te;
6443 TypeTuple *tup;
6445 if (e1->op == TOKtuple) // slicing an expression tuple
6446 { te = (TupleExp *)e1;
6447 length = te->exps->dim;
6449 else if (e1->op == TOKtype) // slicing a type tuple
6450 { tup = (TypeTuple *)t;
6451 length = Argument::dim(tup->arguments);
6453 else
6454 assert(0);
6456 if (i1 <= i2 && i2 <= length)
6457 { size_t j1 = (size_t) i1;
6458 size_t j2 = (size_t) i2;
6460 if (e1->op == TOKtuple)
6461 { Expressions *exps = new Expressions;
6462 exps->setDim(j2 - j1);
6463 for (size_t i = 0; i < j2 - j1; i++)
6464 { Expression *e = (Expression *)te->exps->data[j1 + i];
6465 exps->data[i] = (void *)e;
6467 e = new TupleExp(loc, exps);
6469 else
6470 { Arguments *args = new Arguments;
6471 args->reserve(j2 - j1);
6472 for (size_t i = j1; i < j2; i++)
6473 { Argument *arg = Argument::getNth(tup->arguments, i);
6474 args->push(arg);
6476 e = new TypeExp(e1->loc, new TypeTuple(args));
6478 e = e->semantic(sc);
6480 else
6482 error("string slice [%"PRIuMAX" .. %"PRIuMAX"] is out of bounds", i1, i2);
6483 e = e1;
6485 return e;
6488 type = t->next->arrayOf();
6489 return e;
6491 Lerror:
6492 char *s;
6493 if (t->ty == Tvoid)
6494 s = e1->toChars();
6495 else
6496 s = t->toChars();
6497 error("%s cannot be sliced with []", s);
6498 type = Type::terror;
6499 return e;
6502 void SliceExp::checkEscape()
6504 e1->checkEscape();
6507 Expression *SliceExp::toLvalue(Scope *sc, Expression *e)
6509 return this;
6512 Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e)
6514 error("slice expression %s is not a modifiable lvalue", toChars());
6515 return this;
6518 void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6520 expToCBuffer(buf, hgs, e1, precedence[op]);
6521 buf->writeByte('[');
6522 if (upr || lwr)
6524 if (lwr)
6525 expToCBuffer(buf, hgs, lwr, PREC_assign);
6526 else
6527 buf->writeByte('0');
6528 buf->writestring("..");
6529 if (upr)
6530 expToCBuffer(buf, hgs, upr, PREC_assign);
6531 else
6532 buf->writestring("length"); // BUG: should be array.length
6534 buf->writeByte(']');
6537 /********************** ArrayLength **************************************/
6539 ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1)
6540 : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1)
6544 Expression *ArrayLengthExp::semantic(Scope *sc)
6545 { Expression *e;
6547 #if LOGSEMANTIC
6548 printf("ArrayLengthExp::semantic('%s')\n", toChars());
6549 #endif
6550 if (!type)
6552 UnaExp::semantic(sc);
6553 e1 = resolveProperties(sc, e1);
6555 type = Type::tsize_t;
6557 return this;
6560 void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6562 expToCBuffer(buf, hgs, e1, PREC_primary);
6563 buf->writestring(".length");
6566 /*********************** ArrayExp *************************************/
6568 // e1 [ i1, i2, i3, ... ]
6570 ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args)
6571 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1)
6573 arguments = args;
6576 Expression *ArrayExp::syntaxCopy()
6578 return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
6581 Expression *ArrayExp::semantic(Scope *sc)
6582 { Expression *e;
6583 Type *t1;
6585 #if LOGSEMANTIC
6586 printf("ArrayExp::semantic('%s')\n", toChars());
6587 #endif
6588 UnaExp::semantic(sc);
6589 e1 = resolveProperties(sc, e1);
6591 t1 = e1->type->toBasetype();
6592 if (t1->ty != Tclass && t1->ty != Tstruct)
6593 { // Convert to IndexExp
6594 if (arguments->dim != 1)
6595 error("only one index allowed to index %s", t1->toChars());
6596 e = new IndexExp(loc, e1, (Expression *)arguments->data[0]);
6597 return e->semantic(sc);
6600 // Run semantic() on each argument
6601 for (size_t i = 0; i < arguments->dim; i++)
6602 { e = (Expression *)arguments->data[i];
6604 e = e->semantic(sc);
6605 if (!e->type)
6606 error("%s has no value", e->toChars());
6607 arguments->data[i] = (void *)e;
6610 expandTuples(arguments);
6611 assert(arguments && arguments->dim);
6613 e = op_overload(sc);
6614 if (!e)
6615 { error("no [] operator overload for type %s", e1->type->toChars());
6616 e = e1;
6618 return e;
6622 Expression *ArrayExp::toLvalue(Scope *sc, Expression *e)
6624 if (type && type->toBasetype()->ty == Tvoid)
6625 error("voids have no value");
6626 return this;
6630 void ArrayExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6631 { int i;
6633 expToCBuffer(buf, hgs, e1, PREC_primary);
6634 buf->writeByte('[');
6635 argsToCBuffer(buf, arguments, hgs);
6636 buf->writeByte(']');
6639 /************************* DotExp ***********************************/
6641 DotExp::DotExp(Loc loc, Expression *e1, Expression *e2)
6642 : BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2)
6646 Expression *DotExp::semantic(Scope *sc)
6648 #if LOGSEMANTIC
6649 printf("DotExp::semantic('%s')\n", toChars());
6650 if (type) printf("\ttype = %s\n", type->toChars());
6651 #endif
6652 e1 = e1->semantic(sc);
6653 e2 = e2->semantic(sc);
6654 if (e2->op == TOKimport)
6656 ScopeExp *se = (ScopeExp *)e2;
6657 TemplateDeclaration *td = se->sds->isTemplateDeclaration();
6658 if (td)
6659 { Expression *e = new DotTemplateExp(loc, e1, td);
6660 e = e->semantic(sc);
6661 return e;
6664 if (!type)
6665 type = e2->type;
6666 return this;
6670 /************************* CommaExp ***********************************/
6672 CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2)
6673 : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2)
6677 Expression *CommaExp::semantic(Scope *sc)
6679 if (!type)
6680 { BinExp::semanticp(sc);
6681 type = e2->type;
6683 return this;
6686 void CommaExp::checkEscape()
6688 e2->checkEscape();
6691 Expression *CommaExp::toLvalue(Scope *sc, Expression *e)
6693 e2 = e2->toLvalue(sc, NULL);
6694 return this;
6697 Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e)
6699 e2 = e2->modifiableLvalue(sc, e);
6700 return this;
6703 int CommaExp::isBool(int result)
6705 return e2->isBool(result);
6708 int CommaExp::checkSideEffect(int flag)
6710 if (flag == 2)
6711 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
6712 else
6714 // Don't check e1 until we cast(void) the a,b code generation
6715 return e2->checkSideEffect(flag);
6719 /************************** IndexExp **********************************/
6721 // e1 [ e2 ]
6723 IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2)
6724 : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2)
6726 //printf("IndexExp::IndexExp('%s')\n", toChars());
6727 lengthVar = NULL;
6728 modifiable = 0; // assume it is an rvalue
6731 Expression *IndexExp::semantic(Scope *sc)
6732 { Expression *e;
6733 BinExp *b;
6734 UnaExp *u;
6735 Type *t1;
6736 ScopeDsymbol *sym;
6738 #if LOGSEMANTIC
6739 printf("IndexExp::semantic('%s')\n", toChars());
6740 #endif
6741 if (type)
6742 return this;
6743 if (!e1->type)
6744 e1 = e1->semantic(sc);
6745 assert(e1->type); // semantic() should already be run on it
6746 e = this;
6748 // Note that unlike C we do not implement the int[ptr]
6750 t1 = e1->type->toBasetype();
6752 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
6753 { // Create scope for 'length' variable
6754 sym = new ArrayScopeSymbol(this);
6755 sym->loc = loc;
6756 sym->parent = sc->scopesym;
6757 sc = sc->push(sym);
6760 e2 = e2->semantic(sc);
6761 if (!e2->type)
6763 error("%s has no value", e2->toChars());
6764 e2->type = Type::terror;
6766 e2 = resolveProperties(sc, e2);
6768 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
6769 sc = sc->pop();
6771 switch (t1->ty)
6773 case Tpointer:
6774 case Tarray:
6775 e2 = e2->implicitCastTo(sc, Type::tsize_t);
6776 e->type = t1->next;
6777 break;
6779 case Tsarray:
6781 e2 = e2->implicitCastTo(sc, Type::tsize_t);
6783 TypeSArray *tsa = (TypeSArray *)t1;
6785 #if 0 // Don't do now, because it might be short-circuit evaluated
6786 // Do compile time array bounds checking if possible
6787 e2 = e2->optimize(WANTvalue);
6788 if (e2->op == TOKint64)
6790 integer_t index = e2->toInteger();
6791 integer_t length = tsa->dim->toInteger();
6792 if (index < 0 || index >= length)
6793 error("array index [%lld] is outside array bounds [0 .. %lld]",
6794 index, length);
6796 #endif
6797 e->type = t1->next;
6798 break;
6801 case Taarray:
6802 { TypeAArray *taa = (TypeAArray *)t1;
6804 e2 = e2->implicitCastTo(sc, taa->index); // type checking
6805 e2 = e2->implicitCastTo(sc, taa->key); // actual argument type
6806 type = taa->next;
6807 break;
6810 case Ttuple:
6812 e2 = e2->implicitCastTo(sc, Type::tsize_t);
6813 e2 = e2->optimize(WANTvalue);
6814 uinteger_t index = e2->toUInteger();
6815 size_t length;
6816 TupleExp *te;
6817 TypeTuple *tup;
6819 if (e1->op == TOKtuple)
6820 { te = (TupleExp *)e1;
6821 length = te->exps->dim;
6823 else if (e1->op == TOKtype)
6825 tup = (TypeTuple *)t1;
6826 length = Argument::dim(tup->arguments);
6828 else
6829 assert(0);
6831 if (index < length)
6834 if (e1->op == TOKtuple)
6835 e = (Expression *)te->exps->data[(size_t)index];
6836 else
6837 e = new TypeExp(e1->loc, Argument::getNth(tup->arguments, (size_t)index)->type);
6839 else
6841 error("array index [%"PRIuMAX"] is outside array bounds [0 .. %"PRIuSIZE"]",
6842 index, length);
6843 e = e1;
6845 break;
6848 default:
6849 error("%s must be an array or pointer type, not %s",
6850 e1->toChars(), e1->type->toChars());
6851 type = Type::tint32;
6852 break;
6854 return e;
6857 Expression *IndexExp::toLvalue(Scope *sc, Expression *e)
6859 // if (type && type->toBasetype()->ty == Tvoid)
6860 // error("voids have no value");
6861 return this;
6864 Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
6866 //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
6867 modifiable = 1;
6868 if (e1->op == TOKstring)
6869 error("string literals are immutable");
6870 if (e1->type->toBasetype()->ty == Taarray)
6871 e1 = e1->modifiableLvalue(sc, e1);
6872 return toLvalue(sc, e);
6875 void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6877 expToCBuffer(buf, hgs, e1, PREC_primary);
6878 buf->writeByte('[');
6879 expToCBuffer(buf, hgs, e2, PREC_assign);
6880 buf->writeByte(']');
6884 /************************* PostExp ***********************************/
6886 PostExp::PostExp(enum TOK op, Loc loc, Expression *e)
6887 : BinExp(loc, op, sizeof(PostExp), e,
6888 new IntegerExp(loc, 1, Type::tint32))
6892 Expression *PostExp::semantic(Scope *sc)
6893 { Expression *e = this;
6895 if (!type)
6897 BinExp::semantic(sc);
6898 e2 = resolveProperties(sc, e2);
6900 e = op_overload(sc);
6901 if (e)
6902 return e;
6904 e = this;
6905 e1 = e1->modifiableLvalue(sc, e1);
6906 e1->checkScalar();
6907 e1->checkNoBool();
6908 if (e1->type->ty == Tpointer)
6909 e = scaleFactor(sc);
6910 else
6911 e2 = e2->castTo(sc, e1->type);
6912 e->type = e1->type;
6914 return e;
6917 void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6919 expToCBuffer(buf, hgs, e1, precedence[op]);
6920 buf->writestring((op == TOKplusplus) ? (char *)"++" : (char *)"--");
6923 /************************************************************/
6925 /* Can be TOKconstruct too */
6927 AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2)
6928 : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2)
6930 ismemset = 0;
6933 Expression *AssignExp::semantic(Scope *sc)
6934 { Type *t1;
6935 Expression *e1old = e1;
6937 #if LOGSEMANTIC
6938 printf("AssignExp::semantic('%s')\n", toChars());
6939 #endif
6940 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
6942 /* Look for operator overloading of a[i]=value.
6943 * Do it before semantic() otherwise the a[i] will have been
6944 * converted to a.opIndex() already.
6946 if (e1->op == TOKarray)
6947 { Type *t1;
6948 ArrayExp *ae = (ArrayExp *)e1;
6949 AggregateDeclaration *ad;
6950 Identifier *id = Id::index;
6952 ae->e1 = ae->e1->semantic(sc);
6953 t1 = ae->e1->type->toBasetype();
6954 if (t1->ty == Tstruct)
6956 ad = ((TypeStruct *)t1)->sym;
6957 goto L1;
6959 else if (t1->ty == Tclass)
6961 ad = ((TypeClass *)t1)->sym;
6963 // Rewrite (a[i] = value) to (a.opIndexAssign(value, i))
6964 if (search_function(ad, Id::indexass))
6965 { Expression *e = new DotIdExp(loc, ae->e1, Id::indexass);
6966 Expressions *a = (Expressions *)ae->arguments->copy();
6968 a->insert(0, e2);
6969 e = new CallExp(loc, e, a);
6970 e = e->semantic(sc);
6971 return e;
6973 else
6975 // Rewrite (a[i] = value) to (a.opIndex(i, value))
6976 if (search_function(ad, id))
6977 { Expression *e = new DotIdExp(loc, ae->e1, id);
6979 if (1 || !global.params.useDeprecated)
6980 error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
6982 e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2);
6983 e = e->semantic(sc);
6984 return e;
6989 /* Look for operator overloading of a[i..j]=value.
6990 * Do it before semantic() otherwise the a[i..j] will have been
6991 * converted to a.opSlice() already.
6993 if (e1->op == TOKslice)
6994 { Type *t1;
6995 SliceExp *ae = (SliceExp *)e1;
6996 AggregateDeclaration *ad;
6997 Identifier *id = Id::index;
6999 ae->e1 = ae->e1->semantic(sc);
7000 ae->e1 = resolveProperties(sc, ae->e1);
7001 t1 = ae->e1->type->toBasetype();
7002 if (t1->ty == Tstruct)
7004 ad = ((TypeStruct *)t1)->sym;
7005 goto L2;
7007 else if (t1->ty == Tclass)
7009 ad = ((TypeClass *)t1)->sym;
7011 // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j))
7012 if (search_function(ad, Id::sliceass))
7013 { Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass);
7014 Expressions *a = new Expressions();
7016 a->push(e2);
7017 if (ae->lwr)
7018 { a->push(ae->lwr);
7019 assert(ae->upr);
7020 a->push(ae->upr);
7022 else
7023 assert(!ae->upr);
7024 e = new CallExp(loc, e, a);
7025 e = e->semantic(sc);
7026 return e;
7031 BinExp::semantic(sc);
7032 e2 = resolveProperties(sc, e2);
7033 assert(e1->type);
7035 /* Rewrite tuple assignment as a tuple of assignments.
7037 if (e1->op == TOKtuple && e2->op == TOKtuple)
7038 { TupleExp *tup1 = (TupleExp *)e1;
7039 TupleExp *tup2 = (TupleExp *)e2;
7040 size_t dim = tup1->exps->dim;
7041 if (dim != tup2->exps->dim)
7043 error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim);
7045 else
7046 { Expressions *exps = new Expressions;
7047 exps->setDim(dim);
7049 for (int i = 0; i < dim; i++)
7050 { Expression *ex1 = (Expression *)tup1->exps->data[i];
7051 Expression *ex2 = (Expression *)tup2->exps->data[i];
7052 exps->data[i] = (void *) new AssignExp(loc, ex1, ex2);
7054 Expression *e = new TupleExp(loc, exps);
7055 e = e->semantic(sc);
7056 return e;
7060 t1 = e1->type->toBasetype();
7062 if (t1->ty == Tfunction)
7063 { // Rewrite f=value to f(value)
7064 Expression *e;
7066 e = new CallExp(loc, e1, e2);
7067 e = e->semantic(sc);
7068 return e;
7071 /* If it is an assignment from a 'foreign' type,
7072 * check for operator overloading.
7074 if (t1->ty == Tclass || t1->ty == Tstruct)
7076 if (!e2->type->implicitConvTo(e1->type))
7078 Expression *e = op_overload(sc);
7079 if (e)
7080 return e;
7084 e2->rvalue();
7086 if (e1->op == TOKarraylength)
7088 // e1 is not an lvalue, but we let code generator handle it
7089 ArrayLengthExp *ale = (ArrayLengthExp *)e1;
7091 ale->e1 = ale->e1->modifiableLvalue(sc, e1);
7093 else if (e1->op == TOKslice)
7095 else
7096 { // Try to do a decent error message with the expression
7097 // before it got constant folded
7098 e1 = e1->modifiableLvalue(sc, e1old);
7101 if (e1->op == TOKslice &&
7102 t1->nextOf() &&
7103 e2->implicitConvTo(t1->nextOf())
7104 // !(t1->nextOf()->equals(e2->type->nextOf()))
7106 { // memset
7107 ismemset = 1; // make it easy for back end to tell what this is
7108 e2 = e2->implicitCastTo(sc, t1->next);
7110 else if (t1->ty == Tsarray)
7112 error("cannot assign to static array %s", e1->toChars());
7114 else
7116 e2 = e2->implicitCastTo(sc, e1->type);
7118 type = e1->type;
7119 assert(type);
7120 return this;
7123 Expression *AssignExp::checkToBoolean()
7125 // Things like:
7126 // if (a = b) ...
7127 // are usually mistakes.
7129 error("'=' does not give a boolean result");
7130 return this;
7133 /************************************************************/
7135 /* Allow pointer arithmetic on e1? */
7136 static bool allowPtrArith(Scope *sc, Expression *e1)
7138 if (e1->type->ty == Tpointer)
7139 return true;
7140 else if (e1->type->ty == Tmaybe && e1->type->next->ty == Tpointer)
7142 if (!sc->inDtemplate)
7143 e1->error("Can't do pointer arithmetic on pointer ('%s') that could be null",
7144 e1->toChars());
7145 return true;
7147 return false;
7150 AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
7151 : BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
7155 Expression *AddAssignExp::semantic(Scope *sc)
7156 { Expression *e;
7158 if (type)
7159 return this;
7161 BinExp::semantic(sc);
7162 e2 = resolveProperties(sc, e2);
7164 e = op_overload(sc);
7165 if (e)
7166 return e;
7168 e1 = e1->modifiableLvalue(sc, e1);
7170 Type *tb1 = e1->type->toBasetype();
7171 Type *tb2 = e2->type->toBasetype();
7173 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
7174 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
7175 tb1->next->equals(tb2->next)
7178 type = e1->type;
7179 e = this;
7181 else
7183 e1->checkScalar();
7184 e1->checkNoBool();
7185 if (allowPtrArith(sc, e1) && tb2->isintegral())
7186 e = scaleFactor(sc);
7187 else if (tb1->ty == Tbit || tb1->ty == Tbool)
7189 #if 0
7190 // Need to rethink this
7191 if (e1->op != TOKvar)
7192 { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2
7193 VarDeclaration *v;
7194 Expression *ea;
7195 Expression *ex;
7197 char name[6+6+1];
7198 Identifier *id;
7199 static int idn;
7200 sprintf(name, "__name%d", ++idn);
7201 id = Lexer::idPool(name);
7203 v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL);
7204 v->semantic(sc);
7205 if (!sc->insert(v))
7206 assert(0);
7207 v->parent = sc->func;
7209 ea = new AddrExp(loc, e1);
7210 ea = new AssignExp(loc, new VarExp(loc, v), ea);
7212 ex = new VarExp(loc, v);
7213 ex = new PtrExp(loc, ex);
7214 e = new AddExp(loc, ex, e2);
7215 e = new CastExp(loc, e, e1->type);
7216 e = new AssignExp(loc, ex->syntaxCopy(), e);
7218 e = new CommaExp(loc, ea, e);
7220 else
7221 #endif
7222 { // Rewrite e1+=e2 to e1=e1+e2
7223 // BUG: doesn't account for side effects in e1
7224 // BUG: other assignment operators for bits aren't handled at all
7225 e = new AddExp(loc, e1, e2);
7226 e = new CastExp(loc, e, e1->type);
7227 e = new AssignExp(loc, e1->syntaxCopy(), e);
7229 e = e->semantic(sc);
7231 else
7233 type = e1->type;
7234 typeCombine(sc);
7235 e1->checkArithmetic();
7236 e2->checkArithmetic();
7237 if (type->isreal() || type->isimaginary())
7239 assert(global.errors || e2->type->isfloating());
7240 e2 = e2->castTo(sc, e1->type);
7242 e = this;
7245 return e;
7248 /************************************************************/
7250 MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
7251 : BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
7255 Expression *MinAssignExp::semantic(Scope *sc)
7256 { Expression *e;
7258 if (type)
7259 return this;
7261 BinExp::semantic(sc);
7262 e2 = resolveProperties(sc, e2);
7264 e = op_overload(sc);
7265 if (e)
7266 return e;
7268 e1 = e1->modifiableLvalue(sc, e1);
7269 e1->checkScalar();
7270 e1->checkNoBool();
7272 if (allowPtrArith(sc, e1) && e2->type->isintegral())
7273 e = scaleFactor(sc);
7274 else
7276 e1 = e1->checkArithmetic();
7277 e2 = e2->checkArithmetic();
7278 type = e1->type;
7279 typeCombine(sc);
7280 if (type->isreal() || type->isimaginary())
7282 assert(e2->type->isfloating());
7283 e2 = e2->castTo(sc, e1->type);
7285 e = this;
7287 return e;
7290 /************************************************************/
7292 CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
7293 : BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
7297 Expression *CatAssignExp::semantic(Scope *sc)
7298 { Expression *e;
7300 BinExp::semantic(sc);
7301 e2 = resolveProperties(sc, e2);
7303 e = op_overload(sc);
7304 if (e)
7305 return e;
7307 if (e1->op == TOKslice)
7308 { SliceExp *se = (SliceExp *)e1;
7310 if (se->e1->type->toBasetype()->ty == Tsarray)
7311 error("cannot append to static array %s", se->e1->type->toChars());
7314 e1 = e1->modifiableLvalue(sc, e1);
7316 Type *tb1 = e1->type->toBasetype();
7317 Type *tb2 = e2->type->toBasetype();
7319 e2->rvalue();
7321 if ((tb1->ty == Tarray) &&
7322 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
7323 e2->implicitConvTo(e1->type)
7324 //e1->type->next->equals(e2->type->next)
7326 { // Append array
7327 e2 = e2->castTo(sc, e1->type);
7328 type = e1->type;
7329 e = this;
7331 else if ((tb1->ty == Tarray) &&
7332 e2->implicitConvTo(tb1->next)
7334 { // Append element
7335 e2 = e2->castTo(sc, tb1->next);
7336 type = e1->type;
7337 e = this;
7339 else
7341 error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars());
7342 type = Type::tint32;
7343 e = this;
7345 return e;
7348 /************************************************************/
7350 MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
7351 : BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
7355 Expression *MulAssignExp::semantic(Scope *sc)
7356 { Expression *e;
7358 BinExp::semantic(sc);
7359 e2 = resolveProperties(sc, e2);
7361 e = op_overload(sc);
7362 if (e)
7363 return e;
7365 e1 = e1->modifiableLvalue(sc, e1);
7366 e1->checkScalar();
7367 e1->checkNoBool();
7368 type = e1->type;
7369 typeCombine(sc);
7370 e1->checkArithmetic();
7371 e2->checkArithmetic();
7372 if (e2->type->isfloating())
7373 { Type *t1;
7374 Type *t2;
7376 t1 = e1->type;
7377 t2 = e2->type;
7378 if (t1->isreal())
7380 if (t2->isimaginary() || t2->iscomplex())
7382 e2 = e2->castTo(sc, t1);
7385 else if (t1->isimaginary())
7387 if (t2->isimaginary() || t2->iscomplex())
7389 switch (t1->ty)
7391 case Timaginary32: t2 = Type::tfloat32; break;
7392 case Timaginary64: t2 = Type::tfloat64; break;
7393 case Timaginary80: t2 = Type::tfloat80; break;
7394 default:
7395 assert(0);
7397 e2 = e2->castTo(sc, t2);
7401 return this;
7404 /************************************************************/
7406 DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
7407 : BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
7411 Expression *DivAssignExp::semantic(Scope *sc)
7412 { Expression *e;
7414 BinExp::semantic(sc);
7415 e2 = resolveProperties(sc, e2);
7417 e = op_overload(sc);
7418 if (e)
7419 return e;
7421 e1 = e1->modifiableLvalue(sc, e1);
7422 e1->checkScalar();
7423 e1->checkNoBool();
7424 type = e1->type;
7425 typeCombine(sc);
7426 e1->checkArithmetic();
7427 e2->checkArithmetic();
7428 if (e2->type->isimaginary())
7429 { Type *t1;
7430 Type *t2;
7432 t1 = e1->type;
7433 if (t1->isreal())
7434 { // x/iv = i(-x/v)
7435 // Therefore, the result is 0
7436 e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1));
7437 e2->type = t1;
7438 e = new AssignExp(loc, e1, e2);
7439 e->type = t1;
7440 return e;
7442 else if (t1->isimaginary())
7443 { Expression *e;
7445 switch (t1->ty)
7447 case Timaginary32: t2 = Type::tfloat32; break;
7448 case Timaginary64: t2 = Type::tfloat64; break;
7449 case Timaginary80: t2 = Type::tfloat80; break;
7450 default:
7451 assert(0);
7453 e2 = e2->castTo(sc, t2);
7454 e = new AssignExp(loc, e1, e2);
7455 e->type = t1;
7456 return e;
7459 return this;
7462 /************************************************************/
7464 ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
7465 : BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
7469 Expression *ModAssignExp::semantic(Scope *sc)
7471 return commonSemanticAssign(sc);
7474 /************************************************************/
7476 ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
7477 : BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
7481 Expression *ShlAssignExp::semantic(Scope *sc)
7482 { Expression *e;
7484 //printf("ShlAssignExp::semantic()\n");
7485 BinExp::semantic(sc);
7486 e2 = resolveProperties(sc, e2);
7488 e = op_overload(sc);
7489 if (e)
7490 return e;
7492 e1 = e1->modifiableLvalue(sc, e1);
7493 e1->checkScalar();
7494 e1->checkNoBool();
7495 type = e1->type;
7496 typeCombine(sc);
7497 e1->checkIntegral();
7498 e2 = e2->checkIntegral();
7499 e2 = e2->castTo(sc, Type::tshiftcnt);
7500 return this;
7503 /************************************************************/
7505 ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
7506 : BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
7510 Expression *ShrAssignExp::semantic(Scope *sc)
7511 { Expression *e;
7513 BinExp::semantic(sc);
7514 e2 = resolveProperties(sc, e2);
7516 e = op_overload(sc);
7517 if (e)
7518 return e;
7520 e1 = e1->modifiableLvalue(sc, e1);
7521 e1->checkScalar();
7522 e1->checkNoBool();
7523 type = e1->type;
7524 typeCombine(sc);
7525 e1->checkIntegral();
7526 e2 = e2->checkIntegral();
7527 e2 = e2->castTo(sc, Type::tshiftcnt);
7528 return this;
7531 /************************************************************/
7533 UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
7534 : BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
7538 Expression *UshrAssignExp::semantic(Scope *sc)
7539 { Expression *e;
7541 BinExp::semantic(sc);
7542 e2 = resolveProperties(sc, e2);
7544 e = op_overload(sc);
7545 if (e)
7546 return e;
7548 e1 = e1->modifiableLvalue(sc, e1);
7549 e1->checkScalar();
7550 e1->checkNoBool();
7551 type = e1->type;
7552 typeCombine(sc);
7553 e1->checkIntegral();
7554 e2 = e2->checkIntegral();
7555 e2 = e2->castTo(sc, Type::tshiftcnt);
7556 return this;
7559 /************************************************************/
7561 AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
7562 : BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
7566 Expression *AndAssignExp::semantic(Scope *sc)
7568 return commonSemanticAssignIntegral(sc);
7571 /************************************************************/
7573 OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
7574 : BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
7578 Expression *OrAssignExp::semantic(Scope *sc)
7580 return commonSemanticAssignIntegral(sc);
7583 /************************************************************/
7585 XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
7586 : BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
7590 Expression *XorAssignExp::semantic(Scope *sc)
7592 return commonSemanticAssignIntegral(sc);
7595 /************************* AddExp *****************************/
7597 AddExp::AddExp(Loc loc, Expression *e1, Expression *e2)
7598 : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2)
7602 Expression *AddExp::semantic(Scope *sc)
7603 { Expression *e;
7605 #if LOGSEMANTIC
7606 printf("AddExp::semantic('%s')\n", toChars());
7607 #endif
7608 if (!type)
7610 BinExp::semanticp(sc);
7612 e = op_overload(sc);
7613 if (e)
7614 return e;
7616 Type *tb1 = e1->type->toBasetype();
7617 Type *tb2 = e2->type->toBasetype();
7619 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
7620 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
7621 tb1->next->equals(tb2->next)
7624 type = e1->type;
7625 e = this;
7627 else if (tb1->ty == Tpointer && e2->type->isintegral() ||
7628 tb2->ty == Tpointer && e1->type->isintegral())
7629 e = scaleFactor(sc);
7630 else if (tb1->ty == Tpointer && tb2->ty == Tpointer)
7632 incompatibleTypes();
7633 type = e1->type;
7634 e = this;
7636 else
7638 typeCombine(sc);
7639 if ((e1->type->isreal() && e2->type->isimaginary()) ||
7640 (e1->type->isimaginary() && e2->type->isreal()))
7642 switch (type->toBasetype()->ty)
7644 case Tfloat32:
7645 case Timaginary32:
7646 type = Type::tcomplex32;
7647 break;
7649 case Tfloat64:
7650 case Timaginary64:
7651 type = Type::tcomplex64;
7652 break;
7654 case Tfloat80:
7655 case Timaginary80:
7656 type = Type::tcomplex80;
7657 break;
7659 default:
7660 assert(0);
7663 e = this;
7665 return e;
7667 return this;
7670 /************************************************************/
7672 MinExp::MinExp(Loc loc, Expression *e1, Expression *e2)
7673 : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2)
7677 Expression *MinExp::semantic(Scope *sc)
7678 { Expression *e;
7679 Type *t1;
7680 Type *t2;
7682 #if LOGSEMANTIC
7683 printf("MinExp::semantic('%s')\n", toChars());
7684 #endif
7685 if (type)
7686 return this;
7688 BinExp::semanticp(sc);
7690 e = op_overload(sc);
7691 if (e)
7692 return e;
7694 e = this;
7695 t1 = e1->type->toBasetype();
7696 t2 = e2->type->toBasetype();
7697 if (t1->ty == Tpointer)
7699 if (t2->ty == Tpointer)
7700 { // Need to divide the result by the stride
7701 // Replace (ptr - ptr) with (ptr - ptr) / stride
7702 d_int64 stride;
7703 Expression *e;
7705 typeCombine(sc); // make sure pointer types are compatible
7706 type = Type::tptrdiff_t;
7707 stride = t2->next->size();
7708 e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
7709 e->type = Type::tptrdiff_t;
7710 return e;
7712 else if (t2->isintegral())
7713 e = scaleFactor(sc);
7714 else
7715 { error("incompatible types for -");
7716 return new IntegerExp(0);
7719 else if (t2->ty == Tpointer)
7721 type = e2->type;
7722 error("can't subtract pointer from %s", e1->type->toChars());
7723 return new IntegerExp(0);
7725 else
7727 typeCombine(sc);
7728 t1 = e1->type->toBasetype();
7729 t2 = e2->type->toBasetype();
7730 if ((t1->isreal() && t2->isimaginary()) ||
7731 (t1->isimaginary() && t2->isreal()))
7733 switch (type->ty)
7735 case Tfloat32:
7736 case Timaginary32:
7737 type = Type::tcomplex32;
7738 break;
7740 case Tfloat64:
7741 case Timaginary64:
7742 type = Type::tcomplex64;
7743 break;
7745 case Tfloat80:
7746 case Timaginary80:
7747 type = Type::tcomplex80;
7748 break;
7750 default:
7751 assert(0);
7755 return e;
7758 /************************* CatExp *****************************/
7760 CatExp::CatExp(Loc loc, Expression *e1, Expression *e2)
7761 : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2)
7765 Expression *CatExp::semantic(Scope *sc)
7766 { Expression *e;
7768 //printf("CatExp::semantic() %s\n", toChars());
7769 if (!type)
7771 BinExp::semanticp(sc);
7772 e = op_overload(sc);
7773 if (e)
7774 return e;
7776 Type *tb1 = e1->type->toBasetype();
7777 Type *tb2 = e2->type->toBasetype();
7780 /* BUG: Should handle things like:
7781 * char c;
7782 * c ~ ' '
7783 * ' ' ~ c;
7786 #if 0
7787 e1->type->print();
7788 e2->type->print();
7789 #endif
7790 if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
7791 e2->type->equals(tb1->next))
7793 type = tb1->next->arrayOf();
7794 if (tb2->ty == Tarray)
7795 { // Make e2 into [e2]
7796 e2 = new ArrayLiteralExp(e2->loc, e2);
7797 e2->type = type;
7799 return this;
7801 else if ((tb2->ty == Tsarray || tb2->ty == Tarray) &&
7802 e1->type->equals(tb2->next))
7804 type = tb2->next->arrayOf();
7805 if (tb1->ty == Tarray)
7806 { // Make e1 into [e1]
7807 e1 = new ArrayLiteralExp(e1->loc, e1);
7808 e1->type = type;
7810 return this;
7813 typeCombine(sc);
7815 if (type->ty == Tmaybe)
7816 error("Cannot join arrays that may be null (%s)", toChars());
7818 if (type->toBasetype()->ty == Tsarray)
7819 type = type->toBasetype()->next->arrayOf();
7820 #if 0
7821 e1->type->print();
7822 e2->type->print();
7823 type->print();
7824 print();
7825 #endif
7826 if (e1->op == TOKstring && e2->op == TOKstring)
7827 e = optimize(WANTvalue);
7828 else if (e1->type->equals(e2->type) &&
7829 (e1->type->toBasetype()->ty == Tarray ||
7830 e1->type->toBasetype()->ty == Tsarray))
7832 e = this;
7834 else
7836 error("Can only concatenate arrays, not (%s ~ %s)",
7837 e1->type->toChars(), e2->type->toChars());
7838 type = Type::tint32;
7839 e = this;
7841 e->type = e->type->semantic(loc, sc);
7842 return e;
7844 return this;
7847 /************************************************************/
7849 MulExp::MulExp(Loc loc, Expression *e1, Expression *e2)
7850 : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2)
7854 Expression *MulExp::semantic(Scope *sc)
7855 { Expression *e;
7857 #if 0
7858 printf("MulExp::semantic() %s\n", toChars());
7859 #endif
7860 if (type)
7862 return this;
7865 BinExp::semanticp(sc);
7866 e = op_overload(sc);
7867 if (e)
7868 return e;
7870 typeCombine(sc);
7871 e1->checkArithmetic();
7872 e2->checkArithmetic();
7873 if (type->isfloating())
7874 { Type *t1 = e1->type;
7875 Type *t2 = e2->type;
7877 if (t1->isreal())
7879 type = t2;
7881 else if (t2->isreal())
7883 type = t1;
7885 else if (t1->isimaginary())
7887 if (t2->isimaginary())
7888 { Expression *e;
7890 switch (t1->ty)
7892 case Timaginary32: type = Type::tfloat32; break;
7893 case Timaginary64: type = Type::tfloat64; break;
7894 case Timaginary80: type = Type::tfloat80; break;
7895 default: assert(0);
7898 // iy * iv = -yv
7899 e1->type = type;
7900 e2->type = type;
7901 e = new NegExp(loc, this);
7902 e = e->semantic(sc);
7903 return e;
7905 else
7906 type = t2; // t2 is complex
7908 else if (t2->isimaginary())
7910 type = t1; // t1 is complex
7913 return this;
7916 /************************************************************/
7918 DivExp::DivExp(Loc loc, Expression *e1, Expression *e2)
7919 : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2)
7923 Expression *DivExp::semantic(Scope *sc)
7924 { Expression *e;
7926 if (type)
7927 return this;
7929 BinExp::semanticp(sc);
7930 e = op_overload(sc);
7931 if (e)
7932 return e;
7934 typeCombine(sc);
7935 e1->checkArithmetic();
7936 e2->checkArithmetic();
7937 if (type->isfloating())
7938 { Type *t1 = e1->type;
7939 Type *t2 = e2->type;
7941 if (t1->isreal())
7943 type = t2;
7944 if (t2->isimaginary())
7945 { Expression *e;
7947 // x/iv = i(-x/v)
7948 e2->type = t1;
7949 e = new NegExp(loc, this);
7950 e = e->semantic(sc);
7951 return e;
7954 else if (t2->isreal())
7956 type = t1;
7958 else if (t1->isimaginary())
7960 if (t2->isimaginary())
7962 switch (t1->ty)
7964 case Timaginary32: type = Type::tfloat32; break;
7965 case Timaginary64: type = Type::tfloat64; break;
7966 case Timaginary80: type = Type::tfloat80; break;
7967 default: assert(0);
7970 else
7971 type = t2; // t2 is complex
7973 else if (t2->isimaginary())
7975 type = t1; // t1 is complex
7978 return this;
7981 /************************************************************/
7983 ModExp::ModExp(Loc loc, Expression *e1, Expression *e2)
7984 : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2)
7988 Expression *ModExp::semantic(Scope *sc)
7989 { Expression *e;
7991 if (type)
7992 return this;
7994 BinExp::semanticp(sc);
7995 e = op_overload(sc);
7996 if (e)
7997 return e;
7999 typeCombine(sc);
8000 e1->checkArithmetic();
8001 e2->checkArithmetic();
8002 if (type->isfloating())
8003 { type = e1->type;
8004 if (e2->type->iscomplex())
8005 { error("cannot perform modulo complex arithmetic");
8006 return new IntegerExp(0);
8009 return this;
8012 /************************************************************/
8014 ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2)
8015 : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2)
8019 Expression *ShlExp::semantic(Scope *sc)
8020 { Expression *e;
8022 //printf("ShlExp::semantic(), type = %p\n", type);
8023 if (!type)
8024 { BinExp::semanticp(sc);
8025 e = op_overload(sc);
8026 if (e)
8027 return e;
8028 e1 = e1->checkIntegral();
8029 e2 = e2->checkIntegral();
8030 e1 = e1->integralPromotions(sc);
8031 e2 = e2->castTo(sc, Type::tshiftcnt);
8032 type = e1->type;
8034 return this;
8037 /************************************************************/
8039 ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2)
8040 : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2)
8044 Expression *ShrExp::semantic(Scope *sc)
8045 { Expression *e;
8047 if (!type)
8048 { BinExp::semanticp(sc);
8049 e = op_overload(sc);
8050 if (e)
8051 return e;
8052 e1 = e1->checkIntegral();
8053 e2 = e2->checkIntegral();
8054 e1 = e1->integralPromotions(sc);
8055 e2 = e2->castTo(sc, Type::tshiftcnt);
8056 type = e1->type;
8058 return this;
8061 /************************************************************/
8063 UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2)
8064 : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2)
8068 Expression *UshrExp::semantic(Scope *sc)
8069 { Expression *e;
8071 if (!type)
8072 { BinExp::semanticp(sc);
8073 e = op_overload(sc);
8074 if (e)
8075 return e;
8076 e1 = e1->checkIntegral();
8077 e2 = e2->checkIntegral();
8078 e1 = e1->integralPromotions(sc);
8079 e2 = e2->castTo(sc, Type::tshiftcnt);
8080 type = e1->type;
8082 return this;
8085 /************************************************************/
8087 AndExp::AndExp(Loc loc, Expression *e1, Expression *e2)
8088 : BinExp(loc, TOKand, sizeof(AndExp), e1, e2)
8092 Expression *AndExp::semantic(Scope *sc)
8093 { Expression *e;
8095 if (!type)
8096 { BinExp::semanticp(sc);
8097 e = op_overload(sc);
8098 if (e)
8099 return e;
8100 if (e1->type->toBasetype()->ty == Tbool &&
8101 e2->type->toBasetype()->ty == Tbool)
8103 type = e1->type;
8104 e = this;
8106 else
8108 typeCombine(sc);
8109 e1->checkIntegral();
8110 e2->checkIntegral();
8113 return this;
8116 /************************************************************/
8118 OrExp::OrExp(Loc loc, Expression *e1, Expression *e2)
8119 : BinExp(loc, TOKor, sizeof(OrExp), e1, e2)
8123 Expression *OrExp::semantic(Scope *sc)
8124 { Expression *e;
8126 if (!type)
8127 { BinExp::semanticp(sc);
8128 e = op_overload(sc);
8129 if (e)
8130 return e;
8131 if (e1->type->toBasetype()->ty == Tbool &&
8132 e2->type->toBasetype()->ty == Tbool)
8134 type = e1->type;
8135 e = this;
8137 else
8139 typeCombine(sc);
8140 e1->checkIntegral();
8141 e2->checkIntegral();
8144 return this;
8147 /************************************************************/
8149 XorExp::XorExp(Loc loc, Expression *e1, Expression *e2)
8150 : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2)
8154 Expression *XorExp::semantic(Scope *sc)
8155 { Expression *e;
8157 if (!type)
8158 { BinExp::semanticp(sc);
8159 e = op_overload(sc);
8160 if (e)
8161 return e;
8162 if (e1->type->toBasetype()->ty == Tbool &&
8163 e2->type->toBasetype()->ty == Tbool)
8165 type = e1->type;
8166 e = this;
8168 else
8170 typeCombine(sc);
8171 e1->checkIntegral();
8172 e2->checkIntegral();
8175 return this;
8179 /************************************************************/
8181 OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2)
8182 : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2)
8186 Expression *OrOrExp::semantic(Scope *sc)
8188 unsigned cs1;
8190 // same as for AndAnd
8191 e1 = e1->semantic(sc);
8192 e1 = resolveProperties(sc, e1);
8193 e1 = e1->checkToPointer();
8194 e1 = e1->checkToBoolean();
8195 cs1 = sc->callSuper;
8197 if (sc->flags & SCOPEstaticif)
8199 /* If in static if, don't evaluate e2 if we don't have to.
8201 e1 = e1->optimize(WANTflags);
8202 if (e1->isBool(TRUE))
8204 return new IntegerExp(loc, 1, Type::tboolean);
8208 e2 = e2->semantic(sc);
8209 sc->mergeCallSuper(loc, cs1);
8210 e2 = resolveProperties(sc, e2);
8211 e2 = e2->checkToPointer();
8213 type = Type::tboolean;
8214 if (e1->type->ty == Tvoid)
8215 type = Type::tvoid;
8216 if (e2->op == TOKtype || e2->op == TOKimport)
8217 error("%s is not an expression", e2->toChars());
8218 return this;
8221 Expression *OrOrExp::checkToBoolean()
8223 e2 = e2->checkToBoolean();
8224 return this;
8227 int OrOrExp::isBit()
8229 return TRUE;
8232 int OrOrExp::checkSideEffect(int flag)
8234 if (flag == 2)
8236 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
8238 else
8239 { e1->checkSideEffect(1);
8240 return e2->checkSideEffect(flag);
8244 /************************************************************/
8246 AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2)
8247 : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2)
8251 Expression *AndAndExp::semantic(Scope *sc)
8253 unsigned cs1;
8255 // same as for OrOr
8256 e1 = e1->semantic(sc);
8257 e1 = resolveProperties(sc, e1);
8258 e1 = e1->checkToPointer();
8259 e1 = e1->checkToBoolean();
8260 cs1 = sc->callSuper;
8262 if (sc->flags & SCOPEstaticif)
8264 /* If in static if, don't evaluate e2 if we don't have to.
8266 e1 = e1->optimize(WANTflags);
8267 if (e1->isBool(FALSE))
8269 return new IntegerExp(loc, 0, Type::tboolean);
8273 e2 = e2->semantic(sc);
8274 sc->mergeCallSuper(loc, cs1);
8275 e2 = resolveProperties(sc, e2);
8276 e2 = e2->checkToPointer();
8278 type = Type::tboolean;
8279 if (e1->type->ty == Tvoid)
8280 type = Type::tvoid;
8281 if (e2->op == TOKtype || e2->op == TOKimport)
8282 error("%s is not an expression", e2->toChars());
8283 return this;
8286 Expression *AndAndExp::checkToBoolean()
8288 e2 = e2->checkToBoolean();
8289 return this;
8292 int AndAndExp::isBit()
8294 return TRUE;
8297 int AndAndExp::checkSideEffect(int flag)
8299 if (flag == 2)
8301 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
8303 else
8305 e1->checkSideEffect(1);
8306 return e2->checkSideEffect(flag);
8310 /************************************************************/
8312 InExp::InExp(Loc loc, Expression *e1, Expression *e2)
8313 : BinExp(loc, TOKin, sizeof(InExp), e1, e2)
8317 Expression *InExp::semantic(Scope *sc)
8318 { Expression *e;
8320 if (type)
8321 return this;
8323 BinExp::semanticp(sc);
8324 e = op_overload(sc);
8325 if (e)
8326 return e;
8328 //type = Type::tboolean;
8329 Type *t2b = e2->type->toBasetype();
8330 if (t2b->ty != Taarray)
8332 error("rvalue of in expression must be an associative array, not %s", e2->type->toChars());
8333 type = Type::terror;
8335 else
8337 TypeAArray *ta = (TypeAArray *)t2b;
8339 // Convert key to type of key
8340 e1 = e1->implicitCastTo(sc, ta->index);
8342 // Return type is pointer to value
8343 type = ta->next->pointerTo();
8345 return this;
8348 int InExp::isBit()
8350 return FALSE;
8354 /************************************************************/
8356 /* This deletes the key e1 from the associative array e2
8359 RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2)
8360 : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2)
8362 type = Type::tvoid;
8365 /************************************************************/
8367 CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
8368 : BinExp(loc, op, sizeof(CmpExp), e1, e2)
8372 Expression *CmpExp::semantic(Scope *sc)
8373 { Expression *e;
8374 Type *t1;
8375 Type *t2;
8377 #if LOGSEMANTIC
8378 printf("CmpExp::semantic('%s')\n", toChars());
8379 #endif
8380 if (type)
8381 return this;
8383 BinExp::semanticp(sc);
8385 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
8386 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
8388 error("do not use null when comparing class types");
8391 e = op_overload(sc);
8392 if (e)
8394 e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32));
8395 e = e->semantic(sc);
8396 return e;
8399 typeCombine(sc);
8400 type = Type::tboolean;
8402 // Special handling for array comparisons
8403 t1 = e1->type->toBasetype();
8404 t2 = e2->type->toBasetype();
8405 if ((t1->ty == Tarray || t1->ty == Tsarray) &&
8406 (t2->ty == Tarray || t2->ty == Tsarray))
8408 if (!t1->next->equals(t2->next))
8409 error("array comparison type mismatch, %s vs %s", t1->next->toChars(), t2->next->toChars());
8410 e = this;
8412 else if (t1->ty == Tstruct || t2->ty == Tstruct ||
8413 (t1->ty == Tclass && t2->ty == Tclass))
8415 if (t2->ty == Tstruct)
8416 error("need member function opCmp() for %s %s to compare", t2->toDsymbol(sc)->kind(), t2->toChars());
8417 else
8418 error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars());
8419 e = this;
8421 #if 1
8422 else if (t1->iscomplex() || t2->iscomplex())
8424 error("compare not defined for complex operands");
8425 e = new IntegerExp(0);
8427 #endif
8428 else
8429 e = this;
8430 return e;
8433 int CmpExp::isBit()
8435 return TRUE;
8439 /************************************************************/
8441 EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
8442 : BinExp(loc, op, sizeof(EqualExp), e1, e2)
8444 assert(op == TOKequal || op == TOKnotequal);
8447 Expression *EqualExp::semantic(Scope *sc)
8448 { Expression *e;
8449 Type *t1;
8450 Type *t2;
8452 //printf("EqualExp::semantic('%s')\n", toChars());
8453 if (type)
8454 return this;
8456 BinExp::semanticp(sc);
8458 /* Before checking for operator overloading, check to see if we're
8459 * comparing the addresses of two statics. If so, we can just see
8460 * if they are the same symbol.
8462 if (e1->op == TOKaddress && e2->op == TOKaddress)
8463 { AddrExp *ae1 = (AddrExp *)e1;
8464 AddrExp *ae2 = (AddrExp *)e2;
8466 if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar)
8467 { VarExp *ve1 = (VarExp *)ae1->e1;
8468 VarExp *ve2 = (VarExp *)ae2->e1;
8470 if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/)
8472 // They are the same, result is 'true' for ==, 'false' for !=
8473 e = new IntegerExp(loc, (op == TOKequal), Type::tboolean);
8474 return e;
8479 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
8480 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
8482 error("use '%s' instead of '%s' when comparing with null",
8483 Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity),
8484 Token::toChars(op));
8487 //if (e2->op != TOKnull)
8489 e = op_overload(sc);
8490 if (e)
8492 if (op == TOKnotequal)
8494 e = new NotExp(e->loc, e);
8495 e = e->semantic(sc);
8497 return e;
8501 e = typeCombine(sc);
8502 type = Type::tboolean;
8504 // Special handling for array comparisons
8505 t1 = e1->type->toBasetype();
8506 t2 = e2->type->toBasetype();
8507 if ((t1->ty == Tarray || t1->ty == Tsarray) &&
8508 (t2->ty == Tarray || t2->ty == Tsarray))
8510 if (!t1->next->equals(t2->next))
8511 error("array comparison type mismatch, %s vs %s", t1->next->toChars(), t2->next->toChars());
8513 else
8515 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
8517 // Cast both to complex
8518 e1 = e1->castTo(sc, Type::tcomplex80);
8519 e2 = e2->castTo(sc, Type::tcomplex80);
8522 return e;
8525 int EqualExp::isBit()
8527 return TRUE;
8532 /************************************************************/
8534 IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
8535 : BinExp(loc, op, sizeof(IdentityExp), e1, e2)
8539 Expression *IdentityExp::semantic(Scope *sc)
8541 if (type)
8542 return this;
8544 BinExp::semanticp(sc);
8545 type = Type::tboolean;
8546 typeCombine(sc);
8547 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
8549 // Cast both to complex
8550 e1 = e1->castTo(sc, Type::tcomplex80);
8551 e2 = e2->castTo(sc, Type::tcomplex80);
8553 return this;
8556 int IdentityExp::isBit()
8558 return TRUE;
8562 /****************************************************************/
8564 CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2)
8565 : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2)
8567 this->econd = econd;
8570 Expression *CondExp::syntaxCopy()
8572 return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy());
8576 Expression *CondExp::semantic(Scope *sc)
8577 { Type *t1;
8578 Type *t2;
8579 unsigned cs0;
8580 unsigned cs1;
8582 #if LOGSEMANTIC
8583 printf("CondExp::semantic('%s')\n", toChars());
8584 #endif
8585 if (type)
8586 return this;
8588 econd = econd->semantic(sc);
8589 econd = resolveProperties(sc, econd);
8590 econd = econd->checkToPointer();
8591 econd = econd->checkToBoolean();
8593 #if 0 /* this cannot work right because the types of e1 and e2
8594 * both contribute to the type of the result.
8596 if (sc->flags & SCOPEstaticif)
8598 /* If in static if, don't evaluate what we don't have to.
8600 econd = econd->optimize(WANTflags);
8601 if (econd->isBool(TRUE))
8603 e1 = e1->semantic(sc);
8604 e1 = resolveProperties(sc, e1);
8605 return e1;
8607 else if (econd->isBool(FALSE))
8609 e2 = e2->semantic(sc);
8610 e2 = resolveProperties(sc, e2);
8611 return e2;
8614 #endif
8617 cs0 = sc->callSuper;
8618 e1 = e1->semantic(sc);
8619 e1 = resolveProperties(sc, e1);
8620 cs1 = sc->callSuper;
8621 sc->callSuper = cs0;
8622 e2 = e2->semantic(sc);
8623 e2 = resolveProperties(sc, e2);
8624 sc->mergeCallSuper(loc, cs1);
8627 // If either operand is void, the result is void
8628 t1 = e1->type;
8629 t2 = e2->type;
8630 if (t1->ty == Tvoid || t2->ty == Tvoid)
8631 type = Type::tvoid;
8632 else if (t1 == t2)
8633 type = t1;
8634 else
8636 typeCombine(sc);
8637 switch (e1->type->toBasetype()->ty)
8639 case Tcomplex32:
8640 case Tcomplex64:
8641 case Tcomplex80:
8642 e2 = e2->castTo(sc, e1->type);
8643 break;
8645 switch (e2->type->toBasetype()->ty)
8647 case Tcomplex32:
8648 case Tcomplex64:
8649 case Tcomplex80:
8650 e1 = e1->castTo(sc, e2->type);
8651 break;
8654 return this;
8657 Expression *CondExp::toLvalue(Scope *sc, Expression *ex)
8659 PtrExp *e;
8661 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
8662 e = new PtrExp(loc, this, type);
8664 e1 = e1->addressOf(sc);
8665 //e1 = e1->toLvalue(sc, NULL);
8667 e2 = e2->addressOf(sc);
8668 //e2 = e2->toLvalue(sc, NULL);
8670 typeCombine(sc);
8672 type = e2->type;
8673 return e;
8676 Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e)
8678 error("conditional expression %s is not a modifiable lvalue", toChars());
8679 return this;
8682 void CondExp::checkEscape()
8684 e1->checkEscape();
8685 e2->checkEscape();
8689 Expression *CondExp::checkToBoolean()
8691 e1 = e1->checkToBoolean();
8692 e2 = e2->checkToBoolean();
8693 return this;
8696 int CondExp::checkSideEffect(int flag)
8698 if (flag == 2)
8700 return econd->checkSideEffect(2) ||
8701 e1->checkSideEffect(2) ||
8702 e2->checkSideEffect(2);
8704 else
8706 econd->checkSideEffect(1);
8707 e1->checkSideEffect(flag);
8708 return e2->checkSideEffect(flag);
8712 void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
8714 expToCBuffer(buf, hgs, econd, PREC_oror);
8715 buf->writestring(" ? ");
8716 expToCBuffer(buf, hgs, e1, PREC_expr);
8717 buf->writestring(" : ");
8718 expToCBuffer(buf, hgs, e2, PREC_cond);