Special unchecked nulls for d
[delight/core.git] / dmd2 / expression.c
blob327b0b2db4150d786395c6e4cac4275005231b80
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;
111 precedence[TOKdefault] = PREC_primary;
113 // post
114 precedence[TOKdotti] = PREC_primary;
115 precedence[TOKdot] = PREC_primary;
116 // precedence[TOKarrow] = PREC_primary;
117 precedence[TOKplusplus] = PREC_primary;
118 precedence[TOKminusminus] = PREC_primary;
119 precedence[TOKcall] = PREC_primary;
120 precedence[TOKslice] = PREC_primary;
121 precedence[TOKarray] = PREC_primary;
123 precedence[TOKaddress] = PREC_unary;
124 precedence[TOKstar] = PREC_unary;
125 precedence[TOKneg] = PREC_unary;
126 precedence[TOKuadd] = PREC_unary;
127 precedence[TOKnot] = PREC_unary;
128 precedence[TOKtobool] = PREC_add;
129 precedence[TOKtilde] = PREC_unary;
130 precedence[TOKdelete] = PREC_unary;
131 precedence[TOKnew] = PREC_unary;
132 precedence[TOKcast] = PREC_unary;
134 precedence[TOKmul] = PREC_mul;
135 precedence[TOKdiv] = PREC_mul;
136 precedence[TOKmod] = PREC_mul;
138 precedence[TOKadd] = PREC_add;
139 precedence[TOKmin] = PREC_add;
140 precedence[TOKcat] = PREC_add;
142 precedence[TOKshl] = PREC_shift;
143 precedence[TOKshr] = PREC_shift;
144 precedence[TOKushr] = PREC_shift;
146 precedence[TOKlt] = PREC_rel;
147 precedence[TOKle] = PREC_rel;
148 precedence[TOKgt] = PREC_rel;
149 precedence[TOKge] = PREC_rel;
150 precedence[TOKunord] = PREC_rel;
151 precedence[TOKlg] = PREC_rel;
152 precedence[TOKleg] = PREC_rel;
153 precedence[TOKule] = PREC_rel;
154 precedence[TOKul] = PREC_rel;
155 precedence[TOKuge] = PREC_rel;
156 precedence[TOKug] = PREC_rel;
157 precedence[TOKue] = PREC_rel;
158 precedence[TOKin] = PREC_rel;
160 precedence[TOKequal] = PREC_equal;
161 precedence[TOKnotequal] = PREC_equal;
162 precedence[TOKidentity] = PREC_equal;
163 precedence[TOKnotidentity] = PREC_equal;
165 precedence[TOKand] = PREC_and;
167 precedence[TOKxor] = PREC_xor;
169 precedence[TOKor] = PREC_or;
171 precedence[TOKandand] = PREC_andand;
173 precedence[TOKoror] = PREC_oror;
175 precedence[TOKquestion] = PREC_cond;
177 precedence[TOKassign] = PREC_assign;
178 precedence[TOKconstruct] = PREC_assign;
179 precedence[TOKblit] = PREC_assign;
180 precedence[TOKaddass] = PREC_assign;
181 precedence[TOKminass] = PREC_assign;
182 precedence[TOKcatass] = PREC_assign;
183 precedence[TOKmulass] = PREC_assign;
184 precedence[TOKdivass] = PREC_assign;
185 precedence[TOKmodass] = PREC_assign;
186 precedence[TOKshlass] = PREC_assign;
187 precedence[TOKshrass] = PREC_assign;
188 precedence[TOKushrass] = PREC_assign;
189 precedence[TOKandass] = PREC_assign;
190 precedence[TOKorass] = PREC_assign;
191 precedence[TOKxorass] = PREC_assign;
193 precedence[TOKcomma] = PREC_expr;
196 /*************************************************************
197 * Given var, we need to get the
198 * right 'this' pointer if var is in an outer class, but our
199 * existing 'this' pointer is in an inner class.
200 * Input:
201 * e1 existing 'this'
202 * ad struct or class we need the correct 'this' for
203 * var the specific member of ad we're accessing
206 Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
207 Expression *e1, Declaration *var)
210 Type *t = e1->type->toBasetype();
212 /* If e1 is not the 'this' pointer for ad
214 if (ad &&
215 !(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
216 ((TypeStruct *)t->nextOf())->sym == ad)
218 !(t->ty == Tstruct &&
219 ((TypeStruct *)t)->sym == ad)
222 ClassDeclaration *cd = ad->isClassDeclaration();
223 ClassDeclaration *tcd = t->isClassHandle();
225 /* e1 is the right this if ad is a base class of e1
227 if (!cd || !tcd ||
228 !(tcd == cd || cd->isBaseOf(tcd, NULL))
231 /* Only classes can be inner classes with an 'outer'
232 * member pointing to the enclosing class instance
234 if (tcd && tcd->isNested())
235 { /* e1 is the 'this' pointer for an inner class.
236 * Rewrite it as the 'this' pointer for the outer class.
239 e1 = new DotVarExp(loc, e1, tcd->vthis);
240 e1 = e1->semantic(sc);
242 // Skip up over nested functions, and get the enclosing
243 // class type.
244 Dsymbol *s;
245 for (s = tcd->toParent();
246 s && s->isFuncDeclaration();
247 s = s->toParent())
248 { FuncDeclaration *f = s->isFuncDeclaration();
249 if (f->vthis)
251 e1 = new VarExp(loc, f->vthis);
254 if (s && s->isClassDeclaration())
255 e1->type = s->isClassDeclaration()->type;
256 e1 = e1->semantic(sc);
257 goto L1;
260 /* Can't find a path from e1 to ad
262 error("this for %s needs to be type %s not type %s",
263 var->toChars(), ad->toChars(), t->toChars());
266 return e1;
269 /*****************************************
270 * Determine if 'this' is available.
271 * If it is, return the FuncDeclaration that has it.
274 FuncDeclaration *hasThis(Scope *sc)
275 { FuncDeclaration *fd;
276 FuncDeclaration *fdthis;
278 //printf("hasThis()\n");
279 fdthis = sc->parent->isFuncDeclaration();
280 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : "");
282 // Go upwards until we find the enclosing member function
283 fd = fdthis;
284 while (1)
286 if (!fd)
288 goto Lno;
290 if (!fd->isNested())
291 break;
293 Dsymbol *parent = fd->parent;
294 while (parent)
296 TemplateInstance *ti = parent->isTemplateInstance();
297 if (ti)
298 parent = ti->parent;
299 else
300 break;
303 fd = fd->parent->isFuncDeclaration();
306 if (!fd->isThis())
307 { //printf("test '%s'\n", fd->toChars());
308 goto Lno;
311 assert(fd->vthis);
312 return fd;
314 Lno:
315 return NULL; // don't have 'this' available
319 /***************************************
320 * Pull out any properties.
323 Expression *resolveProperties(Scope *sc, Expression *e)
325 //printf("resolveProperties(%s)\n", e->toChars());
326 if (e->type)
328 Type *t = e->type->toBasetype();
330 if (t->ty == Tfunction || e->op == TOKoverloadset)
332 e = new CallExp(e->loc, e);
333 e = e->semantic(sc);
336 /* Look for e being a lazy parameter; rewrite as delegate call
338 else if (e->op == TOKvar)
339 { VarExp *ve = (VarExp *)e;
341 if (ve->var->storage_class & STClazy)
343 e = new CallExp(e->loc, e);
344 e = e->semantic(sc);
348 else if (e->op == TOKdotexp)
350 e->error("expression has no value");
354 return e;
357 /******************************
358 * Perform semantic() on an array of Expressions.
361 void arrayExpressionSemantic(Expressions *exps, Scope *sc)
363 if (exps)
365 for (size_t i = 0; i < exps->dim; i++)
366 { Expression *e = (Expression *)exps->data[i];
368 e = e->semantic(sc);
369 exps->data[i] = (void *)e;
375 /******************************
376 * Perform canThrow() on an array of Expressions.
379 int arrayExpressionCanThrow(Expressions *exps)
381 if (exps)
383 for (size_t i = 0; i < exps->dim; i++)
384 { Expression *e = (Expression *)exps->data[i];
385 if (e && e->canThrow())
386 return 1;
389 return 0;
393 /****************************************
394 * Expand tuples.
397 void expandTuples(Expressions *exps)
399 //printf("expandTuples()\n");
400 if (exps)
402 for (size_t i = 0; i < exps->dim; i++)
403 { Expression *arg = (Expression *)exps->data[i];
404 if (!arg)
405 continue;
407 // Look for tuple with 0 members
408 if (arg->op == TOKtype)
409 { TypeExp *e = (TypeExp *)arg;
410 if (e->type->toBasetype()->ty == Ttuple)
411 { TypeTuple *tt = (TypeTuple *)e->type->toBasetype();
413 if (!tt->arguments || tt->arguments->dim == 0)
415 exps->remove(i);
416 if (i == exps->dim)
417 return;
418 i--;
419 continue;
424 // Inline expand all the tuples
425 while (arg->op == TOKtuple)
426 { TupleExp *te = (TupleExp *)arg;
428 exps->remove(i); // remove arg
429 exps->insert(i, te->exps); // replace with tuple contents
430 if (i == exps->dim)
431 return; // empty tuple, no more arguments
432 arg = (Expression *)exps->data[i];
438 /****************************************
439 * Preprocess arguments to function.
442 void preFunctionArguments(Loc loc, Scope *sc, Expressions *exps)
444 if (exps)
446 expandTuples(exps);
448 for (size_t i = 0; i < exps->dim; i++)
449 { Expression *arg = (Expression *)exps->data[i];
451 if (!arg->type)
453 #ifdef DEBUG
454 if (!global.gag)
455 printf("1: \n");
456 #endif
457 arg->error("%s is not an expression", arg->toChars());
458 arg = new IntegerExp(arg->loc, 0, Type::tint32);
461 arg = resolveProperties(sc, arg);
462 exps->data[i] = (void *) arg;
464 //arg->rvalue();
465 #if 0
466 if (arg->type->ty == Tfunction)
468 arg = new AddrExp(arg->loc, arg);
469 arg = arg->semantic(sc);
470 exps->data[i] = (void *) arg;
472 #endif
477 /*********************************************
478 * Call copy constructor for struct value argument.
481 Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
483 Type *tb = e->type->toBasetype();
484 assert(tb->ty == Tstruct);
485 StructDeclaration *sd = ((TypeStruct *)tb)->sym;
486 if (sd->cpctor)
488 /* Create a variable tmp, and replace the argument e with:
489 * (tmp = e),tmp
490 * and let AssignExp() handle the construction.
491 * This is not the most efficent, ideally tmp would be constructed
492 * directly onto the stack.
494 Identifier *idtmp = Lexer::uniqueId("__tmp");
495 VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e));
496 Expression *ae = new DeclarationExp(loc, tmp);
497 e = new CommaExp(loc, ae, new VarExp(loc, tmp));
498 e = e->semantic(sc);
500 return e;
503 /****************************************
504 * Now that we know the exact type of the function we're calling,
505 * the arguments[] need to be adjusted:
506 * 1. implicitly convert argument to the corresponding parameter type
507 * 2. add default arguments for any missing arguments
508 * 3. do default promotions on arguments corresponding to ...
509 * 4. add hidden _arguments[] argument
510 * 5. call copy constructor for struct value arguments
513 void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments)
515 unsigned n;
517 //printf("functionArguments()\n");
518 assert(arguments);
519 size_t nargs = arguments ? arguments->dim : 0;
520 size_t nparams = Argument::dim(tf->parameters);
522 if (nargs > nparams && tf->varargs == 0)
523 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
525 n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
527 int done = 0;
528 for (size_t i = 0; i < n; i++)
530 Expression *arg;
532 if (i < nargs)
533 arg = (Expression *)arguments->data[i];
534 else
535 arg = NULL;
536 Type *tb;
538 if (i < nparams)
540 Argument *p = Argument::getNth(tf->parameters, i);
542 if (!arg)
544 if (!p->defaultArg)
546 if (tf->varargs == 2 && i + 1 == nparams)
547 goto L2;
548 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
549 break;
551 arg = p->defaultArg;
552 if (arg->op == TOKdefault)
553 { DefaultInitExp *de = (DefaultInitExp *)arg;
554 arg = de->resolve(loc, sc);
556 else
557 arg = arg->copy();
558 arguments->push(arg);
559 nargs++;
562 if (tf->varargs == 2 && i + 1 == nparams)
564 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
565 if (arg->implicitConvTo(p->type))
567 if (nargs != nparams)
568 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
569 goto L1;
572 Type *tb = p->type->toBasetype();
573 Type *tret = p->isLazyArray();
574 switch (tb->ty)
576 case Tsarray:
577 case Tarray:
578 { // Create a static array variable v of type arg->type
579 #ifdef IN_GCC
580 /* GCC 4.0 does not like zero length arrays used like
581 this; pass a null array value instead. Could also
582 just make a one-element array. */
583 if (nargs - i == 0)
585 arg = new NullExp(loc);
586 break;
588 #endif
589 Identifier *id = Lexer::uniqueId("__arrayArg");
590 Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i));
591 t = t->semantic(loc, sc);
592 VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc));
593 v->semantic(sc);
594 v->parent = sc->parent;
595 //sc->insert(v);
597 Expression *c = new DeclarationExp(0, v);
598 c->type = v->type;
600 for (size_t u = i; u < nargs; u++)
601 { Expression *a = (Expression *)arguments->data[u];
602 if (tret && !((TypeArray *)tb)->next->equals(a->type))
603 a = a->toDelegate(sc, tret);
605 Expression *e = new VarExp(loc, v);
606 e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
607 AssignExp *ae = new AssignExp(loc, e, a);
608 ae->op = TOKconstruct;
609 if (c)
610 c = new CommaExp(loc, c, ae);
611 else
612 c = ae;
614 arg = new VarExp(loc, v);
615 if (c)
616 arg = new CommaExp(loc, c, arg);
617 break;
619 case Tclass:
620 { /* Set arg to be:
621 * new Tclass(arg0, arg1, ..., argn)
623 Expressions *args = new Expressions();
624 args->setDim(nargs - i);
625 for (size_t u = i; u < nargs; u++)
626 args->data[u - i] = arguments->data[u];
627 arg = new NewExp(loc, NULL, NULL, p->type, args);
628 break;
630 default:
631 if (!arg)
632 { error(loc, "not enough arguments");
633 return;
635 break;
637 arg = arg->semantic(sc);
638 //printf("\targ = '%s'\n", arg->toChars());
639 arguments->setDim(i + 1);
640 done = 1;
644 if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
646 if (p->type != arg->type)
648 //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
649 arg = arg->implicitCastTo(sc, p->type);
650 arg = arg->optimize(WANTvalue);
653 if (p->storageClass & STCref)
655 arg = arg->toLvalue(sc, arg);
657 else if (p->storageClass & STCout)
659 arg = arg->modifiableLvalue(sc, arg);
662 // Convert static arrays to pointers
663 tb = arg->type->toBasetype();
664 if (tb->ty == Tsarray)
666 arg = arg->checkToPointer();
669 if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
671 arg = callCpCtor(loc, sc, arg);
674 // Convert lazy argument to a delegate
675 if (p->storageClass & STClazy)
677 arg = arg->toDelegate(sc, p->type);
680 else
683 // If not D linkage, do promotions
684 if (tf->linkage != LINKd)
686 // Promote bytes, words, etc., to ints
687 arg = arg->integralPromotions(sc);
689 // Promote floats to doubles
690 switch (arg->type->ty)
692 case Tfloat32:
693 arg = arg->castTo(sc, Type::tfloat64);
694 break;
696 case Timaginary32:
697 arg = arg->castTo(sc, Type::timaginary64);
698 break;
702 // Convert static arrays to dynamic arrays
703 tb = arg->type->toBasetype();
704 if (tb->ty == Tsarray)
705 { TypeSArray *ts = (TypeSArray *)tb;
706 Type *ta = ts->next->arrayOf();
707 if (ts->size(arg->loc) == 0)
708 { arg = new NullExp(arg->loc);
709 arg->type = ta;
711 else
712 arg = arg->castTo(sc, ta);
715 if (tb->ty == Tstruct)
717 arg = callCpCtor(loc, sc, arg);
720 // Give error for overloaded function addresses
721 if (arg->op == TOKsymoff)
722 { SymOffExp *se = (SymOffExp *)arg;
723 if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
724 arg->error("function %s is overloaded", arg->toChars());
726 arg->rvalue();
729 arg = arg->optimize(WANTvalue);
730 arguments->data[i] = (void *) arg;
731 if (done)
732 break;
735 // If D linkage and variadic, add _arguments[] as first argument
736 if (tf->linkage == LINKd && tf->varargs == 1)
738 Expression *e;
740 e = createTypeInfoArray(sc, (Expression **)&arguments->data[nparams],
741 arguments->dim - nparams);
742 arguments->insert(0, e);
746 /**************************************************
747 * Write expression out to buf, but wrap it
748 * in ( ) if its precedence is less than pr.
751 void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr)
753 //if (precedence[e->op] == 0) e->dump(0);
754 if (precedence[e->op] < pr)
756 buf->writeByte('(');
757 e->toCBuffer(buf, hgs);
758 buf->writeByte(')');
760 else
761 e->toCBuffer(buf, hgs);
764 /**************************************************
765 * Write out argument list to buf.
768 void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
770 if (arguments)
772 for (size_t i = 0; i < arguments->dim; i++)
773 { Expression *arg = (Expression *)arguments->data[i];
775 if (arg)
776 { if (i)
777 buf->writeByte(',');
778 expToCBuffer(buf, hgs, arg, PREC_assign);
784 /**************************************************
785 * Write out argument types to buf.
788 void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
790 if (arguments)
791 { OutBuffer argbuf;
793 for (size_t i = 0; i < arguments->dim; i++)
794 { Expression *arg = (Expression *)arguments->data[i];
796 if (i)
797 buf->writeByte(',');
798 argbuf.reset();
799 arg->type->toCBuffer2(&argbuf, hgs, 0);
800 buf->write(&argbuf);
805 /******************************** Expression **************************/
807 Expression::Expression(Loc loc, enum TOK op, int size)
808 : loc(loc)
810 this->loc = loc;
811 this->op = op;
812 this->size = size;
813 type = NULL;
816 Expression *Expression::syntaxCopy()
818 //printf("Expression::syntaxCopy()\n");
819 //dump(0);
820 return copy();
823 /*********************************
824 * Does *not* do a deep copy.
827 Expression *Expression::copy()
829 Expression *e;
830 if (!size)
832 #ifdef DEBUG
833 fprintf(stdmsg, "No expression copy for: %s\n", toChars());
834 printf("op = %d\n", op);
835 dump(0);
836 #endif
837 assert(0);
839 e = (Expression *)mem.malloc(size);
840 return (Expression *)memcpy(e, this, size);
843 /**************************
844 * Semantically analyze Expression.
845 * Determine types, fold constants, etc.
848 Expression *Expression::semantic(Scope *sc)
850 #if LOGSEMANTIC
851 printf("Expression::semantic() %s\n", toChars());
852 #endif
853 if (type)
854 type = type->semantic(loc, sc);
855 else
856 type = Type::tvoid;
857 return this;
860 void Expression::print()
862 fprintf(stdmsg, "%s\n", toChars());
863 fflush(stdmsg);
866 char *Expression::toChars()
867 { OutBuffer *buf;
868 HdrGenState hgs;
870 memset(&hgs, 0, sizeof(hgs));
871 buf = new OutBuffer();
872 toCBuffer(buf, &hgs);
873 return buf->toChars();
876 void Expression::error(const char *format, ...)
878 va_list ap;
879 va_start(ap, format);
880 ::verror(loc, format, ap);
881 va_end( ap );
884 void Expression::rvalue()
886 if (type && type->toBasetype()->ty == Tvoid)
887 { error("expression %s is void and has no value", toChars());
888 #if 0
889 dump(0);
890 halt();
891 #endif
892 type = Type::tint32;
896 Expression *Expression::combine(Expression *e1, Expression *e2)
898 if (e1)
900 if (e2)
902 e1 = new CommaExp(e1->loc, e1, e2);
903 e1->type = e2->type;
906 else
907 e1 = e2;
908 return e1;
911 integer_t Expression::toInteger()
913 //printf("Expression %s\n", Token::toChars(op));
914 error("Integer constant expression expected instead of %s", toChars());
915 return 0;
918 uinteger_t Expression::toUInteger()
920 //printf("Expression %s\n", Token::toChars(op));
921 return (uinteger_t)toInteger();
924 real_t Expression::toReal()
926 error("Floating point constant expression expected instead of %s", toChars());
927 return 0;
930 real_t Expression::toImaginary()
932 error("Floating point constant expression expected instead of %s", toChars());
933 return 0;
936 complex_t Expression::toComplex()
938 error("Floating point constant expression expected instead of %s", toChars());
939 #ifdef IN_GCC
940 return complex_t(real_t(0)); // %% nicer
941 #else
942 return 0;
943 #endif
946 void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
948 buf->writestring(Token::toChars(op));
951 void Expression::toMangleBuffer(OutBuffer *buf)
953 error("expression %s is not a valid template value argument", toChars());
956 /*******************************
957 * Give error if we're not an lvalue.
958 * If we can, convert expression to be an lvalue.
961 Expression *Expression::toLvalue(Scope *sc, Expression *e)
963 if (!e)
964 e = this;
965 else if (!loc.filename)
966 loc = e->loc;
967 error("%s is not an lvalue", e->toChars());
968 return this;
971 Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
973 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
975 // See if this expression is a modifiable lvalue (i.e. not const)
976 if (type && (!type->isMutable() || !type->isAssignable()))
977 error("%s is not mutable", e->toChars());
979 return toLvalue(sc, e);
982 /************************************
983 * Detect cases where pointers to the stack can 'escape' the
984 * lifetime of the stack frame.
987 void Expression::checkEscape()
991 void Expression::checkScalar()
993 if (!type->isscalar())
994 error("'%s' is not a scalar, it is a %s", toChars(), type->toChars());
997 void Expression::checkNoBool()
999 if (type->toBasetype()->ty == Tbool)
1000 error("operation not allowed on bool '%s'", toChars());
1003 Expression *Expression::checkIntegral()
1005 if (!type->isintegral())
1006 { error("'%s' is not of integral type, it is a %s", toChars(), type->toChars());
1007 return new IntegerExp(0);
1009 return this;
1012 Expression *Expression::checkArithmetic()
1014 if (!type->isintegral() && !type->isfloating())
1015 { error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
1016 return new IntegerExp(0);
1018 return this;
1021 void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
1023 s->checkDeprecated(loc, sc);
1026 /********************************
1027 * Check for expressions that have no use.
1028 * Input:
1029 * flag 0 not going to use the result, so issue error message if no
1030 * side effects
1031 * 1 the result of the expression is used, but still check
1032 * for useless subexpressions
1033 * 2 do not issue error messages, just return !=0 if expression
1034 * has side effects
1037 int Expression::checkSideEffect(int flag)
1039 if (flag == 0)
1040 { if (op == TOKimport)
1042 error("%s has no effect", toChars());
1044 else
1045 error("%s has no effect in expression (%s)",
1046 Token::toChars(op), toChars());
1048 return 0;
1051 /*****************************
1052 * Check that expression can be tested for true or false.
1055 Expression *Expression::checkToBoolean()
1057 // Default is 'yes' - do nothing
1059 #ifdef DEBUG
1060 if (!type)
1061 dump(0);
1062 #endif
1064 if (!type->checkBoolean())
1066 error("expression %s of type %s does not have a boolean value", toChars(), type->toChars());
1068 return this;
1071 /****************************
1074 Expression *Expression::checkToPointer()
1076 Expression *e;
1077 Type *tb;
1079 //printf("Expression::checkToPointer()\n");
1080 e = this;
1082 // If C static array, convert to pointer
1083 tb = type->toBasetype();
1084 if (tb->ty == Tsarray)
1085 { TypeSArray *ts = (TypeSArray *)tb;
1086 if (ts->size(loc) == 0)
1087 e = new NullExp(loc);
1088 else
1089 e = new AddrExp(loc, this);
1090 e->type = ts->next->pointerTo();
1092 return e;
1095 /******************************
1096 * Take address of expression.
1099 Expression *Expression::addressOf(Scope *sc)
1101 Expression *e;
1103 //printf("Expression::addressOf()\n");
1104 e = toLvalue(sc, NULL);
1105 e = new AddrExp(loc, e);
1106 e->type = type->pointerTo();
1107 return e;
1110 /******************************
1111 * If this is a reference, dereference it.
1114 Expression *Expression::deref()
1116 //printf("Expression::deref()\n");
1117 if (type->ty == Treference)
1118 { Expression *e;
1120 e = new PtrExp(loc, this);
1121 e->type = ((TypeReference *)type)->next;
1122 return e;
1124 return this;
1127 /********************************
1128 * Does this expression statically evaluate to a boolean TRUE or FALSE?
1131 int Expression::isBool(int result)
1133 return FALSE;
1136 /********************************
1137 * Does this expression result in either a 1 or a 0?
1140 int Expression::isBit()
1142 return FALSE;
1145 /********************************
1146 * Can this expression throw an exception?
1147 * Valid only after semantic() pass.
1150 int Expression::canThrow()
1152 return FALSE;
1157 Expressions *Expression::arraySyntaxCopy(Expressions *exps)
1158 { Expressions *a = NULL;
1160 if (exps)
1162 a = new Expressions();
1163 a->setDim(exps->dim);
1164 for (int i = 0; i < a->dim; i++)
1165 { Expression *e = (Expression *)exps->data[i];
1167 e = e->syntaxCopy();
1168 a->data[i] = e;
1171 return a;
1174 /******************************** IntegerExp **************************/
1176 IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type)
1177 : Expression(loc, TOKint64, sizeof(IntegerExp))
1179 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
1180 if (type && !type->isscalar())
1182 //printf("%s, loc = %d\n", toChars(), loc.linnum);
1183 error("integral constant must be scalar type, not %s", type->toChars());
1184 type = Type::terror;
1186 this->type = type;
1187 this->value = value;
1190 IntegerExp::IntegerExp(integer_t value)
1191 : Expression(0, TOKint64, sizeof(IntegerExp))
1193 this->type = Type::tint32;
1194 this->value = value;
1197 int IntegerExp::equals(Object *o)
1198 { IntegerExp *ne;
1200 if (this == o ||
1201 (((Expression *)o)->op == TOKint64 &&
1202 ((ne = (IntegerExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
1203 value == ne->value))
1204 return 1;
1205 return 0;
1208 char *IntegerExp::toChars()
1210 #if 1
1211 return Expression::toChars();
1212 #else
1213 static char buffer[sizeof(value) * 3 + 1];
1215 sprintf(buffer, "%"PRIdMAX, value);
1216 return buffer;
1217 #endif
1220 integer_t IntegerExp::toInteger()
1221 { Type *t;
1223 t = type;
1224 while (t)
1226 switch (t->ty)
1228 case Tbit:
1229 case Tbool: value = (value != 0); break;
1230 case Tint8: value = (d_int8) value; break;
1231 case Tchar:
1232 case Tuns8: value = (d_uns8) value; break;
1233 case Tint16: value = (d_int16) value; break;
1234 case Twchar:
1235 case Tuns16: value = (d_uns16) value; break;
1236 case Tint32: value = (d_int32) value; break;
1237 case Tdchar:
1238 case Tuns32: value = (d_uns32) value; break;
1239 case Tint64: value = (d_int64) value; break;
1240 case Tuns64: value = (d_uns64) value; break;
1242 case Tpointer:
1243 switch (PTRSIZE)
1245 case 4: value = (d_uns32) value; break;
1246 case 8: value = (d_uns64) value; break;
1247 default:
1248 assert(PTRSIZE == 4 || PTRSIZE == 8);
1250 break;
1252 case Tenum:
1254 TypeEnum *te = (TypeEnum *)t;
1255 t = te->sym->memtype;
1256 continue;
1259 case Ttypedef:
1261 TypeTypedef *tt = (TypeTypedef *)t;
1262 t = tt->sym->basetype;
1263 continue;
1266 default:
1267 type->print();
1268 assert(0);
1269 break;
1271 break;
1273 return value;
1276 real_t IntegerExp::toReal()
1278 Type *t;
1280 toInteger();
1281 t = type->toBasetype();
1282 if (t->ty == Tuns64)
1283 return (real_t)(d_uns64)value;
1284 else
1285 return (real_t)(d_int64)value;
1288 real_t IntegerExp::toImaginary()
1290 return (real_t) 0;
1293 complex_t IntegerExp::toComplex()
1295 return toReal();
1298 int IntegerExp::isBool(int result)
1300 return result ? value != 0 : value == 0;
1303 Expression *IntegerExp::semantic(Scope *sc)
1305 if (!type)
1307 // Determine what the type of this number is
1308 integer_t number = value;
1310 if (number & 0x8000000000000000LL)
1311 type = Type::tuns64;
1312 else if (number & 0xFFFFFFFF80000000LL)
1313 type = Type::tint64;
1314 else
1315 type = Type::tint32;
1317 else
1318 { if (!type->deco)
1319 type = type->semantic(loc, sc);
1321 return this;
1324 Expression *IntegerExp::toLvalue(Scope *sc, Expression *e)
1326 if (!e)
1327 e = this;
1328 else if (!loc.filename)
1329 loc = e->loc;
1330 e->error("constant %s is not an lvalue", e->toChars());
1331 return this;
1334 void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1336 integer_t v = toInteger();
1338 if (type)
1339 { Type *t = type;
1342 switch (t->ty)
1344 case Tenum:
1345 { TypeEnum *te = (TypeEnum *)t;
1346 buf->printf("cast(%s)", te->sym->toChars());
1347 t = te->sym->memtype;
1348 goto L1;
1351 case Ttypedef:
1352 { TypeTypedef *tt = (TypeTypedef *)t;
1353 buf->printf("cast(%s)", tt->sym->toChars());
1354 t = tt->sym->basetype;
1355 goto L1;
1358 case Twchar: // BUG: need to cast(wchar)
1359 case Tdchar: // BUG: need to cast(dchar)
1360 if ((uinteger_t)v > 0xFF)
1362 buf->printf("'\\U%08x'", v);
1363 break;
1365 case Tchar:
1366 if (v == '\'')
1367 buf->writestring("'\\''");
1368 else if (isprint(v) && v != '\\')
1369 buf->printf("'%c'", (int)v);
1370 else
1371 buf->printf("'\\x%02x'", (int)v);
1372 break;
1374 case Tint8:
1375 buf->writestring("cast(byte)");
1376 goto L2;
1378 case Tint16:
1379 buf->writestring("cast(short)");
1380 goto L2;
1382 case Tint32:
1384 buf->printf("%d", (int)v);
1385 break;
1387 case Tuns8:
1388 buf->writestring("cast(ubyte)");
1389 goto L3;
1391 case Tuns16:
1392 buf->writestring("cast(ushort)");
1393 goto L3;
1395 case Tuns32:
1397 buf->printf("%du", (unsigned)v);
1398 break;
1400 case Tint64:
1401 buf->printf("%"PRIdMAX"L", v);
1402 break;
1404 case Tuns64:
1405 buf->printf("%"PRIuMAX"LU", v);
1406 break;
1408 case Tbit:
1409 case Tbool:
1410 buf->writestring((char *)(v ? "true" : "false"));
1411 break;
1413 case Tpointer:
1414 buf->writestring("cast(");
1415 buf->writestring(t->toChars());
1416 buf->writeByte(')');
1417 goto L3;
1419 default:
1420 #ifdef DEBUG
1421 t->print();
1422 #endif
1423 assert(0);
1426 else if (v & 0x8000000000000000LL)
1427 buf->printf("0x%"PRIxMAX, v);
1428 else
1429 buf->printf("%"PRIdMAX, v);
1432 void IntegerExp::toMangleBuffer(OutBuffer *buf)
1434 if ((sinteger_t)value < 0)
1435 buf->printf("N%"PRIdMAX, -value);
1436 else
1437 buf->printf("%"PRIdMAX, value);
1440 /******************************** RealExp **************************/
1442 RealExp::RealExp(Loc loc, real_t value, Type *type)
1443 : Expression(loc, TOKfloat64, sizeof(RealExp))
1445 //printf("RealExp::RealExp(%Lg)\n", value);
1446 this->value = value;
1447 this->type = type;
1450 char *RealExp::toChars()
1452 char buffer[sizeof(value) * 3 + 8 + 1 + 1];
1454 #ifdef IN_GCC
1455 value.format(buffer, sizeof(buffer));
1456 if (type->isimaginary())
1457 strcat(buffer, "i");
1458 #else
1459 sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value);
1460 #endif
1461 assert(strlen(buffer) < sizeof(buffer));
1462 return mem.strdup(buffer);
1465 integer_t RealExp::toInteger()
1467 #ifdef IN_GCC
1468 return (d_int64) toReal().toInt();
1469 #else
1470 return (sinteger_t) toReal();
1471 #endif
1474 uinteger_t RealExp::toUInteger()
1476 #ifdef IN_GCC
1477 return (uinteger_t) toReal().toInt();
1478 #else
1479 return (uinteger_t) toReal();
1480 #endif
1483 real_t RealExp::toReal()
1485 return type->isreal() ? value : 0;
1488 real_t RealExp::toImaginary()
1490 return type->isreal() ? 0 : value;
1493 complex_t RealExp::toComplex()
1495 #ifdef __DMC__
1496 return toReal() + toImaginary() * I;
1497 #else
1498 return complex_t(toReal(), toImaginary());
1499 #endif
1502 /********************************
1503 * Test to see if two reals are the same.
1504 * Regard NaN's as equivalent.
1505 * Regard +0 and -0 as different.
1508 int RealEquals(real_t x1, real_t x2)
1510 #ifndef IN_GCC
1511 return (isnan(x1) && isnan(x2)) ||
1512 /* In some cases, the REALPAD bytes get garbage in them,
1513 * so be sure and ignore them.
1515 memcmp(&x1, &x2, REALSIZE - REALPAD) == 0;
1516 #else
1517 return (x1.isNan() && x2.isNan()) || x1.isIdenticalTo(x2);
1518 #endif
1521 int RealExp::equals(Object *o)
1522 { RealExp *ne;
1524 if (this == o ||
1525 (((Expression *)o)->op == TOKfloat64 &&
1526 ((ne = (RealExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
1527 RealEquals(value, ne->value)
1530 return 1;
1531 return 0;
1534 Expression *RealExp::semantic(Scope *sc)
1536 if (!type)
1537 type = Type::tfloat64;
1538 else
1539 type = type->semantic(loc, sc);
1540 return this;
1543 int RealExp::isBool(int result)
1545 #ifdef IN_GCC
1546 return result ? (! value.isZero()) : (value.isZero());
1547 #else
1548 return result ? (value != 0)
1549 : (value == 0);
1550 #endif
1553 void floatToBuffer(OutBuffer *buf, Type *type, const real_t & value)
1555 /* In order to get an exact representation, try converting it
1556 * to decimal then back again. If it matches, use it.
1557 * If it doesn't, fall back to hex, which is
1558 * always exact.
1560 char buffer[48];
1561 #ifdef IN_GCC
1562 real_t parsed_value;
1564 value.format(buffer, sizeof(buffer));
1565 parsed_value = real_t::parse(buffer, real_t::LongDouble);
1566 if (parsed_value.isIdenticalTo( value ))
1567 buf->writestring(buffer);
1568 else
1570 value.formatHex(buffer, sizeof(buffer));
1571 buf->writestring(buffer);
1573 #else
1574 sprintf(buffer, "%Lg", value);
1575 assert(strlen(buffer) < sizeof(buffer));
1576 #if _WIN32 && __DMC__
1577 char *save = __locale_decpoint;
1578 __locale_decpoint = ".";
1579 real_t r = strtold(buffer, NULL);
1580 __locale_decpoint = save;
1581 #else
1582 real_t r = strtold(buffer, NULL);
1583 #endif
1584 if (r == value) // if exact duplication
1585 buf->writestring(buffer);
1586 else
1587 buf->printf("%La", value); // ensure exact duplication
1588 #endif
1590 if (type)
1592 Type *t = type->toBasetype();
1593 switch (t->ty)
1595 case Tfloat32:
1596 case Timaginary32:
1597 case Tcomplex32:
1598 buf->writeByte('F');
1599 break;
1601 case Tfloat80:
1602 case Timaginary80:
1603 case Tcomplex80:
1604 buf->writeByte('L');
1605 break;
1607 default:
1608 break;
1610 if (t->isimaginary())
1611 buf->writeByte('i');
1615 void RealExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1617 floatToBuffer(buf, type, value);
1620 void realToMangleBuffer(OutBuffer *buf, real_t value)
1622 /* Rely on %A to get portable mangling.
1623 * Must munge result to get only identifier characters.
1625 * Possible values from %A => mangled result
1626 * NAN => NAN
1627 * -INF => NINF
1628 * INF => INF
1629 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79
1630 * 0X1.9P+2 => 19P2
1633 #ifdef IN_GCC
1634 if (value.isNan())
1635 buf->writestring("NAN"); // no -NAN bugs
1636 else if (value.isInf())
1637 buf->writestring(value.isNegative()?"NINF":"INF");
1638 #else
1639 if (isnan(value))
1640 buf->writestring("NAN"); // no -NAN bugs
1641 #endif
1642 else
1644 char buffer[64];
1645 #ifdef IN_GCC
1646 value.formatHex(buffer, sizeof(buffer));
1647 int n = strlen(buffer);
1648 #else
1649 int n = sprintf(buffer, "%LA", value);
1650 assert(n > 0 && n < sizeof(buffer));
1651 #endif
1652 for (int i = 0; i < n; i++)
1653 { char c = buffer[i];
1655 switch (c)
1657 case '-':
1658 buf->writeByte('N');
1659 break;
1661 case '+':
1662 case 'x':
1663 case 'X':
1664 case '.':
1665 break;
1667 case '0':
1668 if (i < 2)
1669 break; // skip leading 0X
1670 default:
1671 buf->writeByte(c);
1672 break;
1678 void RealExp::toMangleBuffer(OutBuffer *buf)
1680 buf->writeByte('e');
1681 realToMangleBuffer(buf, value);
1685 /******************************** ComplexExp **************************/
1687 ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type)
1688 : Expression(loc, TOKcomplex80, sizeof(ComplexExp))
1690 this->value = value;
1691 this->type = type;
1692 //printf("ComplexExp::ComplexExp(%s)\n", toChars());
1695 char *ComplexExp::toChars()
1697 char buffer[sizeof(value) * 3 + 8 + 1];
1699 #ifdef IN_GCC
1700 char buf1[sizeof(value) * 3 + 8 + 1];
1701 char buf2[sizeof(value) * 3 + 8 + 1];
1702 creall(value).format(buf1, sizeof(buf1));
1703 cimagl(value).format(buf2, sizeof(buf2));
1704 sprintf(buffer, "(%s+%si)", buf1, buf2);
1705 #else
1706 sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value));
1707 assert(strlen(buffer) < sizeof(buffer));
1708 #endif
1709 return mem.strdup(buffer);
1712 integer_t ComplexExp::toInteger()
1714 #ifdef IN_GCC
1715 return (d_int64) toReal().toInt();
1716 #else
1717 return (sinteger_t) toReal();
1718 #endif
1721 uinteger_t ComplexExp::toUInteger()
1723 #ifdef IN_GCC
1724 return (uinteger_t) toReal().toInt();
1725 #else
1726 return (uinteger_t) toReal();
1727 #endif
1730 real_t ComplexExp::toReal()
1732 return creall(value);
1735 real_t ComplexExp::toImaginary()
1737 return cimagl(value);
1740 complex_t ComplexExp::toComplex()
1742 return value;
1745 int ComplexExp::equals(Object *o)
1746 { ComplexExp *ne;
1748 if (this == o ||
1749 (((Expression *)o)->op == TOKcomplex80 &&
1750 ((ne = (ComplexExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
1751 #ifndef IN_GCC
1752 RealEquals(creall(value), creall(ne->value)) &&
1753 RealEquals(cimagl(value), cimagl(ne->value))
1754 #else
1755 RealEquals(value.re, ne->value.re) &&
1756 RealEquals(value.im, ne->value.im)
1757 #endif
1760 return 1;
1761 return 0;
1764 Expression *ComplexExp::semantic(Scope *sc)
1766 if (!type)
1767 type = Type::tcomplex80;
1768 else
1769 type = type->semantic(loc, sc);
1770 return this;
1773 int ComplexExp::isBool(int result)
1775 if (result)
1776 return (bool)(value);
1777 else
1778 return !value;
1781 void ComplexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1783 /* Print as:
1784 * (re+imi)
1786 #ifdef IN_GCC
1787 char buf1[sizeof(value) * 3 + 8 + 1];
1788 char buf2[sizeof(value) * 3 + 8 + 1];
1789 creall(value).format(buf1, sizeof(buf1));
1790 cimagl(value).format(buf2, sizeof(buf2));
1791 buf->printf("(%s+%si)", buf1, buf2);
1792 #else
1793 buf->writeByte('(');
1794 floatToBuffer(buf, type, creall(value));
1795 buf->writeByte('+');
1796 floatToBuffer(buf, type, cimagl(value));
1797 buf->writestring("i)");
1798 #endif
1801 void ComplexExp::toMangleBuffer(OutBuffer *buf)
1803 buf->writeByte('c');
1804 real_t r = toReal();
1805 realToMangleBuffer(buf, r);
1806 buf->writeByte('c'); // separate the two
1807 r = toImaginary();
1808 realToMangleBuffer(buf, r);
1811 /******************************** IdentifierExp **************************/
1813 IdentifierExp::IdentifierExp(Loc loc, Identifier *ident)
1814 : Expression(loc, TOKidentifier, sizeof(IdentifierExp))
1816 this->ident = ident;
1819 Expression *IdentifierExp::semantic(Scope *sc)
1821 Dsymbol *s;
1822 Dsymbol *scopesym;
1824 #if LOGSEMANTIC
1825 printf("IdentifierExp::semantic('%s')\n", ident->toChars());
1826 #endif
1827 s = sc->search(loc, ident, &scopesym);
1828 if (s)
1829 { Expression *e;
1830 WithScopeSymbol *withsym;
1832 /* See if the symbol was a member of an enclosing 'with'
1834 withsym = scopesym->isWithScopeSymbol();
1835 if (withsym)
1837 s = s->toAlias();
1839 // Same as wthis.ident
1840 if (s->needThis() || s->isTemplateDeclaration())
1842 e = new VarExp(loc, withsym->withstate->wthis);
1843 e = new DotIdExp(loc, e, ident);
1845 else
1846 { Type *t = withsym->withstate->wthis->type;
1847 if (t->ty == Tpointer)
1848 t = ((TypePointer *)t)->next;
1849 e = new TypeDotIdExp(loc, t, ident);
1852 else
1854 /* If f is really a function template,
1855 * then replace f with the function template declaration.
1857 FuncDeclaration *f = s->isFuncDeclaration();
1858 if (f && f->parent)
1859 { TemplateInstance *ti = f->parent->isTemplateInstance();
1861 if (ti &&
1862 !ti->isTemplateMixin() &&
1863 (ti->name == f->ident ||
1864 ti->toAlias()->ident == f->ident)
1866 ti->tempdecl && ti->tempdecl->onemember)
1868 TemplateDeclaration *tempdecl = ti->tempdecl;
1869 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's
1870 tempdecl = tempdecl->overroot; // then get the start
1871 e = new TemplateExp(loc, tempdecl);
1872 e = e->semantic(sc);
1873 return e;
1876 // Haven't done overload resolution yet, so pass 1
1877 e = new DsymbolExp(loc, s, 1);
1879 return e->semantic(sc);
1881 error("undefined identifier %s", ident->toChars());
1882 type = Type::terror;
1883 return this;
1886 char *IdentifierExp::toChars()
1888 return ident->toChars();
1891 void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1893 if (hgs->hdrgen)
1894 buf->writestring(ident->toHChars2());
1895 else
1896 buf->writestring(ident->toChars());
1899 Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e)
1901 #if 0
1902 tym = tybasic(e1->ET->Tty);
1903 if (!(tyscalar(tym) ||
1904 tym == TYstruct ||
1905 tym == TYarray && e->Eoper == TOKaddr))
1906 synerr(EM_lvalue); // lvalue expected
1907 #endif
1908 return this;
1911 /******************************** DollarExp **************************/
1913 DollarExp::DollarExp(Loc loc)
1914 : IdentifierExp(loc, Id::dollar)
1918 /******************************** DsymbolExp **************************/
1920 DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, int hasOverloads)
1921 : Expression(loc, TOKdsymbol, sizeof(DsymbolExp))
1923 this->s = s;
1924 this->hasOverloads = hasOverloads;
1927 Expression *DsymbolExp::semantic(Scope *sc)
1929 #if LOGSEMANTIC
1930 printf("DsymbolExp::semantic('%s')\n", s->toChars());
1931 #endif
1933 Lagain:
1934 EnumMember *em;
1935 Expression *e;
1936 VarDeclaration *v;
1937 FuncDeclaration *f;
1938 FuncLiteralDeclaration *fld;
1939 OverloadSet *o;
1940 Declaration *d;
1941 ClassDeclaration *cd;
1942 ClassDeclaration *thiscd = NULL;
1943 Import *imp;
1944 Package *pkg;
1945 Type *t;
1947 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
1948 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
1949 if (type)
1950 return this;
1951 if (!s->isFuncDeclaration()) // functions are checked after overloading
1952 checkDeprecated(sc, s);
1953 s = s->toAlias();
1954 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
1955 if (!s->isFuncDeclaration())
1956 checkDeprecated(sc, s);
1958 if (sc->func)
1959 thiscd = sc->func->parent->isClassDeclaration();
1961 // BUG: This should happen after overload resolution for functions, not before
1962 if (s->needThis())
1964 if (hasThis(sc) && !s->isFuncDeclaration())
1966 // Supply an implicit 'this', as in
1967 // this.ident
1969 DotVarExp *de;
1971 de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration());
1972 return de->semantic(sc);
1976 em = s->isEnumMember();
1977 if (em)
1979 e = em->value;
1980 e = e->semantic(sc);
1981 return e;
1983 v = s->isVarDeclaration();
1984 if (v)
1986 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
1987 if (!type)
1988 { type = v->type;
1989 if (!v->type)
1990 { error("forward reference of %s", v->toChars());
1991 type = Type::terror;
1994 e = new VarExp(loc, v);
1995 e->type = type;
1996 e = e->semantic(sc);
1997 return e->deref();
1999 fld = s->isFuncLiteralDeclaration();
2000 if (fld)
2001 { //printf("'%s' is a function literal\n", fld->toChars());
2002 e = new FuncExp(loc, fld);
2003 return e->semantic(sc);
2005 f = s->isFuncDeclaration();
2006 if (f)
2007 { //printf("'%s' is a function\n", f->toChars());
2008 return new VarExp(loc, f, hasOverloads);
2010 o = s->isOverloadSet();
2011 if (o)
2012 { //printf("'%s' is an overload set\n", o->toChars());
2013 return new OverExp(o);
2015 cd = s->isClassDeclaration();
2016 if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis())
2018 // We need to add an implicit 'this' if cd is this class or a base class.
2019 DotTypeExp *dte;
2021 dte = new DotTypeExp(loc, new ThisExp(loc), s);
2022 return dte->semantic(sc);
2024 imp = s->isImport();
2025 if (imp)
2027 ScopeExp *ie;
2029 ie = new ScopeExp(loc, imp->pkg);
2030 return ie->semantic(sc);
2032 pkg = s->isPackage();
2033 if (pkg)
2035 ScopeExp *ie;
2037 ie = new ScopeExp(loc, pkg);
2038 return ie->semantic(sc);
2040 Module *mod = s->isModule();
2041 if (mod)
2043 ScopeExp *ie;
2045 ie = new ScopeExp(loc, mod);
2046 return ie->semantic(sc);
2049 t = s->getType();
2050 if (t)
2052 return new TypeExp(loc, t);
2055 TupleDeclaration *tup = s->isTupleDeclaration();
2056 if (tup)
2058 e = new TupleExp(loc, tup);
2059 e = e->semantic(sc);
2060 return e;
2063 TemplateInstance *ti = s->isTemplateInstance();
2064 if (ti && !global.errors)
2065 { if (!ti->semanticdone)
2066 ti->semantic(sc);
2067 s = ti->inst->toAlias();
2068 if (!s->isTemplateInstance())
2069 goto Lagain;
2070 e = new ScopeExp(loc, ti);
2071 e = e->semantic(sc);
2072 return e;
2075 TemplateDeclaration *td = s->isTemplateDeclaration();
2076 if (td)
2078 e = new TemplateExp(loc, td);
2079 e = e->semantic(sc);
2080 return e;
2083 Lerr:
2084 error("%s '%s' is not a variable", s->kind(), s->toChars());
2085 type = Type::terror;
2086 return this;
2089 char *DsymbolExp::toChars()
2091 return s->toChars();
2094 void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2096 buf->writestring(s->toChars());
2099 Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e)
2101 #if 0
2102 tym = tybasic(e1->ET->Tty);
2103 if (!(tyscalar(tym) ||
2104 tym == TYstruct ||
2105 tym == TYarray && e->Eoper == TOKaddr))
2106 synerr(EM_lvalue); // lvalue expected
2107 #endif
2108 return this;
2111 /******************************** GetLoggerExp **************************/
2113 GetLoggerExp::GetLoggerExp(Loc loc)
2114 : Expression(loc, TOKlogger, sizeof(GetLoggerExp))
2118 Expression *GetLoggerExp::semantic(Scope *sc)
2120 Expression *log = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), Id::__log);
2121 return log->semantic(sc);
2124 void GetLoggerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2126 buf->writestring("log");
2129 /******************************** ThisExp **************************/
2131 ThisExp::ThisExp(Loc loc)
2132 : Expression(loc, TOKthis, sizeof(ThisExp))
2134 var = NULL;
2137 Expression *ThisExp::semantic(Scope *sc)
2138 { FuncDeclaration *fd;
2139 FuncDeclaration *fdthis;
2140 int nested = 0;
2142 #if LOGSEMANTIC
2143 printf("ThisExp::semantic()\n");
2144 #endif
2145 if (type)
2146 { //assert(global.errors || var);
2147 return this;
2150 /* Special case for typeof(this) and typeof(super) since both
2151 * should work even if they are not inside a non-static member function
2153 if (sc->intypeof)
2155 // Find enclosing struct or class
2156 for (Dsymbol *s = sc->parent; 1; s = s->parent)
2158 ClassDeclaration *cd;
2159 StructDeclaration *sd;
2161 if (!s)
2163 error("%s is not in a struct or class scope", toChars());
2164 goto Lerr;
2166 cd = s->isClassDeclaration();
2167 if (cd)
2169 type = cd->type;
2170 return this;
2172 sd = s->isStructDeclaration();
2173 if (sd)
2175 type = sd->type->pointerTo();
2176 return this;
2181 fdthis = sc->parent->isFuncDeclaration();
2182 fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2183 if (!fd)
2184 goto Lerr;
2186 assert(fd->vthis);
2187 var = fd->vthis;
2188 assert(var->parent);
2189 type = var->type;
2190 var->isVarDeclaration()->checkNestedReference(sc, loc);
2191 sc->callSuper |= CSXthis;
2192 return this;
2194 Lerr:
2195 error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars());
2196 type = Type::terror;
2197 return this;
2200 int ThisExp::isBool(int result)
2202 return result ? TRUE : FALSE;
2205 void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2207 buf->writestring("this");
2210 Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
2212 return this;
2215 /******************************** SuperExp **************************/
2217 SuperExp::SuperExp(Loc loc)
2218 : ThisExp(loc)
2220 op = TOKsuper;
2223 Expression *SuperExp::semantic(Scope *sc)
2224 { FuncDeclaration *fd;
2225 FuncDeclaration *fdthis;
2226 ClassDeclaration *cd;
2227 Dsymbol *s;
2229 #if LOGSEMANTIC
2230 printf("SuperExp::semantic('%s')\n", toChars());
2231 #endif
2232 if (type)
2233 return this;
2235 /* Special case for typeof(this) and typeof(super) since both
2236 * should work even if they are not inside a non-static member function
2238 if (sc->intypeof)
2240 // Find enclosing class
2241 for (Dsymbol *s = sc->parent; 1; s = s->parent)
2243 ClassDeclaration *cd;
2245 if (!s)
2247 error("%s is not in a class scope", toChars());
2248 goto Lerr;
2250 cd = s->isClassDeclaration();
2251 if (cd)
2253 cd = cd->baseClass;
2254 if (!cd)
2255 { error("class %s has no 'super'", s->toChars());
2256 goto Lerr;
2258 type = cd->type;
2259 return this;
2264 fdthis = sc->parent->isFuncDeclaration();
2265 fd = hasThis(sc);
2266 if (!fd)
2267 goto Lerr;
2268 assert(fd->vthis);
2269 var = fd->vthis;
2270 assert(var->parent);
2272 s = fd->toParent();
2273 while (s && s->isTemplateInstance())
2274 s = s->toParent();
2275 assert(s);
2276 cd = s->isClassDeclaration();
2277 //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
2278 if (!cd)
2279 goto Lerr;
2280 if (!cd->baseClass)
2282 error("no base class for %s", cd->toChars());
2283 type = fd->vthis->type;
2285 else
2287 type = cd->baseClass->type;
2290 var->isVarDeclaration()->checkNestedReference(sc, loc);
2292 sc->callSuper |= CSXsuper;
2293 return this;
2296 Lerr:
2297 error("'super' is only allowed in non-static class member functions");
2298 type = Type::tint32;
2299 return this;
2302 void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2304 buf->writestring("super");
2308 /******************************** NullExp **************************/
2310 NullExp::NullExp(Loc loc)
2311 : Expression(loc, TOKnull, sizeof(NullExp))
2313 committed = 0;
2314 dUnchecked = false;
2317 Expression *NullExp::semantic(Scope *sc)
2319 #if LOGSEMANTIC
2320 printf("NullExp::semantic('%s')\n", toChars());
2321 #endif
2322 // NULL is the same as (void *)0
2323 if (!type)
2324 type = Type::tvoid->pointerTo();
2325 return this;
2328 int NullExp::isBool(int result)
2330 return result ? FALSE : TRUE;
2333 void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2335 buf->writestring("null");
2338 void NullExp::toMangleBuffer(OutBuffer *buf)
2340 buf->writeByte('n');
2343 /******************************** StringExp **************************/
2345 StringExp::StringExp(Loc loc, char *string)
2346 : Expression(loc, TOKstring, sizeof(StringExp))
2348 this->string = string;
2349 this->len = strlen(string);
2350 this->sz = 1;
2351 this->committed = 0;
2352 this->postfix = 0;
2355 StringExp::StringExp(Loc loc, void *string, size_t len)
2356 : Expression(loc, TOKstring, sizeof(StringExp))
2358 this->string = string;
2359 this->len = len;
2360 this->sz = 1;
2361 this->committed = 0;
2362 this->postfix = 0;
2365 StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix)
2366 : Expression(loc, TOKstring, sizeof(StringExp))
2368 this->string = string;
2369 this->len = len;
2370 this->sz = 1;
2371 this->committed = 0;
2372 this->postfix = postfix;
2375 #if 0
2376 Expression *StringExp::syntaxCopy()
2378 printf("StringExp::syntaxCopy() %s\n", toChars());
2379 return copy();
2381 #endif
2383 int StringExp::equals(Object *o)
2385 //printf("StringExp::equals('%s')\n", o->toChars());
2386 if (o && o->dyncast() == DYNCAST_EXPRESSION)
2387 { Expression *e = (Expression *)o;
2389 if (e->op == TOKstring)
2391 return compare(o) == 0;
2394 return FALSE;
2397 char *StringExp::toChars()
2399 OutBuffer buf;
2400 HdrGenState hgs;
2401 char *p;
2403 memset(&hgs, 0, sizeof(hgs));
2404 toCBuffer(&buf, &hgs);
2405 buf.writeByte(0);
2406 p = (char *)buf.data;
2407 buf.data = NULL;
2408 return p;
2411 Expression *StringExp::semantic(Scope *sc)
2413 #if LOGSEMANTIC
2414 printf("StringExp::semantic() %s\n", toChars());
2415 #endif
2416 if (!type)
2417 { OutBuffer buffer;
2418 size_t newlen = 0;
2419 char *p;
2420 size_t u;
2421 unsigned c;
2423 switch (postfix)
2425 case 'd':
2426 for (u = 0; u < len;)
2428 p = utf_decodeChar((unsigned char *)string, len, &u, &c);
2429 if (p)
2430 { error("%s", p);
2431 break;
2433 else
2434 { buffer.write4(c);
2435 newlen++;
2438 buffer.write4(0);
2439 string = buffer.extractData();
2440 len = newlen;
2441 sz = 4;
2442 type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex));
2443 committed = 1;
2444 break;
2446 case 'w':
2447 for (u = 0; u < len;)
2449 p = utf_decodeChar((unsigned char *)string, len, &u, &c);
2450 if (p)
2451 { error("%s", p);
2452 break;
2454 else
2455 { buffer.writeUTF16(c);
2456 newlen++;
2457 if (c >= 0x10000)
2458 newlen++;
2461 buffer.writeUTF16(0);
2462 string = buffer.extractData();
2463 len = newlen;
2464 sz = 2;
2465 type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex));
2466 committed = 1;
2467 break;
2469 case 'c':
2470 committed = 1;
2471 default:
2472 type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex));
2473 break;
2475 type = type->semantic(loc, sc);
2476 type = type->invariantOf();
2477 //printf("type = %s\n", type->toChars());
2479 return this;
2482 /****************************************
2483 * Convert string to char[].
2486 StringExp *StringExp::toUTF8(Scope *sc)
2488 if (sz != 1)
2489 { // Convert to UTF-8 string
2490 committed = 0;
2491 Expression *e = castTo(sc, Type::tchar->arrayOf());
2492 e = e->optimize(WANTvalue);
2493 assert(e->op == TOKstring);
2494 StringExp *se = (StringExp *)e;
2495 assert(se->sz == 1);
2496 return se;
2498 return this;
2501 int StringExp::compare(Object *obj)
2503 // Used to sort case statement expressions so we can do an efficient lookup
2504 StringExp *se2 = (StringExp *)(obj);
2506 // This is a kludge so isExpression() in template.c will return 5
2507 // for StringExp's.
2508 if (!se2)
2509 return 5;
2511 assert(se2->op == TOKstring);
2513 int len1 = len;
2514 int len2 = se2->len;
2516 if (len1 == len2)
2518 switch (sz)
2520 case 1:
2521 return strcmp((char *)string, (char *)se2->string);
2523 case 2:
2524 { unsigned u;
2525 d_wchar *s1 = (d_wchar *)string;
2526 d_wchar *s2 = (d_wchar *)se2->string;
2528 for (u = 0; u < len; u++)
2530 if (s1[u] != s2[u])
2531 return s1[u] - s2[u];
2535 case 4:
2536 { unsigned u;
2537 d_dchar *s1 = (d_dchar *)string;
2538 d_dchar *s2 = (d_dchar *)se2->string;
2540 for (u = 0; u < len; u++)
2542 if (s1[u] != s2[u])
2543 return s1[u] - s2[u];
2546 break;
2548 default:
2549 assert(0);
2552 return len1 - len2;
2555 int StringExp::isBool(int result)
2557 return result ? TRUE : FALSE;
2560 unsigned StringExp::charAt(size_t i)
2561 { unsigned value;
2563 switch (sz)
2565 case 1:
2566 value = ((unsigned char *)string)[i];
2567 break;
2569 case 2:
2570 value = ((unsigned short *)string)[i];
2571 break;
2573 case 4:
2574 value = ((unsigned int *)string)[i];
2575 break;
2577 default:
2578 assert(0);
2579 break;
2581 return value;
2584 void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2586 buf->writeByte('"');
2587 for (size_t i = 0; i < len; i++)
2588 { unsigned c = charAt(i);
2590 switch (c)
2592 case '"':
2593 case '\\':
2594 if (!hgs->console)
2595 buf->writeByte('\\');
2596 default:
2597 if (c <= 0xFF)
2598 { if (c <= 0x7F && (isprint(c) || hgs->console))
2599 buf->writeByte(c);
2600 else
2601 buf->printf("\\x%02x", c);
2603 else if (c <= 0xFFFF)
2604 buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8);
2605 else
2606 buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
2607 c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24);
2608 break;
2611 buf->writeByte('"');
2612 if (postfix)
2613 buf->writeByte(postfix);
2616 void StringExp::toMangleBuffer(OutBuffer *buf)
2617 { char m;
2618 OutBuffer tmp;
2619 char *p;
2620 dchar_t c;
2621 size_t u;
2622 unsigned char *q;
2623 unsigned qlen;
2625 /* Write string in UTF-8 format
2627 switch (sz)
2628 { case 1:
2629 m = 'a';
2630 q = (unsigned char *)string;
2631 qlen = len;
2632 break;
2633 case 2:
2634 m = 'w';
2635 for (u = 0; u < len; )
2637 p = utf_decodeWchar((unsigned short *)string, len, &u, &c);
2638 if (p)
2639 error("%s", p);
2640 else
2641 tmp.writeUTF8(c);
2643 q = tmp.data;
2644 qlen = tmp.offset;
2645 break;
2646 case 4:
2647 m = 'd';
2648 for (u = 0; u < len; u++)
2650 c = ((unsigned *)string)[u];
2651 if (!utf_isValidDchar(c))
2652 error("invalid UCS-32 char \\U%08x", c);
2653 else
2654 tmp.writeUTF8(c);
2656 q = tmp.data;
2657 qlen = tmp.offset;
2658 break;
2659 default:
2660 assert(0);
2662 buf->writeByte(m);
2663 buf->printf("%d_", qlen);
2664 for (size_t i = 0; i < qlen; i++)
2665 buf->printf("%02x", q[i]);
2668 /************************ ArrayLiteralExp ************************************/
2670 // [ e1, e2, e3, ... ]
2672 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements)
2673 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
2675 this->elements = elements;
2678 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e)
2679 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
2681 elements = new Expressions;
2682 elements->push(e);
2685 Expression *ArrayLiteralExp::syntaxCopy()
2687 return new ArrayLiteralExp(loc, arraySyntaxCopy(elements));
2690 Expression *ArrayLiteralExp::semantic(Scope *sc)
2691 { Expression *e;
2692 Type *t0 = NULL;
2694 #if LOGSEMANTIC
2695 printf("ArrayLiteralExp::semantic('%s')\n", toChars());
2696 #endif
2697 if (type)
2698 return this;
2700 // Run semantic() on each element
2701 for (int i = 0; i < elements->dim; i++)
2702 { e = (Expression *)elements->data[i];
2703 e = e->semantic(sc);
2704 elements->data[i] = (void *)e;
2706 expandTuples(elements);
2707 for (int i = 0; i < elements->dim; i++)
2708 { e = (Expression *)elements->data[i];
2710 if (!e->type)
2711 error("%s has no value", e->toChars());
2712 e = resolveProperties(sc, e);
2714 unsigned char committed = 1;
2715 if (e->op == TOKstring)
2716 committed = ((StringExp *)e)->committed;
2718 if (!t0)
2719 { t0 = e->type;
2720 // Convert any static arrays to dynamic arrays
2721 if (t0->ty == Tsarray)
2723 t0 = ((TypeSArray *)t0)->next->arrayOf();
2724 e = e->implicitCastTo(sc, t0);
2727 else
2728 e = e->implicitCastTo(sc, t0);
2729 if (!committed && e->op == TOKstring)
2730 { StringExp *se = (StringExp *)e;
2731 se->committed = 0;
2733 elements->data[i] = (void *)e;
2736 if (!t0)
2737 t0 = Type::tvoid;
2738 type = new TypeSArray(t0, new IntegerExp(elements->dim));
2739 type = type->semantic(loc, sc);
2740 return this;
2743 int ArrayLiteralExp::checkSideEffect(int flag)
2744 { int f = 0;
2746 for (size_t i = 0; i < elements->dim; i++)
2747 { Expression *e = (Expression *)elements->data[i];
2749 f |= e->checkSideEffect(2);
2751 if (flag == 0 && f == 0)
2752 Expression::checkSideEffect(0);
2753 return f;
2756 int ArrayLiteralExp::isBool(int result)
2758 size_t dim = elements ? elements->dim : 0;
2759 return result ? (dim != 0) : (dim == 0);
2762 int ArrayLiteralExp::canThrow()
2764 return 1; // because it can fail allocating memory
2767 void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2769 buf->writeByte('[');
2770 argsToCBuffer(buf, elements, hgs);
2771 buf->writeByte(']');
2774 void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
2776 size_t dim = elements ? elements->dim : 0;
2777 buf->printf("A%"PRIuSIZE, dim);
2778 for (size_t i = 0; i < dim; i++)
2779 { Expression *e = (Expression *)elements->data[i];
2780 e->toMangleBuffer(buf);
2784 /************************ AssocArrayLiteralExp ************************************/
2786 // [ key0 : value0, key1 : value1, ... ]
2788 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc,
2789 Expressions *keys, Expressions *values)
2790 : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp))
2792 assert(keys->dim == values->dim);
2793 this->keys = keys;
2794 this->values = values;
2797 Expression *AssocArrayLiteralExp::syntaxCopy()
2799 return new AssocArrayLiteralExp(loc,
2800 arraySyntaxCopy(keys), arraySyntaxCopy(values));
2803 Expression *AssocArrayLiteralExp::semantic(Scope *sc)
2804 { Expression *e;
2805 Type *tkey = NULL;
2806 Type *tvalue = NULL;
2808 #if LOGSEMANTIC
2809 printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
2810 #endif
2812 // Run semantic() on each element
2813 for (size_t i = 0; i < keys->dim; i++)
2814 { Expression *key = (Expression *)keys->data[i];
2815 Expression *value = (Expression *)values->data[i];
2817 key = key->semantic(sc);
2818 value = value->semantic(sc);
2820 keys->data[i] = (void *)key;
2821 values->data[i] = (void *)value;
2823 expandTuples(keys);
2824 expandTuples(values);
2825 if (keys->dim != values->dim)
2827 error("number of keys is %u, must match number of values %u", keys->dim, values->dim);
2828 keys->setDim(0);
2829 values->setDim(0);
2831 for (size_t i = 0; i < keys->dim; i++)
2832 { Expression *key = (Expression *)keys->data[i];
2833 Expression *value = (Expression *)values->data[i];
2835 if (!key->type)
2836 error("%s has no value", key->toChars());
2837 if (!value->type)
2838 error("%s has no value", value->toChars());
2839 key = resolveProperties(sc, key);
2840 value = resolveProperties(sc, value);
2842 if (!tkey)
2843 tkey = key->type;
2844 else
2845 key = key->implicitCastTo(sc, tkey);
2846 keys->data[i] = (void *)key;
2848 if (!tvalue)
2849 tvalue = value->type;
2850 else
2851 value = value->implicitCastTo(sc, tvalue);
2852 values->data[i] = (void *)value;
2855 if (!tkey)
2856 tkey = Type::tvoid;
2857 if (!tvalue)
2858 tvalue = Type::tvoid;
2859 type = new TypeAArray(tvalue, tkey);
2860 type = type->semantic(loc, sc);
2861 return this;
2864 int AssocArrayLiteralExp::checkSideEffect(int flag)
2865 { int f = 0;
2867 for (size_t i = 0; i < keys->dim; i++)
2868 { Expression *key = (Expression *)keys->data[i];
2869 Expression *value = (Expression *)values->data[i];
2871 f |= key->checkSideEffect(2);
2872 f |= value->checkSideEffect(2);
2874 if (flag == 0 && f == 0)
2875 Expression::checkSideEffect(0);
2876 return f;
2879 int AssocArrayLiteralExp::isBool(int result)
2881 size_t dim = keys->dim;
2882 return result ? (dim != 0) : (dim == 0);
2885 int AssocArrayLiteralExp::canThrow()
2887 return 1;
2890 void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2892 buf->writeByte('[');
2893 for (size_t i = 0; i < keys->dim; i++)
2894 { Expression *key = (Expression *)keys->data[i];
2895 Expression *value = (Expression *)values->data[i];
2897 if (i)
2898 buf->writeByte(',');
2899 expToCBuffer(buf, hgs, key, PREC_assign);
2900 buf->writeByte(':');
2901 expToCBuffer(buf, hgs, value, PREC_assign);
2903 buf->writeByte(']');
2906 void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
2908 size_t dim = keys->dim;
2909 buf->printf("A%u", dim);
2910 for (size_t i = 0; i < dim; i++)
2911 { Expression *key = (Expression *)keys->data[i];
2912 Expression *value = (Expression *)values->data[i];
2914 key->toMangleBuffer(buf);
2915 value->toMangleBuffer(buf);
2919 /************************ StructLiteralExp ************************************/
2921 // sd( e1, e2, e3, ... )
2923 StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements)
2924 : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp))
2926 this->sd = sd;
2927 this->elements = elements;
2928 this->sym = NULL;
2929 this->soffset = 0;
2930 this->fillHoles = 1;
2933 Expression *StructLiteralExp::syntaxCopy()
2935 return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements));
2938 Expression *StructLiteralExp::semantic(Scope *sc)
2939 { Expression *e;
2941 #if LOGSEMANTIC
2942 printf("StructLiteralExp::semantic('%s')\n", toChars());
2943 #endif
2944 if (type)
2945 return this;
2947 // Run semantic() on each element
2948 for (size_t i = 0; i < elements->dim; i++)
2949 { e = (Expression *)elements->data[i];
2950 if (!e)
2951 continue;
2952 e = e->semantic(sc);
2953 elements->data[i] = (void *)e;
2955 expandTuples(elements);
2956 size_t offset = 0;
2957 for (size_t i = 0; i < elements->dim; i++)
2958 { e = (Expression *)elements->data[i];
2959 if (!e)
2960 continue;
2962 if (!e->type)
2963 error("%s has no value", e->toChars());
2964 e = resolveProperties(sc, e);
2965 if (i >= sd->fields.dim)
2966 { error("more initializers than fields of %s", sd->toChars());
2967 break;
2969 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
2970 VarDeclaration *v = s->isVarDeclaration();
2971 assert(v);
2972 if (v->offset < offset)
2973 error("overlapping initialization for %s", v->toChars());
2974 offset = v->offset + v->type->size();
2976 Type *telem = v->type;
2977 while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray)
2978 { /* Static array initialization, as in:
2979 * T[3][5] = e;
2981 telem = telem->toBasetype()->nextOf();
2984 e = e->implicitCastTo(sc, telem);
2986 elements->data[i] = (void *)e;
2989 /* Fill out remainder of elements[] with default initializers for fields[]
2991 for (size_t i = elements->dim; i < sd->fields.dim; i++)
2992 { Dsymbol *s = (Dsymbol *)sd->fields.data[i];
2993 VarDeclaration *v = s->isVarDeclaration();
2994 assert(v);
2996 if (v->offset < offset)
2997 { e = NULL;
2998 sd->hasUnions = 1;
3000 else
3002 if (v->init)
3003 { e = v->init->toExpression();
3004 if (!e)
3005 error("cannot make expression out of initializer for %s", v->toChars());
3007 else
3008 { e = v->type->defaultInit();
3009 e->loc = loc;
3011 offset = v->offset + v->type->size();
3013 elements->push(e);
3016 type = sd->type;
3017 return this;
3020 /**************************************
3021 * Gets expression at offset of type.
3022 * Returns NULL if not found.
3025 Expression *StructLiteralExp::getField(Type *type, unsigned offset)
3027 //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
3028 // /*toChars()*/"", type->toChars(), offset);
3029 Expression *e = NULL;
3030 int i = getFieldIndex(type, offset);
3032 if (i != -1)
3034 //printf("\ti = %d\n", i);
3035 assert(i < elements->dim);
3036 e = (Expression *)elements->data[i];
3037 if (e)
3039 e = e->copy();
3040 e->type = type;
3043 return e;
3046 /************************************
3047 * Get index of field.
3048 * Returns -1 if not found.
3051 int StructLiteralExp::getFieldIndex(Type *type, unsigned offset)
3053 /* Find which field offset is by looking at the field offsets
3055 for (size_t i = 0; i < sd->fields.dim; i++)
3057 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
3058 VarDeclaration *v = s->isVarDeclaration();
3059 assert(v);
3061 if (offset == v->offset &&
3062 type->size() == v->type->size())
3063 { Expression *e = (Expression *)elements->data[i];
3064 if (e)
3066 return i;
3068 break;
3071 return -1;
3075 Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e)
3077 return this;
3081 int StructLiteralExp::checkSideEffect(int flag)
3082 { int f = 0;
3084 for (size_t i = 0; i < elements->dim; i++)
3085 { Expression *e = (Expression *)elements->data[i];
3086 if (!e)
3087 continue;
3089 f |= e->checkSideEffect(2);
3091 if (flag == 0 && f == 0)
3092 Expression::checkSideEffect(0);
3093 return f;
3096 int StructLiteralExp::canThrow()
3098 return arrayExpressionCanThrow(elements);
3101 void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3103 buf->writestring(sd->toChars());
3104 buf->writeByte('(');
3105 argsToCBuffer(buf, elements, hgs);
3106 buf->writeByte(')');
3109 void StructLiteralExp::toMangleBuffer(OutBuffer *buf)
3111 size_t dim = elements ? elements->dim : 0;
3112 buf->printf("S%u", dim);
3113 for (size_t i = 0; i < dim; i++)
3114 { Expression *e = (Expression *)elements->data[i];
3115 if (e)
3116 e->toMangleBuffer(buf);
3117 else
3118 buf->writeByte('v'); // 'v' for void
3122 /************************ TypeDotIdExp ************************************/
3124 /* Things like:
3125 * int.size
3126 * foo.size
3127 * (foo).size
3128 * cast(foo).size
3131 TypeDotIdExp::TypeDotIdExp(Loc loc, Type *type, Identifier *ident)
3132 : Expression(loc, TOKtypedot, sizeof(TypeDotIdExp))
3134 this->type = type;
3135 this->ident = ident;
3138 Expression *TypeDotIdExp::syntaxCopy()
3140 TypeDotIdExp *te = new TypeDotIdExp(loc, type->syntaxCopy(), ident);
3141 return te;
3144 Expression *TypeDotIdExp::semantic(Scope *sc)
3145 { Expression *e;
3147 #if LOGSEMANTIC
3148 printf("TypeDotIdExp::semantic()\n");
3149 #endif
3150 e = new DotIdExp(loc, new TypeExp(loc, type), ident);
3151 e = e->semantic(sc);
3152 return e;
3155 void TypeDotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3157 buf->writeByte('(');
3158 type->toCBuffer(buf, NULL, hgs);
3159 buf->writeByte(')');
3160 buf->writeByte('.');
3161 buf->writestring(ident->toChars());
3164 /************************************************************/
3166 // Mainly just a placeholder
3168 TypeExp::TypeExp(Loc loc, Type *type)
3169 : Expression(loc, TOKtype, sizeof(TypeExp))
3171 //printf("TypeExp::TypeExp(%s)\n", type->toChars());
3172 this->type = type;
3175 Expression *TypeExp::semantic(Scope *sc)
3177 //printf("TypeExp::semantic(%s)\n", type->toChars());
3178 type = type->semantic(loc, sc);
3179 return this;
3182 void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3184 type->toCBuffer(buf, NULL, hgs);
3187 /************************************************************/
3189 // Mainly just a placeholder
3191 ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg)
3192 : Expression(loc, TOKimport, sizeof(ScopeExp))
3194 //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars());
3195 //static int count; if (++count == 38) *(char*)0=0;
3196 this->sds = pkg;
3199 Expression *ScopeExp::syntaxCopy()
3201 ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL));
3202 return se;
3205 Expression *ScopeExp::semantic(Scope *sc)
3207 TemplateInstance *ti;
3208 ScopeDsymbol *sds2;
3210 #if LOGSEMANTIC
3211 printf("+ScopeExp::semantic('%s')\n", toChars());
3212 #endif
3213 Lagain:
3214 ti = sds->isTemplateInstance();
3215 if (ti && !global.errors)
3216 { Dsymbol *s;
3217 if (!ti->semanticdone)
3218 ti->semantic(sc);
3219 s = ti->inst->toAlias();
3220 sds2 = s->isScopeDsymbol();
3221 if (!sds2)
3222 { Expression *e;
3224 //printf("s = %s, '%s'\n", s->kind(), s->toChars());
3225 if (ti->withsym)
3227 // Same as wthis.s
3228 e = new VarExp(loc, ti->withsym->withstate->wthis);
3229 e = new DotVarExp(loc, e, s->isDeclaration());
3231 else
3232 e = new DsymbolExp(loc, s);
3233 e = e->semantic(sc);
3234 //printf("-1ScopeExp::semantic()\n");
3235 return e;
3237 if (sds2 != sds)
3239 sds = sds2;
3240 goto Lagain;
3242 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3244 else
3246 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3247 //printf("\tparent = '%s'\n", sds->parent->toChars());
3248 sds->semantic(sc);
3250 type = Type::tvoid;
3251 //printf("-2ScopeExp::semantic() %s\n", toChars());
3252 return this;
3255 void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3257 if (sds->isTemplateInstance())
3259 sds->toCBuffer(buf, hgs);
3261 else
3263 buf->writestring(sds->kind());
3264 buf->writestring(" ");
3265 buf->writestring(sds->toChars());
3269 /********************** TemplateExp **************************************/
3271 // Mainly just a placeholder
3273 TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td)
3274 : Expression(loc, TOKtemplate, sizeof(TemplateExp))
3276 //printf("TemplateExp(): %s\n", td->toChars());
3277 this->td = td;
3280 void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3282 buf->writestring(td->toChars());
3285 void TemplateExp::rvalue()
3287 error("template %s has no value", toChars());
3290 /********************** NewExp **************************************/
3292 NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
3293 Type *newtype, Expressions *arguments)
3294 : Expression(loc, TOKnew, sizeof(NewExp))
3296 this->thisexp = thisexp;
3297 this->newargs = newargs;
3298 this->newtype = newtype;
3299 this->arguments = arguments;
3300 member = NULL;
3301 allocator = NULL;
3302 onstack = 0;
3305 Expression *NewExp::syntaxCopy()
3307 return new NewExp(loc,
3308 thisexp ? thisexp->syntaxCopy() : NULL,
3309 arraySyntaxCopy(newargs),
3310 newtype->syntaxCopy(), arraySyntaxCopy(arguments));
3314 Expression *NewExp::semantic(Scope *sc)
3315 { int i;
3316 Type *tb;
3317 ClassDeclaration *cdthis = NULL;
3319 #if LOGSEMANTIC
3320 printf("NewExp::semantic() %s\n", toChars());
3321 if (thisexp)
3322 printf("\tthisexp = %s\n", thisexp->toChars());
3323 printf("\tnewtype: %s\n", newtype->toChars());
3324 #endif
3325 if (type) // if semantic() already run
3326 return this;
3328 Lagain:
3329 if (thisexp)
3330 { thisexp = thisexp->semantic(sc);
3331 cdthis = thisexp->type->isClassHandle();
3332 if (cdthis)
3334 sc = sc->push(cdthis);
3335 type = newtype->semantic(loc, sc);
3336 sc = sc->pop();
3338 else
3340 error("'this' for nested class must be a class type, not %s", thisexp->type->toChars());
3341 type = newtype->semantic(loc, sc);
3344 else
3345 type = newtype->semantic(loc, sc);
3346 newtype = type; // in case type gets cast to something else
3347 tb = type->toBasetype();
3348 //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco);
3350 arrayExpressionSemantic(newargs, sc);
3351 preFunctionArguments(loc, sc, newargs);
3352 arrayExpressionSemantic(arguments, sc);
3353 preFunctionArguments(loc, sc, arguments);
3355 if (thisexp && tb->ty != Tclass)
3356 error("e.new is only for allocating nested classes, not %s", tb->toChars());
3358 if (tb->ty == Tclass)
3359 { TypeFunction *tf;
3361 TypeClass *tc = (TypeClass *)(tb);
3362 ClassDeclaration *cd = tc->sym->isClassDeclaration();
3363 if (cd->isInterfaceDeclaration())
3364 error("cannot create instance of interface %s", cd->toChars());
3365 else if (cd->isAbstract())
3366 { error("cannot create instance of abstract class %s", cd->toChars());
3367 for (int i = 0; i < cd->vtbl.dim; i++)
3368 { FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration();
3369 if (fd && fd->isAbstract())
3370 error("function %s is abstract", fd->toChars());
3373 checkDeprecated(sc, cd);
3374 if (cd->isNested())
3375 { /* We need a 'this' pointer for the nested class.
3376 * Ensure we have the right one.
3378 Dsymbol *s = cd->toParent2();
3379 ClassDeclaration *cdn = s->isClassDeclaration();
3380 FuncDeclaration *fdn = s->isFuncDeclaration();
3382 //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
3383 if (cdn)
3385 if (!cdthis)
3387 // Supply an implicit 'this' and try again
3388 thisexp = new ThisExp(loc);
3389 for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
3390 { if (!sp)
3392 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
3393 break;
3395 ClassDeclaration *cdp = sp->isClassDeclaration();
3396 if (!cdp)
3397 continue;
3398 if (cdp == cdn || cdn->isBaseOf(cdp, NULL))
3399 break;
3400 // Add a '.outer' and try again
3401 thisexp = new DotIdExp(loc, thisexp, Id::outer);
3403 if (!global.errors)
3404 goto Lagain;
3406 if (cdthis)
3408 //printf("cdthis = %s\n", cdthis->toChars());
3409 if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL))
3410 error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars());
3412 #if 0
3413 else
3415 for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration())
3417 if (!sf)
3419 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
3420 break;
3422 printf("sf = %s\n", sf->toChars());
3423 AggregateDeclaration *ad = sf->isThis();
3424 if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL)))
3425 break;
3428 #endif
3430 else if (fdn)
3431 { /* The nested class cd is nested inside a function,
3432 * we'll let getEthis() look for errors.
3434 //printf("nested class %s is nested inside function %s, we're in %s\n", cd->toChars(), fdn->toChars(), sc->func->toChars());
3435 if (thisexp)
3436 // Because thisexp cannot be a function frame pointer
3437 error("e.new is only for allocating nested classes");
3439 else
3440 assert(0);
3442 else if (thisexp)
3443 error("e.new is only for allocating nested classes");
3445 FuncDeclaration *f = cd->ctor;
3446 if (f)
3448 assert(f);
3449 f = f->overloadResolve(loc, NULL, arguments);
3450 checkDeprecated(sc, f);
3451 member = f->isCtorDeclaration();
3452 assert(member);
3454 cd->accessCheck(loc, sc, member);
3456 tf = (TypeFunction *)f->type;
3457 // type = tf->next;
3459 if (!arguments)
3460 arguments = new Expressions();
3461 functionArguments(loc, sc, tf, arguments);
3463 else
3465 if (arguments && arguments->dim)
3466 error("no constructor for %s", cd->toChars());
3469 if (cd->aggNew)
3470 { Expression *e;
3472 f = cd->aggNew;
3474 // Prepend the uint size argument to newargs[]
3475 e = new IntegerExp(loc, cd->size(loc), Type::tsize_t);
3476 if (!newargs)
3477 newargs = new Expressions();
3478 newargs->shift(e);
3480 f = f->overloadResolve(loc, NULL, newargs);
3481 allocator = f->isNewDeclaration();
3482 assert(allocator);
3484 tf = (TypeFunction *)f->type;
3485 functionArguments(loc, sc, tf, newargs);
3487 else
3489 if (newargs && newargs->dim)
3490 error("no allocator for %s", cd->toChars());
3494 else if (tb->ty == Tstruct)
3496 TypeStruct *ts = (TypeStruct *)tb;
3497 StructDeclaration *sd = ts->sym;
3498 FuncDeclaration *f = sd->aggNew;
3499 TypeFunction *tf;
3501 if (arguments && arguments->dim)
3502 error("no constructor for %s", type->toChars());
3504 if (f)
3506 Expression *e;
3508 // Prepend the uint size argument to newargs[]
3509 e = new IntegerExp(loc, sd->size(loc), Type::tsize_t);
3510 if (!newargs)
3511 newargs = new Expressions();
3512 newargs->shift(e);
3514 f = f->overloadResolve(loc, NULL, newargs);
3515 allocator = f->isNewDeclaration();
3516 assert(allocator);
3518 tf = (TypeFunction *)f->type;
3519 functionArguments(loc, sc, tf, newargs);
3521 e = new VarExp(loc, f);
3522 e = new CallExp(loc, e, newargs);
3523 e = e->semantic(sc);
3524 e->type = type->pointerTo();
3525 return e;
3528 type = type->pointerTo();
3530 else if (tb->ty == Tarray && (arguments && arguments->dim))
3532 for (size_t i = 0; i < arguments->dim; i++)
3534 if (tb->ty != Tarray)
3535 { error("too many arguments for array");
3536 arguments->dim = i;
3537 break;
3540 Expression *arg = (Expression *)arguments->data[i];
3541 arg = resolveProperties(sc, arg);
3542 arg = arg->implicitCastTo(sc, Type::tsize_t);
3543 arg = arg->optimize(WANTvalue);
3544 if (arg->op == TOKint64 && (long long)arg->toInteger() < 0)
3545 error("negative array index %s", arg->toChars());
3546 arguments->data[i] = (void *) arg;
3547 tb = ((TypeDArray *)tb)->next->toBasetype();
3550 else if (tb->isscalar())
3552 if (arguments && arguments->dim)
3553 error("no constructor for %s", type->toChars());
3555 type = type->pointerTo();
3557 else
3559 error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars());
3560 type = type->pointerTo();
3563 //printf("NewExp: '%s'\n", toChars());
3564 //printf("NewExp:type '%s'\n", type->toChars());
3566 return this;
3569 int NewExp::checkSideEffect(int flag)
3571 return 1;
3574 int NewExp::canThrow()
3576 return 1;
3579 void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3580 { int i;
3582 if (thisexp)
3583 { expToCBuffer(buf, hgs, thisexp, PREC_primary);
3584 buf->writeByte('.');
3586 buf->writestring("new ");
3587 if (newargs && newargs->dim)
3589 buf->writeByte('(');
3590 argsToCBuffer(buf, newargs, hgs);
3591 buf->writeByte(')');
3593 newtype->toCBuffer(buf, NULL, hgs);
3594 if (arguments && arguments->dim)
3596 buf->writeByte('(');
3597 argsToCBuffer(buf, arguments, hgs);
3598 buf->writeByte(')');
3602 /********************** NewAnonClassExp **************************************/
3604 NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp,
3605 Expressions *newargs, ClassDeclaration *cd, Expressions *arguments)
3606 : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp))
3608 this->thisexp = thisexp;
3609 this->newargs = newargs;
3610 this->cd = cd;
3611 this->arguments = arguments;
3614 Expression *NewAnonClassExp::syntaxCopy()
3616 return new NewAnonClassExp(loc,
3617 thisexp ? thisexp->syntaxCopy() : NULL,
3618 arraySyntaxCopy(newargs),
3619 (ClassDeclaration *)cd->syntaxCopy(NULL),
3620 arraySyntaxCopy(arguments));
3624 Expression *NewAnonClassExp::semantic(Scope *sc)
3626 #if LOGSEMANTIC
3627 printf("NewAnonClassExp::semantic() %s\n", toChars());
3628 //printf("type: %s\n", type->toChars());
3629 #endif
3631 Expression *d = new DeclarationExp(loc, cd);
3632 d = d->semantic(sc);
3634 Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments);
3636 Expression *c = new CommaExp(loc, d, n);
3637 return c->semantic(sc);
3640 int NewAnonClassExp::checkSideEffect(int flag)
3642 return 1;
3645 int NewAnonClassExp::canThrow()
3647 return 1;
3650 void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3651 { int i;
3653 if (thisexp)
3654 { expToCBuffer(buf, hgs, thisexp, PREC_primary);
3655 buf->writeByte('.');
3657 buf->writestring("new");
3658 if (newargs && newargs->dim)
3660 buf->writeByte('(');
3661 argsToCBuffer(buf, newargs, hgs);
3662 buf->writeByte(')');
3664 buf->writestring(" class ");
3665 if (arguments && arguments->dim)
3667 buf->writeByte('(');
3668 argsToCBuffer(buf, arguments, hgs);
3669 buf->writeByte(')');
3671 //buf->writestring(" { }");
3672 if (cd)
3674 cd->toCBuffer(buf, hgs);
3678 /********************** SymOffExp **************************************/
3680 SymbolExp::SymbolExp(Loc loc, enum TOK op, int size, Declaration *var, int hasOverloads)
3681 : Expression(loc, op, size)
3683 assert(var);
3684 this->var = var;
3685 this->hasOverloads = hasOverloads;
3688 /********************** SymOffExp **************************************/
3690 SymOffExp::SymOffExp(Loc loc, Declaration *var, target_size_t offset, int hasOverloads)
3691 : SymbolExp(loc, TOKsymoff, sizeof(SymOffExp), var, hasOverloads)
3693 this->offset = offset;
3695 VarDeclaration *v = var->isVarDeclaration();
3696 if (v && v->needThis())
3697 error("need 'this' for address of %s", v->toChars());
3700 Expression *SymOffExp::semantic(Scope *sc)
3702 #if LOGSEMANTIC
3703 printf("SymOffExp::semantic('%s')\n", toChars());
3704 #endif
3705 //var->semantic(sc);
3706 if (!type)
3707 type = var->type->pointerTo();
3708 VarDeclaration *v = var->isVarDeclaration();
3709 if (v)
3710 v->checkNestedReference(sc, loc);
3711 return this;
3714 int SymOffExp::isBool(int result)
3716 return result ? TRUE : FALSE;
3719 void SymOffExp::checkEscape()
3721 VarDeclaration *v = var->isVarDeclaration();
3722 if (v)
3724 if (!v->isDataseg())
3725 error("escaping reference to local variable %s", v->toChars());
3729 void SymOffExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3731 if (offset)
3732 buf->printf("(& %s+%"PRIuTSIZE")", var->toChars(), offset);
3733 else
3734 buf->printf("& %s", var->toChars());
3737 /******************************** VarExp **************************/
3739 VarExp::VarExp(Loc loc, Declaration *var, int hasOverloads)
3740 : SymbolExp(loc, TOKvar, sizeof(VarExp), var, hasOverloads)
3742 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
3743 //if (strcmp(var->ident->toChars(), "func") == 0) halt();
3744 this->type = var->type;
3747 int VarExp::equals(Object *o)
3748 { VarExp *ne;
3750 if (this == o ||
3751 (((Expression *)o)->op == TOKvar &&
3752 ((ne = (VarExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
3753 var == ne->var))
3754 return 1;
3755 return 0;
3758 Expression *VarExp::semantic(Scope *sc)
3759 { FuncLiteralDeclaration *fd;
3761 #if LOGSEMANTIC
3762 printf("VarExp::semantic(%s)\n", toChars());
3763 #endif
3764 if (!type)
3765 { type = var->type;
3766 #if 0
3767 if (var->storage_class & STClazy)
3769 TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd);
3770 type = new TypeDelegate(tf);
3771 type = type->semantic(loc, sc);
3773 #endif
3776 VarDeclaration *v = var->isVarDeclaration();
3777 if (v)
3779 #if 0
3780 if ((v->isConst() || v->isInvariant()) &&
3781 type->toBasetype()->ty != Tsarray && v->init)
3783 ExpInitializer *ei = v->init->isExpInitializer();
3784 if (ei)
3786 //ei->exp->implicitCastTo(sc, type)->print();
3787 return ei->exp->implicitCastTo(sc, type);
3790 #endif
3791 v->checkNestedReference(sc, loc);
3793 #if 0
3794 else if ((fd = var->isFuncLiteralDeclaration()) != NULL)
3795 { Expression *e;
3796 e = new FuncExp(loc, fd);
3797 e->type = type;
3798 return e;
3800 #endif
3801 return this;
3804 char *VarExp::toChars()
3806 return var->toChars();
3809 void VarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3811 buf->writestring(var->toChars());
3814 void VarExp::checkEscape()
3816 VarDeclaration *v = var->isVarDeclaration();
3817 if (v)
3818 { Type *tb = v->type->toBasetype();
3819 // if reference type
3820 if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass)
3822 if ((v->isAuto() || v->isScope()) && !v->noauto)
3823 error("escaping reference to auto local %s", v->toChars());
3824 else if (v->storage_class & STCvariadic)
3825 error("escaping reference to variadic parameter %s", v->toChars());
3830 Expression *VarExp::toLvalue(Scope *sc, Expression *e)
3832 #if 0
3833 tym = tybasic(e1->ET->Tty);
3834 if (!(tyscalar(tym) ||
3835 tym == TYstruct ||
3836 tym == TYarray && e->Eoper == TOKaddr))
3837 synerr(EM_lvalue); // lvalue expected
3838 #endif
3839 if (var->storage_class & STClazy)
3840 error("lazy variables cannot be lvalues");
3841 return this;
3844 Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
3846 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
3847 if (type && type->toBasetype()->ty == Tsarray)
3848 error("cannot change reference to static array '%s'", var->toChars());
3850 var->checkModify(loc, sc, type);
3852 // See if this expression is a modifiable lvalue (i.e. not const)
3853 return toLvalue(sc, e);
3857 /******************************** OverExp **************************/
3859 OverExp::OverExp(OverloadSet *s)
3860 : Expression(loc, TOKoverloadset, sizeof(OverExp))
3862 //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
3863 vars = s;
3864 type = Type::tvoid;
3867 Expression *OverExp::toLvalue(Scope *sc, Expression *e)
3869 return this;
3873 /******************************** TupleExp **************************/
3875 TupleExp::TupleExp(Loc loc, Expressions *exps)
3876 : Expression(loc, TOKtuple, sizeof(TupleExp))
3878 //printf("TupleExp(this = %p)\n", this);
3879 this->exps = exps;
3880 this->type = NULL;
3884 TupleExp::TupleExp(Loc loc, TupleDeclaration *tup)
3885 : Expression(loc, TOKtuple, sizeof(TupleExp))
3887 exps = new Expressions();
3888 type = NULL;
3890 exps->reserve(tup->objects->dim);
3891 for (size_t i = 0; i < tup->objects->dim; i++)
3892 { Object *o = (Object *)tup->objects->data[i];
3893 if (o->dyncast() == DYNCAST_EXPRESSION)
3895 Expression *e = (Expression *)o;
3896 e = e->syntaxCopy();
3897 exps->push(e);
3899 else if (o->dyncast() == DYNCAST_DSYMBOL)
3901 Dsymbol *s = (Dsymbol *)o;
3902 Expression *e = new DsymbolExp(loc, s);
3903 exps->push(e);
3905 else if (o->dyncast() == DYNCAST_TYPE)
3907 Type *t = (Type *)o;
3908 Expression *e = new TypeExp(loc, t);
3909 exps->push(e);
3911 else
3913 error("%s is not an expression", o->toChars());
3918 int TupleExp::equals(Object *o)
3919 { TupleExp *ne;
3921 if (this == o)
3922 return 1;
3923 if (((Expression *)o)->op == TOKtuple)
3925 TupleExp *te = (TupleExp *)o;
3926 if (exps->dim != te->exps->dim)
3927 return 0;
3928 for (size_t i = 0; i < exps->dim; i++)
3929 { Expression *e1 = (Expression *)exps->data[i];
3930 Expression *e2 = (Expression *)te->exps->data[i];
3932 if (!e1->equals(e2))
3933 return 0;
3935 return 1;
3937 return 0;
3940 Expression *TupleExp::syntaxCopy()
3942 return new TupleExp(loc, arraySyntaxCopy(exps));
3945 Expression *TupleExp::semantic(Scope *sc)
3947 #if LOGSEMANTIC
3948 printf("+TupleExp::semantic(%s)\n", toChars());
3949 #endif
3950 if (type)
3951 return this;
3953 // Run semantic() on each argument
3954 for (size_t i = 0; i < exps->dim; i++)
3955 { Expression *e = (Expression *)exps->data[i];
3957 e = e->semantic(sc);
3958 if (!e->type)
3959 { error("%s has no value", e->toChars());
3960 e->type = Type::terror;
3962 exps->data[i] = (void *)e;
3965 expandTuples(exps);
3966 if (0 && exps->dim == 1)
3968 return (Expression *)exps->data[0];
3970 type = new TypeTuple(exps);
3971 //printf("-TupleExp::semantic(%s)\n", toChars());
3972 return this;
3975 void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3977 buf->writestring("tuple(");
3978 argsToCBuffer(buf, exps, hgs);
3979 buf->writeByte(')');
3982 int TupleExp::checkSideEffect(int flag)
3983 { int f = 0;
3985 for (int i = 0; i < exps->dim; i++)
3986 { Expression *e = (Expression *)exps->data[i];
3988 f |= e->checkSideEffect(2);
3990 if (flag == 0 && f == 0)
3991 Expression::checkSideEffect(0);
3992 return f;
3995 int TupleExp::canThrow()
3997 return arrayExpressionCanThrow(exps);
4000 void TupleExp::checkEscape()
4002 for (size_t i = 0; i < exps->dim; i++)
4003 { Expression *e = (Expression *)exps->data[i];
4004 e->checkEscape();
4008 /******************************** FuncExp *********************************/
4010 FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd)
4011 : Expression(loc, TOKfunction, sizeof(FuncExp))
4013 this->fd = fd;
4016 Expression *FuncExp::syntaxCopy()
4018 return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL));
4021 Expression *FuncExp::semantic(Scope *sc)
4023 #if LOGSEMANTIC
4024 printf("FuncExp::semantic(%s)\n", toChars());
4025 #endif
4026 if (!type)
4028 fd->semantic(sc);
4029 fd->parent = sc->parent;
4030 if (global.errors)
4033 else
4035 fd->semantic2(sc);
4036 if (!global.errors)
4038 fd->semantic3(sc);
4040 if (!global.errors && global.params.useInline)
4041 fd->inlineScan();
4045 // Type is a "delegate to" or "pointer to" the function literal
4046 if (fd->isNested())
4048 type = new TypeDelegate(fd->type);
4049 type = type->semantic(loc, sc);
4051 else
4053 type = fd->type->pointerTo();
4055 fd->tookAddressOf++;
4057 return this;
4060 char *FuncExp::toChars()
4062 return fd->toChars();
4065 void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4067 buf->writestring(fd->toChars());
4071 /******************************** DeclarationExp **************************/
4073 DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration)
4074 : Expression(loc, TOKdeclaration, sizeof(DeclarationExp))
4076 this->declaration = declaration;
4079 Expression *DeclarationExp::syntaxCopy()
4081 return new DeclarationExp(loc, declaration->syntaxCopy(NULL));
4084 Expression *DeclarationExp::semantic(Scope *sc)
4086 if (type)
4087 return this;
4089 #if LOGSEMANTIC
4090 printf("DeclarationExp::semantic() %s\n", toChars());
4091 #endif
4093 /* This is here to support extern(linkage) declaration,
4094 * where the extern(linkage) winds up being an AttribDeclaration
4095 * wrapper.
4097 Dsymbol *s = declaration;
4099 AttribDeclaration *ad = declaration->isAttribDeclaration();
4100 if (ad)
4102 if (ad->decl && ad->decl->dim == 1)
4103 s = (Dsymbol *)ad->decl->data[0];
4106 if (s->isVarDeclaration())
4107 { // Do semantic() on initializer first, so:
4108 // int a = a;
4109 // will be illegal.
4110 declaration->semantic(sc);
4111 s->parent = sc->parent;
4114 //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc);
4115 // Insert into both local scope and function scope.
4116 // Must be unique in both.
4117 if (s->ident)
4119 if (!sc->insert(s))
4120 error("declaration %s is already defined", s->toPrettyChars());
4121 else if (sc->func)
4122 { VarDeclaration *v = s->isVarDeclaration();
4123 if (s->isFuncDeclaration() &&
4124 !sc->func->localsymtab->insert(s))
4125 error("declaration %s is already defined in another scope in %s", s->toPrettyChars(), sc->func->toChars());
4126 else if (!global.params.useDeprecated)
4127 { // Disallow shadowing
4129 for (Scope *scx = sc->enclosing; scx && scx->func == sc->func; scx = scx->enclosing)
4130 { Dsymbol *s2;
4132 if (scx->scopesym && scx->scopesym->symtab &&
4133 (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL &&
4134 s != s2)
4136 error("shadowing declaration %s is deprecated", s->toPrettyChars());
4142 if (!s->isVarDeclaration())
4144 declaration->semantic(sc);
4145 s->parent = sc->parent;
4147 if (!global.errors)
4149 declaration->semantic2(sc);
4150 if (!global.errors)
4152 declaration->semantic3(sc);
4154 if (!global.errors && global.params.useInline)
4155 declaration->inlineScan();
4159 type = Type::tvoid;
4160 return this;
4163 int DeclarationExp::checkSideEffect(int flag)
4165 return 1;
4168 int DeclarationExp::canThrow()
4170 VarDeclaration *v = declaration->isVarDeclaration();
4171 if (v && v->init)
4172 { ExpInitializer *ie = v->init->isExpInitializer();
4173 return ie && ie->exp->canThrow();
4175 return 0;
4178 void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4180 declaration->toCBuffer(buf, hgs);
4184 /************************ TypeidExp ************************************/
4187 * typeid(int)
4190 TypeidExp::TypeidExp(Loc loc, Type *typeidType)
4191 : Expression(loc, TOKtypeid, sizeof(TypeidExp))
4193 this->typeidType = typeidType;
4197 Expression *TypeidExp::syntaxCopy()
4199 return new TypeidExp(loc, typeidType->syntaxCopy());
4203 Expression *TypeidExp::semantic(Scope *sc)
4204 { Expression *e;
4206 #if LOGSEMANTIC
4207 printf("TypeidExp::semantic()\n");
4208 #endif
4209 typeidType = typeidType->semantic(loc, sc);
4210 e = typeidType->getTypeInfo(sc);
4211 return e;
4214 void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4216 buf->writestring("typeid(");
4217 typeidType->toCBuffer(buf, NULL, hgs);
4218 buf->writeByte(')');
4221 /************************ TraitsExp ************************************/
4224 * __traits(identifier, args...)
4227 TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args)
4228 : Expression(loc, TOKtraits, sizeof(TraitsExp))
4230 this->ident = ident;
4231 this->args = args;
4235 Expression *TraitsExp::syntaxCopy()
4237 return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args));
4241 void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4243 buf->writestring("__traits(");
4244 buf->writestring(ident->toChars());
4245 if (args)
4247 for (int i = 0; i < args->dim; i++)
4249 buf->writeByte(',');
4250 Object *oarg = (Object *)args->data[i];
4251 ObjectToCBuffer(buf, hgs, oarg);
4254 buf->writeByte(')');
4257 /************************************************************/
4259 HaltExp::HaltExp(Loc loc)
4260 : Expression(loc, TOKhalt, sizeof(HaltExp))
4264 Expression *HaltExp::semantic(Scope *sc)
4266 #if LOGSEMANTIC
4267 printf("HaltExp::semantic()\n");
4268 #endif
4269 type = Type::tvoid;
4270 return this;
4273 int HaltExp::checkSideEffect(int flag)
4275 return 1;
4278 void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4280 buf->writestring("halt");
4283 /************************************************************/
4285 IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
4286 Type *tspec, enum TOK tok2, TemplateParameters *parameters)
4287 : Expression(loc, TOKis, sizeof(IsExp))
4289 this->targ = targ;
4290 this->id = id;
4291 this->tok = tok;
4292 this->tspec = tspec;
4293 this->tok2 = tok2;
4294 this->parameters = parameters;
4297 Expression *IsExp::syntaxCopy()
4299 // This section is identical to that in TemplateDeclaration::syntaxCopy()
4300 TemplateParameters *p = NULL;
4301 if (parameters)
4303 p = new TemplateParameters();
4304 p->setDim(parameters->dim);
4305 for (int i = 0; i < p->dim; i++)
4306 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
4307 p->data[i] = (void *)tp->syntaxCopy();
4311 return new IsExp(loc,
4312 targ->syntaxCopy(),
4314 tok,
4315 tspec ? tspec->syntaxCopy() : NULL,
4316 tok2,
4320 Expression *IsExp::semantic(Scope *sc)
4321 { Type *tded;
4323 /* is(targ id tok tspec)
4324 * is(targ id == tok2)
4327 //printf("IsExp::semantic(%s)\n", toChars());
4328 if (id && !(sc->flags & SCOPEstaticif))
4329 error("can only declare type aliases within static if conditionals");
4331 unsigned errors_save = global.errors;
4332 global.errors = 0;
4333 global.gag++; // suppress printing of error messages
4334 targ = targ->semantic(loc, sc);
4335 global.gag--;
4336 unsigned gerrors = global.errors;
4337 global.errors = errors_save;
4339 if (gerrors) // if any errors happened
4340 { // then condition is false
4341 goto Lno;
4343 else if (tok2 != TOKreserved)
4345 switch (tok2)
4347 case TOKtypedef:
4348 if (targ->ty != Ttypedef)
4349 goto Lno;
4350 tded = ((TypeTypedef *)targ)->sym->basetype;
4351 break;
4353 case TOKstruct:
4354 if (targ->ty != Tstruct)
4355 goto Lno;
4356 if (((TypeStruct *)targ)->sym->isUnionDeclaration())
4357 goto Lno;
4358 tded = targ;
4359 break;
4361 case TOKunion:
4362 if (targ->ty != Tstruct)
4363 goto Lno;
4364 if (!((TypeStruct *)targ)->sym->isUnionDeclaration())
4365 goto Lno;
4366 tded = targ;
4367 break;
4369 case TOKclass:
4370 if (targ->ty != Tclass)
4371 goto Lno;
4372 if (((TypeClass *)targ)->sym->isInterfaceDeclaration())
4373 goto Lno;
4374 tded = targ;
4375 break;
4377 case TOKinterface:
4378 if (targ->ty != Tclass)
4379 goto Lno;
4380 if (!((TypeClass *)targ)->sym->isInterfaceDeclaration())
4381 goto Lno;
4382 tded = targ;
4383 break;
4385 #if V2
4386 case TOKconst:
4387 if (!targ->isConst())
4388 goto Lno;
4389 tded = targ;
4390 break;
4392 case TOKinvariant:
4393 if (!targ->isInvariant())
4394 goto Lno;
4395 tded = targ;
4396 break;
4397 #endif
4399 case TOKsuper:
4400 // If class or interface, get the base class and interfaces
4401 if (targ->ty != Tclass)
4402 goto Lno;
4403 else
4404 { ClassDeclaration *cd = ((TypeClass *)targ)->sym;
4405 Arguments *args = new Arguments;
4406 args->reserve(cd->baseclasses.dim);
4407 for (size_t i = 0; i < cd->baseclasses.dim; i++)
4408 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
4409 args->push(new Argument(STCin, b->type, NULL, NULL));
4411 tded = new TypeTuple(args);
4413 break;
4415 case TOKenum:
4416 if (targ->ty != Tenum)
4417 goto Lno;
4418 tded = ((TypeEnum *)targ)->sym->memtype;
4419 break;
4421 case TOKdelegate:
4422 if (targ->ty != Tdelegate)
4423 goto Lno;
4424 tded = ((TypeDelegate *)targ)->next; // the underlying function type
4425 break;
4427 case TOKfunction:
4429 if (targ->ty != Tfunction)
4430 goto Lno;
4431 tded = targ;
4433 /* Generate tuple from function parameter types.
4435 assert(tded->ty == Tfunction);
4436 Arguments *params = ((TypeFunction *)tded)->parameters;
4437 size_t dim = Argument::dim(params);
4438 Arguments *args = new Arguments;
4439 args->reserve(dim);
4440 for (size_t i = 0; i < dim; i++)
4441 { Argument *arg = Argument::getNth(params, i);
4442 assert(arg && arg->type);
4443 args->push(new Argument(arg->storageClass, arg->type, NULL, NULL));
4445 tded = new TypeTuple(args);
4446 break;
4448 case TOKreturn:
4449 /* Get the 'return type' for the function,
4450 * delegate, or pointer to function.
4452 if (targ->ty == Tfunction)
4453 tded = ((TypeFunction *)targ)->next;
4454 else if (targ->ty == Tdelegate)
4455 { tded = ((TypeDelegate *)targ)->next;
4456 tded = ((TypeFunction *)tded)->next;
4458 else if (targ->ty == Tpointer &&
4459 ((TypePointer *)targ)->next->ty == Tfunction)
4460 { tded = ((TypePointer *)targ)->next;
4461 tded = ((TypeFunction *)tded)->next;
4463 else
4464 goto Lno;
4465 break;
4467 default:
4468 assert(0);
4470 goto Lyes;
4472 else if (id && tspec)
4474 /* Evaluate to TRUE if targ matches tspec.
4475 * If TRUE, declare id as an alias for the specialized type.
4478 MATCH m;
4479 assert(parameters && parameters->dim);
4481 Objects dedtypes;
4482 dedtypes.setDim(parameters->dim);
4483 dedtypes.zero();
4485 m = targ->deduceType(NULL, tspec, parameters, &dedtypes);
4486 if (m == MATCHnomatch ||
4487 (m != MATCHexact && tok == TOKequal))
4488 goto Lno;
4489 else
4491 tded = (Type *)dedtypes.data[0];
4492 if (!tded)
4493 tded = targ;
4495 Objects tiargs;
4496 tiargs.setDim(1);
4497 tiargs.data[0] = (void *)targ;
4499 for (int i = 1; i < parameters->dim; i++)
4500 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
4501 Declaration *s;
4503 m = tp->matchArg(sc, &tiargs, i, parameters, &dedtypes, &s);
4504 if (m == MATCHnomatch)
4505 goto Lno;
4506 s->semantic(sc);
4507 if (!sc->insert(s))
4508 error("declaration %s is already defined", s->toChars());
4509 #if 0
4510 Object *o = (Object *)dedtypes.data[i];
4511 Dsymbol *s = TemplateDeclaration::declareParameter(loc, sc, tp, o);
4512 #endif
4513 if (sc->sd)
4514 s->addMember(sc, sc->sd, 1);
4517 goto Lyes;
4520 else if (id)
4522 /* Declare id as an alias for type targ. Evaluate to TRUE
4524 tded = targ;
4525 goto Lyes;
4527 else if (tspec)
4529 /* Evaluate to TRUE if targ matches tspec
4531 tspec = tspec->semantic(loc, sc);
4532 //printf("targ = %s\n", targ->toChars());
4533 //printf("tspec = %s\n", tspec->toChars());
4534 if (tok == TOKcolon)
4535 { if (targ->implicitConvTo(tspec))
4536 goto Lyes;
4537 else
4538 goto Lno;
4540 else /* == */
4541 { if (targ->equals(tspec))
4542 goto Lyes;
4543 else
4544 goto Lno;
4548 Lyes:
4549 if (id)
4551 Dsymbol *s = new AliasDeclaration(loc, id, tded);
4552 s->semantic(sc);
4553 if (!sc->insert(s))
4554 error("declaration %s is already defined", s->toChars());
4555 if (sc->sd)
4556 s->addMember(sc, sc->sd, 1);
4558 return new IntegerExp(loc, 1, Type::tbool);
4560 Lno:
4561 return new IntegerExp(loc, 0, Type::tbool);
4564 void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4566 buf->writestring("is(");
4567 targ->toCBuffer(buf, id, hgs);
4568 if (tok2 != TOKreserved)
4570 buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2));
4572 else if (tspec)
4574 if (tok == TOKcolon)
4575 buf->writestring(" : ");
4576 else
4577 buf->writestring(" == ");
4578 tspec->toCBuffer(buf, NULL, hgs);
4580 if (parameters)
4581 { // First parameter is already output, so start with second
4582 for (int i = 1; i < parameters->dim; i++)
4584 buf->writeByte(',');
4585 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
4586 tp->toCBuffer(buf, hgs);
4589 buf->writeByte(')');
4593 /************************************************************/
4595 UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1)
4596 : Expression(loc, op, size)
4598 this->e1 = e1;
4601 Expression *UnaExp::syntaxCopy()
4602 { UnaExp *e;
4604 e = (UnaExp *)copy();
4605 e->type = NULL;
4606 e->e1 = e->e1->syntaxCopy();
4607 return e;
4610 Expression *UnaExp::semantic(Scope *sc)
4612 #if LOGSEMANTIC
4613 printf("UnaExp::semantic('%s')\n", toChars());
4614 #endif
4615 e1 = e1->semantic(sc);
4616 // if (!e1->type)
4617 // error("%s has no value", e1->toChars());
4618 return this;
4621 int UnaExp::canThrow()
4623 return e1->canThrow();
4626 void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4628 buf->writestring(Token::toChars(op));
4629 expToCBuffer(buf, hgs, e1, precedence[op]);
4632 /************************************************************/
4634 BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2)
4635 : Expression(loc, op, size)
4637 this->e1 = e1;
4638 this->e2 = e2;
4641 Expression *BinExp::syntaxCopy()
4642 { BinExp *e;
4644 e = (BinExp *)copy();
4645 e->type = NULL;
4646 e->e1 = e->e1->syntaxCopy();
4647 e->e2 = e->e2->syntaxCopy();
4648 return e;
4651 Expression *BinExp::semantic(Scope *sc)
4653 #if LOGSEMANTIC
4654 printf("BinExp::semantic('%s')\n", toChars());
4655 #endif
4656 e1 = e1->semantic(sc);
4657 if (!e1->type)
4659 error("%s has no value", e1->toChars());
4660 e1->type = Type::terror;
4662 e2 = e2->semantic(sc);
4663 if (!e2->type)
4665 error("%s has no value", e2->toChars());
4666 e2->type = Type::terror;
4668 assert(e1->type);
4669 return this;
4672 Expression *BinExp::semanticp(Scope *sc)
4674 BinExp::semantic(sc);
4675 e1 = resolveProperties(sc, e1);
4676 e2 = resolveProperties(sc, e2);
4677 return this;
4680 /***************************
4681 * Common semantic routine for some xxxAssignExp's.
4684 Expression *BinExp::commonSemanticAssign(Scope *sc)
4685 { Expression *e;
4687 if (!type)
4689 BinExp::semantic(sc);
4690 e2 = resolveProperties(sc, e2);
4692 e = op_overload(sc);
4693 if (e)
4694 return e;
4696 e1 = e1->modifiableLvalue(sc, e1);
4697 e1->checkScalar();
4698 type = e1->type;
4699 if (type->toBasetype()->ty == Tbool)
4701 error("operator not allowed on bool expression %s", toChars());
4703 typeCombine(sc);
4704 e1->checkArithmetic();
4705 e2->checkArithmetic();
4707 if (op == TOKmodass && e2->type->iscomplex())
4708 { error("cannot perform modulo complex arithmetic");
4709 return new IntegerExp(0);
4712 return this;
4715 Expression *BinExp::commonSemanticAssignIntegral(Scope *sc)
4716 { Expression *e;
4718 if (!type)
4720 BinExp::semantic(sc);
4721 e2 = resolveProperties(sc, e2);
4723 e = op_overload(sc);
4724 if (e)
4725 return e;
4727 e1 = e1->modifiableLvalue(sc, e1);
4728 e1->checkScalar();
4729 type = e1->type;
4730 if (type->toBasetype()->ty == Tbool)
4732 e2 = e2->implicitCastTo(sc, type);
4735 typeCombine(sc);
4736 e1->checkIntegral();
4737 e2->checkIntegral();
4739 return this;
4742 int BinExp::checkSideEffect(int flag)
4744 if (op == TOKplusplus ||
4745 op == TOKminusminus ||
4746 op == TOKassign ||
4747 op == TOKconstruct ||
4748 op == TOKblit ||
4749 op == TOKaddass ||
4750 op == TOKminass ||
4751 op == TOKcatass ||
4752 op == TOKmulass ||
4753 op == TOKdivass ||
4754 op == TOKmodass ||
4755 op == TOKshlass ||
4756 op == TOKshrass ||
4757 op == TOKushrass ||
4758 op == TOKandass ||
4759 op == TOKorass ||
4760 op == TOKxorass ||
4761 op == TOKin ||
4762 op == TOKremove)
4763 return 1;
4764 return Expression::checkSideEffect(flag);
4767 void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4769 expToCBuffer(buf, hgs, e1, precedence[op]);
4770 buf->writeByte(' ');
4771 buf->writestring(Token::toChars(op));
4772 buf->writeByte(' ');
4773 expToCBuffer(buf, hgs, e2, (enum PREC)(precedence[op] + 1));
4776 int BinExp::isunsigned()
4778 return e1->type->isunsigned() || e2->type->isunsigned();
4781 int BinExp::canThrow()
4783 return e1->canThrow() || e2->canThrow();
4786 void BinExp::incompatibleTypes()
4788 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
4789 e1->toChars(), Token::toChars(op), e2->toChars(),
4790 e1->type->toChars(), e2->type->toChars());
4793 /************************************************************/
4795 CompileExp::CompileExp(Loc loc, Expression *e)
4796 : UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
4800 Expression *CompileExp::semantic(Scope *sc)
4802 #if LOGSEMANTIC
4803 printf("CompileExp::semantic('%s')\n", toChars());
4804 #endif
4805 UnaExp::semantic(sc);
4806 e1 = resolveProperties(sc, e1);
4807 e1 = e1->optimize(WANTvalue | WANTinterpret);
4808 if (e1->op != TOKstring)
4809 { error("argument to mixin must be a string, not (%s)", e1->toChars());
4810 type = Type::terror;
4811 return this;
4813 StringExp *se = (StringExp *)e1;
4814 se = se->toUTF8(sc);
4815 Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
4816 p.loc = loc;
4817 p.nextToken();
4818 //printf("p.loc.linnum = %d\n", p.loc.linnum);
4819 Expression *e = p.parseExpression();
4820 if (p.token.value != TOKeof)
4821 error("incomplete mixin expression (%s)", se->toChars());
4822 return e->semantic(sc);
4825 void CompileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4827 buf->writestring("mixin(");
4828 expToCBuffer(buf, hgs, e1, PREC_assign);
4829 buf->writeByte(')');
4832 /************************************************************/
4834 FileExp::FileExp(Loc loc, Expression *e)
4835 : UnaExp(loc, TOKmixin, sizeof(FileExp), e)
4839 Expression *FileExp::semantic(Scope *sc)
4840 { char *name;
4841 StringExp *se;
4843 #if LOGSEMANTIC
4844 printf("FileExp::semantic('%s')\n", toChars());
4845 #endif
4846 UnaExp::semantic(sc);
4847 e1 = resolveProperties(sc, e1);
4848 e1 = e1->optimize(WANTvalue);
4849 if (e1->op != TOKstring)
4850 { error("file name argument must be a string, not (%s)", e1->toChars());
4851 goto Lerror;
4853 se = (StringExp *)e1;
4854 se = se->toUTF8(sc);
4855 name = (char *)se->string;
4857 if (!global.params.fileImppath)
4858 { error("need -Jpath switch to import text file %s", name);
4859 goto Lerror;
4862 if (name != FileName::name(name))
4863 { error("use -Jpath switch to provide path for filename %s", name);
4864 goto Lerror;
4867 name = FileName::searchPath(global.filePath, name, 0);
4868 if (!name)
4869 { error("file %s cannot be found, check -Jpath", se->toChars());
4870 goto Lerror;
4873 if (global.params.verbose)
4874 printf("file %s\t(%s)\n", se->string, name);
4876 { File f(name);
4877 if (f.read())
4878 { error("cannot read file %s", f.toChars());
4879 goto Lerror;
4881 else
4883 f.ref = 1;
4884 se = new StringExp(loc, f.buffer, f.len);
4887 Lret:
4888 return se->semantic(sc);
4890 Lerror:
4891 se = new StringExp(loc, "");
4892 goto Lret;
4895 void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4897 buf->writestring("import(");
4898 expToCBuffer(buf, hgs, e1, PREC_assign);
4899 buf->writeByte(')');
4902 /************************************************************/
4904 AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg)
4905 : UnaExp(loc, TOKassert, sizeof(AssertExp), e)
4907 this->msg = msg;
4910 Expression *AssertExp::syntaxCopy()
4912 AssertExp *ae = new AssertExp(loc, e1->syntaxCopy(),
4913 msg ? msg->syntaxCopy() : NULL);
4914 return ae;
4917 Expression *AssertExp::semantic(Scope *sc)
4919 #if LOGSEMANTIC
4920 printf("AssertExp::semantic('%s')\n", toChars());
4921 #endif
4922 UnaExp::semantic(sc);
4923 e1 = resolveProperties(sc, e1);
4924 // BUG: see if we can do compile time elimination of the Assert
4925 e1 = e1->optimize(WANTvalue);
4926 e1 = e1->checkToBoolean();
4927 if (msg)
4929 msg = msg->semantic(sc);
4930 msg = resolveProperties(sc, msg);
4931 msg = msg->implicitCastTo(sc, Type::tchar->constOf()->arrayOf());
4932 msg = msg->optimize(WANTvalue);
4934 if (e1->isBool(FALSE))
4936 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
4937 fd->hasReturnExp |= 4;
4939 if (!global.params.useAssert)
4940 { Expression *e = new HaltExp(loc);
4941 e = e->semantic(sc);
4942 return e;
4945 type = Type::tvoid;
4946 return this;
4949 int AssertExp::checkSideEffect(int flag)
4951 return 1;
4954 int AssertExp::canThrow()
4956 return (global.params.useAssert != 0);
4959 void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4961 buf->writestring("assert(");
4962 expToCBuffer(buf, hgs, e1, PREC_assign);
4963 if (msg)
4965 buf->writeByte(',');
4966 expToCBuffer(buf, hgs, msg, PREC_assign);
4968 buf->writeByte(')');
4971 /************************************************************/
4973 DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident)
4974 : UnaExp(loc, TOKdot, sizeof(DotIdExp), e)
4976 this->ident = ident;
4979 Expression *DotIdExp::semantic(Scope *sc)
4980 { Expression *e;
4981 Expression *eleft;
4982 Expression *eright;
4984 #if LOGSEMANTIC
4985 printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars());
4986 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
4987 #endif
4989 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
4991 #if 0
4992 /* Don't do semantic analysis if we'll be converting
4993 * it to a string.
4995 if (ident == Id::stringof)
4996 { char *s = e1->toChars();
4997 e = new StringExp(loc, s, strlen(s), 'c');
4998 e = e->semantic(sc);
4999 return e;
5001 #endif
5003 /* Special case: rewrite this.id and super.id
5004 * to be classtype.id and baseclasstype.id
5005 * if we have no this pointer.
5007 if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc))
5008 { ClassDeclaration *cd;
5009 StructDeclaration *sd;
5010 AggregateDeclaration *ad;
5012 ad = sc->getStructClassScope();
5013 if (ad)
5015 cd = ad->isClassDeclaration();
5016 if (cd)
5018 if (e1->op == TOKthis)
5020 e = new TypeDotIdExp(loc, cd->type, ident);
5021 return e->semantic(sc);
5023 else if (cd->baseClass && e1->op == TOKsuper)
5025 e = new TypeDotIdExp(loc, cd->baseClass->type, ident);
5026 return e->semantic(sc);
5029 else
5031 sd = ad->isStructDeclaration();
5032 if (sd)
5034 if (e1->op == TOKthis)
5036 e = new TypeDotIdExp(loc, sd->type, ident);
5037 return e->semantic(sc);
5044 UnaExp::semantic(sc);
5046 if (e1->op == TOKdotexp)
5048 DotExp *de = (DotExp *)e1;
5049 eleft = de->e1;
5050 eright = de->e2;
5052 else
5054 e1 = resolveProperties(sc, e1);
5055 eleft = NULL;
5056 eright = e1;
5059 if (e1->op == TOKtuple && ident == Id::offsetof)
5060 { /* 'distribute' the .offsetof to each of the tuple elements.
5062 TupleExp *te = (TupleExp *)e1;
5063 Expressions *exps = new Expressions();
5064 exps->setDim(te->exps->dim);
5065 for (int i = 0; i < exps->dim; i++)
5066 { Expression *e = (Expression *)te->exps->data[i];
5067 e = e->semantic(sc);
5068 e = new DotIdExp(e->loc, e, Id::offsetof);
5069 exps->data[i] = (void *)e;
5071 e = new TupleExp(loc, exps);
5072 e = e->semantic(sc);
5073 return e;
5076 if (e1->op == TOKtuple && ident == Id::length)
5078 TupleExp *te = (TupleExp *)e1;
5079 e = new IntegerExp(loc, te->exps->dim, Type::tsize_t);
5080 return e;
5083 if (eright->op == TOKimport) // also used for template alias's
5085 Dsymbol *s;
5086 ScopeExp *ie = (ScopeExp *)eright;
5088 s = ie->sds->search(loc, ident, 0);
5089 if (s)
5091 s = s->toAlias();
5092 checkDeprecated(sc, s);
5094 EnumMember *em = s->isEnumMember();
5095 if (em)
5097 e = em->value;
5098 e = e->semantic(sc);
5099 return e;
5102 VarDeclaration *v = s->isVarDeclaration();
5103 if (v)
5105 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
5106 if (v->inuse)
5108 error("circular reference to '%s'", v->toChars());
5109 type = Type::tint32;
5110 return this;
5112 type = v->type;
5113 #if 0
5114 if (v->isConst() || v->isInvariant())
5116 if (v->init)
5118 ExpInitializer *ei = v->init->isExpInitializer();
5119 if (ei)
5121 //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars());
5122 //ei->exp = ei->exp->semantic(sc);
5123 if (ei->exp->type == type)
5125 e = ei->exp->copy(); // make copy so we can change loc
5126 e->loc = loc;
5127 return e;
5131 else if (type->isscalar())
5133 e = type->defaultInit();
5134 e->loc = loc;
5135 return e;
5138 #endif
5139 if (v->needThis())
5141 if (!eleft)
5142 eleft = new ThisExp(loc);
5143 e = new DotVarExp(loc, eleft, v);
5144 e = e->semantic(sc);
5146 else
5148 e = new VarExp(loc, v);
5149 if (eleft)
5150 { e = new CommaExp(loc, eleft, e);
5151 e->type = v->type;
5154 return e->deref();
5157 FuncDeclaration *f = s->isFuncDeclaration();
5158 if (f)
5160 //printf("it's a function\n");
5161 if (f->needThis())
5163 if (!eleft)
5164 eleft = new ThisExp(loc);
5165 e = new DotVarExp(loc, eleft, f);
5166 e = e->semantic(sc);
5168 else
5170 e = new VarExp(loc, f, 1);
5171 if (eleft)
5172 { e = new CommaExp(loc, eleft, e);
5173 e->type = f->type;
5176 return e;
5179 Type *t = s->getType();
5180 if (t)
5182 return new TypeExp(loc, t);
5185 TupleDeclaration *tup = s->isTupleDeclaration();
5186 if (tup)
5188 if (eleft)
5189 error("cannot have e.tuple");
5190 e = new TupleExp(loc, tup);
5191 e = e->semantic(sc);
5192 return e;
5195 ScopeDsymbol *sds = s->isScopeDsymbol();
5196 if (sds)
5198 //printf("it's a ScopeDsymbol\n");
5199 e = new ScopeExp(loc, sds);
5200 e = e->semantic(sc);
5201 if (eleft)
5202 e = new DotExp(loc, eleft, e);
5203 return e;
5206 Import *imp = s->isImport();
5207 if (imp)
5209 ScopeExp *ie;
5211 ie = new ScopeExp(loc, imp->pkg);
5212 return ie->semantic(sc);
5215 // BUG: handle other cases like in IdentifierExp::semantic()
5216 #ifdef DEBUG
5217 printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind());
5218 #endif
5219 assert(0);
5221 else if (ident == Id::stringof)
5222 { char *s = ie->toChars();
5223 e = new StringExp(loc, s, strlen(s), 'c');
5224 e = e->semantic(sc);
5225 return e;
5227 error("undefined identifier %s", toChars());
5228 type = Type::tvoid;
5229 return this;
5231 else if (e1->type->ty == Tpointer &&
5232 ident != Id::init && ident != Id::__sizeof &&
5233 ident != Id::alignof && ident != Id::offsetof &&
5234 ident != Id::mangleof && ident != Id::stringof)
5236 e = new PtrExp(loc, e1);
5237 e->type = ((TypePointer *)e1->type)->next;
5238 return e->type->dotExp(sc, e, ident);
5240 else
5242 e = e1->type->dotExp(sc, e1, ident);
5243 e = e->semantic(sc);
5244 return e;
5248 void DotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5250 //printf("DotIdExp::toCBuffer()\n");
5251 expToCBuffer(buf, hgs, e1, PREC_primary);
5252 buf->writeByte('.');
5253 buf->writestring(ident->toChars());
5256 /********************** DotTemplateExp ***********************************/
5258 // Mainly just a placeholder
5260 DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td)
5261 : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e)
5264 this->td = td;
5267 void DotTemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5269 expToCBuffer(buf, hgs, e1, PREC_primary);
5270 buf->writeByte('.');
5271 buf->writestring(td->toChars());
5275 /************************************************************/
5277 DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v, int hasOverloads)
5278 : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e)
5280 //printf("DotVarExp()\n");
5281 this->var = v;
5282 this->hasOverloads = hasOverloads;
5285 Expression *DotVarExp::semantic(Scope *sc)
5287 #if LOGSEMANTIC
5288 printf("DotVarExp::semantic('%s')\n", toChars());
5289 #endif
5290 if (!type)
5292 var = var->toAlias()->isDeclaration();
5294 TupleDeclaration *tup = var->isTupleDeclaration();
5295 if (tup)
5296 { /* Replace:
5297 * e1.tuple(a, b, c)
5298 * with:
5299 * tuple(e1.a, e1.b, e1.c)
5301 Expressions *exps = new Expressions;
5303 exps->reserve(tup->objects->dim);
5304 for (size_t i = 0; i < tup->objects->dim; i++)
5305 { Object *o = (Object *)tup->objects->data[i];
5306 if (o->dyncast() != DYNCAST_EXPRESSION)
5308 error("%s is not an expression", o->toChars());
5310 else
5312 Expression *e = (Expression *)o;
5313 if (e->op != TOKdsymbol)
5314 error("%s is not a member", e->toChars());
5315 else
5316 { DsymbolExp *ve = (DsymbolExp *)e;
5318 e = new DotVarExp(loc, e1, ve->s->isDeclaration());
5319 exps->push(e);
5323 Expression *e = new TupleExp(loc, exps);
5324 e = e->semantic(sc);
5325 return e;
5328 e1 = e1->semantic(sc);
5330 type = var->type;
5331 if (!type && global.errors)
5332 { // var is goofed up, just return 0
5333 return new IntegerExp(0);
5335 assert(type);
5337 if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution
5339 Type *t1 = e1->type;
5340 if (t1->ty == Tpointer)
5341 t1 = t1->nextOf();
5342 if (t1->isConst())
5343 type = type->constOf();
5344 else if (t1->isInvariant())
5345 type = type->invariantOf();
5347 AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration();
5348 e1 = getRightThis(loc, sc, ad, e1, var);
5349 if (!sc->noaccesscheck)
5350 accessCheck(loc, sc, e1, var);
5353 //printf("-DotVarExp::semantic('%s')\n", toChars());
5354 return this;
5357 Expression *DotVarExp::toLvalue(Scope *sc, Expression *e)
5359 //printf("DotVarExp::toLvalue(%s)\n", toChars());
5360 return this;
5363 Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
5365 #if 0
5366 printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
5367 printf("e1->type = %s\n", e1->type->toChars());
5368 printf("var->type = %s\n", var->type->toChars());
5369 #endif
5371 // Also need this for non-null fields.
5372 VarDeclaration *v = var->isVarDeclaration();
5373 if (v) // When is it not a VarDeclaration?
5374 v->ctorinit = 1;
5375 else
5376 error("Just curious");
5378 if (var->isCtorinit())
5379 { // It's only modifiable if inside the right constructor
5380 Dsymbol *s = sc->func;
5381 while (1)
5383 FuncDeclaration *fd = NULL;
5384 if (s)
5385 fd = s->isFuncDeclaration();
5386 if (fd &&
5387 ((fd->isCtorDeclaration() && var->storage_class & STCfield) ||
5388 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) &&
5389 fd->toParent() == var->toParent() &&
5390 e1->op == TOKthis
5393 VarDeclaration *v = var->isVarDeclaration();
5394 assert(v);
5395 v->ctorinit = 1;
5396 //printf("setting ctorinit\n");
5398 else
5400 if (s)
5401 { s = s->toParent2();
5402 continue;
5404 else
5406 const char *p = var->isStatic() ? "static " : "";
5407 error("can only initialize %sconst member %s inside %sconstructor",
5408 p, var->toChars(), p);
5411 break;
5414 else
5416 Type *t1 = e1->type->toBasetype();
5418 if (!t1->isMutable() ||
5419 (t1->ty == Tpointer && !t1->nextOf()->isMutable()) ||
5420 !var->type->isMutable() ||
5421 !var->type->isAssignable() ||
5422 var->storage_class & STCmanifest
5424 error("cannot modify const/invariant %s", toChars());
5426 return this;
5429 void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5431 expToCBuffer(buf, hgs, e1, PREC_primary);
5432 buf->writeByte('.');
5433 buf->writestring(var->toChars());
5436 /************************************************************/
5438 /* Things like:
5439 * foo.bar!(args)
5442 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti)
5443 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e)
5445 //printf("DotTemplateInstanceExp()\n");
5446 this->ti = ti;
5449 Expression *DotTemplateInstanceExp::syntaxCopy()
5451 DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc,
5452 e1->syntaxCopy(),
5453 (TemplateInstance *)ti->syntaxCopy(NULL));
5454 return de;
5457 Expression *DotTemplateInstanceExp::semantic(Scope *sc)
5458 { Dsymbol *s;
5459 Dsymbol *s2;
5460 TemplateDeclaration *td;
5461 Expression *e;
5462 Identifier *id;
5463 Type *t1;
5464 Expression *eleft = NULL;
5465 Expression *eright;
5467 #if LOGSEMANTIC
5468 printf("DotTemplateInstanceExp::semantic('%s')\n", toChars());
5469 #endif
5470 //e1->print();
5471 //print();
5472 e1 = e1->semantic(sc);
5473 t1 = e1->type;
5474 if (t1)
5475 t1 = t1->toBasetype();
5476 //t1->print();
5478 /* Extract the following from e1:
5479 * s: the symbol which ti should be a member of
5480 * eleft: if not NULL, it is the 'this' pointer for ti
5483 if (e1->op == TOKdotexp)
5484 { DotExp *de = (DotExp *)e1;
5485 eleft = de->e1;
5486 eright = de->e2;
5488 else
5489 { eleft = NULL;
5490 eright = e1;
5492 if (eright->op == TOKimport)
5494 s = ((ScopeExp *)eright)->sds;
5496 else if (e1->op == TOKtype)
5498 s = t1->isClassHandle();
5499 if (!s)
5500 { if (t1->ty == Tstruct)
5501 s = ((TypeStruct *)t1)->sym;
5502 else
5503 goto L1;
5506 else if (t1 && (t1->ty == Tstruct || t1->ty == Tclass))
5508 s = t1->toDsymbol(sc);
5509 eleft = e1;
5511 else if (t1 && t1->ty == Tpointer)
5513 t1 = ((TypePointer *)t1)->next->toBasetype();
5514 if (t1->ty != Tstruct)
5515 goto L1;
5516 s = t1->toDsymbol(sc);
5517 eleft = e1;
5519 else
5522 error("template %s is not a member of %s", ti->toChars(), e1->toChars());
5523 goto Lerr;
5526 assert(s);
5527 id = ti->name;
5528 s2 = s->search(loc, id, 0);
5529 if (!s2)
5530 { error("template identifier %s is not a member of %s %s", id->toChars(), s->kind(), s->ident->toChars());
5531 goto Lerr;
5533 s = s2;
5534 s->semantic(sc);
5535 s = s->toAlias();
5536 td = s->isTemplateDeclaration();
5537 if (!td)
5539 error("%s is not a template", id->toChars());
5540 goto Lerr;
5542 if (global.errors)
5543 goto Lerr;
5545 ti->tempdecl = td;
5547 if (eleft)
5548 { Declaration *v;
5550 ti->semantic(sc);
5551 s = ti->inst->toAlias();
5552 v = s->isDeclaration();
5553 if (v)
5554 { e = new DotVarExp(loc, eleft, v);
5555 e = e->semantic(sc);
5556 return e;
5560 e = new ScopeExp(loc, ti);
5561 if (eleft)
5563 e = new DotExp(loc, eleft, e);
5565 e = e->semantic(sc);
5566 return e;
5568 Lerr:
5569 return new IntegerExp(0);
5572 void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5574 expToCBuffer(buf, hgs, e1, PREC_primary);
5575 buf->writeByte('.');
5576 ti->toCBuffer(buf, hgs);
5579 /************************************************************/
5581 DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f, int hasOverloads)
5582 : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
5584 this->func = f;
5585 this->hasOverloads = hasOverloads;
5588 Expression *DelegateExp::semantic(Scope *sc)
5590 #if LOGSEMANTIC
5591 printf("DelegateExp::semantic('%s')\n", toChars());
5592 #endif
5593 if (!type)
5595 e1 = e1->semantic(sc);
5596 type = new TypeDelegate(func->type);
5597 type = type->semantic(loc, sc);
5598 AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration();
5599 if (func->needThis())
5600 e1 = getRightThis(loc, sc, ad, e1, func);
5602 return this;
5605 void DelegateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5607 buf->writeByte('&');
5608 if (!func->isNested())
5610 expToCBuffer(buf, hgs, e1, PREC_primary);
5611 buf->writeByte('.');
5613 buf->writestring(func->toChars());
5616 /************************************************************/
5618 DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s)
5619 : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e)
5621 this->sym = s;
5622 this->type = s->getType();
5625 Expression *DotTypeExp::semantic(Scope *sc)
5627 #if LOGSEMANTIC
5628 printf("DotTypeExp::semantic('%s')\n", toChars());
5629 #endif
5630 UnaExp::semantic(sc);
5631 return this;
5634 void DotTypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5636 expToCBuffer(buf, hgs, e1, PREC_primary);
5637 buf->writeByte('.');
5638 buf->writestring(sym->toChars());
5641 /************************************************************/
5643 CallExp::CallExp(Loc loc, Expression *e, Expressions *exps)
5644 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5646 this->arguments = exps;
5649 CallExp::CallExp(Loc loc, Expression *e)
5650 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5652 this->arguments = NULL;
5655 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1)
5656 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5658 Expressions *arguments = new Expressions();
5659 arguments->setDim(1);
5660 arguments->data[0] = (void *)earg1;
5662 this->arguments = arguments;
5665 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2)
5666 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5668 Expressions *arguments = new Expressions();
5669 arguments->setDim(2);
5670 arguments->data[0] = (void *)earg1;
5671 arguments->data[1] = (void *)earg2;
5673 this->arguments = arguments;
5676 Expression *CallExp::syntaxCopy()
5678 return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
5682 Expression *CallExp::semantic(Scope *sc)
5684 TypeFunction *tf;
5685 FuncDeclaration *f;
5686 int i;
5687 Type *t1;
5688 int istemp;
5689 Objects *targsi = NULL; // initial list of template arguments
5691 #if LOGSEMANTIC
5692 printf("CallExp::semantic() %s\n", toChars());
5693 e1->dump(0);
5694 #endif
5695 if (type)
5696 return this; // semantic() already run
5697 #if 0
5698 if (arguments && arguments->dim)
5700 Expression *earg = (Expression *)arguments->data[0];
5701 earg->print();
5702 if (earg->type) earg->type->print();
5704 #endif
5706 if (e1->op == TOKdelegate)
5707 { DelegateExp *de = (DelegateExp *)e1;
5709 e1 = new DotVarExp(de->loc, de->e1, de->func);
5710 return semantic(sc);
5713 /* Transform:
5714 * array.id(args) into id(array,args)
5715 * aa.remove(arg) into delete aa[arg]
5717 if (e1->op == TOKdot)
5719 // BUG: we should handle array.a.b.c.e(args) too
5721 DotIdExp *dotid = (DotIdExp *)(e1);
5722 dotid->e1 = dotid->e1->semantic(sc);
5723 assert(dotid->e1);
5724 if (dotid->e1->type)
5726 TY e1ty = dotid->e1->type->toBasetype()->ty;
5727 if (e1ty == Taarray && dotid->ident == Id::remove)
5729 if (!arguments || arguments->dim != 1)
5730 { error("expected key as argument to aa.remove()");
5731 goto Lagain;
5733 Expression *key = (Expression *)arguments->data[0];
5734 key = key->semantic(sc);
5735 key = resolveProperties(sc, key);
5736 key->rvalue();
5738 TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype();
5739 key = key->implicitCastTo(sc, taa->index);
5741 return new RemoveExp(loc, dotid->e1, key);
5743 else if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray)
5745 if (!arguments)
5746 arguments = new Expressions();
5747 arguments->shift(dotid->e1);
5748 e1 = new IdentifierExp(dotid->loc, dotid->ident);
5753 /* This recognizes:
5754 * foo!(tiargs)(funcargs)
5756 if (e1->op == TOKimport && !e1->type)
5757 { ScopeExp *se = (ScopeExp *)e1;
5758 TemplateInstance *ti = se->sds->isTemplateInstance();
5759 if (ti && !ti->semanticdone)
5761 /* Attempt to instantiate ti. If that works, go with it.
5762 * If not, go with partial explicit specialization.
5764 unsigned errors = global.errors;
5765 global.gag++;
5766 ti->semantic(sc);
5767 global.gag--;
5768 if (errors != global.errors)
5770 global.errors = errors;
5771 targsi = ti->tiargs;
5772 e1 = new IdentifierExp(loc, ti->name);
5777 /* This recognizes:
5778 * expr.foo!(tiargs)(funcargs)
5780 if (e1->op == TOKdotti && !e1->type)
5781 { DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1;
5782 TemplateInstance *ti = se->ti;
5783 if (!ti->semanticdone)
5785 /* Attempt to instantiate ti. If that works, go with it.
5786 * If not, go with partial explicit specialization.
5788 Expression *etmp;
5789 unsigned errors = global.errors;
5790 global.gag++;
5791 etmp = e1->semantic(sc);
5792 global.gag--;
5793 if (errors != global.errors)
5795 global.errors = errors;
5796 targsi = ti->tiargs;
5797 e1 = new DotIdExp(loc, se->e1, ti->name);
5799 else
5800 e1 = etmp;
5804 istemp = 0;
5805 Lagain:
5806 //printf("Lagain: %s\n", toChars());
5807 f = NULL;
5808 if (e1->op == TOKthis || e1->op == TOKsuper)
5810 // semantic() run later for these
5812 else
5814 UnaExp::semantic(sc);
5816 /* Look for e1 being a lazy parameter
5818 if (e1->op == TOKvar)
5819 { VarExp *ve = (VarExp *)e1;
5821 if (ve->var->storage_class & STClazy)
5823 TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd);
5824 TypeDelegate *t = new TypeDelegate(tf);
5825 ve->type = t->semantic(loc, sc);
5829 if (e1->op == TOKimport)
5830 { // Perhaps this should be moved to ScopeExp::semantic()
5831 ScopeExp *se = (ScopeExp *)e1;
5832 e1 = new DsymbolExp(loc, se->sds);
5833 e1 = e1->semantic(sc);
5835 #if 1 // patch for #540 by Oskar Linde
5836 else if (e1->op == TOKdotexp)
5838 DotExp *de = (DotExp *) e1;
5840 if (de->e2->op == TOKimport)
5841 { // This should *really* be moved to ScopeExp::semantic()
5842 ScopeExp *se = (ScopeExp *)de->e2;
5843 de->e2 = new DsymbolExp(loc, se->sds);
5844 de->e2 = de->e2->semantic(sc);
5847 if (de->e2->op == TOKtemplate)
5848 { TemplateExp *te = (TemplateExp *) de->e2;
5849 e1 = new DotTemplateExp(loc,de->e1,te->td);
5852 #endif
5855 if (e1->op == TOKcomma)
5857 CommaExp *ce = (CommaExp *)e1;
5859 e1 = ce->e2;
5860 e1->type = ce->type;
5861 ce->e2 = this;
5862 ce->type = NULL;
5863 return ce->semantic(sc);
5866 t1 = NULL;
5867 if (e1->type)
5868 t1 = e1->type->toBasetype();
5870 // Check for call operator overload
5871 if (t1)
5872 { AggregateDeclaration *ad;
5874 if (t1->ty == Tstruct)
5876 ad = ((TypeStruct *)t1)->sym;
5877 if (search_function(ad, Id::call))
5878 goto L1; // overload of opCall, therefore it's a call
5880 if (e1->op != TOKtype)
5881 error("%s %s does not overload ()", ad->kind(), ad->toChars());
5882 /* It's a struct literal
5884 Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments);
5885 e = e->semantic(sc);
5886 e->type = e1->type; // in case e1->type was a typedef
5887 return e;
5889 else if (t1->ty == Tclass)
5891 ad = ((TypeClass *)t1)->sym;
5892 goto L1;
5894 // Rewrite as e1.call(arguments)
5895 Expression *e = new DotIdExp(loc, e1, Id::call);
5896 e = new CallExp(loc, e, arguments);
5897 e = e->semantic(sc);
5898 return e;
5902 arrayExpressionSemantic(arguments, sc);
5903 preFunctionArguments(loc, sc, arguments);
5905 if (e1->op == TOKdotvar && t1->ty == Tfunction ||
5906 e1->op == TOKdottd)
5908 DotVarExp *dve;
5909 DotTemplateExp *dte;
5910 AggregateDeclaration *ad;
5911 UnaExp *ue = (UnaExp *)(e1);
5913 if (e1->op == TOKdotvar)
5914 { // Do overload resolution
5915 dve = (DotVarExp *)(e1);
5917 f = dve->var->isFuncDeclaration();
5918 assert(f);
5919 f = f->overloadResolve(loc, ue->e1, arguments);
5921 ad = f->toParent()->isAggregateDeclaration();
5923 else
5924 { dte = (DotTemplateExp *)(e1);
5925 TemplateDeclaration *td = dte->td;
5926 assert(td);
5927 if (!arguments)
5928 // Should fix deduceFunctionTemplate() so it works on NULL argument
5929 arguments = new Expressions();
5930 f = td->deduceFunctionTemplate(sc, loc, targsi, ue->e1, arguments);
5931 if (!f)
5932 { type = Type::terror;
5933 return this;
5935 ad = td->toParent()->isAggregateDeclaration();
5937 if (f->needThis())
5938 ue->e1 = getRightThis(loc, sc, ad, ue->e1, f);
5940 checkDeprecated(sc, f);
5941 accessCheck(loc, sc, ue->e1, f);
5942 if (!f->needThis())
5944 VarExp *ve = new VarExp(loc, f);
5945 e1 = new CommaExp(loc, ue->e1, ve);
5946 e1->type = f->type;
5948 else
5950 if (e1->op == TOKdotvar)
5951 dve->var = f;
5952 else
5953 e1 = new DotVarExp(loc, dte->e1, f);
5954 e1->type = f->type;
5955 #if 0
5956 printf("ue->e1 = %s\n", ue->e1->toChars());
5957 printf("f = %s\n", f->toChars());
5958 printf("t = %s\n", t->toChars());
5959 printf("e1 = %s\n", e1->toChars());
5960 printf("e1->type = %s\n", e1->type->toChars());
5961 #endif
5962 // Const member function can take const/invariant/mutable this
5963 if (!(f->type->isConst()))
5965 // Check for const/invariant compatibility
5966 Type *tthis = ue->e1->type->toBasetype();
5967 if (tthis->ty == Tpointer)
5968 tthis = tthis->nextOf()->toBasetype();
5969 if (f->type->isInvariant())
5971 if (tthis->mod != MODinvariant)
5972 error("%s can only be called on an invariant object", e1->toChars());
5974 else
5976 if (tthis->mod != 0)
5977 { //printf("mod = %x\n", tthis->mod);
5978 error("%s can only be called on a mutable object, not %s", e1->toChars(), tthis->toChars());
5982 /* Cannot call mutable method on a final struct
5984 if (tthis->ty == Tstruct &&
5985 ue->e1->op == TOKvar)
5986 { VarExp *v = (VarExp *)ue->e1;
5987 if (v->var->storage_class & STCfinal)
5988 error("cannot call mutable method on final struct");
5992 // See if we need to adjust the 'this' pointer
5993 AggregateDeclaration *ad = f->isThis();
5994 ClassDeclaration *cd = ue->e1->type->isClassHandle();
5995 if (ad && cd && ad->isClassDeclaration() && ad != cd &&
5996 ue->e1->op != TOKsuper)
5998 ue->e1 = ue->e1->castTo(sc, ad->type); //new CastExp(loc, ue->e1, ad->type);
5999 ue->e1 = ue->e1->semantic(sc);
6002 t1 = e1->type;
6004 else if (e1->op == TOKsuper)
6006 // Base class constructor call
6007 ClassDeclaration *cd = NULL;
6009 if (sc->func)
6010 cd = sc->func->toParent()->isClassDeclaration();
6011 if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration())
6013 error("super class constructor call must be in a constructor");
6014 type = Type::terror;
6015 return this;
6017 else
6019 f = cd->baseClass->ctor;
6020 if (!f)
6021 { error("no super class constructor for %s", cd->baseClass->toChars());
6022 type = Type::terror;
6023 return this;
6025 else
6027 #if 0
6028 if (sc->callSuper & (CSXthis | CSXsuper))
6029 error("reference to this before super()");
6030 #endif
6031 if (sc->noctor || sc->callSuper & CSXlabel)
6032 error("constructor calls not allowed in loops or after labels");
6033 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
6034 error("multiple constructor calls");
6035 sc->callSuper |= CSXany_ctor | CSXsuper_ctor;
6037 f = f->overloadResolve(loc, NULL, arguments);
6038 checkDeprecated(sc, f);
6039 e1 = new DotVarExp(e1->loc, e1, f);
6040 e1 = e1->semantic(sc);
6041 t1 = e1->type;
6045 else if (e1->op == TOKthis)
6047 // same class constructor call
6048 ClassDeclaration *cd = NULL;
6050 if (sc->func)
6051 cd = sc->func->toParent()->isClassDeclaration();
6052 if (!cd || !sc->func->isCtorDeclaration())
6054 error("class constructor call must be in a constructor");
6055 type = Type::terror;
6056 return this;
6058 else
6060 #if 0
6061 if (sc->callSuper & (CSXthis | CSXsuper))
6062 error("reference to this before super()");
6063 #endif
6064 if (sc->noctor || sc->callSuper & CSXlabel)
6065 error("constructor calls not allowed in loops or after labels");
6066 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
6067 error("multiple constructor calls");
6068 sc->callSuper |= CSXany_ctor | CSXthis_ctor;
6070 f = cd->ctor;
6071 f = f->overloadResolve(loc, NULL, arguments);
6072 checkDeprecated(sc, f);
6073 e1 = new DotVarExp(e1->loc, e1, f);
6074 e1 = e1->semantic(sc);
6075 t1 = e1->type;
6077 // BUG: this should really be done by checking the static
6078 // call graph
6079 if (f == sc->func)
6080 error("cyclic constructor call");
6083 else if (e1->op == TOKoverloadset)
6085 OverExp *eo = (OverExp *)e1;
6086 FuncDeclaration *f = NULL;
6087 for (int i = 0; i < eo->vars->a.dim; i++)
6088 { Dsymbol *s = (Dsymbol *)eo->vars->a.data[i];
6089 FuncDeclaration *f2 = s->isFuncDeclaration();
6090 if (f2)
6092 f2 = f2->overloadResolve(loc, NULL, arguments, 1);
6094 else
6095 { TemplateDeclaration *td = s->isTemplateDeclaration();
6096 assert(td);
6097 f2 = td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments, 1);
6099 if (f2)
6100 { if (f)
6101 /* Error if match in more than one overload set,
6102 * even if one is a 'better' match than the other.
6104 ScopeDsymbol::multiplyDefined(loc, f, f2);
6105 else
6106 f = f2;
6109 if (!f)
6110 { /* No overload matches, just set f and rely on error
6111 * message being generated later.
6113 f = (FuncDeclaration *)eo->vars->a.data[0];
6115 e1 = new VarExp(loc, f);
6116 goto Lagain;
6118 else if (!t1)
6120 error("function expected before (), not '%s'", e1->toChars());
6121 type = Type::terror;
6122 return this;
6124 else if (t1->ty != Tfunction)
6126 if (t1->ty == Tdelegate)
6127 { TypeDelegate *td = (TypeDelegate *)t1;
6128 assert(td->next->ty == Tfunction);
6129 tf = (TypeFunction *)(td->next);
6130 goto Lcheckargs;
6132 else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction)
6133 { Expression *e;
6135 e = new PtrExp(loc, e1);
6136 t1 = ((TypePointer *)t1)->next;
6137 e->type = t1;
6138 e1 = e;
6140 else if (e1->op == TOKtemplate)
6142 TemplateExp *te = (TemplateExp *)e1;
6143 f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments);
6144 if (!f)
6145 { type = Type::terror;
6146 return this;
6148 if (f->needThis() && hasThis(sc))
6150 // Supply an implicit 'this', as in
6151 // this.ident
6153 e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td);
6154 goto Lagain;
6157 e1 = new VarExp(loc, f);
6158 goto Lagain;
6160 else
6161 { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars());
6162 type = Type::terror;
6163 return this;
6166 else if (e1->op == TOKvar)
6168 // Do overload resolution
6169 VarExp *ve = (VarExp *)e1;
6171 f = ve->var->isFuncDeclaration();
6172 assert(f);
6174 if (ve->hasOverloads)
6175 f = f->overloadResolve(loc, NULL, arguments);
6176 checkDeprecated(sc, f);
6178 if (f->needThis() && hasThis(sc))
6180 // Supply an implicit 'this', as in
6181 // this.ident
6183 e1 = new DotVarExp(loc, new ThisExp(loc), f);
6184 goto Lagain;
6187 accessCheck(loc, sc, NULL, f);
6189 ve->var = f;
6190 // ve->hasOverloads = 0;
6191 ve->type = f->type;
6192 t1 = f->type;
6194 assert(t1->ty == Tfunction);
6195 tf = (TypeFunction *)(t1);
6197 Lcheckargs:
6198 assert(tf->ty == Tfunction);
6199 type = tf->next;
6201 if (!arguments)
6202 arguments = new Expressions();
6203 functionArguments(loc, sc, tf, arguments);
6205 assert(type);
6207 if (f && f->tintro)
6209 Type *t = type;
6210 target_ptrdiff_t offset = 0;
6211 TypeFunction *tf = (TypeFunction *)f->tintro;
6213 if (tf->next->isBaseOf(t, &offset) && offset)
6215 type = tf->next;
6216 return castTo(sc, t);
6220 return this;
6223 int CallExp::checkSideEffect(int flag)
6225 return 1;
6228 int CallExp::canThrow()
6230 return 1;
6233 Expression *CallExp::toLvalue(Scope *sc, Expression *e)
6235 if (type->toBasetype()->ty == Tstruct)
6236 return this;
6237 else
6238 return Expression::toLvalue(sc, e);
6241 void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6242 { int i;
6244 expToCBuffer(buf, hgs, e1, precedence[op]);
6245 buf->writeByte('(');
6246 argsToCBuffer(buf, arguments, hgs);
6247 buf->writeByte(')');
6251 /************************************************************/
6253 AddrExp::AddrExp(Loc loc, Expression *e)
6254 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e)
6258 Expression *AddrExp::semantic(Scope *sc)
6260 #if LOGSEMANTIC
6261 printf("AddrExp::semantic('%s')\n", toChars());
6262 #endif
6263 if (!type)
6265 UnaExp::semantic(sc);
6266 e1 = e1->toLvalue(sc, NULL);
6267 if (!e1->type)
6269 error("cannot take address of %s", e1->toChars());
6270 type = Type::tint32;
6271 return this;
6273 type = e1->type->pointerTo();
6275 // See if this should really be a delegate
6276 if (e1->op == TOKdotvar)
6278 DotVarExp *dve = (DotVarExp *)e1;
6280 FuncDeclaration *f = dve->var->isFuncDeclaration();
6282 if (f)
6284 if (!dve->hasOverloads)
6285 f->tookAddressOf = 1;
6286 Expression *e = new DelegateExp(loc, dve->e1, f, dve->hasOverloads);
6287 e = e->semantic(sc);
6288 return e;
6291 else if (e1->op == TOKvar)
6293 VarExp *ve = (VarExp *)e1;
6295 VarDeclaration *v = ve->var->isVarDeclaration();
6296 if (v && !v->canTakeAddressOf())
6297 error("cannot take address of %s", e1->toChars());
6299 FuncDeclaration *f = ve->var->isFuncDeclaration();
6301 if (f)
6303 if (!ve->hasOverloads)
6304 f->tookAddressOf = 1;
6305 if (f->isNested())
6307 Expression *e = new DelegateExp(loc, e1, f, ve->hasOverloads);
6308 e = e->semantic(sc);
6309 return e;
6311 if (f->needThis() && hasThis(sc))
6313 /* Should probably supply 'this' after overload resolution,
6314 * not before.
6316 Expression *ethis = new ThisExp(loc);
6317 Expression *e = new DelegateExp(loc, ethis, f, ve->hasOverloads);
6318 e = e->semantic(sc);
6319 return e;
6323 return optimize(WANTvalue);
6325 return this;
6328 /************************************************************/
6330 PtrExp::PtrExp(Loc loc, Expression *e)
6331 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
6333 if (e->type)
6334 type = ((TypePointer *)e->type)->next;
6337 PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
6338 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
6340 type = t;
6343 Expression *PtrExp::semantic(Scope *sc)
6344 { Type *tb;
6346 #if LOGSEMANTIC
6347 printf("PtrExp::semantic('%s')\n", toChars());
6348 #endif
6349 if (!type)
6351 UnaExp::semantic(sc);
6352 e1 = resolveProperties(sc, e1);
6353 if (!e1->type)
6354 printf("PtrExp::semantic('%s')\n", toChars());
6355 Expression *e = op_overload(sc);
6356 if (e)
6357 return e;
6358 tb = e1->type->toBasetype();
6359 switch (tb->ty)
6361 case Tpointer:
6362 type = ((TypePointer *)tb)->next;
6363 break;
6365 case Tsarray:
6366 case Tarray:
6367 type = ((TypeArray *)tb)->next;
6368 e1 = e1->castTo(sc, type->pointerTo());
6369 break;
6371 default:
6372 error("can only * a pointer, not a '%s'", e1->type->toChars());
6373 type = Type::tint32;
6374 break;
6376 rvalue();
6378 return this;
6381 Expression *PtrExp::toLvalue(Scope *sc, Expression *e)
6383 #if 0
6384 tym = tybasic(e1->ET->Tty);
6385 if (!(tyscalar(tym) ||
6386 tym == TYstruct ||
6387 tym == TYarray && e->Eoper == TOKaddr))
6388 synerr(EM_lvalue); // lvalue expected
6389 #endif
6390 return this;
6393 Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e)
6395 //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
6397 if (e1->op == TOKsymoff)
6398 { SymOffExp *se = (SymOffExp *)e1;
6399 se->var->checkModify(loc, sc, type);
6400 //return toLvalue(sc, e);
6403 return Expression::modifiableLvalue(sc, e);
6407 void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6409 buf->writeByte('*');
6410 expToCBuffer(buf, hgs, e1, precedence[op]);
6413 /************************************************************/
6415 NegExp::NegExp(Loc loc, Expression *e)
6416 : UnaExp(loc, TOKneg, sizeof(NegExp), e)
6420 Expression *NegExp::semantic(Scope *sc)
6421 { Expression *e;
6423 #if LOGSEMANTIC
6424 printf("NegExp::semantic('%s')\n", toChars());
6425 #endif
6426 if (!type)
6428 UnaExp::semantic(sc);
6429 e1 = resolveProperties(sc, e1);
6430 e = op_overload(sc);
6431 if (e)
6432 return e;
6434 e1->checkNoBool();
6435 e1->checkArithmetic();
6436 type = e1->type;
6438 return this;
6441 /************************************************************/
6443 UAddExp::UAddExp(Loc loc, Expression *e)
6444 : UnaExp(loc, TOKuadd, sizeof(UAddExp), e)
6448 Expression *UAddExp::semantic(Scope *sc)
6449 { Expression *e;
6451 #if LOGSEMANTIC
6452 printf("UAddExp::semantic('%s')\n", toChars());
6453 #endif
6454 assert(!type);
6455 UnaExp::semantic(sc);
6456 e1 = resolveProperties(sc, e1);
6457 e = op_overload(sc);
6458 if (e)
6459 return e;
6460 e1->checkNoBool();
6461 e1->checkArithmetic();
6462 return e1;
6465 /************************************************************/
6467 ComExp::ComExp(Loc loc, Expression *e)
6468 : UnaExp(loc, TOKtilde, sizeof(ComExp), e)
6472 Expression *ComExp::semantic(Scope *sc)
6473 { Expression *e;
6475 if (!type)
6477 UnaExp::semantic(sc);
6478 e1 = resolveProperties(sc, e1);
6479 e = op_overload(sc);
6480 if (e)
6481 return e;
6483 e1->checkNoBool();
6484 e1 = e1->checkIntegral();
6485 type = e1->type;
6487 return this;
6490 /************************************************************/
6492 NotExp::NotExp(Loc loc, Expression *e)
6493 : UnaExp(loc, TOKnot, sizeof(NotExp), e)
6497 Expression *NotExp::semantic(Scope *sc)
6499 UnaExp::semantic(sc);
6500 e1 = resolveProperties(sc, e1);
6501 e1 = e1->checkToBoolean();
6502 type = Type::tboolean;
6503 return this;
6506 int NotExp::isBit()
6508 return TRUE;
6513 /************************************************************/
6515 BoolExp::BoolExp(Loc loc, Expression *e, Type *t)
6516 : UnaExp(loc, TOKtobool, sizeof(BoolExp), e)
6518 type = t;
6521 Expression *BoolExp::semantic(Scope *sc)
6523 UnaExp::semantic(sc);
6524 e1 = resolveProperties(sc, e1);
6525 e1 = e1->checkToBoolean();
6526 type = Type::tboolean;
6527 return this;
6530 int BoolExp::isBit()
6532 return TRUE;
6535 /************************************************************/
6537 DeleteExp::DeleteExp(Loc loc, Expression *e)
6538 : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e)
6542 Expression *DeleteExp::semantic(Scope *sc)
6544 Type *tb;
6546 UnaExp::semantic(sc);
6547 e1 = resolveProperties(sc, e1);
6548 e1 = e1->toLvalue(sc, NULL);
6549 type = Type::tvoid;
6551 tb = e1->type->toBasetype();
6552 switch (tb->ty)
6553 { case Tclass:
6554 { TypeClass *tc = (TypeClass *)tb;
6555 ClassDeclaration *cd = tc->sym;
6557 if (cd->isCOMinterface())
6558 { /* Because COM classes are deleted by IUnknown.Release()
6560 error("cannot delete instance of COM interface %s", cd->toChars());
6562 break;
6564 case Tpointer:
6565 tb = ((TypePointer *)tb)->next->toBasetype();
6566 if (tb->ty == Tstruct)
6568 TypeStruct *ts = (TypeStruct *)tb;
6569 StructDeclaration *sd = ts->sym;
6570 FuncDeclaration *f = sd->aggDelete;
6571 FuncDeclaration *fd = sd->dtor;
6573 if (!f && !fd)
6574 break;
6576 /* Construct:
6577 * ea = copy e1 to a tmp to do side effects only once
6578 * eb = call destructor
6579 * ec = call deallocator
6581 Expression *ea = NULL;
6582 Expression *eb = NULL;
6583 Expression *ec = NULL;
6584 VarDeclaration *v;
6586 if (fd && f)
6587 { Identifier *id = Lexer::idPool("__tmp");
6588 v = new VarDeclaration(loc, e1->type, id, new ExpInitializer(loc, e1));
6589 v->semantic(sc);
6590 v->parent = sc->parent;
6591 ea = new DeclarationExp(loc, v);
6592 ea->type = v->type;
6595 if (fd)
6596 { Expression *e = ea ? new VarExp(loc, v) : e1;
6597 e = new DotVarExp(0, e, fd, 0);
6598 eb = new CallExp(loc, e);
6599 eb = eb->semantic(sc);
6602 if (f)
6604 Type *tpv = Type::tvoid->pointerTo();
6605 Expression *e = ea ? new VarExp(loc, v) : e1->castTo(sc, tpv);
6606 e = new CallExp(loc, new VarExp(loc, f), e);
6607 ec = e->semantic(sc);
6609 ea = combine(ea, eb);
6610 ea = combine(ea, ec);
6611 assert(ea);
6612 return ea;
6614 break;
6616 case Tarray:
6617 /* BUG: look for deleting arrays of structs with dtors.
6619 break;
6621 default:
6622 if (e1->op == TOKindex)
6624 IndexExp *ae = (IndexExp *)(e1);
6625 Type *tb1 = ae->e1->type->toBasetype();
6626 if (tb1->ty == Taarray)
6627 break;
6629 error("cannot delete type %s", e1->type->toChars());
6630 break;
6633 if (e1->op == TOKindex)
6635 IndexExp *ae = (IndexExp *)(e1);
6636 Type *tb1 = ae->e1->type->toBasetype();
6637 if (tb1->ty == Taarray)
6638 { if (!global.params.useDeprecated)
6639 error("delete aa[key] deprecated, use aa.remove(key)");
6643 return this;
6646 int DeleteExp::checkSideEffect(int flag)
6648 return 1;
6651 Expression *DeleteExp::checkToBoolean()
6653 error("delete does not give a boolean result");
6654 return this;
6657 void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6659 buf->writestring("delete ");
6660 expToCBuffer(buf, hgs, e1, precedence[op]);
6663 /************************************************************/
6665 CastExp::CastExp(Loc loc, Expression *e, Type *t)
6666 : UnaExp(loc, TOKcast, sizeof(CastExp), e)
6668 to = t;
6669 this->tok = TOKreserved;
6672 /* For cast(const) and cast(invariant)
6674 CastExp::CastExp(Loc loc, Expression *e, enum TOK tok)
6675 : UnaExp(loc, TOKcast, sizeof(CastExp), e)
6677 to = NULL;
6678 this->tok = tok;
6681 Expression *CastExp::syntaxCopy()
6683 return to ? new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy())
6684 : new CastExp(loc, e1->syntaxCopy(), tok);
6688 Expression *CastExp::semantic(Scope *sc)
6689 { Expression *e;
6690 BinExp *b;
6691 UnaExp *u;
6693 #if LOGSEMANTIC
6694 printf("CastExp::semantic('%s')\n", toChars());
6695 #endif
6697 //static int x; assert(++x < 10);
6699 if (type)
6700 return this;
6701 UnaExp::semantic(sc);
6702 if (e1->type) // if not a tuple
6704 e1 = resolveProperties(sc, e1);
6706 /* Handle cast(const) and cast(invariant)
6708 if (!to)
6709 { if (tok == TOKconst)
6710 to = e1->type->constOf();
6711 else if (tok == TOKinvariant)
6712 to = e1->type->invariantOf();
6713 else
6714 assert(0);
6716 else
6717 to = to->semantic(loc, sc);
6719 e = op_overload(sc);
6720 if (e)
6722 return e->implicitCastTo(sc, to);
6725 Type *tob = to->toBasetype();
6726 if (tob->ty == Tstruct &&
6727 !tob->equals(e1->type->toBasetype()) &&
6728 ((TypeStruct *)to)->sym->search(0, Id::call, 0)
6731 /* Look to replace:
6732 * cast(S)t
6733 * with:
6734 * S(t)
6737 // Rewrite as to.call(e1)
6738 e = new TypeExp(loc, to);
6739 e = new DotIdExp(loc, e, Id::call);
6740 e = new CallExp(loc, e, e1);
6741 e = e->semantic(sc);
6742 return e;
6745 else if (!to)
6746 { error("cannot cast tuple");
6747 to = Type::terror;
6749 e = e1->castTo(sc, to->maybe(true));
6750 return e;
6753 int CastExp::checkSideEffect(int flag)
6755 /* if not:
6756 * cast(void)
6757 * cast(classtype)func()
6759 if (!to->equals(Type::tvoid) &&
6760 !(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass))
6761 return Expression::checkSideEffect(flag);
6762 return 1;
6765 void CastExp::checkEscape()
6766 { Type *tb = type->toBasetype();
6767 if (tb->ty == Tarray && e1->op == TOKvar &&
6768 e1->type->toBasetype()->ty == Tsarray)
6769 { VarExp *ve = (VarExp *)e1;
6770 VarDeclaration *v = ve->var->isVarDeclaration();
6771 if (v)
6773 if (!v->isDataseg() && !v->isParameter())
6774 error("escaping reference to local %s", v->toChars());
6779 void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6781 buf->writestring("cast(");
6782 if (to)
6783 to->toCBuffer(buf, NULL, hgs);
6784 else
6785 buf->writestring(Token::tochars[tok]);
6786 buf->writeByte(')');
6787 expToCBuffer(buf, hgs, e1, precedence[op]);
6791 /************************************************************/
6793 SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr)
6794 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1)
6796 this->upr = upr;
6797 this->lwr = lwr;
6798 lengthVar = NULL;
6801 Expression *SliceExp::syntaxCopy()
6803 Expression *lwr = NULL;
6804 if (this->lwr)
6805 lwr = this->lwr->syntaxCopy();
6807 Expression *upr = NULL;
6808 if (this->upr)
6809 upr = this->upr->syntaxCopy();
6811 return new SliceExp(loc, e1->syntaxCopy(), lwr, upr);
6814 Expression *SliceExp::semantic(Scope *sc)
6815 { Expression *e;
6816 AggregateDeclaration *ad;
6817 //FuncDeclaration *fd;
6818 ScopeDsymbol *sym;
6820 #if LOGSEMANTIC
6821 printf("SliceExp::semantic('%s')\n", toChars());
6822 #endif
6823 if (type)
6824 return this;
6826 UnaExp::semantic(sc);
6827 e1 = resolveProperties(sc, e1);
6829 e = this;
6831 Type *t = e1->type->toBasetype();
6832 if (t->ty == Tpointer)
6834 if (!lwr || !upr)
6835 error("need upper and lower bound to slice pointer");
6837 else if (t->ty == Tarray)
6840 else if (t->ty == Tsarray)
6843 else if (t->ty == Tclass)
6845 ad = ((TypeClass *)t)->sym;
6846 goto L1;
6848 else if (t->ty == Tstruct)
6850 ad = ((TypeStruct *)t)->sym;
6853 if (search_function(ad, Id::slice))
6855 // Rewrite as e1.slice(lwr, upr)
6856 e = new DotIdExp(loc, e1, Id::slice);
6858 if (lwr)
6860 assert(upr);
6861 e = new CallExp(loc, e, lwr, upr);
6863 else
6864 { assert(!upr);
6865 e = new CallExp(loc, e);
6867 e = e->semantic(sc);
6868 return e;
6870 goto Lerror;
6872 else if (t->ty == Ttuple)
6874 if (!lwr && !upr)
6875 return e1;
6876 if (!lwr || !upr)
6877 { error("need upper and lower bound to slice tuple");
6878 goto Lerror;
6881 else
6882 goto Lerror;
6884 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
6886 sym = new ArrayScopeSymbol(sc, this);
6887 sym->loc = loc;
6888 sym->parent = sc->scopesym;
6889 sc = sc->push(sym);
6892 if (lwr)
6893 { lwr = lwr->semantic(sc);
6894 lwr = resolveProperties(sc, lwr);
6895 lwr = lwr->implicitCastTo(sc, Type::tsize_t);
6897 if (upr)
6898 { upr = upr->semantic(sc);
6899 upr = resolveProperties(sc, upr);
6900 upr = upr->implicitCastTo(sc, Type::tsize_t);
6903 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
6904 sc->pop();
6906 if (t->ty == Ttuple)
6908 lwr = lwr->optimize(WANTvalue);
6909 upr = upr->optimize(WANTvalue);
6910 uinteger_t i1 = lwr->toUInteger();
6911 uinteger_t i2 = upr->toUInteger();
6913 size_t length;
6914 TupleExp *te;
6915 TypeTuple *tup;
6917 if (e1->op == TOKtuple) // slicing an expression tuple
6918 { te = (TupleExp *)e1;
6919 length = te->exps->dim;
6921 else if (e1->op == TOKtype) // slicing a type tuple
6922 { tup = (TypeTuple *)t;
6923 length = Argument::dim(tup->arguments);
6925 else
6926 assert(0);
6928 if (i1 <= i2 && i2 <= length)
6929 { size_t j1 = (size_t) i1;
6930 size_t j2 = (size_t) i2;
6932 if (e1->op == TOKtuple)
6933 { Expressions *exps = new Expressions;
6934 exps->setDim(j2 - j1);
6935 for (size_t i = 0; i < j2 - j1; i++)
6936 { Expression *e = (Expression *)te->exps->data[j1 + i];
6937 exps->data[i] = (void *)e;
6939 e = new TupleExp(loc, exps);
6941 else
6942 { Arguments *args = new Arguments;
6943 args->reserve(j2 - j1);
6944 for (size_t i = j1; i < j2; i++)
6945 { Argument *arg = Argument::getNth(tup->arguments, i);
6946 args->push(arg);
6948 e = new TypeExp(e1->loc, new TypeTuple(args));
6950 e = e->semantic(sc);
6952 else
6954 error("string slice [%"PRIuMAX" .. %"PRIuMAX"] is out of bounds", i1, i2);
6955 e = e1;
6957 return e;
6960 type = t->nextOf()->arrayOf();
6961 return e;
6963 Lerror:
6964 char *s;
6965 if (t->ty == Tvoid)
6966 s = e1->toChars();
6967 else
6968 s = t->toChars();
6969 error("%s cannot be sliced with []", s);
6970 type = Type::terror;
6971 return e;
6974 void SliceExp::checkEscape()
6976 e1->checkEscape();
6979 Expression *SliceExp::toLvalue(Scope *sc, Expression *e)
6981 return this;
6984 Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e)
6986 error("slice expression %s is not a modifiable lvalue", toChars());
6987 return this;
6990 void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6992 expToCBuffer(buf, hgs, e1, precedence[op]);
6993 buf->writeByte('[');
6994 if (upr || lwr)
6996 if (lwr)
6997 expToCBuffer(buf, hgs, lwr, PREC_assign);
6998 else
6999 buf->writeByte('0');
7000 buf->writestring("..");
7001 if (upr)
7002 expToCBuffer(buf, hgs, upr, PREC_assign);
7003 else
7004 buf->writestring("length"); // BUG: should be array.length
7006 buf->writeByte(']');
7009 /********************** ArrayLength **************************************/
7011 ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1)
7012 : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1)
7016 Expression *ArrayLengthExp::semantic(Scope *sc)
7017 { Expression *e;
7019 #if LOGSEMANTIC
7020 printf("ArrayLengthExp::semantic('%s')\n", toChars());
7021 #endif
7022 if (!type)
7024 UnaExp::semantic(sc);
7025 e1 = resolveProperties(sc, e1);
7027 type = Type::tsize_t;
7029 return this;
7032 void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7034 expToCBuffer(buf, hgs, e1, PREC_primary);
7035 buf->writestring(".length");
7038 /*********************** ArrayExp *************************************/
7040 // e1 [ i1, i2, i3, ... ]
7042 ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args)
7043 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1)
7045 arguments = args;
7048 Expression *ArrayExp::syntaxCopy()
7050 return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
7053 Expression *ArrayExp::semantic(Scope *sc)
7054 { Expression *e;
7055 Type *t1;
7057 #if LOGSEMANTIC
7058 printf("ArrayExp::semantic('%s')\n", toChars());
7059 #endif
7060 UnaExp::semantic(sc);
7061 e1 = resolveProperties(sc, e1);
7063 t1 = e1->type->toBasetype();
7064 if (t1->ty != Tclass && t1->ty != Tstruct)
7065 { // Convert to IndexExp
7066 if (arguments->dim != 1)
7067 error("only one index allowed to index %s", t1->toChars());
7068 e = new IndexExp(loc, e1, (Expression *)arguments->data[0]);
7069 return e->semantic(sc);
7072 // Run semantic() on each argument
7073 for (size_t i = 0; i < arguments->dim; i++)
7074 { e = (Expression *)arguments->data[i];
7076 e = e->semantic(sc);
7077 if (!e->type)
7078 error("%s has no value", e->toChars());
7079 arguments->data[i] = (void *)e;
7082 expandTuples(arguments);
7083 assert(arguments && arguments->dim);
7085 e = op_overload(sc);
7086 if (!e)
7087 { error("no [] operator overload for type %s", e1->type->toChars());
7088 e = e1;
7090 return e;
7094 Expression *ArrayExp::toLvalue(Scope *sc, Expression *e)
7096 if (type && type->toBasetype()->ty == Tvoid)
7097 error("voids have no value");
7098 return this;
7102 void ArrayExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7103 { int i;
7105 expToCBuffer(buf, hgs, e1, PREC_primary);
7106 buf->writeByte('[');
7107 argsToCBuffer(buf, arguments, hgs);
7108 buf->writeByte(']');
7111 /************************* DotExp ***********************************/
7113 DotExp::DotExp(Loc loc, Expression *e1, Expression *e2)
7114 : BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2)
7118 Expression *DotExp::semantic(Scope *sc)
7120 #if LOGSEMANTIC
7121 printf("DotExp::semantic('%s')\n", toChars());
7122 if (type) printf("\ttype = %s\n", type->toChars());
7123 #endif
7124 e1 = e1->semantic(sc);
7125 e2 = e2->semantic(sc);
7126 if (e2->op == TOKimport)
7128 ScopeExp *se = (ScopeExp *)e2;
7129 TemplateDeclaration *td = se->sds->isTemplateDeclaration();
7130 if (td)
7131 { Expression *e = new DotTemplateExp(loc, e1, td);
7132 e = e->semantic(sc);
7133 return e;
7136 if (!type)
7137 type = e2->type;
7138 return this;
7142 /************************* CommaExp ***********************************/
7144 CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2)
7145 : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2)
7149 Expression *CommaExp::semantic(Scope *sc)
7151 if (!type)
7152 { BinExp::semanticp(sc);
7153 type = e2->type;
7155 return this;
7158 void CommaExp::checkEscape()
7160 e2->checkEscape();
7163 Expression *CommaExp::toLvalue(Scope *sc, Expression *e)
7165 e2 = e2->toLvalue(sc, NULL);
7166 return this;
7169 Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e)
7171 e2 = e2->modifiableLvalue(sc, e);
7172 return this;
7175 int CommaExp::isBool(int result)
7177 return e2->isBool(result);
7180 int CommaExp::checkSideEffect(int flag)
7182 if (flag == 2)
7183 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
7184 else
7186 // Don't check e1 until we cast(void) the a,b code generation
7187 return e2->checkSideEffect(flag);
7191 /************************** IndexExp **********************************/
7193 // e1 [ e2 ]
7195 IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2)
7196 : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2)
7198 //printf("IndexExp::IndexExp('%s')\n", toChars());
7199 lengthVar = NULL;
7200 modifiable = 0; // assume it is an rvalue
7203 Expression *IndexExp::semantic(Scope *sc)
7204 { Expression *e;
7205 BinExp *b;
7206 UnaExp *u;
7207 Type *t1;
7208 ScopeDsymbol *sym;
7210 #if LOGSEMANTIC
7211 printf("IndexExp::semantic('%s')\n", toChars());
7212 #endif
7213 if (type)
7214 return this;
7215 if (!e1->type)
7216 e1 = e1->semantic(sc);
7217 assert(e1->type); // semantic() should already be run on it
7218 e = this;
7220 // Note that unlike C we do not implement the int[ptr]
7222 t1 = e1->type->toBasetype();
7224 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
7225 { // Create scope for 'length' variable
7226 sym = new ArrayScopeSymbol(sc, this);
7227 sym->loc = loc;
7228 sym->parent = sc->scopesym;
7229 sc = sc->push(sym);
7232 e2 = e2->semantic(sc);
7233 if (!e2->type)
7235 error("%s has no value", e2->toChars());
7236 e2->type = Type::terror;
7238 e2 = resolveProperties(sc, e2);
7240 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
7241 sc = sc->pop();
7243 switch (t1->ty)
7245 case Tpointer:
7246 case Tarray:
7247 e2 = e2->implicitCastTo(sc, Type::tsize_t);
7248 e->type = ((TypeNext *)t1)->next;
7249 break;
7251 case Tsarray:
7253 e2 = e2->implicitCastTo(sc, Type::tsize_t);
7255 TypeSArray *tsa = (TypeSArray *)t1;
7257 #if 0 // Don't do now, because it might be short-circuit evaluated
7258 // Do compile time array bounds checking if possible
7259 e2 = e2->optimize(WANTvalue);
7260 if (e2->op == TOKint64)
7262 integer_t index = e2->toInteger();
7263 integer_t length = tsa->dim->toInteger();
7264 if (index < 0 || index >= length)
7265 error("array index [%lld] is outside array bounds [0 .. %lld]",
7266 index, length);
7268 #endif
7269 e->type = t1->nextOf();
7270 break;
7273 case Taarray:
7274 { TypeAArray *taa = (TypeAArray *)t1;
7276 e2 = e2->implicitCastTo(sc, taa->index); // type checking
7277 type = taa->next;
7278 break;
7281 case Ttuple:
7283 e2 = e2->implicitCastTo(sc, Type::tsize_t);
7284 e2 = e2->optimize(WANTvalue | WANTinterpret);
7285 uinteger_t index = e2->toUInteger();
7286 size_t length;
7287 TupleExp *te;
7288 TypeTuple *tup;
7290 if (e1->op == TOKtuple)
7291 { te = (TupleExp *)e1;
7292 length = te->exps->dim;
7294 else if (e1->op == TOKtype)
7296 tup = (TypeTuple *)t1;
7297 length = Argument::dim(tup->arguments);
7299 else
7300 assert(0);
7302 if (index < length)
7305 if (e1->op == TOKtuple)
7306 e = (Expression *)te->exps->data[(size_t)index];
7307 else
7308 e = new TypeExp(e1->loc, Argument::getNth(tup->arguments, (size_t)index)->type);
7310 else
7312 error("array index [%"PRIuMAX"] is outside array bounds [0 .. %"PRIuSIZE"]",
7313 index, length);
7314 e = e1;
7316 break;
7319 default:
7320 error("%s must be an array or pointer type, not %s",
7321 e1->toChars(), e1->type->toChars());
7322 type = Type::tint32;
7323 break;
7325 return e;
7328 Expression *IndexExp::toLvalue(Scope *sc, Expression *e)
7330 // if (type && type->toBasetype()->ty == Tvoid)
7331 // error("voids have no value");
7332 return this;
7335 Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
7337 //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
7338 modifiable = 1;
7339 if (e1->op == TOKstring)
7340 error("string literals are immutable");
7341 if (type && !type->isMutable())
7342 error("%s isn't mutable", e->toChars());
7343 if (e1->type->toBasetype()->ty == Taarray)
7344 e1 = e1->modifiableLvalue(sc, e1);
7345 return toLvalue(sc, e);
7348 void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7350 expToCBuffer(buf, hgs, e1, PREC_primary);
7351 buf->writeByte('[');
7352 expToCBuffer(buf, hgs, e2, PREC_assign);
7353 buf->writeByte(']');
7357 /************************* PostExp ***********************************/
7359 PostExp::PostExp(enum TOK op, Loc loc, Expression *e)
7360 : BinExp(loc, op, sizeof(PostExp), e,
7361 new IntegerExp(loc, 1, Type::tint32))
7365 Expression *PostExp::semantic(Scope *sc)
7366 { Expression *e = this;
7368 if (!type)
7370 BinExp::semantic(sc);
7371 e2 = resolveProperties(sc, e2);
7373 e = op_overload(sc);
7374 if (e)
7375 return e;
7377 e = this;
7378 e1 = e1->modifiableLvalue(sc, e1);
7379 e1->checkScalar();
7380 e1->checkNoBool();
7381 if (e1->type->ty == Tpointer)
7382 e = scaleFactor(sc);
7383 else
7384 e2 = e2->castTo(sc, e1->type);
7385 e->type = e1->type;
7387 return e;
7390 void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7392 expToCBuffer(buf, hgs, e1, precedence[op]);
7393 buf->writestring((op == TOKplusplus) ? (char *)"++" : (char *)"--");
7396 /************************************************************/
7398 /* op can be TOKassign, TOKconstruct, or TOKblit */
7400 AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2)
7401 : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2)
7403 ismemset = 0;
7406 Expression *AssignExp::semantic(Scope *sc)
7408 Expression *e1old = e1;
7410 #if LOGSEMANTIC
7411 printf("AssignExp::semantic('%s')\n", toChars());
7412 #endif
7413 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
7414 //printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op));
7416 if (type)
7417 return this;
7419 if (e2->op == TOKcomma)
7420 { /* Rewrite to get rid of the comma from rvalue
7422 AssignExp *ea = new AssignExp(loc, e1, ((CommaExp *)e2)->e2);
7423 ea->op = op;
7424 Expression *e = new CommaExp(loc, ((CommaExp *)e2)->e1, ea);
7425 return e->semantic(sc);
7428 /* Look for operator overloading of a[i]=value.
7429 * Do it before semantic() otherwise the a[i] will have been
7430 * converted to a.opIndex() already.
7432 if (e1->op == TOKarray)
7434 ArrayExp *ae = (ArrayExp *)e1;
7435 AggregateDeclaration *ad;
7436 Identifier *id = Id::index;
7438 ae->e1 = ae->e1->semantic(sc);
7439 Type *t1 = ae->e1->type->toBasetype();
7440 if (t1->ty == Tstruct)
7442 ad = ((TypeStruct *)t1)->sym;
7443 goto L1;
7445 else if (t1->ty == Tclass)
7447 ad = ((TypeClass *)t1)->sym;
7449 // Rewrite (a[i] = value) to (a.opIndexAssign(value, i))
7450 if (search_function(ad, Id::indexass))
7451 { Expression *e = new DotIdExp(loc, ae->e1, Id::indexass);
7452 Expressions *a = (Expressions *)ae->arguments->copy();
7454 a->insert(0, e2);
7455 e = new CallExp(loc, e, a);
7456 e = e->semantic(sc);
7457 return e;
7459 else
7461 // Rewrite (a[i] = value) to (a.opIndex(i, value))
7462 if (search_function(ad, id))
7463 { Expression *e = new DotIdExp(loc, ae->e1, id);
7465 if (1 || !global.params.useDeprecated)
7466 error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
7468 e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2);
7469 e = e->semantic(sc);
7470 return e;
7475 /* Look for operator overloading of a[i..j]=value.
7476 * Do it before semantic() otherwise the a[i..j] will have been
7477 * converted to a.opSlice() already.
7479 if (e1->op == TOKslice)
7480 { Type *t1;
7481 SliceExp *ae = (SliceExp *)e1;
7482 AggregateDeclaration *ad;
7483 Identifier *id = Id::index;
7485 ae->e1 = ae->e1->semantic(sc);
7486 ae->e1 = resolveProperties(sc, ae->e1);
7487 t1 = ae->e1->type->toBasetype();
7488 if (t1->ty == Tstruct)
7490 ad = ((TypeStruct *)t1)->sym;
7491 goto L2;
7493 else if (t1->ty == Tclass)
7495 ad = ((TypeClass *)t1)->sym;
7497 // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j))
7498 if (search_function(ad, Id::sliceass))
7499 { Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass);
7500 Expressions *a = new Expressions();
7502 a->push(e2);
7503 if (ae->lwr)
7504 { a->push(ae->lwr);
7505 assert(ae->upr);
7506 a->push(ae->upr);
7508 else
7509 assert(!ae->upr);
7510 e = new CallExp(loc, e, a);
7511 e = e->semantic(sc);
7512 return e;
7517 BinExp::semantic(sc);
7518 e2 = resolveProperties(sc, e2);
7519 assert(e1->type);
7521 /* Rewrite tuple assignment as a tuple of assignments.
7523 if (e1->op == TOKtuple && e2->op == TOKtuple)
7524 { TupleExp *tup1 = (TupleExp *)e1;
7525 TupleExp *tup2 = (TupleExp *)e2;
7526 size_t dim = tup1->exps->dim;
7527 if (dim != tup2->exps->dim)
7529 error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim);
7531 else
7532 { Expressions *exps = new Expressions;
7533 exps->setDim(dim);
7535 for (int i = 0; i < dim; i++)
7536 { Expression *ex1 = (Expression *)tup1->exps->data[i];
7537 Expression *ex2 = (Expression *)tup2->exps->data[i];
7538 exps->data[i] = (void *) new AssignExp(loc, ex1, ex2);
7540 Expression *e = new TupleExp(loc, exps);
7541 e = e->semantic(sc);
7542 return e;
7546 Type *t1 = e1->type->toBasetype();
7548 if (t1->ty == Tfunction)
7549 { // Rewrite f=value to f(value)
7550 Expression *e;
7552 e = new CallExp(loc, e1, e2);
7553 e = e->semantic(sc);
7554 return e;
7557 /* If it is an assignment from a 'foreign' type,
7558 * check for operator overloading.
7560 if (t1->ty == Tstruct)
7562 StructDeclaration *sd = ((TypeStruct *)t1)->sym;
7563 if (op == TOKassign)
7565 Expression *e = op_overload(sc);
7566 if (e)
7567 return e;
7569 else if (op == TOKconstruct)
7570 { Type *t2 = e2->type->toBasetype();
7571 if (t2->ty == Tstruct &&
7572 sd == ((TypeStruct *)t2)->sym &&
7573 sd->cpctor)
7574 { /* We have a copy constructor for this
7576 if (e2->op == TOKvar || e2->op == TOKstar)
7577 { /* Write as:
7578 * e1.cpctor(e2);
7580 Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0);
7581 e = new CallExp(loc, e, e2);
7582 return e->semantic(sc);
7584 else if (e2->op == TOKquestion)
7585 { /* Write as:
7586 * a ? e1 = b : e1 = c;
7588 CondExp *ec = (CondExp *)e2;
7589 AssignExp *ea1 = new AssignExp(ec->e1->loc, e1, ec->e1);
7590 ea1->op = op;
7591 AssignExp *ea2 = new AssignExp(ec->e1->loc, e1, ec->e2);
7592 ea2->op = op;
7593 Expression *e = new CondExp(loc, ec->econd, ea1, ea2);
7594 return e->semantic(sc);
7599 else if (t1->ty == Tclass)
7600 { // Disallow assignment operator overloads for same type
7601 if (!e2->type->implicitConvTo(e1->type))
7603 Expression *e = op_overload(sc);
7604 if (e)
7605 return e;
7609 if (t1->ty == Tsarray)
7611 Expression *e = new SliceExp(e1->loc, e1, NULL, NULL);
7612 e1 = e->semantic(sc);
7613 t1 = e1->type->toBasetype();
7616 e2->rvalue();
7618 if (e1->op == TOKarraylength)
7620 // e1 is not an lvalue, but we let code generator handle it
7621 ArrayLengthExp *ale = (ArrayLengthExp *)e1;
7623 ale->e1 = ale->e1->modifiableLvalue(sc, e1);
7625 else if (e1->op == TOKslice)
7627 Type *tn = e1->type->nextOf();
7628 if (tn && !tn->isMutable() && op != TOKconstruct)
7629 error("slice %s is not mutable", e1->toChars());
7631 else
7632 { // Try to do a decent error message with the expression
7633 // before it got constant folded
7634 if (e1->op != TOKvar)
7635 e1 = e1->optimize(WANTvalue);
7636 if (op != TOKconstruct)
7637 e1 = e1->modifiableLvalue(sc, e1old);
7640 Type *t2 = e2->type;
7641 if (e1->op == TOKslice &&
7642 t1->nextOf() &&
7643 e2->implicitConvTo(t1->nextOf())
7645 { // memset
7646 ismemset = 1; // make it easy for back end to tell what this is
7647 e2 = e2->implicitCastTo(sc, t1->nextOf());
7649 else if (t1->ty == Tsarray)
7651 /* Should have already converted e1 => e1[]
7653 assert(0);
7654 //error("cannot assign to static array %s", e1->toChars());
7656 else if (e1->op == TOKslice)
7658 e2 = e2->implicitCastTo(sc, e1->type->constOf());
7660 else
7662 e2 = e2->implicitCastTo(sc, e1->type);
7664 type = e1->type;
7665 assert(type);
7666 return this;
7669 Expression *AssignExp::checkToBoolean()
7671 // Things like:
7672 // if (a = b) ...
7673 // are usually mistakes.
7675 error("'=' does not give a boolean result");
7676 return this;
7679 /************************************************************/
7681 /* Allow pointer arithmetic on e1? */
7682 static bool allowPtrArith(Scope *sc, Expression *e1)
7684 if (e1->type->ty == Tpointer)
7685 return true;
7686 else if (e1->type->ty == Tmaybe && e1->type->nextOf()->ty == Tpointer)
7688 if (!sc->inDtemplate)
7689 e1->error("Can't do pointer arithmetic on pointer ('%s') that could be null",
7690 e1->toChars());
7691 return true;
7693 return false;
7696 AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
7697 : BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
7701 Expression *AddAssignExp::semantic(Scope *sc)
7702 { Expression *e;
7704 if (type)
7705 return this;
7707 BinExp::semantic(sc);
7708 e2 = resolveProperties(sc, e2);
7710 e = op_overload(sc);
7711 if (e)
7712 return e;
7714 e1 = e1->modifiableLvalue(sc, e1);
7716 Type *tb1 = e1->type->toBasetype();
7717 Type *tb2 = e2->type->toBasetype();
7719 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
7720 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
7721 tb1->nextOf()->equals(tb2->nextOf())
7724 type = e1->type;
7725 e = this;
7727 else
7729 e1->checkScalar();
7730 e1->checkNoBool();
7731 if (allowPtrArith(sc, e1) && tb2->isintegral())
7732 e = scaleFactor(sc);
7733 else if (tb1->ty == Tbit || tb1->ty == Tbool)
7735 #if 0
7736 // Need to rethink this
7737 if (e1->op != TOKvar)
7738 { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2
7739 VarDeclaration *v;
7740 Expression *ea;
7741 Expression *ex;
7743 Identifier *id = Lexer::uniqueId("__name");
7745 v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL);
7746 v->semantic(sc);
7747 if (!sc->insert(v))
7748 assert(0);
7749 v->parent = sc->func;
7751 ea = new AddrExp(loc, e1);
7752 ea = new AssignExp(loc, new VarExp(loc, v), ea);
7754 ex = new VarExp(loc, v);
7755 ex = new PtrExp(loc, ex);
7756 e = new AddExp(loc, ex, e2);
7757 e = new CastExp(loc, e, e1->type);
7758 e = new AssignExp(loc, ex->syntaxCopy(), e);
7760 e = new CommaExp(loc, ea, e);
7762 else
7763 #endif
7764 { // Rewrite e1+=e2 to e1=e1+e2
7765 // BUG: doesn't account for side effects in e1
7766 // BUG: other assignment operators for bits aren't handled at all
7767 e = new AddExp(loc, e1, e2);
7768 e = new CastExp(loc, e, e1->type);
7769 e = new AssignExp(loc, e1->syntaxCopy(), e);
7771 e = e->semantic(sc);
7773 else
7775 type = e1->type;
7776 typeCombine(sc);
7777 e1->checkArithmetic();
7778 e2->checkArithmetic();
7779 if (type->isreal() || type->isimaginary())
7781 assert(global.errors || e2->type->isfloating());
7782 e2 = e2->castTo(sc, e1->type);
7784 e = this;
7787 return e;
7790 /************************************************************/
7792 MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
7793 : BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
7797 Expression *MinAssignExp::semantic(Scope *sc)
7798 { Expression *e;
7800 if (type)
7801 return this;
7803 BinExp::semantic(sc);
7804 e2 = resolveProperties(sc, e2);
7806 e = op_overload(sc);
7807 if (e)
7808 return e;
7810 e1 = e1->modifiableLvalue(sc, e1);
7811 e1->checkScalar();
7812 e1->checkNoBool();
7814 if (allowPtrArith(sc, e1) && e2->type->isintegral())
7815 e = scaleFactor(sc);
7816 else
7818 e1 = e1->checkArithmetic();
7819 e2 = e2->checkArithmetic();
7820 type = e1->type;
7821 typeCombine(sc);
7822 if (type->isreal() || type->isimaginary())
7824 assert(e2->type->isfloating());
7825 e2 = e2->castTo(sc, e1->type);
7827 e = this;
7829 return e;
7832 /************************************************************/
7834 CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
7835 : BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
7839 Expression *CatAssignExp::semantic(Scope *sc)
7840 { Expression *e;
7842 BinExp::semantic(sc);
7843 e2 = resolveProperties(sc, e2);
7845 e = op_overload(sc);
7846 if (e)
7847 return e;
7849 if (e1->op == TOKslice)
7850 { SliceExp *se = (SliceExp *)e1;
7852 if (se->e1->type->toBasetype()->ty == Tsarray)
7853 error("cannot append to static array %s", se->e1->type->toChars());
7856 e1 = e1->modifiableLvalue(sc, e1);
7858 Type *tb1 = e1->type->toBasetype();
7859 Type *tb2 = e2->type->toBasetype();
7861 e2->rvalue();
7863 if ((tb1->ty == Tarray) &&
7864 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
7865 (e2->implicitConvTo(e1->type) ||
7866 tb2->nextOf()->implicitConvTo(tb1->nextOf()))
7868 { // Append array
7869 e2 = e2->castTo(sc, e1->type);
7870 type = e1->type;
7871 e = this;
7873 else if ((tb1->ty == Tarray) &&
7874 e2->implicitConvTo(tb1->nextOf())
7876 { // Append element
7877 e2 = e2->castTo(sc, tb1->nextOf());
7878 type = e1->type;
7879 e = this;
7881 else
7883 error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars());
7884 type = Type::tint32;
7885 e = this;
7887 return e;
7890 /************************************************************/
7892 MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
7893 : BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
7897 Expression *MulAssignExp::semantic(Scope *sc)
7898 { Expression *e;
7900 BinExp::semantic(sc);
7901 e2 = resolveProperties(sc, e2);
7903 e = op_overload(sc);
7904 if (e)
7905 return e;
7907 e1 = e1->modifiableLvalue(sc, e1);
7908 e1->checkScalar();
7909 e1->checkNoBool();
7910 type = e1->type;
7911 typeCombine(sc);
7912 e1->checkArithmetic();
7913 e2->checkArithmetic();
7914 if (e2->type->isfloating())
7915 { Type *t1;
7916 Type *t2;
7918 t1 = e1->type;
7919 t2 = e2->type;
7920 if (t1->isreal())
7922 if (t2->isimaginary() || t2->iscomplex())
7924 e2 = e2->castTo(sc, t1);
7927 else if (t1->isimaginary())
7929 if (t2->isimaginary() || t2->iscomplex())
7931 switch (t1->ty)
7933 case Timaginary32: t2 = Type::tfloat32; break;
7934 case Timaginary64: t2 = Type::tfloat64; break;
7935 case Timaginary80: t2 = Type::tfloat80; break;
7936 default:
7937 assert(0);
7939 e2 = e2->castTo(sc, t2);
7943 return this;
7946 /************************************************************/
7948 DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
7949 : BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
7953 Expression *DivAssignExp::semantic(Scope *sc)
7954 { Expression *e;
7956 BinExp::semantic(sc);
7957 e2 = resolveProperties(sc, e2);
7959 e = op_overload(sc);
7960 if (e)
7961 return e;
7963 e1 = e1->modifiableLvalue(sc, e1);
7964 e1->checkScalar();
7965 e1->checkNoBool();
7966 type = e1->type;
7967 typeCombine(sc);
7968 e1->checkArithmetic();
7969 e2->checkArithmetic();
7970 if (e2->type->isimaginary())
7971 { Type *t1;
7972 Type *t2;
7974 t1 = e1->type;
7975 if (t1->isreal())
7976 { // x/iv = i(-x/v)
7977 // Therefore, the result is 0
7978 e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1));
7979 e2->type = t1;
7980 e = new AssignExp(loc, e1, e2);
7981 e->type = t1;
7982 return e;
7984 else if (t1->isimaginary())
7985 { Expression *e;
7987 switch (t1->ty)
7989 case Timaginary32: t2 = Type::tfloat32; break;
7990 case Timaginary64: t2 = Type::tfloat64; break;
7991 case Timaginary80: t2 = Type::tfloat80; break;
7992 default:
7993 assert(0);
7995 e2 = e2->castTo(sc, t2);
7996 e = new AssignExp(loc, e1, e2);
7997 e->type = t1;
7998 return e;
8001 return this;
8004 /************************************************************/
8006 ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
8007 : BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
8011 Expression *ModAssignExp::semantic(Scope *sc)
8013 return commonSemanticAssign(sc);
8016 /************************************************************/
8018 ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
8019 : BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
8023 Expression *ShlAssignExp::semantic(Scope *sc)
8024 { Expression *e;
8026 //printf("ShlAssignExp::semantic()\n");
8027 BinExp::semantic(sc);
8028 e2 = resolveProperties(sc, e2);
8030 e = op_overload(sc);
8031 if (e)
8032 return e;
8034 e1 = e1->modifiableLvalue(sc, e1);
8035 e1->checkScalar();
8036 e1->checkNoBool();
8037 type = e1->type;
8038 typeCombine(sc);
8039 e1->checkIntegral();
8040 e2 = e2->checkIntegral();
8041 e2 = e2->castTo(sc, Type::tshiftcnt);
8042 return this;
8045 /************************************************************/
8047 ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
8048 : BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
8052 Expression *ShrAssignExp::semantic(Scope *sc)
8053 { Expression *e;
8055 BinExp::semantic(sc);
8056 e2 = resolveProperties(sc, e2);
8058 e = op_overload(sc);
8059 if (e)
8060 return e;
8062 e1 = e1->modifiableLvalue(sc, e1);
8063 e1->checkScalar();
8064 e1->checkNoBool();
8065 type = e1->type;
8066 typeCombine(sc);
8067 e1->checkIntegral();
8068 e2 = e2->checkIntegral();
8069 e2 = e2->castTo(sc, Type::tshiftcnt);
8070 return this;
8073 /************************************************************/
8075 UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
8076 : BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
8080 Expression *UshrAssignExp::semantic(Scope *sc)
8081 { Expression *e;
8083 BinExp::semantic(sc);
8084 e2 = resolveProperties(sc, e2);
8086 e = op_overload(sc);
8087 if (e)
8088 return e;
8090 e1 = e1->modifiableLvalue(sc, e1);
8091 e1->checkScalar();
8092 e1->checkNoBool();
8093 type = e1->type;
8094 typeCombine(sc);
8095 e1->checkIntegral();
8096 e2 = e2->checkIntegral();
8097 e2 = e2->castTo(sc, Type::tshiftcnt);
8098 return this;
8101 /************************************************************/
8103 AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
8104 : BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
8108 Expression *AndAssignExp::semantic(Scope *sc)
8110 return commonSemanticAssignIntegral(sc);
8113 /************************************************************/
8115 OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
8116 : BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
8120 Expression *OrAssignExp::semantic(Scope *sc)
8122 return commonSemanticAssignIntegral(sc);
8125 /************************************************************/
8127 XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
8128 : BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
8132 Expression *XorAssignExp::semantic(Scope *sc)
8134 return commonSemanticAssignIntegral(sc);
8137 /************************* AddExp *****************************/
8139 AddExp::AddExp(Loc loc, Expression *e1, Expression *e2)
8140 : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2)
8144 Expression *AddExp::semantic(Scope *sc)
8145 { Expression *e;
8147 #if LOGSEMANTIC
8148 printf("AddExp::semantic('%s')\n", toChars());
8149 #endif
8150 if (!type)
8152 BinExp::semanticp(sc);
8154 e = op_overload(sc);
8155 if (e)
8156 return e;
8158 Type *tb1 = e1->type->toBasetype();
8159 Type *tb2 = e2->type->toBasetype();
8161 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
8162 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
8163 tb1->nextOf()->equals(tb2->nextOf())
8166 type = e1->type;
8167 e = this;
8169 else if (tb1->ty == Tpointer && e2->type->isintegral() ||
8170 tb2->ty == Tpointer && e1->type->isintegral())
8171 e = scaleFactor(sc);
8172 else if (tb1->ty == Tpointer && tb2->ty == Tpointer)
8174 incompatibleTypes();
8175 type = e1->type;
8176 e = this;
8178 else
8180 typeCombine(sc);
8181 if ((e1->type->isreal() && e2->type->isimaginary()) ||
8182 (e1->type->isimaginary() && e2->type->isreal()))
8184 switch (type->toBasetype()->ty)
8186 case Tfloat32:
8187 case Timaginary32:
8188 type = Type::tcomplex32;
8189 break;
8191 case Tfloat64:
8192 case Timaginary64:
8193 type = Type::tcomplex64;
8194 break;
8196 case Tfloat80:
8197 case Timaginary80:
8198 type = Type::tcomplex80;
8199 break;
8201 default:
8202 assert(0);
8205 e = this;
8207 return e;
8209 return this;
8212 /************************************************************/
8214 MinExp::MinExp(Loc loc, Expression *e1, Expression *e2)
8215 : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2)
8219 Expression *MinExp::semantic(Scope *sc)
8220 { Expression *e;
8221 Type *t1;
8222 Type *t2;
8224 #if LOGSEMANTIC
8225 printf("MinExp::semantic('%s')\n", toChars());
8226 #endif
8227 if (type)
8228 return this;
8230 BinExp::semanticp(sc);
8232 e = op_overload(sc);
8233 if (e)
8234 return e;
8236 e = this;
8237 t1 = e1->type->toBasetype();
8238 t2 = e2->type->toBasetype();
8239 if (t1->ty == Tpointer)
8241 if (t2->ty == Tpointer)
8242 { // Need to divide the result by the stride
8243 // Replace (ptr - ptr) with (ptr - ptr) / stride
8244 d_int64 stride;
8245 Expression *e;
8247 typeCombine(sc); // make sure pointer types are compatible
8248 type = Type::tptrdiff_t;
8249 stride = t2->nextOf()->size();
8250 e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
8251 e->type = Type::tptrdiff_t;
8252 return e;
8254 else if (t2->isintegral())
8255 e = scaleFactor(sc);
8256 else
8257 { error("incompatible types for -");
8258 return new IntegerExp(0);
8261 else if (t2->ty == Tpointer)
8263 type = e2->type;
8264 error("can't subtract pointer from %s", e1->type->toChars());
8265 return new IntegerExp(0);
8267 else
8269 typeCombine(sc);
8270 t1 = e1->type->toBasetype();
8271 t2 = e2->type->toBasetype();
8272 if ((t1->isreal() && t2->isimaginary()) ||
8273 (t1->isimaginary() && t2->isreal()))
8275 switch (type->ty)
8277 case Tfloat32:
8278 case Timaginary32:
8279 type = Type::tcomplex32;
8280 break;
8282 case Tfloat64:
8283 case Timaginary64:
8284 type = Type::tcomplex64;
8285 break;
8287 case Tfloat80:
8288 case Timaginary80:
8289 type = Type::tcomplex80;
8290 break;
8292 default:
8293 assert(0);
8297 return e;
8300 /************************* CatExp *****************************/
8302 CatExp::CatExp(Loc loc, Expression *e1, Expression *e2)
8303 : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2)
8307 Expression *CatExp::semantic(Scope *sc)
8308 { Expression *e;
8310 //printf("CatExp::semantic() %s\n", toChars());
8311 if (!type)
8313 BinExp::semanticp(sc);
8314 e = op_overload(sc);
8315 if (e)
8316 return e;
8318 Type *tb1 = e1->type->toBasetype();
8319 Type *tb2 = e2->type->toBasetype();
8322 /* BUG: Should handle things like:
8323 * char c;
8324 * c ~ ' '
8325 * ' ' ~ c;
8328 #if 0
8329 e1->type->print();
8330 e2->type->print();
8331 #endif
8332 if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
8333 e2->type->implicitConvTo(tb1->nextOf()) >= MATCHconst)
8335 type = tb1->nextOf()->arrayOf();
8336 if (tb2->ty == Tarray)
8337 { // Make e2 into [e2]
8338 e2 = new ArrayLiteralExp(e2->loc, e2);
8339 e2->type = type;
8341 return this;
8343 else if ((tb2->ty == Tsarray || tb2->ty == Tarray) &&
8344 e1->type->implicitConvTo(tb2->nextOf()) >= MATCHconst)
8346 type = tb2->nextOf()->arrayOf();
8347 if (tb1->ty == Tarray)
8348 { // Make e1 into [e1]
8349 e1 = new ArrayLiteralExp(e1->loc, e1);
8350 e1->type = type;
8352 return this;
8355 typeCombine(sc);
8356 if (type->ty == Tmaybe)
8357 error("Cannot join arrays that may be null (%s)", toChars());
8359 type = type->toHeadMutable();
8361 Type *tb = type->toBasetype();
8362 if (tb->ty == Tsarray)
8363 type = tb->nextOf()->arrayOf();
8364 if (type->ty == Tarray && tb1->nextOf() && tb2->nextOf() &&
8365 tb1->nextOf()->mod != tb2->nextOf()->mod)
8366 type = type->nextOf()->toHeadMutable()->arrayOf();
8367 #if 0
8368 e1->type->print();
8369 e2->type->print();
8370 type->print();
8371 print();
8372 #endif
8373 Type *t1 = e1->type->toBasetype();
8374 Type *t2 = e2->type->toBasetype();
8375 if (e1->op == TOKstring && e2->op == TOKstring)
8376 e = optimize(WANTvalue);
8377 else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
8378 (t2->ty == Tarray || t2->ty == Tsarray))
8380 e = this;
8382 else
8384 //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars());
8385 error("Can only concatenate arrays, not (%s ~ %s)",
8386 e1->type->toChars(), e2->type->toChars());
8387 type = Type::tint32;
8388 e = this;
8390 e->type = e->type->semantic(loc, sc);
8391 return e;
8393 return this;
8396 /************************************************************/
8398 MulExp::MulExp(Loc loc, Expression *e1, Expression *e2)
8399 : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2)
8403 Expression *MulExp::semantic(Scope *sc)
8404 { Expression *e;
8406 #if 0
8407 printf("MulExp::semantic() %s\n", toChars());
8408 #endif
8409 if (type)
8411 return this;
8414 BinExp::semanticp(sc);
8415 e = op_overload(sc);
8416 if (e)
8417 return e;
8419 typeCombine(sc);
8420 e1->checkArithmetic();
8421 e2->checkArithmetic();
8422 if (type->isfloating())
8423 { Type *t1 = e1->type;
8424 Type *t2 = e2->type;
8426 if (t1->isreal())
8428 type = t2;
8430 else if (t2->isreal())
8432 type = t1;
8434 else if (t1->isimaginary())
8436 if (t2->isimaginary())
8437 { Expression *e;
8439 switch (t1->ty)
8441 case Timaginary32: type = Type::tfloat32; break;
8442 case Timaginary64: type = Type::tfloat64; break;
8443 case Timaginary80: type = Type::tfloat80; break;
8444 default: assert(0);
8447 // iy * iv = -yv
8448 e1->type = type;
8449 e2->type = type;
8450 e = new NegExp(loc, this);
8451 e = e->semantic(sc);
8452 return e;
8454 else
8455 type = t2; // t2 is complex
8457 else if (t2->isimaginary())
8459 type = t1; // t1 is complex
8462 return this;
8465 /************************************************************/
8467 DivExp::DivExp(Loc loc, Expression *e1, Expression *e2)
8468 : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2)
8472 Expression *DivExp::semantic(Scope *sc)
8473 { Expression *e;
8475 if (type)
8476 return this;
8478 BinExp::semanticp(sc);
8479 e = op_overload(sc);
8480 if (e)
8481 return e;
8483 typeCombine(sc);
8484 e1->checkArithmetic();
8485 e2->checkArithmetic();
8486 if (type->isfloating())
8487 { Type *t1 = e1->type;
8488 Type *t2 = e2->type;
8490 if (t1->isreal())
8492 type = t2;
8493 if (t2->isimaginary())
8494 { Expression *e;
8496 // x/iv = i(-x/v)
8497 e2->type = t1;
8498 e = new NegExp(loc, this);
8499 e = e->semantic(sc);
8500 return e;
8503 else if (t2->isreal())
8505 type = t1;
8507 else if (t1->isimaginary())
8509 if (t2->isimaginary())
8511 switch (t1->ty)
8513 case Timaginary32: type = Type::tfloat32; break;
8514 case Timaginary64: type = Type::tfloat64; break;
8515 case Timaginary80: type = Type::tfloat80; break;
8516 default: assert(0);
8519 else
8520 type = t2; // t2 is complex
8522 else if (t2->isimaginary())
8524 type = t1; // t1 is complex
8527 return this;
8530 /************************************************************/
8532 ModExp::ModExp(Loc loc, Expression *e1, Expression *e2)
8533 : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2)
8537 Expression *ModExp::semantic(Scope *sc)
8538 { Expression *e;
8540 if (type)
8541 return this;
8543 BinExp::semanticp(sc);
8544 e = op_overload(sc);
8545 if (e)
8546 return e;
8548 typeCombine(sc);
8549 e1->checkArithmetic();
8550 e2->checkArithmetic();
8551 if (type->isfloating())
8552 { type = e1->type;
8553 if (e2->type->iscomplex())
8554 { error("cannot perform modulo complex arithmetic");
8555 return new IntegerExp(0);
8558 return this;
8561 /************************************************************/
8563 ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2)
8564 : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2)
8568 Expression *ShlExp::semantic(Scope *sc)
8569 { Expression *e;
8571 //printf("ShlExp::semantic(), type = %p\n", type);
8572 if (!type)
8573 { BinExp::semanticp(sc);
8574 e = op_overload(sc);
8575 if (e)
8576 return e;
8577 e1 = e1->checkIntegral();
8578 e2 = e2->checkIntegral();
8579 e1 = e1->integralPromotions(sc);
8580 e2 = e2->castTo(sc, Type::tshiftcnt);
8581 type = e1->type;
8583 return this;
8586 /************************************************************/
8588 ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2)
8589 : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2)
8593 Expression *ShrExp::semantic(Scope *sc)
8594 { Expression *e;
8596 if (!type)
8597 { BinExp::semanticp(sc);
8598 e = op_overload(sc);
8599 if (e)
8600 return e;
8601 e1 = e1->checkIntegral();
8602 e2 = e2->checkIntegral();
8603 e1 = e1->integralPromotions(sc);
8604 e2 = e2->castTo(sc, Type::tshiftcnt);
8605 type = e1->type;
8607 return this;
8610 /************************************************************/
8612 UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2)
8613 : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2)
8617 Expression *UshrExp::semantic(Scope *sc)
8618 { Expression *e;
8620 if (!type)
8621 { BinExp::semanticp(sc);
8622 e = op_overload(sc);
8623 if (e)
8624 return e;
8625 e1 = e1->checkIntegral();
8626 e2 = e2->checkIntegral();
8627 e1 = e1->integralPromotions(sc);
8628 e2 = e2->castTo(sc, Type::tshiftcnt);
8629 type = e1->type;
8631 return this;
8634 /************************************************************/
8636 AndExp::AndExp(Loc loc, Expression *e1, Expression *e2)
8637 : BinExp(loc, TOKand, sizeof(AndExp), e1, e2)
8641 Expression *AndExp::semantic(Scope *sc)
8642 { Expression *e;
8644 if (!type)
8645 { BinExp::semanticp(sc);
8646 e = op_overload(sc);
8647 if (e)
8648 return e;
8649 if (e1->type->toBasetype()->ty == Tbool &&
8650 e2->type->toBasetype()->ty == Tbool)
8652 type = e1->type;
8653 e = this;
8655 else
8657 typeCombine(sc);
8658 e1->checkIntegral();
8659 e2->checkIntegral();
8662 return this;
8665 /************************************************************/
8667 OrExp::OrExp(Loc loc, Expression *e1, Expression *e2)
8668 : BinExp(loc, TOKor, sizeof(OrExp), e1, e2)
8672 Expression *OrExp::semantic(Scope *sc)
8673 { Expression *e;
8675 if (!type)
8676 { BinExp::semanticp(sc);
8677 e = op_overload(sc);
8678 if (e)
8679 return e;
8680 if (e1->type->toBasetype()->ty == Tbool &&
8681 e2->type->toBasetype()->ty == Tbool)
8683 type = e1->type;
8684 e = this;
8686 else
8688 typeCombine(sc);
8689 e1->checkIntegral();
8690 e2->checkIntegral();
8693 return this;
8696 /************************************************************/
8698 XorExp::XorExp(Loc loc, Expression *e1, Expression *e2)
8699 : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2)
8703 Expression *XorExp::semantic(Scope *sc)
8704 { Expression *e;
8706 if (!type)
8707 { BinExp::semanticp(sc);
8708 e = op_overload(sc);
8709 if (e)
8710 return e;
8711 if (e1->type->toBasetype()->ty == Tbool &&
8712 e2->type->toBasetype()->ty == Tbool)
8714 type = e1->type;
8715 e = this;
8717 else
8719 typeCombine(sc);
8720 e1->checkIntegral();
8721 e2->checkIntegral();
8724 return this;
8728 /************************************************************/
8730 OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2)
8731 : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2)
8735 Expression *OrOrExp::semantic(Scope *sc)
8737 unsigned cs1;
8739 // same as for AndAnd
8740 e1 = e1->semantic(sc);
8741 e1 = resolveProperties(sc, e1);
8742 e1 = e1->checkToPointer();
8743 e1 = e1->checkToBoolean();
8744 cs1 = sc->callSuper;
8746 if (sc->flags & SCOPEstaticif)
8748 /* If in static if, don't evaluate e2 if we don't have to.
8750 e1 = e1->optimize(WANTflags);
8751 if (e1->isBool(TRUE))
8753 return new IntegerExp(loc, 1, Type::tboolean);
8757 e2 = e2->semantic(sc);
8758 sc->mergeCallSuper(loc, cs1);
8759 e2 = resolveProperties(sc, e2);
8760 e2 = e2->checkToPointer();
8762 type = Type::tboolean;
8763 if (e1->type->ty == Tvoid)
8764 type = Type::tvoid;
8765 if (e2->op == TOKtype || e2->op == TOKimport)
8766 error("%s is not an expression", e2->toChars());
8767 return this;
8770 Expression *OrOrExp::checkToBoolean()
8772 e2 = e2->checkToBoolean();
8773 return this;
8776 int OrOrExp::isBit()
8778 return TRUE;
8781 int OrOrExp::checkSideEffect(int flag)
8783 if (flag == 2)
8785 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
8787 else
8788 { e1->checkSideEffect(1);
8789 return e2->checkSideEffect(flag);
8793 /************************************************************/
8795 AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2)
8796 : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2)
8800 Expression *AndAndExp::semantic(Scope *sc)
8802 unsigned cs1;
8804 // same as for OrOr
8805 e1 = e1->semantic(sc);
8806 e1 = resolveProperties(sc, e1);
8807 e1 = e1->checkToPointer();
8808 e1 = e1->checkToBoolean();
8809 cs1 = sc->callSuper;
8811 if (sc->flags & SCOPEstaticif)
8813 /* If in static if, don't evaluate e2 if we don't have to.
8815 e1 = e1->optimize(WANTflags);
8816 if (e1->isBool(FALSE))
8818 return new IntegerExp(loc, 0, Type::tboolean);
8822 e2 = e2->semantic(sc);
8823 sc->mergeCallSuper(loc, cs1);
8824 e2 = resolveProperties(sc, e2);
8825 e2 = e2->checkToPointer();
8827 type = Type::tboolean;
8828 if (e1->type->ty == Tvoid)
8829 type = Type::tvoid;
8830 if (e2->op == TOKtype || e2->op == TOKimport)
8831 error("%s is not an expression", e2->toChars());
8832 return this;
8835 Expression *AndAndExp::checkToBoolean()
8837 e2 = e2->checkToBoolean();
8838 return this;
8841 int AndAndExp::isBit()
8843 return TRUE;
8846 int AndAndExp::checkSideEffect(int flag)
8848 if (flag == 2)
8850 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
8852 else
8854 e1->checkSideEffect(1);
8855 return e2->checkSideEffect(flag);
8859 /************************************************************/
8861 InExp::InExp(Loc loc, Expression *e1, Expression *e2)
8862 : BinExp(loc, TOKin, sizeof(InExp), e1, e2)
8866 Expression *InExp::semantic(Scope *sc)
8867 { Expression *e;
8869 if (type)
8870 return this;
8872 BinExp::semanticp(sc);
8873 e = op_overload(sc);
8874 if (e)
8875 return e;
8877 //type = Type::tboolean;
8878 Type *t2b = e2->type->toBasetype();
8879 if (t2b->ty != Taarray)
8881 error("rvalue of in expression must be an associative array, not %s", e2->type->toChars());
8882 type = Type::terror;
8884 else
8886 TypeAArray *ta = (TypeAArray *)t2b;
8888 // Convert key to type of key
8889 e1 = e1->implicitCastTo(sc, ta->index);
8891 // Return type is pointer to value
8892 type = ta->nextOf()->pointerTo()->maybe(true);
8894 return this;
8897 int InExp::isBit()
8899 return FALSE;
8903 /************************************************************/
8905 /* This deletes the key e1 from the associative array e2
8908 RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2)
8909 : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2)
8911 type = Type::tvoid;
8914 /************************************************************/
8916 CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
8917 : BinExp(loc, op, sizeof(CmpExp), e1, e2)
8921 Expression *CmpExp::semantic(Scope *sc)
8922 { Expression *e;
8923 Type *t1;
8924 Type *t2;
8926 #if LOGSEMANTIC
8927 printf("CmpExp::semantic('%s')\n", toChars());
8928 #endif
8929 if (type)
8930 return this;
8932 BinExp::semanticp(sc);
8934 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
8935 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
8937 error("do not use null when comparing class types");
8940 e = op_overload(sc);
8941 if (e)
8943 e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32));
8944 e = e->semantic(sc);
8945 return e;
8948 typeCombine(sc);
8949 type = Type::tboolean;
8951 // Special handling for array comparisons
8952 t1 = e1->type->toBasetype();
8953 t2 = e2->type->toBasetype();
8954 if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
8955 (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
8957 if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
8958 t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
8959 (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
8960 error("array comparison type mismatch, %s vs %s", t1->nextOf()->toChars(), t2->nextOf()->toChars());
8961 e = this;
8963 else if (t1->ty == Tstruct || t2->ty == Tstruct ||
8964 (t1->ty == Tclass && t2->ty == Tclass))
8966 if (t2->ty == Tstruct)
8967 error("need member function opCmp() for %s %s to compare", t2->toDsymbol(sc)->kind(), t2->toChars());
8968 else
8969 error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars());
8970 e = this;
8972 #if 1
8973 else if (t1->iscomplex() || t2->iscomplex())
8975 error("compare not defined for complex operands");
8976 e = new IntegerExp(0);
8978 #endif
8979 else
8980 e = this;
8981 //printf("CmpExp: %s\n", e->toChars());
8982 return e;
8985 int CmpExp::isBit()
8987 return TRUE;
8991 /************************************************************/
8993 EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
8994 : BinExp(loc, op, sizeof(EqualExp), e1, e2)
8996 assert(op == TOKequal || op == TOKnotequal);
8999 Expression *EqualExp::semantic(Scope *sc)
9000 { Expression *e;
9001 Type *t1;
9002 Type *t2;
9004 //printf("EqualExp::semantic('%s')\n", toChars());
9005 if (type)
9006 return this;
9008 BinExp::semanticp(sc);
9010 /* Before checking for operator overloading, check to see if we're
9011 * comparing the addresses of two statics. If so, we can just see
9012 * if they are the same symbol.
9014 if (e1->op == TOKaddress && e2->op == TOKaddress)
9015 { AddrExp *ae1 = (AddrExp *)e1;
9016 AddrExp *ae2 = (AddrExp *)e2;
9018 if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar)
9019 { VarExp *ve1 = (VarExp *)ae1->e1;
9020 VarExp *ve2 = (VarExp *)ae2->e1;
9022 if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/)
9024 // They are the same, result is 'true' for ==, 'false' for !=
9025 e = new IntegerExp(loc, (op == TOKequal), Type::tboolean);
9026 return e;
9031 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
9032 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
9034 error("use '%s' instead of '%s' when comparing with null",
9035 Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity),
9036 Token::toChars(op));
9039 //if (e2->op != TOKnull)
9041 e = op_overload(sc);
9042 if (e)
9044 if (op == TOKnotequal)
9046 e = new NotExp(e->loc, e);
9047 e = e->semantic(sc);
9049 return e;
9053 e = typeCombine(sc);
9054 type = Type::tboolean;
9056 // Special handling for array comparisons
9057 t1 = e1->type->toBasetype();
9058 t2 = e2->type->toBasetype();
9060 if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
9061 (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
9063 if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
9064 t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
9065 (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
9066 error("array equality comparison type mismatch, %s vs %s", t1->toChars(), t2->toChars());
9068 else
9070 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
9072 // Cast both to complex
9073 e1 = e1->castTo(sc, Type::tcomplex80);
9074 e2 = e2->castTo(sc, Type::tcomplex80);
9077 return e;
9080 int EqualExp::isBit()
9082 return TRUE;
9087 /************************************************************/
9089 IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
9090 : BinExp(loc, op, sizeof(IdentityExp), e1, e2)
9094 Expression *IdentityExp::semantic(Scope *sc)
9096 if (type)
9097 return this;
9099 BinExp::semanticp(sc);
9100 type = Type::tboolean;
9101 typeCombine(sc);
9102 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
9104 // Cast both to complex
9105 e1 = e1->castTo(sc, Type::tcomplex80);
9106 e2 = e2->castTo(sc, Type::tcomplex80);
9108 return this;
9111 int IdentityExp::isBit()
9113 return TRUE;
9117 /****************************************************************/
9119 CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2)
9120 : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2)
9122 this->econd = econd;
9125 Expression *CondExp::syntaxCopy()
9127 return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy());
9131 Expression *CondExp::semantic(Scope *sc)
9132 { Type *t1;
9133 Type *t2;
9134 unsigned cs0;
9135 unsigned cs1;
9137 #if LOGSEMANTIC
9138 printf("CondExp::semantic('%s')\n", toChars());
9139 #endif
9140 if (type)
9141 return this;
9143 econd = econd->semantic(sc);
9144 econd = resolveProperties(sc, econd);
9145 econd = econd->checkToPointer();
9146 econd = econd->checkToBoolean();
9148 #if 0 /* this cannot work right because the types of e1 and e2
9149 * both contribute to the type of the result.
9151 if (sc->flags & SCOPEstaticif)
9153 /* If in static if, don't evaluate what we don't have to.
9155 econd = econd->optimize(WANTflags);
9156 if (econd->isBool(TRUE))
9158 e1 = e1->semantic(sc);
9159 e1 = resolveProperties(sc, e1);
9160 return e1;
9162 else if (econd->isBool(FALSE))
9164 e2 = e2->semantic(sc);
9165 e2 = resolveProperties(sc, e2);
9166 return e2;
9169 #endif
9172 cs0 = sc->callSuper;
9173 e1 = e1->semantic(sc);
9174 e1 = resolveProperties(sc, e1);
9175 cs1 = sc->callSuper;
9176 sc->callSuper = cs0;
9177 e2 = e2->semantic(sc);
9178 e2 = resolveProperties(sc, e2);
9179 sc->mergeCallSuper(loc, cs1);
9182 // If either operand is void, the result is void
9183 t1 = e1->type;
9184 t2 = e2->type;
9185 if (t1->ty == Tvoid || t2->ty == Tvoid)
9186 type = Type::tvoid;
9187 else if (t1 == t2)
9188 type = t1;
9189 else
9191 typeCombine(sc);
9192 switch (e1->type->toBasetype()->ty)
9194 case Tcomplex32:
9195 case Tcomplex64:
9196 case Tcomplex80:
9197 e2 = e2->castTo(sc, e1->type);
9198 break;
9200 switch (e2->type->toBasetype()->ty)
9202 case Tcomplex32:
9203 case Tcomplex64:
9204 case Tcomplex80:
9205 e1 = e1->castTo(sc, e2->type);
9206 break;
9208 if (type->toBasetype()->ty == Tarray)
9210 e1 = e1->castTo(sc, type);
9211 e2 = e2->castTo(sc, type);
9214 #if 0
9215 printf("res: %s\n", type->toChars());
9216 printf("e1 : %s\n", e1->type->toChars());
9217 printf("e2 : %s\n", e2->type->toChars());
9218 #endif
9219 return this;
9222 Expression *CondExp::toLvalue(Scope *sc, Expression *ex)
9224 PtrExp *e;
9226 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
9227 e = new PtrExp(loc, this, type);
9229 e1 = e1->addressOf(sc);
9230 //e1 = e1->toLvalue(sc, NULL);
9232 e2 = e2->addressOf(sc);
9233 //e2 = e2->toLvalue(sc, NULL);
9235 typeCombine(sc);
9237 type = e2->type;
9238 return e;
9241 Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e)
9243 error("conditional expression %s is not a modifiable lvalue", toChars());
9244 return this;
9247 void CondExp::checkEscape()
9249 e1->checkEscape();
9250 e2->checkEscape();
9254 Expression *CondExp::checkToBoolean()
9256 e1 = e1->checkToBoolean();
9257 e2 = e2->checkToBoolean();
9258 return this;
9261 int CondExp::checkSideEffect(int flag)
9263 if (flag == 2)
9265 return econd->checkSideEffect(2) ||
9266 e1->checkSideEffect(2) ||
9267 e2->checkSideEffect(2);
9269 else
9271 econd->checkSideEffect(1);
9272 e1->checkSideEffect(flag);
9273 return e2->checkSideEffect(flag);
9277 int CondExp::canThrow()
9279 return econd->canThrow() || e1->canThrow() || e2->canThrow();
9283 void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
9285 expToCBuffer(buf, hgs, econd, PREC_oror);
9286 buf->writestring(" ? ");
9287 expToCBuffer(buf, hgs, e1, PREC_expr);
9288 buf->writestring(" : ");
9289 expToCBuffer(buf, hgs, e2, PREC_cond);
9293 /****************************************************************/
9295 DefaultInitExp::DefaultInitExp(Loc loc, enum TOK subop, int size)
9296 : Expression(loc, TOKdefault, size)
9298 this->subop = subop;
9301 void DefaultInitExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
9303 buf->writestring(Token::toChars(subop));
9306 /****************************************************************/
9308 FileInitExp::FileInitExp(Loc loc)
9309 : DefaultInitExp(loc, TOKfile, sizeof(FileInitExp))
9313 Expression *FileInitExp::semantic(Scope *sc)
9315 //printf("FileInitExp::semantic()\n");
9316 type = Type::tchar->invariantOf()->arrayOf();
9317 return this;
9320 Expression *FileInitExp::resolve(Loc loc, Scope *sc)
9322 //printf("FileInitExp::resolve() %s\n", toChars());
9323 char *s = loc.filename ? loc.filename : sc->module->ident->toChars();
9324 Expression *e = new StringExp(loc, s);
9325 e = e->semantic(sc);
9326 e = e->castTo(sc, type);
9327 return e;
9330 /****************************************************************/
9332 LineInitExp::LineInitExp(Loc loc)
9333 : DefaultInitExp(loc, TOKline, sizeof(LineInitExp))
9337 Expression *LineInitExp::semantic(Scope *sc)
9339 type = Type::tint32;
9340 return this;
9343 Expression *LineInitExp::resolve(Loc loc, Scope *sc)
9345 Expression *e = new IntegerExp(loc, loc.linnum, Type::tint32);
9346 e = e->castTo(sc, type);
9347 return e;