Disallow x[y] if x has a maybe type
[delight/core.git] / dmd2 / expression.c
blobdc5de9e88030f0441fbef2fa33a59c0290ba8e16
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 ((NullExp *) arg)->dUnchecked = true;
587 break;
589 #endif
590 Identifier *id = Lexer::uniqueId("__arrayArg");
591 Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i));
592 t = t->semantic(loc, sc);
593 VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc));
594 v->semantic(sc);
595 v->parent = sc->parent;
596 //sc->insert(v);
598 Expression *c = new DeclarationExp(0, v);
599 c->type = v->type;
601 for (size_t u = i; u < nargs; u++)
602 { Expression *a = (Expression *)arguments->data[u];
603 if (tret && !((TypeArray *)tb)->next->equals(a->type))
604 a = a->toDelegate(sc, tret);
606 Expression *e = new VarExp(loc, v);
607 e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
608 AssignExp *ae = new AssignExp(loc, e, a);
609 ae->op = TOKconstruct;
610 if (c)
611 c = new CommaExp(loc, c, ae);
612 else
613 c = ae;
615 arg = new VarExp(loc, v);
616 if (c)
617 arg = new CommaExp(loc, c, arg);
618 break;
620 case Tclass:
621 { /* Set arg to be:
622 * new Tclass(arg0, arg1, ..., argn)
624 Expressions *args = new Expressions();
625 args->setDim(nargs - i);
626 for (size_t u = i; u < nargs; u++)
627 args->data[u - i] = arguments->data[u];
628 arg = new NewExp(loc, NULL, NULL, p->type, args);
629 break;
631 default:
632 if (!arg)
633 { error(loc, "not enough arguments");
634 return;
636 break;
638 arg = arg->semantic(sc);
639 //printf("\targ = '%s'\n", arg->toChars());
640 arguments->setDim(i + 1);
641 done = 1;
645 if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
647 if (p->type != arg->type)
649 //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
650 arg = arg->implicitCastTo(sc, p->type);
651 arg = arg->optimize(WANTvalue);
654 if (p->storageClass & STCref)
656 arg = arg->toLvalue(sc, arg);
658 else if (p->storageClass & STCout)
660 arg = arg->modifiableLvalue(sc, arg);
663 // Convert static arrays to pointers
664 tb = arg->type->toBasetype();
665 if (tb->ty == Tsarray)
667 arg = arg->checkToPointer();
670 if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
672 arg = callCpCtor(loc, sc, arg);
675 // Convert lazy argument to a delegate
676 if (p->storageClass & STClazy)
678 arg = arg->toDelegate(sc, p->type);
681 else
684 // If not D linkage, do promotions
685 if (tf->linkage != LINKd)
687 // Promote bytes, words, etc., to ints
688 arg = arg->integralPromotions(sc);
690 // Promote floats to doubles
691 switch (arg->type->ty)
693 case Tfloat32:
694 arg = arg->castTo(sc, Type::tfloat64);
695 break;
697 case Timaginary32:
698 arg = arg->castTo(sc, Type::timaginary64);
699 break;
703 // Convert static arrays to dynamic arrays
704 tb = arg->type->toBasetype();
705 if (tb->ty == Tsarray)
706 { TypeSArray *ts = (TypeSArray *)tb;
707 Type *ta = ts->next->arrayOf();
708 if (ts->size(arg->loc) == 0)
709 { arg = new NullExp(arg->loc);
710 arg->type = ta;
712 else
713 arg = arg->castTo(sc, ta);
716 if (tb->ty == Tstruct)
718 arg = callCpCtor(loc, sc, arg);
721 // Give error for overloaded function addresses
722 if (arg->op == TOKsymoff)
723 { SymOffExp *se = (SymOffExp *)arg;
724 if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
725 arg->error("function %s is overloaded", arg->toChars());
727 arg->rvalue();
730 arg = arg->optimize(WANTvalue);
731 arguments->data[i] = (void *) arg;
732 if (done)
733 break;
736 // If D linkage and variadic, add _arguments[] as first argument
737 if (tf->linkage == LINKd && tf->varargs == 1)
739 Expression *e;
741 e = createTypeInfoArray(sc, (Expression **)&arguments->data[nparams],
742 arguments->dim - nparams);
743 arguments->insert(0, e);
747 /**************************************************
748 * Write expression out to buf, but wrap it
749 * in ( ) if its precedence is less than pr.
752 void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr)
754 //if (precedence[e->op] == 0) e->dump(0);
755 if (precedence[e->op] < pr)
757 buf->writeByte('(');
758 e->toCBuffer(buf, hgs);
759 buf->writeByte(')');
761 else
762 e->toCBuffer(buf, hgs);
765 /**************************************************
766 * Write out argument list to buf.
769 void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
771 if (arguments)
773 for (size_t i = 0; i < arguments->dim; i++)
774 { Expression *arg = (Expression *)arguments->data[i];
776 if (arg)
777 { if (i)
778 buf->writeByte(',');
779 expToCBuffer(buf, hgs, arg, PREC_assign);
785 /**************************************************
786 * Write out argument types to buf.
789 void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
791 if (arguments)
792 { OutBuffer argbuf;
794 for (size_t i = 0; i < arguments->dim; i++)
795 { Expression *arg = (Expression *)arguments->data[i];
797 if (i)
798 buf->writeByte(',');
799 argbuf.reset();
800 arg->type->toCBuffer2(&argbuf, hgs, 0);
801 buf->write(&argbuf);
806 /******************************** Expression **************************/
808 Expression::Expression(Loc loc, enum TOK op, int size)
809 : loc(loc)
811 this->loc = loc;
812 this->op = op;
813 this->size = size;
814 type = NULL;
817 Expression *Expression::syntaxCopy()
819 //printf("Expression::syntaxCopy()\n");
820 //dump(0);
821 return copy();
824 /*********************************
825 * Does *not* do a deep copy.
828 Expression *Expression::copy()
830 Expression *e;
831 if (!size)
833 #ifdef DEBUG
834 fprintf(stdmsg, "No expression copy for: %s\n", toChars());
835 printf("op = %d\n", op);
836 dump(0);
837 #endif
838 assert(0);
840 e = (Expression *)mem.malloc(size);
841 return (Expression *)memcpy(e, this, size);
844 /**************************
845 * Semantically analyze Expression.
846 * Determine types, fold constants, etc.
849 Expression *Expression::semantic(Scope *sc)
851 #if LOGSEMANTIC
852 printf("Expression::semantic() %s\n", toChars());
853 #endif
854 if (type)
855 type = type->semantic(loc, sc);
856 else
857 type = Type::tvoid;
858 return this;
861 void Expression::print()
863 fprintf(stdmsg, "%s\n", toChars());
864 fflush(stdmsg);
867 char *Expression::toChars()
868 { OutBuffer *buf;
869 HdrGenState hgs;
871 memset(&hgs, 0, sizeof(hgs));
872 buf = new OutBuffer();
873 toCBuffer(buf, &hgs);
874 return buf->toChars();
877 void Expression::error(const char *format, ...)
879 va_list ap;
880 va_start(ap, format);
881 ::verror(loc, format, ap);
882 va_end( ap );
885 void Expression::rvalue()
887 if (type && type->toBasetype()->ty == Tvoid)
888 { error("expression %s is void and has no value", toChars());
889 #if 0
890 dump(0);
891 halt();
892 #endif
893 type = Type::tint32;
897 Expression *Expression::combine(Expression *e1, Expression *e2)
899 if (e1)
901 if (e2)
903 e1 = new CommaExp(e1->loc, e1, e2);
904 e1->type = e2->type;
907 else
908 e1 = e2;
909 return e1;
912 integer_t Expression::toInteger()
914 //printf("Expression %s\n", Token::toChars(op));
915 error("Integer constant expression expected instead of %s", toChars());
916 return 0;
919 uinteger_t Expression::toUInteger()
921 //printf("Expression %s\n", Token::toChars(op));
922 return (uinteger_t)toInteger();
925 real_t Expression::toReal()
927 error("Floating point constant expression expected instead of %s", toChars());
928 return 0;
931 real_t Expression::toImaginary()
933 error("Floating point constant expression expected instead of %s", toChars());
934 return 0;
937 complex_t Expression::toComplex()
939 error("Floating point constant expression expected instead of %s", toChars());
940 #ifdef IN_GCC
941 return complex_t(real_t(0)); // %% nicer
942 #else
943 return 0;
944 #endif
947 void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
949 buf->writestring(Token::toChars(op));
952 void Expression::toMangleBuffer(OutBuffer *buf)
954 error("expression %s is not a valid template value argument", toChars());
957 /*******************************
958 * Give error if we're not an lvalue.
959 * If we can, convert expression to be an lvalue.
962 Expression *Expression::toLvalue(Scope *sc, Expression *e)
964 if (!e)
965 e = this;
966 else if (!loc.filename)
967 loc = e->loc;
968 error("%s is not an lvalue", e->toChars());
969 return this;
972 Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
974 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
976 // See if this expression is a modifiable lvalue (i.e. not const)
977 if (type && (!type->isMutable() || !type->isAssignable()))
978 error("%s is not mutable", e->toChars());
980 return toLvalue(sc, e);
983 /************************************
984 * Detect cases where pointers to the stack can 'escape' the
985 * lifetime of the stack frame.
988 void Expression::checkEscape()
992 void Expression::checkScalar()
994 if (!type->isscalar())
995 error("'%s' is not a scalar, it is a %s", toChars(), type->toChars());
998 void Expression::checkNoBool()
1000 if (type->toBasetype()->ty == Tbool)
1001 error("operation not allowed on bool '%s'", toChars());
1004 Expression *Expression::checkIntegral()
1006 if (!type->isintegral())
1007 { error("'%s' is not of integral type, it is a %s", toChars(), type->toChars());
1008 return new IntegerExp(0);
1010 return this;
1013 Expression *Expression::checkArithmetic()
1015 if (!type->isintegral() && !type->isfloating())
1016 { error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
1017 return new IntegerExp(0);
1019 return this;
1022 void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
1024 s->checkDeprecated(loc, sc);
1027 /********************************
1028 * Check for expressions that have no use.
1029 * Input:
1030 * flag 0 not going to use the result, so issue error message if no
1031 * side effects
1032 * 1 the result of the expression is used, but still check
1033 * for useless subexpressions
1034 * 2 do not issue error messages, just return !=0 if expression
1035 * has side effects
1038 int Expression::checkSideEffect(int flag)
1040 if (flag == 0)
1041 { if (op == TOKimport)
1043 error("%s has no effect", toChars());
1045 else
1046 error("%s has no effect in expression (%s)",
1047 Token::toChars(op), toChars());
1049 return 0;
1052 /*****************************
1053 * Check that expression can be tested for true or false.
1056 Expression *Expression::checkToBoolean()
1058 // Default is 'yes' - do nothing
1060 #ifdef DEBUG
1061 if (!type)
1062 dump(0);
1063 #endif
1065 if (!type->checkBoolean())
1067 error("expression %s of type %s does not have a boolean value", toChars(), type->toChars());
1069 return this;
1072 /****************************
1075 Expression *Expression::checkToPointer()
1077 Expression *e;
1078 Type *tb;
1080 //printf("Expression::checkToPointer()\n");
1081 e = this;
1083 // If C static array, convert to pointer
1084 tb = type->toBasetype();
1085 if (tb->ty == Tsarray)
1086 { TypeSArray *ts = (TypeSArray *)tb;
1087 if (ts->size(loc) == 0)
1088 e = new NullExp(loc);
1089 else
1090 e = new AddrExp(loc, this);
1091 e->type = ts->next->pointerTo();
1093 return e;
1096 /******************************
1097 * Take address of expression.
1100 Expression *Expression::addressOf(Scope *sc)
1102 Expression *e;
1104 //printf("Expression::addressOf()\n");
1105 e = toLvalue(sc, NULL);
1106 e = new AddrExp(loc, e);
1107 e->type = type->pointerTo();
1108 return e;
1111 /******************************
1112 * If this is a reference, dereference it.
1115 Expression *Expression::deref()
1117 //printf("Expression::deref()\n");
1118 if (type->ty == Treference)
1119 { Expression *e;
1121 e = new PtrExp(loc, this);
1122 e->type = ((TypeReference *)type)->next;
1123 return e;
1125 return this;
1128 /********************************
1129 * Does this expression statically evaluate to a boolean TRUE or FALSE?
1132 int Expression::isBool(int result)
1134 return FALSE;
1137 /********************************
1138 * Does this expression result in either a 1 or a 0?
1141 int Expression::isBit()
1143 return FALSE;
1146 /********************************
1147 * Can this expression throw an exception?
1148 * Valid only after semantic() pass.
1151 int Expression::canThrow()
1153 return FALSE;
1158 Expressions *Expression::arraySyntaxCopy(Expressions *exps)
1159 { Expressions *a = NULL;
1161 if (exps)
1163 a = new Expressions();
1164 a->setDim(exps->dim);
1165 for (int i = 0; i < a->dim; i++)
1166 { Expression *e = (Expression *)exps->data[i];
1168 e = e->syntaxCopy();
1169 a->data[i] = e;
1172 return a;
1175 /******************************** IntegerExp **************************/
1177 IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type)
1178 : Expression(loc, TOKint64, sizeof(IntegerExp))
1180 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
1181 if (type && !type->isscalar())
1183 //printf("%s, loc = %d\n", toChars(), loc.linnum);
1184 error("integral constant must be scalar type, not %s", type->toChars());
1185 type = Type::terror;
1187 this->type = type;
1188 this->value = value;
1191 IntegerExp::IntegerExp(integer_t value)
1192 : Expression(0, TOKint64, sizeof(IntegerExp))
1194 this->type = Type::tint32;
1195 this->value = value;
1198 int IntegerExp::equals(Object *o)
1199 { IntegerExp *ne;
1201 if (this == o ||
1202 (((Expression *)o)->op == TOKint64 &&
1203 ((ne = (IntegerExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
1204 value == ne->value))
1205 return 1;
1206 return 0;
1209 char *IntegerExp::toChars()
1211 #if 1
1212 return Expression::toChars();
1213 #else
1214 static char buffer[sizeof(value) * 3 + 1];
1216 sprintf(buffer, "%"PRIdMAX, value);
1217 return buffer;
1218 #endif
1221 integer_t IntegerExp::toInteger()
1222 { Type *t;
1224 t = type;
1225 while (t)
1227 switch (t->ty)
1229 case Tbit:
1230 case Tbool: value = (value != 0); break;
1231 case Tint8: value = (d_int8) value; break;
1232 case Tchar:
1233 case Tuns8: value = (d_uns8) value; break;
1234 case Tint16: value = (d_int16) value; break;
1235 case Twchar:
1236 case Tuns16: value = (d_uns16) value; break;
1237 case Tint32: value = (d_int32) value; break;
1238 case Tdchar:
1239 case Tuns32: value = (d_uns32) value; break;
1240 case Tint64: value = (d_int64) value; break;
1241 case Tuns64: value = (d_uns64) value; break;
1243 case Tpointer:
1244 switch (PTRSIZE)
1246 case 4: value = (d_uns32) value; break;
1247 case 8: value = (d_uns64) value; break;
1248 default:
1249 assert(PTRSIZE == 4 || PTRSIZE == 8);
1251 break;
1253 case Tenum:
1255 TypeEnum *te = (TypeEnum *)t;
1256 t = te->sym->memtype;
1257 continue;
1260 case Ttypedef:
1262 TypeTypedef *tt = (TypeTypedef *)t;
1263 t = tt->sym->basetype;
1264 continue;
1267 default:
1268 type->print();
1269 assert(0);
1270 break;
1272 break;
1274 return value;
1277 real_t IntegerExp::toReal()
1279 Type *t;
1281 toInteger();
1282 t = type->toBasetype();
1283 if (t->ty == Tuns64)
1284 return (real_t)(d_uns64)value;
1285 else
1286 return (real_t)(d_int64)value;
1289 real_t IntegerExp::toImaginary()
1291 return (real_t) 0;
1294 complex_t IntegerExp::toComplex()
1296 return toReal();
1299 int IntegerExp::isBool(int result)
1301 return result ? value != 0 : value == 0;
1304 Expression *IntegerExp::semantic(Scope *sc)
1306 if (!type)
1308 // Determine what the type of this number is
1309 integer_t number = value;
1311 if (number & 0x8000000000000000LL)
1312 type = Type::tuns64;
1313 else if (number & 0xFFFFFFFF80000000LL)
1314 type = Type::tint64;
1315 else
1316 type = Type::tint32;
1318 else
1319 { if (!type->deco)
1320 type = type->semantic(loc, sc);
1322 return this;
1325 Expression *IntegerExp::toLvalue(Scope *sc, Expression *e)
1327 if (!e)
1328 e = this;
1329 else if (!loc.filename)
1330 loc = e->loc;
1331 e->error("constant %s is not an lvalue", e->toChars());
1332 return this;
1335 void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1337 integer_t v = toInteger();
1339 if (type)
1340 { Type *t = type;
1343 switch (t->ty)
1345 case Tenum:
1346 { TypeEnum *te = (TypeEnum *)t;
1347 buf->printf("cast(%s)", te->sym->toChars());
1348 t = te->sym->memtype;
1349 goto L1;
1352 case Ttypedef:
1353 { TypeTypedef *tt = (TypeTypedef *)t;
1354 buf->printf("cast(%s)", tt->sym->toChars());
1355 t = tt->sym->basetype;
1356 goto L1;
1359 case Twchar: // BUG: need to cast(wchar)
1360 case Tdchar: // BUG: need to cast(dchar)
1361 if ((uinteger_t)v > 0xFF)
1363 buf->printf("'\\U%08x'", v);
1364 break;
1366 case Tchar:
1367 if (v == '\'')
1368 buf->writestring("'\\''");
1369 else if (isprint(v) && v != '\\')
1370 buf->printf("'%c'", (int)v);
1371 else
1372 buf->printf("'\\x%02x'", (int)v);
1373 break;
1375 case Tint8:
1376 buf->writestring("cast(byte)");
1377 goto L2;
1379 case Tint16:
1380 buf->writestring("cast(short)");
1381 goto L2;
1383 case Tint32:
1385 buf->printf("%d", (int)v);
1386 break;
1388 case Tuns8:
1389 buf->writestring("cast(ubyte)");
1390 goto L3;
1392 case Tuns16:
1393 buf->writestring("cast(ushort)");
1394 goto L3;
1396 case Tuns32:
1398 buf->printf("%du", (unsigned)v);
1399 break;
1401 case Tint64:
1402 buf->printf("%"PRIdMAX"L", v);
1403 break;
1405 case Tuns64:
1406 buf->printf("%"PRIuMAX"LU", v);
1407 break;
1409 case Tbit:
1410 case Tbool:
1411 buf->writestring((char *)(v ? "true" : "false"));
1412 break;
1414 case Tpointer:
1415 buf->writestring("cast(");
1416 buf->writestring(t->toChars());
1417 buf->writeByte(')');
1418 goto L3;
1420 default:
1421 #ifdef DEBUG
1422 t->print();
1423 #endif
1424 assert(0);
1427 else if (v & 0x8000000000000000LL)
1428 buf->printf("0x%"PRIxMAX, v);
1429 else
1430 buf->printf("%"PRIdMAX, v);
1433 void IntegerExp::toMangleBuffer(OutBuffer *buf)
1435 if ((sinteger_t)value < 0)
1436 buf->printf("N%"PRIdMAX, -value);
1437 else
1438 buf->printf("%"PRIdMAX, value);
1441 /******************************** RealExp **************************/
1443 RealExp::RealExp(Loc loc, real_t value, Type *type)
1444 : Expression(loc, TOKfloat64, sizeof(RealExp))
1446 //printf("RealExp::RealExp(%Lg)\n", value);
1447 this->value = value;
1448 this->type = type;
1451 char *RealExp::toChars()
1453 char buffer[sizeof(value) * 3 + 8 + 1 + 1];
1455 #ifdef IN_GCC
1456 value.format(buffer, sizeof(buffer));
1457 if (type->isimaginary())
1458 strcat(buffer, "i");
1459 #else
1460 sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value);
1461 #endif
1462 assert(strlen(buffer) < sizeof(buffer));
1463 return mem.strdup(buffer);
1466 integer_t RealExp::toInteger()
1468 #ifdef IN_GCC
1469 return (d_int64) toReal().toInt();
1470 #else
1471 return (sinteger_t) toReal();
1472 #endif
1475 uinteger_t RealExp::toUInteger()
1477 #ifdef IN_GCC
1478 return (uinteger_t) toReal().toInt();
1479 #else
1480 return (uinteger_t) toReal();
1481 #endif
1484 real_t RealExp::toReal()
1486 return type->isreal() ? value : 0;
1489 real_t RealExp::toImaginary()
1491 return type->isreal() ? 0 : value;
1494 complex_t RealExp::toComplex()
1496 #ifdef __DMC__
1497 return toReal() + toImaginary() * I;
1498 #else
1499 return complex_t(toReal(), toImaginary());
1500 #endif
1503 /********************************
1504 * Test to see if two reals are the same.
1505 * Regard NaN's as equivalent.
1506 * Regard +0 and -0 as different.
1509 int RealEquals(real_t x1, real_t x2)
1511 #ifndef IN_GCC
1512 return (isnan(x1) && isnan(x2)) ||
1513 /* In some cases, the REALPAD bytes get garbage in them,
1514 * so be sure and ignore them.
1516 memcmp(&x1, &x2, REALSIZE - REALPAD) == 0;
1517 #else
1518 return (x1.isNan() && x2.isNan()) || x1.isIdenticalTo(x2);
1519 #endif
1522 int RealExp::equals(Object *o)
1523 { RealExp *ne;
1525 if (this == o ||
1526 (((Expression *)o)->op == TOKfloat64 &&
1527 ((ne = (RealExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
1528 RealEquals(value, ne->value)
1531 return 1;
1532 return 0;
1535 Expression *RealExp::semantic(Scope *sc)
1537 if (!type)
1538 type = Type::tfloat64;
1539 else
1540 type = type->semantic(loc, sc);
1541 return this;
1544 int RealExp::isBool(int result)
1546 #ifdef IN_GCC
1547 return result ? (! value.isZero()) : (value.isZero());
1548 #else
1549 return result ? (value != 0)
1550 : (value == 0);
1551 #endif
1554 void floatToBuffer(OutBuffer *buf, Type *type, const real_t & value)
1556 /* In order to get an exact representation, try converting it
1557 * to decimal then back again. If it matches, use it.
1558 * If it doesn't, fall back to hex, which is
1559 * always exact.
1561 char buffer[48];
1562 #ifdef IN_GCC
1563 real_t parsed_value;
1565 value.format(buffer, sizeof(buffer));
1566 parsed_value = real_t::parse(buffer, real_t::LongDouble);
1567 if (parsed_value.isIdenticalTo( value ))
1568 buf->writestring(buffer);
1569 else
1571 value.formatHex(buffer, sizeof(buffer));
1572 buf->writestring(buffer);
1574 #else
1575 sprintf(buffer, "%Lg", value);
1576 assert(strlen(buffer) < sizeof(buffer));
1577 #if _WIN32 && __DMC__
1578 char *save = __locale_decpoint;
1579 __locale_decpoint = ".";
1580 real_t r = strtold(buffer, NULL);
1581 __locale_decpoint = save;
1582 #else
1583 real_t r = strtold(buffer, NULL);
1584 #endif
1585 if (r == value) // if exact duplication
1586 buf->writestring(buffer);
1587 else
1588 buf->printf("%La", value); // ensure exact duplication
1589 #endif
1591 if (type)
1593 Type *t = type->toBasetype();
1594 switch (t->ty)
1596 case Tfloat32:
1597 case Timaginary32:
1598 case Tcomplex32:
1599 buf->writeByte('F');
1600 break;
1602 case Tfloat80:
1603 case Timaginary80:
1604 case Tcomplex80:
1605 buf->writeByte('L');
1606 break;
1608 default:
1609 break;
1611 if (t->isimaginary())
1612 buf->writeByte('i');
1616 void RealExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1618 floatToBuffer(buf, type, value);
1621 void realToMangleBuffer(OutBuffer *buf, real_t value)
1623 /* Rely on %A to get portable mangling.
1624 * Must munge result to get only identifier characters.
1626 * Possible values from %A => mangled result
1627 * NAN => NAN
1628 * -INF => NINF
1629 * INF => INF
1630 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79
1631 * 0X1.9P+2 => 19P2
1634 #ifdef IN_GCC
1635 if (value.isNan())
1636 buf->writestring("NAN"); // no -NAN bugs
1637 else if (value.isInf())
1638 buf->writestring(value.isNegative()?"NINF":"INF");
1639 #else
1640 if (isnan(value))
1641 buf->writestring("NAN"); // no -NAN bugs
1642 #endif
1643 else
1645 char buffer[64];
1646 #ifdef IN_GCC
1647 value.formatHex(buffer, sizeof(buffer));
1648 int n = strlen(buffer);
1649 #else
1650 int n = sprintf(buffer, "%LA", value);
1651 assert(n > 0 && n < sizeof(buffer));
1652 #endif
1653 for (int i = 0; i < n; i++)
1654 { char c = buffer[i];
1656 switch (c)
1658 case '-':
1659 buf->writeByte('N');
1660 break;
1662 case '+':
1663 case 'x':
1664 case 'X':
1665 case '.':
1666 break;
1668 case '0':
1669 if (i < 2)
1670 break; // skip leading 0X
1671 default:
1672 buf->writeByte(c);
1673 break;
1679 void RealExp::toMangleBuffer(OutBuffer *buf)
1681 buf->writeByte('e');
1682 realToMangleBuffer(buf, value);
1686 /******************************** ComplexExp **************************/
1688 ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type)
1689 : Expression(loc, TOKcomplex80, sizeof(ComplexExp))
1691 this->value = value;
1692 this->type = type;
1693 //printf("ComplexExp::ComplexExp(%s)\n", toChars());
1696 char *ComplexExp::toChars()
1698 char buffer[sizeof(value) * 3 + 8 + 1];
1700 #ifdef IN_GCC
1701 char buf1[sizeof(value) * 3 + 8 + 1];
1702 char buf2[sizeof(value) * 3 + 8 + 1];
1703 creall(value).format(buf1, sizeof(buf1));
1704 cimagl(value).format(buf2, sizeof(buf2));
1705 sprintf(buffer, "(%s+%si)", buf1, buf2);
1706 #else
1707 sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value));
1708 assert(strlen(buffer) < sizeof(buffer));
1709 #endif
1710 return mem.strdup(buffer);
1713 integer_t ComplexExp::toInteger()
1715 #ifdef IN_GCC
1716 return (d_int64) toReal().toInt();
1717 #else
1718 return (sinteger_t) toReal();
1719 #endif
1722 uinteger_t ComplexExp::toUInteger()
1724 #ifdef IN_GCC
1725 return (uinteger_t) toReal().toInt();
1726 #else
1727 return (uinteger_t) toReal();
1728 #endif
1731 real_t ComplexExp::toReal()
1733 return creall(value);
1736 real_t ComplexExp::toImaginary()
1738 return cimagl(value);
1741 complex_t ComplexExp::toComplex()
1743 return value;
1746 int ComplexExp::equals(Object *o)
1747 { ComplexExp *ne;
1749 if (this == o ||
1750 (((Expression *)o)->op == TOKcomplex80 &&
1751 ((ne = (ComplexExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
1752 #ifndef IN_GCC
1753 RealEquals(creall(value), creall(ne->value)) &&
1754 RealEquals(cimagl(value), cimagl(ne->value))
1755 #else
1756 RealEquals(value.re, ne->value.re) &&
1757 RealEquals(value.im, ne->value.im)
1758 #endif
1761 return 1;
1762 return 0;
1765 Expression *ComplexExp::semantic(Scope *sc)
1767 if (!type)
1768 type = Type::tcomplex80;
1769 else
1770 type = type->semantic(loc, sc);
1771 return this;
1774 int ComplexExp::isBool(int result)
1776 if (result)
1777 return (bool)(value);
1778 else
1779 return !value;
1782 void ComplexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1784 /* Print as:
1785 * (re+imi)
1787 #ifdef IN_GCC
1788 char buf1[sizeof(value) * 3 + 8 + 1];
1789 char buf2[sizeof(value) * 3 + 8 + 1];
1790 creall(value).format(buf1, sizeof(buf1));
1791 cimagl(value).format(buf2, sizeof(buf2));
1792 buf->printf("(%s+%si)", buf1, buf2);
1793 #else
1794 buf->writeByte('(');
1795 floatToBuffer(buf, type, creall(value));
1796 buf->writeByte('+');
1797 floatToBuffer(buf, type, cimagl(value));
1798 buf->writestring("i)");
1799 #endif
1802 void ComplexExp::toMangleBuffer(OutBuffer *buf)
1804 buf->writeByte('c');
1805 real_t r = toReal();
1806 realToMangleBuffer(buf, r);
1807 buf->writeByte('c'); // separate the two
1808 r = toImaginary();
1809 realToMangleBuffer(buf, r);
1812 /******************************** IdentifierExp **************************/
1814 IdentifierExp::IdentifierExp(Loc loc, Identifier *ident)
1815 : Expression(loc, TOKidentifier, sizeof(IdentifierExp))
1817 this->ident = ident;
1820 Expression *IdentifierExp::semantic(Scope *sc)
1822 Dsymbol *s;
1823 Dsymbol *scopesym;
1825 #if LOGSEMANTIC
1826 printf("IdentifierExp::semantic('%s')\n", ident->toChars());
1827 #endif
1828 s = sc->search(loc, ident, &scopesym);
1829 if (s)
1830 { Expression *e;
1831 WithScopeSymbol *withsym;
1833 /* See if the symbol was a member of an enclosing 'with'
1835 withsym = scopesym->isWithScopeSymbol();
1836 if (withsym)
1838 s = s->toAlias();
1840 // Same as wthis.ident
1841 if (s->needThis() || s->isTemplateDeclaration())
1843 e = new VarExp(loc, withsym->withstate->wthis);
1844 e = new DotIdExp(loc, e, ident);
1846 else
1847 { Type *t = withsym->withstate->wthis->type;
1848 if (t->ty == Tpointer)
1849 t = ((TypePointer *)t)->next;
1850 e = new TypeDotIdExp(loc, t, ident);
1853 else
1855 /* If f is really a function template,
1856 * then replace f with the function template declaration.
1858 FuncDeclaration *f = s->isFuncDeclaration();
1859 if (f && f->parent)
1860 { TemplateInstance *ti = f->parent->isTemplateInstance();
1862 if (ti &&
1863 !ti->isTemplateMixin() &&
1864 (ti->name == f->ident ||
1865 ti->toAlias()->ident == f->ident)
1867 ti->tempdecl && ti->tempdecl->onemember)
1869 TemplateDeclaration *tempdecl = ti->tempdecl;
1870 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's
1871 tempdecl = tempdecl->overroot; // then get the start
1872 e = new TemplateExp(loc, tempdecl);
1873 e = e->semantic(sc);
1874 return e;
1877 // Haven't done overload resolution yet, so pass 1
1878 e = new DsymbolExp(loc, s, 1);
1880 return e->semantic(sc);
1882 error("undefined identifier %s", ident->toChars());
1883 type = Type::terror;
1884 return this;
1887 char *IdentifierExp::toChars()
1889 return ident->toChars();
1892 void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1894 if (hgs->hdrgen)
1895 buf->writestring(ident->toHChars2());
1896 else
1897 buf->writestring(ident->toChars());
1900 Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e)
1902 #if 0
1903 tym = tybasic(e1->ET->Tty);
1904 if (!(tyscalar(tym) ||
1905 tym == TYstruct ||
1906 tym == TYarray && e->Eoper == TOKaddr))
1907 synerr(EM_lvalue); // lvalue expected
1908 #endif
1909 return this;
1912 /******************************** DollarExp **************************/
1914 DollarExp::DollarExp(Loc loc)
1915 : IdentifierExp(loc, Id::dollar)
1919 /******************************** DsymbolExp **************************/
1921 DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, int hasOverloads)
1922 : Expression(loc, TOKdsymbol, sizeof(DsymbolExp))
1924 this->s = s;
1925 this->hasOverloads = hasOverloads;
1928 Expression *DsymbolExp::semantic(Scope *sc)
1930 #if LOGSEMANTIC
1931 printf("DsymbolExp::semantic('%s')\n", s->toChars());
1932 #endif
1934 Lagain:
1935 EnumMember *em;
1936 Expression *e;
1937 VarDeclaration *v;
1938 FuncDeclaration *f;
1939 FuncLiteralDeclaration *fld;
1940 OverloadSet *o;
1941 Declaration *d;
1942 ClassDeclaration *cd;
1943 ClassDeclaration *thiscd = NULL;
1944 Import *imp;
1945 Package *pkg;
1946 Type *t;
1948 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
1949 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
1950 if (type)
1951 return this;
1952 if (!s->isFuncDeclaration()) // functions are checked after overloading
1953 checkDeprecated(sc, s);
1954 s = s->toAlias();
1955 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
1956 if (!s->isFuncDeclaration())
1957 checkDeprecated(sc, s);
1959 if (sc->func)
1960 thiscd = sc->func->parent->isClassDeclaration();
1962 // BUG: This should happen after overload resolution for functions, not before
1963 if (s->needThis())
1965 if (hasThis(sc) && !s->isFuncDeclaration())
1967 // Supply an implicit 'this', as in
1968 // this.ident
1970 DotVarExp *de;
1972 de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration());
1973 return de->semantic(sc);
1977 em = s->isEnumMember();
1978 if (em)
1980 e = em->value;
1981 e = e->semantic(sc);
1982 return e;
1984 v = s->isVarDeclaration();
1985 if (v)
1987 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
1988 if (!type)
1989 { type = v->type;
1990 if (!v->type)
1991 { error("forward reference of %s", v->toChars());
1992 type = Type::terror;
1995 e = new VarExp(loc, v);
1996 e->type = type;
1997 e = e->semantic(sc);
1998 return e->deref();
2000 fld = s->isFuncLiteralDeclaration();
2001 if (fld)
2002 { //printf("'%s' is a function literal\n", fld->toChars());
2003 e = new FuncExp(loc, fld);
2004 return e->semantic(sc);
2006 f = s->isFuncDeclaration();
2007 if (f)
2008 { //printf("'%s' is a function\n", f->toChars());
2009 return new VarExp(loc, f, hasOverloads);
2011 o = s->isOverloadSet();
2012 if (o)
2013 { //printf("'%s' is an overload set\n", o->toChars());
2014 return new OverExp(o);
2016 cd = s->isClassDeclaration();
2017 if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis())
2019 // We need to add an implicit 'this' if cd is this class or a base class.
2020 DotTypeExp *dte;
2022 dte = new DotTypeExp(loc, new ThisExp(loc), s);
2023 return dte->semantic(sc);
2025 imp = s->isImport();
2026 if (imp)
2028 ScopeExp *ie;
2030 ie = new ScopeExp(loc, imp->pkg);
2031 return ie->semantic(sc);
2033 pkg = s->isPackage();
2034 if (pkg)
2036 ScopeExp *ie;
2038 ie = new ScopeExp(loc, pkg);
2039 return ie->semantic(sc);
2041 Module *mod = s->isModule();
2042 if (mod)
2044 ScopeExp *ie;
2046 ie = new ScopeExp(loc, mod);
2047 return ie->semantic(sc);
2050 t = s->getType();
2051 if (t)
2053 return new TypeExp(loc, t);
2056 TupleDeclaration *tup = s->isTupleDeclaration();
2057 if (tup)
2059 e = new TupleExp(loc, tup);
2060 e = e->semantic(sc);
2061 return e;
2064 TemplateInstance *ti = s->isTemplateInstance();
2065 if (ti && !global.errors)
2066 { if (!ti->semanticdone)
2067 ti->semantic(sc);
2068 s = ti->inst->toAlias();
2069 if (!s->isTemplateInstance())
2070 goto Lagain;
2071 e = new ScopeExp(loc, ti);
2072 e = e->semantic(sc);
2073 return e;
2076 TemplateDeclaration *td = s->isTemplateDeclaration();
2077 if (td)
2079 e = new TemplateExp(loc, td);
2080 e = e->semantic(sc);
2081 return e;
2084 Lerr:
2085 error("%s '%s' is not a variable", s->kind(), s->toChars());
2086 type = Type::terror;
2087 return this;
2090 char *DsymbolExp::toChars()
2092 return s->toChars();
2095 void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2097 buf->writestring(s->toChars());
2100 Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e)
2102 #if 0
2103 tym = tybasic(e1->ET->Tty);
2104 if (!(tyscalar(tym) ||
2105 tym == TYstruct ||
2106 tym == TYarray && e->Eoper == TOKaddr))
2107 synerr(EM_lvalue); // lvalue expected
2108 #endif
2109 return this;
2112 /******************************** GetLoggerExp **************************/
2114 GetLoggerExp::GetLoggerExp(Loc loc)
2115 : Expression(loc, TOKlogger, sizeof(GetLoggerExp))
2119 Expression *GetLoggerExp::semantic(Scope *sc)
2121 Expression *log = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), Id::__log);
2122 return log->semantic(sc);
2125 void GetLoggerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2127 buf->writestring("log");
2130 /******************************** ThisExp **************************/
2132 ThisExp::ThisExp(Loc loc)
2133 : Expression(loc, TOKthis, sizeof(ThisExp))
2135 var = NULL;
2138 Expression *ThisExp::semantic(Scope *sc)
2139 { FuncDeclaration *fd;
2140 FuncDeclaration *fdthis;
2141 int nested = 0;
2143 #if LOGSEMANTIC
2144 printf("ThisExp::semantic()\n");
2145 #endif
2146 if (type)
2147 { //assert(global.errors || var);
2148 return this;
2151 /* Special case for typeof(this) and typeof(super) since both
2152 * should work even if they are not inside a non-static member function
2154 if (sc->intypeof)
2156 // Find enclosing struct or class
2157 for (Dsymbol *s = sc->parent; 1; s = s->parent)
2159 ClassDeclaration *cd;
2160 StructDeclaration *sd;
2162 if (!s)
2164 error("%s is not in a struct or class scope", toChars());
2165 goto Lerr;
2167 cd = s->isClassDeclaration();
2168 if (cd)
2170 type = cd->type;
2171 return this;
2173 sd = s->isStructDeclaration();
2174 if (sd)
2176 type = sd->type->pointerTo();
2177 return this;
2182 fdthis = sc->parent->isFuncDeclaration();
2183 fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2184 if (!fd)
2185 goto Lerr;
2187 assert(fd->vthis);
2188 var = fd->vthis;
2189 assert(var->parent);
2190 type = var->type;
2191 var->isVarDeclaration()->checkNestedReference(sc, loc);
2192 sc->callSuper |= CSXthis;
2193 return this;
2195 Lerr:
2196 error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars());
2197 type = Type::terror;
2198 return this;
2201 int ThisExp::isBool(int result)
2203 return result ? TRUE : FALSE;
2206 void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2208 buf->writestring("this");
2211 Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
2213 return this;
2216 /******************************** SuperExp **************************/
2218 SuperExp::SuperExp(Loc loc)
2219 : ThisExp(loc)
2221 op = TOKsuper;
2224 Expression *SuperExp::semantic(Scope *sc)
2225 { FuncDeclaration *fd;
2226 FuncDeclaration *fdthis;
2227 ClassDeclaration *cd;
2228 Dsymbol *s;
2230 #if LOGSEMANTIC
2231 printf("SuperExp::semantic('%s')\n", toChars());
2232 #endif
2233 if (type)
2234 return this;
2236 /* Special case for typeof(this) and typeof(super) since both
2237 * should work even if they are not inside a non-static member function
2239 if (sc->intypeof)
2241 // Find enclosing class
2242 for (Dsymbol *s = sc->parent; 1; s = s->parent)
2244 ClassDeclaration *cd;
2246 if (!s)
2248 error("%s is not in a class scope", toChars());
2249 goto Lerr;
2251 cd = s->isClassDeclaration();
2252 if (cd)
2254 cd = cd->baseClass;
2255 if (!cd)
2256 { error("class %s has no 'super'", s->toChars());
2257 goto Lerr;
2259 type = cd->type;
2260 return this;
2265 fdthis = sc->parent->isFuncDeclaration();
2266 fd = hasThis(sc);
2267 if (!fd)
2268 goto Lerr;
2269 assert(fd->vthis);
2270 var = fd->vthis;
2271 assert(var->parent);
2273 s = fd->toParent();
2274 while (s && s->isTemplateInstance())
2275 s = s->toParent();
2276 assert(s);
2277 cd = s->isClassDeclaration();
2278 //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
2279 if (!cd)
2280 goto Lerr;
2281 if (!cd->baseClass)
2283 error("no base class for %s", cd->toChars());
2284 type = fd->vthis->type;
2286 else
2288 type = cd->baseClass->type;
2291 var->isVarDeclaration()->checkNestedReference(sc, loc);
2293 sc->callSuper |= CSXsuper;
2294 return this;
2297 Lerr:
2298 error("'super' is only allowed in non-static class member functions");
2299 type = Type::tint32;
2300 return this;
2303 void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2305 buf->writestring("super");
2309 /******************************** NullExp **************************/
2311 NullExp::NullExp(Loc loc)
2312 : Expression(loc, TOKnull, sizeof(NullExp))
2314 committed = 0;
2315 dUnchecked = false;
2318 Expression *NullExp::semantic(Scope *sc)
2320 #if LOGSEMANTIC
2321 printf("NullExp::semantic('%s')\n", toChars());
2322 #endif
2323 // NULL is the same as (void *)0
2324 if (!type)
2325 type = Type::tvoid->pointerTo();
2326 return this;
2329 int NullExp::isBool(int result)
2331 return result ? FALSE : TRUE;
2334 void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2336 buf->writestring("null");
2339 void NullExp::toMangleBuffer(OutBuffer *buf)
2341 buf->writeByte('n');
2344 /******************************** StringExp **************************/
2346 StringExp::StringExp(Loc loc, char *string)
2347 : Expression(loc, TOKstring, sizeof(StringExp))
2349 this->string = string;
2350 this->len = strlen(string);
2351 this->sz = 1;
2352 this->committed = 0;
2353 this->postfix = 0;
2356 StringExp::StringExp(Loc loc, void *string, size_t len)
2357 : Expression(loc, TOKstring, sizeof(StringExp))
2359 this->string = string;
2360 this->len = len;
2361 this->sz = 1;
2362 this->committed = 0;
2363 this->postfix = 0;
2366 StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix)
2367 : Expression(loc, TOKstring, sizeof(StringExp))
2369 this->string = string;
2370 this->len = len;
2371 this->sz = 1;
2372 this->committed = 0;
2373 this->postfix = postfix;
2376 #if 0
2377 Expression *StringExp::syntaxCopy()
2379 printf("StringExp::syntaxCopy() %s\n", toChars());
2380 return copy();
2382 #endif
2384 int StringExp::equals(Object *o)
2386 //printf("StringExp::equals('%s')\n", o->toChars());
2387 if (o && o->dyncast() == DYNCAST_EXPRESSION)
2388 { Expression *e = (Expression *)o;
2390 if (e->op == TOKstring)
2392 return compare(o) == 0;
2395 return FALSE;
2398 char *StringExp::toChars()
2400 OutBuffer buf;
2401 HdrGenState hgs;
2402 char *p;
2404 memset(&hgs, 0, sizeof(hgs));
2405 toCBuffer(&buf, &hgs);
2406 buf.writeByte(0);
2407 p = (char *)buf.data;
2408 buf.data = NULL;
2409 return p;
2412 Expression *StringExp::semantic(Scope *sc)
2414 #if LOGSEMANTIC
2415 printf("StringExp::semantic() %s\n", toChars());
2416 #endif
2417 if (!type)
2418 { OutBuffer buffer;
2419 size_t newlen = 0;
2420 char *p;
2421 size_t u;
2422 unsigned c;
2424 switch (postfix)
2426 case 'd':
2427 for (u = 0; u < len;)
2429 p = utf_decodeChar((unsigned char *)string, len, &u, &c);
2430 if (p)
2431 { error("%s", p);
2432 break;
2434 else
2435 { buffer.write4(c);
2436 newlen++;
2439 buffer.write4(0);
2440 string = buffer.extractData();
2441 len = newlen;
2442 sz = 4;
2443 type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex));
2444 committed = 1;
2445 break;
2447 case 'w':
2448 for (u = 0; u < len;)
2450 p = utf_decodeChar((unsigned char *)string, len, &u, &c);
2451 if (p)
2452 { error("%s", p);
2453 break;
2455 else
2456 { buffer.writeUTF16(c);
2457 newlen++;
2458 if (c >= 0x10000)
2459 newlen++;
2462 buffer.writeUTF16(0);
2463 string = buffer.extractData();
2464 len = newlen;
2465 sz = 2;
2466 type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex));
2467 committed = 1;
2468 break;
2470 case 'c':
2471 committed = 1;
2472 default:
2473 type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex));
2474 break;
2476 type = type->semantic(loc, sc);
2477 type = type->invariantOf();
2478 //printf("type = %s\n", type->toChars());
2480 return this;
2483 /****************************************
2484 * Convert string to char[].
2487 StringExp *StringExp::toUTF8(Scope *sc)
2489 if (sz != 1)
2490 { // Convert to UTF-8 string
2491 committed = 0;
2492 Expression *e = castTo(sc, Type::tchar->arrayOf());
2493 e = e->optimize(WANTvalue);
2494 assert(e->op == TOKstring);
2495 StringExp *se = (StringExp *)e;
2496 assert(se->sz == 1);
2497 return se;
2499 return this;
2502 int StringExp::compare(Object *obj)
2504 // Used to sort case statement expressions so we can do an efficient lookup
2505 StringExp *se2 = (StringExp *)(obj);
2507 // This is a kludge so isExpression() in template.c will return 5
2508 // for StringExp's.
2509 if (!se2)
2510 return 5;
2512 assert(se2->op == TOKstring);
2514 int len1 = len;
2515 int len2 = se2->len;
2517 if (len1 == len2)
2519 switch (sz)
2521 case 1:
2522 return strcmp((char *)string, (char *)se2->string);
2524 case 2:
2525 { unsigned u;
2526 d_wchar *s1 = (d_wchar *)string;
2527 d_wchar *s2 = (d_wchar *)se2->string;
2529 for (u = 0; u < len; u++)
2531 if (s1[u] != s2[u])
2532 return s1[u] - s2[u];
2536 case 4:
2537 { unsigned u;
2538 d_dchar *s1 = (d_dchar *)string;
2539 d_dchar *s2 = (d_dchar *)se2->string;
2541 for (u = 0; u < len; u++)
2543 if (s1[u] != s2[u])
2544 return s1[u] - s2[u];
2547 break;
2549 default:
2550 assert(0);
2553 return len1 - len2;
2556 int StringExp::isBool(int result)
2558 return result ? TRUE : FALSE;
2561 unsigned StringExp::charAt(size_t i)
2562 { unsigned value;
2564 switch (sz)
2566 case 1:
2567 value = ((unsigned char *)string)[i];
2568 break;
2570 case 2:
2571 value = ((unsigned short *)string)[i];
2572 break;
2574 case 4:
2575 value = ((unsigned int *)string)[i];
2576 break;
2578 default:
2579 assert(0);
2580 break;
2582 return value;
2585 void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2587 buf->writeByte('"');
2588 for (size_t i = 0; i < len; i++)
2589 { unsigned c = charAt(i);
2591 switch (c)
2593 case '"':
2594 case '\\':
2595 if (!hgs->console)
2596 buf->writeByte('\\');
2597 default:
2598 if (c <= 0xFF)
2599 { if (c <= 0x7F && (isprint(c) || hgs->console))
2600 buf->writeByte(c);
2601 else
2602 buf->printf("\\x%02x", c);
2604 else if (c <= 0xFFFF)
2605 buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8);
2606 else
2607 buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
2608 c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24);
2609 break;
2612 buf->writeByte('"');
2613 if (postfix)
2614 buf->writeByte(postfix);
2617 void StringExp::toMangleBuffer(OutBuffer *buf)
2618 { char m;
2619 OutBuffer tmp;
2620 char *p;
2621 dchar_t c;
2622 size_t u;
2623 unsigned char *q;
2624 unsigned qlen;
2626 /* Write string in UTF-8 format
2628 switch (sz)
2629 { case 1:
2630 m = 'a';
2631 q = (unsigned char *)string;
2632 qlen = len;
2633 break;
2634 case 2:
2635 m = 'w';
2636 for (u = 0; u < len; )
2638 p = utf_decodeWchar((unsigned short *)string, len, &u, &c);
2639 if (p)
2640 error("%s", p);
2641 else
2642 tmp.writeUTF8(c);
2644 q = tmp.data;
2645 qlen = tmp.offset;
2646 break;
2647 case 4:
2648 m = 'd';
2649 for (u = 0; u < len; u++)
2651 c = ((unsigned *)string)[u];
2652 if (!utf_isValidDchar(c))
2653 error("invalid UCS-32 char \\U%08x", c);
2654 else
2655 tmp.writeUTF8(c);
2657 q = tmp.data;
2658 qlen = tmp.offset;
2659 break;
2660 default:
2661 assert(0);
2663 buf->writeByte(m);
2664 buf->printf("%d_", qlen);
2665 for (size_t i = 0; i < qlen; i++)
2666 buf->printf("%02x", q[i]);
2669 /************************ ArrayLiteralExp ************************************/
2671 // [ e1, e2, e3, ... ]
2673 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements)
2674 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
2676 this->elements = elements;
2679 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e)
2680 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
2682 elements = new Expressions;
2683 elements->push(e);
2686 Expression *ArrayLiteralExp::syntaxCopy()
2688 return new ArrayLiteralExp(loc, arraySyntaxCopy(elements));
2691 Expression *ArrayLiteralExp::semantic(Scope *sc)
2692 { Expression *e;
2693 Type *t0 = NULL;
2695 #if LOGSEMANTIC
2696 printf("ArrayLiteralExp::semantic('%s')\n", toChars());
2697 #endif
2698 if (type)
2699 return this;
2701 // Run semantic() on each element
2702 for (int i = 0; i < elements->dim; i++)
2703 { e = (Expression *)elements->data[i];
2704 e = e->semantic(sc);
2705 elements->data[i] = (void *)e;
2707 expandTuples(elements);
2708 for (int i = 0; i < elements->dim; i++)
2709 { e = (Expression *)elements->data[i];
2711 if (!e->type)
2712 error("%s has no value", e->toChars());
2713 e = resolveProperties(sc, e);
2715 unsigned char committed = 1;
2716 if (e->op == TOKstring)
2717 committed = ((StringExp *)e)->committed;
2719 if (!t0)
2720 { t0 = e->type;
2721 // Convert any static arrays to dynamic arrays
2722 if (t0->ty == Tsarray)
2724 t0 = ((TypeSArray *)t0)->next->arrayOf();
2725 e = e->implicitCastTo(sc, t0);
2728 else
2729 e = e->implicitCastTo(sc, t0);
2730 if (!committed && e->op == TOKstring)
2731 { StringExp *se = (StringExp *)e;
2732 se->committed = 0;
2734 elements->data[i] = (void *)e;
2737 if (!t0)
2738 t0 = Type::tvoid;
2739 type = new TypeSArray(t0, new IntegerExp(elements->dim));
2740 type = type->semantic(loc, sc);
2741 return this;
2744 int ArrayLiteralExp::checkSideEffect(int flag)
2745 { int f = 0;
2747 for (size_t i = 0; i < elements->dim; i++)
2748 { Expression *e = (Expression *)elements->data[i];
2750 f |= e->checkSideEffect(2);
2752 if (flag == 0 && f == 0)
2753 Expression::checkSideEffect(0);
2754 return f;
2757 int ArrayLiteralExp::isBool(int result)
2759 size_t dim = elements ? elements->dim : 0;
2760 return result ? (dim != 0) : (dim == 0);
2763 int ArrayLiteralExp::canThrow()
2765 return 1; // because it can fail allocating memory
2768 void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2770 buf->writeByte('[');
2771 argsToCBuffer(buf, elements, hgs);
2772 buf->writeByte(']');
2775 void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
2777 size_t dim = elements ? elements->dim : 0;
2778 buf->printf("A%"PRIuSIZE, dim);
2779 for (size_t i = 0; i < dim; i++)
2780 { Expression *e = (Expression *)elements->data[i];
2781 e->toMangleBuffer(buf);
2785 /************************ AssocArrayLiteralExp ************************************/
2787 // [ key0 : value0, key1 : value1, ... ]
2789 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc,
2790 Expressions *keys, Expressions *values)
2791 : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp))
2793 assert(keys->dim == values->dim);
2794 this->keys = keys;
2795 this->values = values;
2798 Expression *AssocArrayLiteralExp::syntaxCopy()
2800 return new AssocArrayLiteralExp(loc,
2801 arraySyntaxCopy(keys), arraySyntaxCopy(values));
2804 Expression *AssocArrayLiteralExp::semantic(Scope *sc)
2805 { Expression *e;
2806 Type *tkey = NULL;
2807 Type *tvalue = NULL;
2809 #if LOGSEMANTIC
2810 printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
2811 #endif
2813 // Run semantic() on each element
2814 for (size_t i = 0; i < keys->dim; i++)
2815 { Expression *key = (Expression *)keys->data[i];
2816 Expression *value = (Expression *)values->data[i];
2818 key = key->semantic(sc);
2819 value = value->semantic(sc);
2821 keys->data[i] = (void *)key;
2822 values->data[i] = (void *)value;
2824 expandTuples(keys);
2825 expandTuples(values);
2826 if (keys->dim != values->dim)
2828 error("number of keys is %u, must match number of values %u", keys->dim, values->dim);
2829 keys->setDim(0);
2830 values->setDim(0);
2832 for (size_t i = 0; i < keys->dim; i++)
2833 { Expression *key = (Expression *)keys->data[i];
2834 Expression *value = (Expression *)values->data[i];
2836 if (!key->type)
2837 error("%s has no value", key->toChars());
2838 if (!value->type)
2839 error("%s has no value", value->toChars());
2840 key = resolveProperties(sc, key);
2841 value = resolveProperties(sc, value);
2843 if (!tkey)
2844 tkey = key->type;
2845 else
2846 key = key->implicitCastTo(sc, tkey);
2847 keys->data[i] = (void *)key;
2849 if (!tvalue)
2850 tvalue = value->type;
2851 else
2852 value = value->implicitCastTo(sc, tvalue);
2853 values->data[i] = (void *)value;
2856 if (!tkey)
2857 tkey = Type::tvoid;
2858 if (!tvalue)
2859 tvalue = Type::tvoid;
2860 type = new TypeAArray(tvalue, tkey);
2861 type = type->semantic(loc, sc);
2862 return this;
2865 int AssocArrayLiteralExp::checkSideEffect(int flag)
2866 { int f = 0;
2868 for (size_t i = 0; i < keys->dim; i++)
2869 { Expression *key = (Expression *)keys->data[i];
2870 Expression *value = (Expression *)values->data[i];
2872 f |= key->checkSideEffect(2);
2873 f |= value->checkSideEffect(2);
2875 if (flag == 0 && f == 0)
2876 Expression::checkSideEffect(0);
2877 return f;
2880 int AssocArrayLiteralExp::isBool(int result)
2882 size_t dim = keys->dim;
2883 return result ? (dim != 0) : (dim == 0);
2886 int AssocArrayLiteralExp::canThrow()
2888 return 1;
2891 void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2893 buf->writeByte('[');
2894 for (size_t i = 0; i < keys->dim; i++)
2895 { Expression *key = (Expression *)keys->data[i];
2896 Expression *value = (Expression *)values->data[i];
2898 if (i)
2899 buf->writeByte(',');
2900 expToCBuffer(buf, hgs, key, PREC_assign);
2901 buf->writeByte(':');
2902 expToCBuffer(buf, hgs, value, PREC_assign);
2904 buf->writeByte(']');
2907 void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
2909 size_t dim = keys->dim;
2910 buf->printf("A%u", dim);
2911 for (size_t i = 0; i < dim; i++)
2912 { Expression *key = (Expression *)keys->data[i];
2913 Expression *value = (Expression *)values->data[i];
2915 key->toMangleBuffer(buf);
2916 value->toMangleBuffer(buf);
2920 /************************ StructLiteralExp ************************************/
2922 // sd( e1, e2, e3, ... )
2924 StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements)
2925 : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp))
2927 this->sd = sd;
2928 this->elements = elements;
2929 this->sym = NULL;
2930 this->soffset = 0;
2931 this->fillHoles = 1;
2934 Expression *StructLiteralExp::syntaxCopy()
2936 return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements));
2939 Expression *StructLiteralExp::semantic(Scope *sc)
2940 { Expression *e;
2942 #if LOGSEMANTIC
2943 printf("StructLiteralExp::semantic('%s')\n", toChars());
2944 #endif
2945 if (type)
2946 return this;
2948 // Run semantic() on each element
2949 for (size_t i = 0; i < elements->dim; i++)
2950 { e = (Expression *)elements->data[i];
2951 if (!e)
2952 continue;
2953 e = e->semantic(sc);
2954 elements->data[i] = (void *)e;
2956 expandTuples(elements);
2957 size_t offset = 0;
2958 for (size_t i = 0; i < elements->dim; i++)
2959 { e = (Expression *)elements->data[i];
2960 if (!e)
2961 continue;
2963 if (!e->type)
2964 error("%s has no value", e->toChars());
2965 e = resolveProperties(sc, e);
2966 if (i >= sd->fields.dim)
2967 { error("more initializers than fields of %s", sd->toChars());
2968 break;
2970 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
2971 VarDeclaration *v = s->isVarDeclaration();
2972 assert(v);
2973 if (v->offset < offset)
2974 error("overlapping initialization for %s", v->toChars());
2975 offset = v->offset + v->type->size();
2977 Type *telem = v->type;
2978 while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray)
2979 { /* Static array initialization, as in:
2980 * T[3][5] = e;
2982 telem = telem->toBasetype()->nextOf();
2985 e = e->implicitCastTo(sc, telem);
2987 elements->data[i] = (void *)e;
2990 /* Fill out remainder of elements[] with default initializers for fields[]
2992 for (size_t i = elements->dim; i < sd->fields.dim; i++)
2993 { Dsymbol *s = (Dsymbol *)sd->fields.data[i];
2994 VarDeclaration *v = s->isVarDeclaration();
2995 assert(v);
2997 if (v->offset < offset)
2998 { e = NULL;
2999 sd->hasUnions = 1;
3001 else
3003 if (v->init)
3004 { e = v->init->toExpression();
3005 if (!e)
3006 error("cannot make expression out of initializer for %s", v->toChars());
3008 else
3009 { e = v->type->defaultInit();
3010 e->loc = loc;
3012 offset = v->offset + v->type->size();
3014 elements->push(e);
3017 type = sd->type;
3018 return this;
3021 /**************************************
3022 * Gets expression at offset of type.
3023 * Returns NULL if not found.
3026 Expression *StructLiteralExp::getField(Type *type, unsigned offset)
3028 //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
3029 // /*toChars()*/"", type->toChars(), offset);
3030 Expression *e = NULL;
3031 int i = getFieldIndex(type, offset);
3033 if (i != -1)
3035 //printf("\ti = %d\n", i);
3036 assert(i < elements->dim);
3037 e = (Expression *)elements->data[i];
3038 if (e)
3040 e = e->copy();
3041 e->type = type;
3044 return e;
3047 /************************************
3048 * Get index of field.
3049 * Returns -1 if not found.
3052 int StructLiteralExp::getFieldIndex(Type *type, unsigned offset)
3054 /* Find which field offset is by looking at the field offsets
3056 for (size_t i = 0; i < sd->fields.dim; i++)
3058 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
3059 VarDeclaration *v = s->isVarDeclaration();
3060 assert(v);
3062 if (offset == v->offset &&
3063 type->size() == v->type->size())
3064 { Expression *e = (Expression *)elements->data[i];
3065 if (e)
3067 return i;
3069 break;
3072 return -1;
3076 Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e)
3078 return this;
3082 int StructLiteralExp::checkSideEffect(int flag)
3083 { int f = 0;
3085 for (size_t i = 0; i < elements->dim; i++)
3086 { Expression *e = (Expression *)elements->data[i];
3087 if (!e)
3088 continue;
3090 f |= e->checkSideEffect(2);
3092 if (flag == 0 && f == 0)
3093 Expression::checkSideEffect(0);
3094 return f;
3097 int StructLiteralExp::canThrow()
3099 return arrayExpressionCanThrow(elements);
3102 void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3104 buf->writestring(sd->toChars());
3105 buf->writeByte('(');
3106 argsToCBuffer(buf, elements, hgs);
3107 buf->writeByte(')');
3110 void StructLiteralExp::toMangleBuffer(OutBuffer *buf)
3112 size_t dim = elements ? elements->dim : 0;
3113 buf->printf("S%u", dim);
3114 for (size_t i = 0; i < dim; i++)
3115 { Expression *e = (Expression *)elements->data[i];
3116 if (e)
3117 e->toMangleBuffer(buf);
3118 else
3119 buf->writeByte('v'); // 'v' for void
3123 /************************ TypeDotIdExp ************************************/
3125 /* Things like:
3126 * int.size
3127 * foo.size
3128 * (foo).size
3129 * cast(foo).size
3132 TypeDotIdExp::TypeDotIdExp(Loc loc, Type *type, Identifier *ident)
3133 : Expression(loc, TOKtypedot, sizeof(TypeDotIdExp))
3135 this->type = type;
3136 this->ident = ident;
3139 Expression *TypeDotIdExp::syntaxCopy()
3141 TypeDotIdExp *te = new TypeDotIdExp(loc, type->syntaxCopy(), ident);
3142 return te;
3145 Expression *TypeDotIdExp::semantic(Scope *sc)
3146 { Expression *e;
3148 #if LOGSEMANTIC
3149 printf("TypeDotIdExp::semantic()\n");
3150 #endif
3151 e = new DotIdExp(loc, new TypeExp(loc, type), ident);
3152 e = e->semantic(sc);
3153 return e;
3156 void TypeDotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3158 buf->writeByte('(');
3159 type->toCBuffer(buf, NULL, hgs);
3160 buf->writeByte(')');
3161 buf->writeByte('.');
3162 buf->writestring(ident->toChars());
3165 /************************************************************/
3167 // Mainly just a placeholder
3169 TypeExp::TypeExp(Loc loc, Type *type)
3170 : Expression(loc, TOKtype, sizeof(TypeExp))
3172 //printf("TypeExp::TypeExp(%s)\n", type->toChars());
3173 this->type = type;
3176 Expression *TypeExp::semantic(Scope *sc)
3178 //printf("TypeExp::semantic(%s)\n", type->toChars());
3179 type = type->semantic(loc, sc);
3180 return this;
3183 void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3185 type->toCBuffer(buf, NULL, hgs);
3188 /************************************************************/
3190 // Mainly just a placeholder
3192 ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg)
3193 : Expression(loc, TOKimport, sizeof(ScopeExp))
3195 //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars());
3196 //static int count; if (++count == 38) *(char*)0=0;
3197 this->sds = pkg;
3200 Expression *ScopeExp::syntaxCopy()
3202 ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL));
3203 return se;
3206 Expression *ScopeExp::semantic(Scope *sc)
3208 TemplateInstance *ti;
3209 ScopeDsymbol *sds2;
3211 #if LOGSEMANTIC
3212 printf("+ScopeExp::semantic('%s')\n", toChars());
3213 #endif
3214 Lagain:
3215 ti = sds->isTemplateInstance();
3216 if (ti && !global.errors)
3217 { Dsymbol *s;
3218 if (!ti->semanticdone)
3219 ti->semantic(sc);
3220 s = ti->inst->toAlias();
3221 sds2 = s->isScopeDsymbol();
3222 if (!sds2)
3223 { Expression *e;
3225 //printf("s = %s, '%s'\n", s->kind(), s->toChars());
3226 if (ti->withsym)
3228 // Same as wthis.s
3229 e = new VarExp(loc, ti->withsym->withstate->wthis);
3230 e = new DotVarExp(loc, e, s->isDeclaration());
3232 else
3233 e = new DsymbolExp(loc, s);
3234 e = e->semantic(sc);
3235 //printf("-1ScopeExp::semantic()\n");
3236 return e;
3238 if (sds2 != sds)
3240 sds = sds2;
3241 goto Lagain;
3243 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3245 else
3247 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3248 //printf("\tparent = '%s'\n", sds->parent->toChars());
3249 sds->semantic(sc);
3251 type = Type::tvoid;
3252 //printf("-2ScopeExp::semantic() %s\n", toChars());
3253 return this;
3256 void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3258 if (sds->isTemplateInstance())
3260 sds->toCBuffer(buf, hgs);
3262 else
3264 buf->writestring(sds->kind());
3265 buf->writestring(" ");
3266 buf->writestring(sds->toChars());
3270 /********************** TemplateExp **************************************/
3272 // Mainly just a placeholder
3274 TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td)
3275 : Expression(loc, TOKtemplate, sizeof(TemplateExp))
3277 //printf("TemplateExp(): %s\n", td->toChars());
3278 this->td = td;
3281 void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3283 buf->writestring(td->toChars());
3286 void TemplateExp::rvalue()
3288 error("template %s has no value", toChars());
3291 /********************** NewExp **************************************/
3293 NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
3294 Type *newtype, Expressions *arguments)
3295 : Expression(loc, TOKnew, sizeof(NewExp))
3297 this->thisexp = thisexp;
3298 this->newargs = newargs;
3299 this->newtype = newtype;
3300 this->arguments = arguments;
3301 member = NULL;
3302 allocator = NULL;
3303 onstack = 0;
3306 Expression *NewExp::syntaxCopy()
3308 return new NewExp(loc,
3309 thisexp ? thisexp->syntaxCopy() : NULL,
3310 arraySyntaxCopy(newargs),
3311 newtype->syntaxCopy(), arraySyntaxCopy(arguments));
3315 Expression *NewExp::semantic(Scope *sc)
3316 { int i;
3317 Type *tb;
3318 ClassDeclaration *cdthis = NULL;
3320 #if LOGSEMANTIC
3321 printf("NewExp::semantic() %s\n", toChars());
3322 if (thisexp)
3323 printf("\tthisexp = %s\n", thisexp->toChars());
3324 printf("\tnewtype: %s\n", newtype->toChars());
3325 #endif
3326 if (type) // if semantic() already run
3327 return this;
3329 Lagain:
3330 if (thisexp)
3331 { thisexp = thisexp->semantic(sc);
3332 cdthis = thisexp->type->isClassHandle();
3333 if (cdthis)
3335 sc = sc->push(cdthis);
3336 type = newtype->semantic(loc, sc);
3337 sc = sc->pop();
3339 else
3341 error("'this' for nested class must be a class type, not %s", thisexp->type->toChars());
3342 type = newtype->semantic(loc, sc);
3345 else
3346 type = newtype->semantic(loc, sc);
3347 newtype = type; // in case type gets cast to something else
3348 tb = type->toBasetype();
3349 //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco);
3351 arrayExpressionSemantic(newargs, sc);
3352 preFunctionArguments(loc, sc, newargs);
3353 arrayExpressionSemantic(arguments, sc);
3354 preFunctionArguments(loc, sc, arguments);
3356 if (thisexp && tb->ty != Tclass)
3357 error("e.new is only for allocating nested classes, not %s", tb->toChars());
3359 if (tb->ty == Tclass)
3360 { TypeFunction *tf;
3362 TypeClass *tc = (TypeClass *)(tb);
3363 ClassDeclaration *cd = tc->sym->isClassDeclaration();
3364 if (cd->isInterfaceDeclaration())
3365 error("cannot create instance of interface %s", cd->toChars());
3366 else if (cd->isAbstract())
3367 { error("cannot create instance of abstract class %s", cd->toChars());
3368 for (int i = 0; i < cd->vtbl.dim; i++)
3369 { FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration();
3370 if (fd && fd->isAbstract())
3371 error("function %s is abstract", fd->toChars());
3374 checkDeprecated(sc, cd);
3375 if (cd->isNested())
3376 { /* We need a 'this' pointer for the nested class.
3377 * Ensure we have the right one.
3379 Dsymbol *s = cd->toParent2();
3380 ClassDeclaration *cdn = s->isClassDeclaration();
3381 FuncDeclaration *fdn = s->isFuncDeclaration();
3383 //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
3384 if (cdn)
3386 if (!cdthis)
3388 // Supply an implicit 'this' and try again
3389 thisexp = new ThisExp(loc);
3390 for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
3391 { if (!sp)
3393 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
3394 break;
3396 ClassDeclaration *cdp = sp->isClassDeclaration();
3397 if (!cdp)
3398 continue;
3399 if (cdp == cdn || cdn->isBaseOf(cdp, NULL))
3400 break;
3401 // Add a '.outer' and try again
3402 thisexp = new DotIdExp(loc, thisexp, Id::outer);
3404 if (!global.errors)
3405 goto Lagain;
3407 if (cdthis)
3409 //printf("cdthis = %s\n", cdthis->toChars());
3410 if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL))
3411 error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars());
3413 #if 0
3414 else
3416 for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration())
3418 if (!sf)
3420 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
3421 break;
3423 printf("sf = %s\n", sf->toChars());
3424 AggregateDeclaration *ad = sf->isThis();
3425 if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL)))
3426 break;
3429 #endif
3431 else if (fdn)
3432 { /* The nested class cd is nested inside a function,
3433 * we'll let getEthis() look for errors.
3435 //printf("nested class %s is nested inside function %s, we're in %s\n", cd->toChars(), fdn->toChars(), sc->func->toChars());
3436 if (thisexp)
3437 // Because thisexp cannot be a function frame pointer
3438 error("e.new is only for allocating nested classes");
3440 else
3441 assert(0);
3443 else if (thisexp)
3444 error("e.new is only for allocating nested classes");
3446 FuncDeclaration *f = cd->ctor;
3447 if (f)
3449 assert(f);
3450 f = f->overloadResolve(loc, NULL, arguments);
3451 checkDeprecated(sc, f);
3452 member = f->isCtorDeclaration();
3453 assert(member);
3455 cd->accessCheck(loc, sc, member);
3457 tf = (TypeFunction *)f->type;
3458 // type = tf->next;
3460 if (!arguments)
3461 arguments = new Expressions();
3462 functionArguments(loc, sc, tf, arguments);
3464 else
3466 if (arguments && arguments->dim)
3467 error("no constructor for %s", cd->toChars());
3470 if (cd->aggNew)
3471 { Expression *e;
3473 f = cd->aggNew;
3475 // Prepend the uint size argument to newargs[]
3476 e = new IntegerExp(loc, cd->size(loc), Type::tsize_t);
3477 if (!newargs)
3478 newargs = new Expressions();
3479 newargs->shift(e);
3481 f = f->overloadResolve(loc, NULL, newargs);
3482 allocator = f->isNewDeclaration();
3483 assert(allocator);
3485 tf = (TypeFunction *)f->type;
3486 functionArguments(loc, sc, tf, newargs);
3488 else
3490 if (newargs && newargs->dim)
3491 error("no allocator for %s", cd->toChars());
3495 else if (tb->ty == Tstruct)
3497 TypeStruct *ts = (TypeStruct *)tb;
3498 StructDeclaration *sd = ts->sym;
3499 FuncDeclaration *f = sd->aggNew;
3500 TypeFunction *tf;
3502 if (arguments && arguments->dim)
3503 error("no constructor for %s", type->toChars());
3505 if (f)
3507 Expression *e;
3509 // Prepend the uint size argument to newargs[]
3510 e = new IntegerExp(loc, sd->size(loc), Type::tsize_t);
3511 if (!newargs)
3512 newargs = new Expressions();
3513 newargs->shift(e);
3515 f = f->overloadResolve(loc, NULL, newargs);
3516 allocator = f->isNewDeclaration();
3517 assert(allocator);
3519 tf = (TypeFunction *)f->type;
3520 functionArguments(loc, sc, tf, newargs);
3522 e = new VarExp(loc, f);
3523 e = new CallExp(loc, e, newargs);
3524 e = e->semantic(sc);
3525 e->type = type->pointerTo();
3526 return e;
3529 type = type->pointerTo();
3531 else if (tb->ty == Tarray && (arguments && arguments->dim))
3533 for (size_t i = 0; i < arguments->dim; i++)
3535 if (tb->ty != Tarray)
3536 { error("too many arguments for array");
3537 arguments->dim = i;
3538 break;
3541 Expression *arg = (Expression *)arguments->data[i];
3542 arg = resolveProperties(sc, arg);
3543 arg = arg->implicitCastTo(sc, Type::tsize_t);
3544 arg = arg->optimize(WANTvalue);
3545 if (arg->op == TOKint64 && (long long)arg->toInteger() < 0)
3546 error("negative array index %s", arg->toChars());
3547 arguments->data[i] = (void *) arg;
3548 tb = ((TypeDArray *)tb)->next->toBasetype();
3551 else if (tb->isscalar())
3553 if (arguments && arguments->dim)
3554 error("no constructor for %s", type->toChars());
3556 type = type->pointerTo();
3558 else
3560 error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars());
3561 type = type->pointerTo();
3564 //printf("NewExp: '%s'\n", toChars());
3565 //printf("NewExp:type '%s'\n", type->toChars());
3567 return this;
3570 int NewExp::checkSideEffect(int flag)
3572 return 1;
3575 int NewExp::canThrow()
3577 return 1;
3580 void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3581 { int i;
3583 if (thisexp)
3584 { expToCBuffer(buf, hgs, thisexp, PREC_primary);
3585 buf->writeByte('.');
3587 buf->writestring("new ");
3588 if (newargs && newargs->dim)
3590 buf->writeByte('(');
3591 argsToCBuffer(buf, newargs, hgs);
3592 buf->writeByte(')');
3594 newtype->toCBuffer(buf, NULL, hgs);
3595 if (arguments && arguments->dim)
3597 buf->writeByte('(');
3598 argsToCBuffer(buf, arguments, hgs);
3599 buf->writeByte(')');
3603 /********************** NewAnonClassExp **************************************/
3605 NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp,
3606 Expressions *newargs, ClassDeclaration *cd, Expressions *arguments)
3607 : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp))
3609 this->thisexp = thisexp;
3610 this->newargs = newargs;
3611 this->cd = cd;
3612 this->arguments = arguments;
3615 Expression *NewAnonClassExp::syntaxCopy()
3617 return new NewAnonClassExp(loc,
3618 thisexp ? thisexp->syntaxCopy() : NULL,
3619 arraySyntaxCopy(newargs),
3620 (ClassDeclaration *)cd->syntaxCopy(NULL),
3621 arraySyntaxCopy(arguments));
3625 Expression *NewAnonClassExp::semantic(Scope *sc)
3627 #if LOGSEMANTIC
3628 printf("NewAnonClassExp::semantic() %s\n", toChars());
3629 //printf("type: %s\n", type->toChars());
3630 #endif
3632 Expression *d = new DeclarationExp(loc, cd);
3633 d = d->semantic(sc);
3635 Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments);
3637 Expression *c = new CommaExp(loc, d, n);
3638 return c->semantic(sc);
3641 int NewAnonClassExp::checkSideEffect(int flag)
3643 return 1;
3646 int NewAnonClassExp::canThrow()
3648 return 1;
3651 void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3652 { int i;
3654 if (thisexp)
3655 { expToCBuffer(buf, hgs, thisexp, PREC_primary);
3656 buf->writeByte('.');
3658 buf->writestring("new");
3659 if (newargs && newargs->dim)
3661 buf->writeByte('(');
3662 argsToCBuffer(buf, newargs, hgs);
3663 buf->writeByte(')');
3665 buf->writestring(" class ");
3666 if (arguments && arguments->dim)
3668 buf->writeByte('(');
3669 argsToCBuffer(buf, arguments, hgs);
3670 buf->writeByte(')');
3672 //buf->writestring(" { }");
3673 if (cd)
3675 cd->toCBuffer(buf, hgs);
3679 /********************** SymOffExp **************************************/
3681 SymbolExp::SymbolExp(Loc loc, enum TOK op, int size, Declaration *var, int hasOverloads)
3682 : Expression(loc, op, size)
3684 assert(var);
3685 this->var = var;
3686 this->hasOverloads = hasOverloads;
3689 /********************** SymOffExp **************************************/
3691 SymOffExp::SymOffExp(Loc loc, Declaration *var, target_size_t offset, int hasOverloads)
3692 : SymbolExp(loc, TOKsymoff, sizeof(SymOffExp), var, hasOverloads)
3694 this->offset = offset;
3696 VarDeclaration *v = var->isVarDeclaration();
3697 if (v && v->needThis())
3698 error("need 'this' for address of %s", v->toChars());
3701 Expression *SymOffExp::semantic(Scope *sc)
3703 #if LOGSEMANTIC
3704 printf("SymOffExp::semantic('%s')\n", toChars());
3705 #endif
3706 //var->semantic(sc);
3707 if (!type)
3708 type = var->type->pointerTo();
3709 VarDeclaration *v = var->isVarDeclaration();
3710 if (v)
3711 v->checkNestedReference(sc, loc);
3712 return this;
3715 int SymOffExp::isBool(int result)
3717 return result ? TRUE : FALSE;
3720 void SymOffExp::checkEscape()
3722 VarDeclaration *v = var->isVarDeclaration();
3723 if (v)
3725 if (!v->isDataseg())
3726 error("escaping reference to local variable %s", v->toChars());
3730 void SymOffExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3732 if (offset)
3733 buf->printf("(& %s+%"PRIuTSIZE")", var->toChars(), offset);
3734 else
3735 buf->printf("& %s", var->toChars());
3738 /******************************** VarExp **************************/
3740 VarExp::VarExp(Loc loc, Declaration *var, int hasOverloads)
3741 : SymbolExp(loc, TOKvar, sizeof(VarExp), var, hasOverloads)
3743 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
3744 //if (strcmp(var->ident->toChars(), "func") == 0) halt();
3745 this->type = var->type;
3748 int VarExp::equals(Object *o)
3749 { VarExp *ne;
3751 if (this == o ||
3752 (((Expression *)o)->op == TOKvar &&
3753 ((ne = (VarExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
3754 var == ne->var))
3755 return 1;
3756 return 0;
3759 Expression *VarExp::semantic(Scope *sc)
3760 { FuncLiteralDeclaration *fd;
3762 #if LOGSEMANTIC
3763 printf("VarExp::semantic(%s)\n", toChars());
3764 #endif
3765 if (!type)
3766 { type = var->type;
3767 #if 0
3768 if (var->storage_class & STClazy)
3770 TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd);
3771 type = new TypeDelegate(tf);
3772 type = type->semantic(loc, sc);
3774 #endif
3777 VarDeclaration *v = var->isVarDeclaration();
3778 if (v)
3780 #if 0
3781 if ((v->isConst() || v->isInvariant()) &&
3782 type->toBasetype()->ty != Tsarray && v->init)
3784 ExpInitializer *ei = v->init->isExpInitializer();
3785 if (ei)
3787 //ei->exp->implicitCastTo(sc, type)->print();
3788 return ei->exp->implicitCastTo(sc, type);
3791 #endif
3792 v->checkNestedReference(sc, loc);
3794 #if 0
3795 else if ((fd = var->isFuncLiteralDeclaration()) != NULL)
3796 { Expression *e;
3797 e = new FuncExp(loc, fd);
3798 e->type = type;
3799 return e;
3801 #endif
3802 return this;
3805 char *VarExp::toChars()
3807 return var->toChars();
3810 void VarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3812 buf->writestring(var->toChars());
3815 void VarExp::checkEscape()
3817 VarDeclaration *v = var->isVarDeclaration();
3818 if (v)
3819 { Type *tb = v->type->toBasetype();
3820 // if reference type
3821 if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass)
3823 if ((v->isAuto() || v->isScope()) && !v->noauto)
3824 error("escaping reference to auto local %s", v->toChars());
3825 else if (v->storage_class & STCvariadic)
3826 error("escaping reference to variadic parameter %s", v->toChars());
3831 Expression *VarExp::toLvalue(Scope *sc, Expression *e)
3833 #if 0
3834 tym = tybasic(e1->ET->Tty);
3835 if (!(tyscalar(tym) ||
3836 tym == TYstruct ||
3837 tym == TYarray && e->Eoper == TOKaddr))
3838 synerr(EM_lvalue); // lvalue expected
3839 #endif
3840 if (var->storage_class & STClazy)
3841 error("lazy variables cannot be lvalues");
3842 return this;
3845 Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
3847 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
3848 if (type && type->toBasetype()->ty == Tsarray)
3849 error("cannot change reference to static array '%s'", var->toChars());
3851 var->checkModify(loc, sc, type);
3853 // See if this expression is a modifiable lvalue (i.e. not const)
3854 return toLvalue(sc, e);
3858 /******************************** OverExp **************************/
3860 OverExp::OverExp(OverloadSet *s)
3861 : Expression(loc, TOKoverloadset, sizeof(OverExp))
3863 //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
3864 vars = s;
3865 type = Type::tvoid;
3868 Expression *OverExp::toLvalue(Scope *sc, Expression *e)
3870 return this;
3874 /******************************** TupleExp **************************/
3876 TupleExp::TupleExp(Loc loc, Expressions *exps)
3877 : Expression(loc, TOKtuple, sizeof(TupleExp))
3879 //printf("TupleExp(this = %p)\n", this);
3880 this->exps = exps;
3881 this->type = NULL;
3885 TupleExp::TupleExp(Loc loc, TupleDeclaration *tup)
3886 : Expression(loc, TOKtuple, sizeof(TupleExp))
3888 exps = new Expressions();
3889 type = NULL;
3891 exps->reserve(tup->objects->dim);
3892 for (size_t i = 0; i < tup->objects->dim; i++)
3893 { Object *o = (Object *)tup->objects->data[i];
3894 if (o->dyncast() == DYNCAST_EXPRESSION)
3896 Expression *e = (Expression *)o;
3897 e = e->syntaxCopy();
3898 exps->push(e);
3900 else if (o->dyncast() == DYNCAST_DSYMBOL)
3902 Dsymbol *s = (Dsymbol *)o;
3903 Expression *e = new DsymbolExp(loc, s);
3904 exps->push(e);
3906 else if (o->dyncast() == DYNCAST_TYPE)
3908 Type *t = (Type *)o;
3909 Expression *e = new TypeExp(loc, t);
3910 exps->push(e);
3912 else
3914 error("%s is not an expression", o->toChars());
3919 int TupleExp::equals(Object *o)
3920 { TupleExp *ne;
3922 if (this == o)
3923 return 1;
3924 if (((Expression *)o)->op == TOKtuple)
3926 TupleExp *te = (TupleExp *)o;
3927 if (exps->dim != te->exps->dim)
3928 return 0;
3929 for (size_t i = 0; i < exps->dim; i++)
3930 { Expression *e1 = (Expression *)exps->data[i];
3931 Expression *e2 = (Expression *)te->exps->data[i];
3933 if (!e1->equals(e2))
3934 return 0;
3936 return 1;
3938 return 0;
3941 Expression *TupleExp::syntaxCopy()
3943 return new TupleExp(loc, arraySyntaxCopy(exps));
3946 Expression *TupleExp::semantic(Scope *sc)
3948 #if LOGSEMANTIC
3949 printf("+TupleExp::semantic(%s)\n", toChars());
3950 #endif
3951 if (type)
3952 return this;
3954 // Run semantic() on each argument
3955 for (size_t i = 0; i < exps->dim; i++)
3956 { Expression *e = (Expression *)exps->data[i];
3958 e = e->semantic(sc);
3959 if (!e->type)
3960 { error("%s has no value", e->toChars());
3961 e->type = Type::terror;
3963 exps->data[i] = (void *)e;
3966 expandTuples(exps);
3967 if (0 && exps->dim == 1)
3969 return (Expression *)exps->data[0];
3971 type = new TypeTuple(exps);
3972 //printf("-TupleExp::semantic(%s)\n", toChars());
3973 return this;
3976 void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3978 buf->writestring("tuple(");
3979 argsToCBuffer(buf, exps, hgs);
3980 buf->writeByte(')');
3983 int TupleExp::checkSideEffect(int flag)
3984 { int f = 0;
3986 for (int i = 0; i < exps->dim; i++)
3987 { Expression *e = (Expression *)exps->data[i];
3989 f |= e->checkSideEffect(2);
3991 if (flag == 0 && f == 0)
3992 Expression::checkSideEffect(0);
3993 return f;
3996 int TupleExp::canThrow()
3998 return arrayExpressionCanThrow(exps);
4001 void TupleExp::checkEscape()
4003 for (size_t i = 0; i < exps->dim; i++)
4004 { Expression *e = (Expression *)exps->data[i];
4005 e->checkEscape();
4009 /******************************** FuncExp *********************************/
4011 FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd)
4012 : Expression(loc, TOKfunction, sizeof(FuncExp))
4014 this->fd = fd;
4017 Expression *FuncExp::syntaxCopy()
4019 return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL));
4022 Expression *FuncExp::semantic(Scope *sc)
4024 #if LOGSEMANTIC
4025 printf("FuncExp::semantic(%s)\n", toChars());
4026 #endif
4027 if (!type)
4029 fd->semantic(sc);
4030 fd->parent = sc->parent;
4031 if (global.errors)
4033 fd->type = fd->type->semantic(loc, sc);
4035 else
4037 fd->semantic2(sc);
4038 if (!global.errors)
4040 fd->semantic3(sc);
4042 if (!global.errors && global.params.useInline)
4043 fd->inlineScan();
4047 // Type is a "delegate to" or "pointer to" the function literal
4048 if (fd->isNested())
4050 type = new TypeDelegate(fd->type);
4051 type = type->semantic(loc, sc);
4053 else
4055 type = fd->type->pointerTo();
4057 fd->tookAddressOf++;
4059 return this;
4062 char *FuncExp::toChars()
4064 return fd->toChars();
4067 void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4069 buf->writestring(fd->toChars());
4073 /******************************** DeclarationExp **************************/
4075 DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration)
4076 : Expression(loc, TOKdeclaration, sizeof(DeclarationExp))
4078 this->declaration = declaration;
4081 Expression *DeclarationExp::syntaxCopy()
4083 return new DeclarationExp(loc, declaration->syntaxCopy(NULL));
4086 Expression *DeclarationExp::semantic(Scope *sc)
4088 if (type)
4089 return this;
4091 #if LOGSEMANTIC
4092 printf("DeclarationExp::semantic() %s\n", toChars());
4093 #endif
4095 /* This is here to support extern(linkage) declaration,
4096 * where the extern(linkage) winds up being an AttribDeclaration
4097 * wrapper.
4099 Dsymbol *s = declaration;
4101 AttribDeclaration *ad = declaration->isAttribDeclaration();
4102 if (ad)
4104 if (ad->decl && ad->decl->dim == 1)
4105 s = (Dsymbol *)ad->decl->data[0];
4108 if (s->isVarDeclaration())
4109 { // Do semantic() on initializer first, so:
4110 // int a = a;
4111 // will be illegal.
4112 declaration->semantic(sc);
4113 s->parent = sc->parent;
4116 //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc);
4117 // Insert into both local scope and function scope.
4118 // Must be unique in both.
4119 if (s->ident)
4121 if (!sc->insert(s))
4122 error("declaration %s is already defined", s->toPrettyChars());
4123 else if (sc->func)
4124 { VarDeclaration *v = s->isVarDeclaration();
4125 if (s->isFuncDeclaration() &&
4126 !sc->func->localsymtab->insert(s))
4127 error("declaration %s is already defined in another scope in %s", s->toPrettyChars(), sc->func->toChars());
4128 else if (!global.params.useDeprecated)
4129 { // Disallow shadowing
4131 for (Scope *scx = sc->enclosing; scx && scx->func == sc->func; scx = scx->enclosing)
4132 { Dsymbol *s2;
4134 if (scx->scopesym && scx->scopesym->symtab &&
4135 (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL &&
4136 s != s2)
4138 error("shadowing declaration %s is deprecated", s->toPrettyChars());
4144 if (!s->isVarDeclaration())
4146 declaration->semantic(sc);
4147 s->parent = sc->parent;
4149 if (!global.errors)
4151 declaration->semantic2(sc);
4152 if (!global.errors)
4154 declaration->semantic3(sc);
4156 if (!global.errors && global.params.useInline)
4157 declaration->inlineScan();
4161 type = Type::tvoid;
4162 return this;
4165 int DeclarationExp::checkSideEffect(int flag)
4167 return 1;
4170 int DeclarationExp::canThrow()
4172 VarDeclaration *v = declaration->isVarDeclaration();
4173 if (v && v->init)
4174 { ExpInitializer *ie = v->init->isExpInitializer();
4175 return ie && ie->exp->canThrow();
4177 return 0;
4180 void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4182 declaration->toCBuffer(buf, hgs);
4186 /************************ TypeidExp ************************************/
4189 * typeid(int)
4192 TypeidExp::TypeidExp(Loc loc, Type *typeidType)
4193 : Expression(loc, TOKtypeid, sizeof(TypeidExp))
4195 this->typeidType = typeidType;
4199 Expression *TypeidExp::syntaxCopy()
4201 return new TypeidExp(loc, typeidType->syntaxCopy());
4205 Expression *TypeidExp::semantic(Scope *sc)
4206 { Expression *e;
4208 #if LOGSEMANTIC
4209 printf("TypeidExp::semantic()\n");
4210 #endif
4211 typeidType = typeidType->semantic(loc, sc);
4212 e = typeidType->getTypeInfo(sc);
4213 return e;
4216 void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4218 buf->writestring("typeid(");
4219 typeidType->toCBuffer(buf, NULL, hgs);
4220 buf->writeByte(')');
4223 /************************ TraitsExp ************************************/
4226 * __traits(identifier, args...)
4229 TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args)
4230 : Expression(loc, TOKtraits, sizeof(TraitsExp))
4232 this->ident = ident;
4233 this->args = args;
4237 Expression *TraitsExp::syntaxCopy()
4239 return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args));
4243 void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4245 buf->writestring("__traits(");
4246 buf->writestring(ident->toChars());
4247 if (args)
4249 for (int i = 0; i < args->dim; i++)
4251 buf->writeByte(',');
4252 Object *oarg = (Object *)args->data[i];
4253 ObjectToCBuffer(buf, hgs, oarg);
4256 buf->writeByte(')');
4259 /************************************************************/
4261 HaltExp::HaltExp(Loc loc)
4262 : Expression(loc, TOKhalt, sizeof(HaltExp))
4266 Expression *HaltExp::semantic(Scope *sc)
4268 #if LOGSEMANTIC
4269 printf("HaltExp::semantic()\n");
4270 #endif
4271 type = Type::tvoid;
4272 return this;
4275 int HaltExp::checkSideEffect(int flag)
4277 return 1;
4280 void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4282 buf->writestring("halt");
4285 /************************************************************/
4287 IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
4288 Type *tspec, enum TOK tok2, TemplateParameters *parameters)
4289 : Expression(loc, TOKis, sizeof(IsExp))
4291 this->targ = targ;
4292 this->id = id;
4293 this->tok = tok;
4294 this->tspec = tspec;
4295 this->tok2 = tok2;
4296 this->parameters = parameters;
4299 Expression *IsExp::syntaxCopy()
4301 // This section is identical to that in TemplateDeclaration::syntaxCopy()
4302 TemplateParameters *p = NULL;
4303 if (parameters)
4305 p = new TemplateParameters();
4306 p->setDim(parameters->dim);
4307 for (int i = 0; i < p->dim; i++)
4308 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
4309 p->data[i] = (void *)tp->syntaxCopy();
4313 return new IsExp(loc,
4314 targ->syntaxCopy(),
4316 tok,
4317 tspec ? tspec->syntaxCopy() : NULL,
4318 tok2,
4322 Expression *IsExp::semantic(Scope *sc)
4323 { Type *tded;
4325 /* is(targ id tok tspec)
4326 * is(targ id == tok2)
4329 //printf("IsExp::semantic(%s)\n", toChars());
4330 if (id && !(sc->flags & SCOPEstaticif))
4331 error("can only declare type aliases within static if conditionals");
4333 unsigned errors_save = global.errors;
4334 global.errors = 0;
4335 global.gag++; // suppress printing of error messages
4336 targ = targ->semantic(loc, sc);
4337 global.gag--;
4338 unsigned gerrors = global.errors;
4339 global.errors = errors_save;
4341 if (gerrors) // if any errors happened
4342 { // then condition is false
4343 goto Lno;
4345 else if (tok2 != TOKreserved)
4347 switch (tok2)
4349 case TOKtypedef:
4350 if (targ->ty != Ttypedef)
4351 goto Lno;
4352 tded = ((TypeTypedef *)targ)->sym->basetype;
4353 break;
4355 case TOKstruct:
4356 if (targ->ty != Tstruct)
4357 goto Lno;
4358 if (((TypeStruct *)targ)->sym->isUnionDeclaration())
4359 goto Lno;
4360 tded = targ;
4361 break;
4363 case TOKunion:
4364 if (targ->ty != Tstruct)
4365 goto Lno;
4366 if (!((TypeStruct *)targ)->sym->isUnionDeclaration())
4367 goto Lno;
4368 tded = targ;
4369 break;
4371 case TOKclass:
4372 if (targ->ty != Tclass)
4373 goto Lno;
4374 if (((TypeClass *)targ)->sym->isInterfaceDeclaration())
4375 goto Lno;
4376 tded = targ;
4377 break;
4379 case TOKinterface:
4380 if (targ->ty != Tclass)
4381 goto Lno;
4382 if (!((TypeClass *)targ)->sym->isInterfaceDeclaration())
4383 goto Lno;
4384 tded = targ;
4385 break;
4387 #if V2
4388 case TOKconst:
4389 if (!targ->isConst())
4390 goto Lno;
4391 tded = targ;
4392 break;
4394 case TOKinvariant:
4395 if (!targ->isInvariant())
4396 goto Lno;
4397 tded = targ;
4398 break;
4399 #endif
4401 case TOKsuper:
4402 // If class or interface, get the base class and interfaces
4403 if (targ->ty != Tclass)
4404 goto Lno;
4405 else
4406 { ClassDeclaration *cd = ((TypeClass *)targ)->sym;
4407 Arguments *args = new Arguments;
4408 args->reserve(cd->baseclasses.dim);
4409 for (size_t i = 0; i < cd->baseclasses.dim; i++)
4410 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
4411 args->push(new Argument(STCin, b->type, NULL, NULL));
4413 tded = new TypeTuple(args);
4415 break;
4417 case TOKenum:
4418 if (targ->ty != Tenum)
4419 goto Lno;
4420 tded = ((TypeEnum *)targ)->sym->memtype;
4421 break;
4423 case TOKdelegate:
4424 if (targ->ty != Tdelegate)
4425 goto Lno;
4426 tded = ((TypeDelegate *)targ)->next; // the underlying function type
4427 break;
4429 case TOKfunction:
4431 if (targ->ty != Tfunction)
4432 goto Lno;
4433 tded = targ;
4435 /* Generate tuple from function parameter types.
4437 assert(tded->ty == Tfunction);
4438 Arguments *params = ((TypeFunction *)tded)->parameters;
4439 size_t dim = Argument::dim(params);
4440 Arguments *args = new Arguments;
4441 args->reserve(dim);
4442 for (size_t i = 0; i < dim; i++)
4443 { Argument *arg = Argument::getNth(params, i);
4444 assert(arg && arg->type);
4445 args->push(new Argument(arg->storageClass, arg->type, NULL, NULL));
4447 tded = new TypeTuple(args);
4448 break;
4450 case TOKreturn:
4451 /* Get the 'return type' for the function,
4452 * delegate, or pointer to function.
4454 if (targ->ty == Tfunction)
4455 tded = ((TypeFunction *)targ)->next;
4456 else if (targ->ty == Tdelegate)
4457 { tded = ((TypeDelegate *)targ)->next;
4458 tded = ((TypeFunction *)tded)->next;
4460 else if (targ->ty == Tpointer &&
4461 ((TypePointer *)targ)->next->ty == Tfunction)
4462 { tded = ((TypePointer *)targ)->next;
4463 tded = ((TypeFunction *)tded)->next;
4465 else
4466 goto Lno;
4467 break;
4469 default:
4470 assert(0);
4472 goto Lyes;
4474 else if (id && tspec)
4476 /* Evaluate to TRUE if targ matches tspec.
4477 * If TRUE, declare id as an alias for the specialized type.
4480 MATCH m;
4481 assert(parameters && parameters->dim);
4483 Objects dedtypes;
4484 dedtypes.setDim(parameters->dim);
4485 dedtypes.zero();
4487 m = targ->deduceType(NULL, tspec, parameters, &dedtypes);
4488 if (m == MATCHnomatch ||
4489 (m != MATCHexact && tok == TOKequal))
4490 goto Lno;
4491 else
4493 tded = (Type *)dedtypes.data[0];
4494 if (!tded)
4495 tded = targ;
4497 Objects tiargs;
4498 tiargs.setDim(1);
4499 tiargs.data[0] = (void *)targ;
4501 for (int i = 1; i < parameters->dim; i++)
4502 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
4503 Declaration *s;
4505 m = tp->matchArg(sc, &tiargs, i, parameters, &dedtypes, &s);
4506 if (m == MATCHnomatch)
4507 goto Lno;
4508 s->semantic(sc);
4509 if (!sc->insert(s))
4510 error("declaration %s is already defined", s->toChars());
4511 #if 0
4512 Object *o = (Object *)dedtypes.data[i];
4513 Dsymbol *s = TemplateDeclaration::declareParameter(loc, sc, tp, o);
4514 #endif
4515 if (sc->sd)
4516 s->addMember(sc, sc->sd, 1);
4519 goto Lyes;
4522 else if (id)
4524 /* Declare id as an alias for type targ. Evaluate to TRUE
4526 tded = targ;
4527 goto Lyes;
4529 else if (tspec)
4531 /* Evaluate to TRUE if targ matches tspec
4533 tspec = tspec->semantic(loc, sc);
4534 //printf("targ = %s\n", targ->toChars());
4535 //printf("tspec = %s\n", tspec->toChars());
4536 if (tok == TOKcolon)
4537 { if (targ->implicitConvTo(tspec))
4538 goto Lyes;
4539 else
4540 goto Lno;
4542 else /* == */
4543 { if (targ->equals(tspec))
4544 goto Lyes;
4545 else
4546 goto Lno;
4550 Lyes:
4551 if (id)
4553 Dsymbol *s = new AliasDeclaration(loc, id, tded);
4554 s->semantic(sc);
4555 if (!sc->insert(s))
4556 error("declaration %s is already defined", s->toChars());
4557 if (sc->sd)
4558 s->addMember(sc, sc->sd, 1);
4560 return new IntegerExp(loc, 1, Type::tbool);
4562 Lno:
4563 return new IntegerExp(loc, 0, Type::tbool);
4566 void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4568 buf->writestring("is(");
4569 targ->toCBuffer(buf, id, hgs);
4570 if (tok2 != TOKreserved)
4572 buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2));
4574 else if (tspec)
4576 if (tok == TOKcolon)
4577 buf->writestring(" : ");
4578 else
4579 buf->writestring(" == ");
4580 tspec->toCBuffer(buf, NULL, hgs);
4582 if (parameters)
4583 { // First parameter is already output, so start with second
4584 for (int i = 1; i < parameters->dim; i++)
4586 buf->writeByte(',');
4587 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
4588 tp->toCBuffer(buf, hgs);
4591 buf->writeByte(')');
4595 /************************************************************/
4597 UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1)
4598 : Expression(loc, op, size)
4600 this->e1 = e1;
4603 Expression *UnaExp::syntaxCopy()
4604 { UnaExp *e;
4606 e = (UnaExp *)copy();
4607 e->type = NULL;
4608 e->e1 = e->e1->syntaxCopy();
4609 return e;
4612 Expression *UnaExp::semantic(Scope *sc)
4614 #if LOGSEMANTIC
4615 printf("UnaExp::semantic('%s')\n", toChars());
4616 #endif
4617 e1 = e1->semantic(sc);
4618 // if (!e1->type)
4619 // error("%s has no value", e1->toChars());
4620 return this;
4623 int UnaExp::canThrow()
4625 return e1->canThrow();
4628 void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4630 buf->writestring(Token::toChars(op));
4631 expToCBuffer(buf, hgs, e1, precedence[op]);
4634 /************************************************************/
4636 BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2)
4637 : Expression(loc, op, size)
4639 this->e1 = e1;
4640 this->e2 = e2;
4643 Expression *BinExp::syntaxCopy()
4644 { BinExp *e;
4646 e = (BinExp *)copy();
4647 e->type = NULL;
4648 e->e1 = e->e1->syntaxCopy();
4649 e->e2 = e->e2->syntaxCopy();
4650 return e;
4653 Expression *BinExp::semantic(Scope *sc)
4655 #if LOGSEMANTIC
4656 printf("BinExp::semantic('%s')\n", toChars());
4657 #endif
4658 e1 = e1->semantic(sc);
4659 if (!e1->type)
4661 error("%s has no value", e1->toChars());
4662 e1->type = Type::terror;
4664 e2 = e2->semantic(sc);
4665 if (!e2->type)
4667 error("%s has no value", e2->toChars());
4668 e2->type = Type::terror;
4670 assert(e1->type);
4671 return this;
4674 Expression *BinExp::semanticp(Scope *sc)
4676 BinExp::semantic(sc);
4677 e1 = resolveProperties(sc, e1);
4678 e2 = resolveProperties(sc, e2);
4679 return this;
4682 /***************************
4683 * Common semantic routine for some xxxAssignExp's.
4686 Expression *BinExp::commonSemanticAssign(Scope *sc)
4687 { Expression *e;
4689 if (!type)
4691 BinExp::semantic(sc);
4692 e2 = resolveProperties(sc, e2);
4694 e = op_overload(sc);
4695 if (e)
4696 return e;
4698 e1 = e1->modifiableLvalue(sc, e1);
4699 e1->checkScalar();
4700 type = e1->type;
4701 if (type->toBasetype()->ty == Tbool)
4703 error("operator not allowed on bool expression %s", toChars());
4705 typeCombine(sc);
4706 e1->checkArithmetic();
4707 e2->checkArithmetic();
4709 if (op == TOKmodass && e2->type->iscomplex())
4710 { error("cannot perform modulo complex arithmetic");
4711 return new IntegerExp(0);
4714 return this;
4717 Expression *BinExp::commonSemanticAssignIntegral(Scope *sc)
4718 { Expression *e;
4720 if (!type)
4722 BinExp::semantic(sc);
4723 e2 = resolveProperties(sc, e2);
4725 e = op_overload(sc);
4726 if (e)
4727 return e;
4729 e1 = e1->modifiableLvalue(sc, e1);
4730 e1->checkScalar();
4731 type = e1->type;
4732 if (type->toBasetype()->ty == Tbool)
4734 e2 = e2->implicitCastTo(sc, type);
4737 typeCombine(sc);
4738 e1->checkIntegral();
4739 e2->checkIntegral();
4741 return this;
4744 int BinExp::checkSideEffect(int flag)
4746 if (op == TOKplusplus ||
4747 op == TOKminusminus ||
4748 op == TOKassign ||
4749 op == TOKconstruct ||
4750 op == TOKblit ||
4751 op == TOKaddass ||
4752 op == TOKminass ||
4753 op == TOKcatass ||
4754 op == TOKmulass ||
4755 op == TOKdivass ||
4756 op == TOKmodass ||
4757 op == TOKshlass ||
4758 op == TOKshrass ||
4759 op == TOKushrass ||
4760 op == TOKandass ||
4761 op == TOKorass ||
4762 op == TOKxorass ||
4763 op == TOKin ||
4764 op == TOKremove)
4765 return 1;
4766 return Expression::checkSideEffect(flag);
4769 void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4771 expToCBuffer(buf, hgs, e1, precedence[op]);
4772 buf->writeByte(' ');
4773 buf->writestring(Token::toChars(op));
4774 buf->writeByte(' ');
4775 expToCBuffer(buf, hgs, e2, (enum PREC)(precedence[op] + 1));
4778 int BinExp::isunsigned()
4780 return e1->type->isunsigned() || e2->type->isunsigned();
4783 int BinExp::canThrow()
4785 return e1->canThrow() || e2->canThrow();
4788 void BinExp::incompatibleTypes()
4790 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
4791 e1->toChars(), Token::toChars(op), e2->toChars(),
4792 e1->type->toChars(), e2->type->toChars());
4795 /************************************************************/
4797 CompileExp::CompileExp(Loc loc, Expression *e)
4798 : UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
4802 Expression *CompileExp::semantic(Scope *sc)
4804 #if LOGSEMANTIC
4805 printf("CompileExp::semantic('%s')\n", toChars());
4806 #endif
4807 UnaExp::semantic(sc);
4808 e1 = resolveProperties(sc, e1);
4809 e1 = e1->optimize(WANTvalue | WANTinterpret);
4810 if (e1->op != TOKstring)
4811 { error("argument to mixin must be a string, not (%s)", e1->toChars());
4812 type = Type::terror;
4813 return this;
4815 StringExp *se = (StringExp *)e1;
4816 se = se->toUTF8(sc);
4817 Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
4818 p.loc = loc;
4819 p.nextToken();
4820 //printf("p.loc.linnum = %d\n", p.loc.linnum);
4821 Expression *e = p.parseExpression();
4822 if (p.token.value != TOKeof)
4823 error("incomplete mixin expression (%s)", se->toChars());
4824 return e->semantic(sc);
4827 void CompileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4829 buf->writestring("mixin(");
4830 expToCBuffer(buf, hgs, e1, PREC_assign);
4831 buf->writeByte(')');
4834 /************************************************************/
4836 FileExp::FileExp(Loc loc, Expression *e)
4837 : UnaExp(loc, TOKmixin, sizeof(FileExp), e)
4841 Expression *FileExp::semantic(Scope *sc)
4842 { char *name;
4843 StringExp *se;
4845 #if LOGSEMANTIC
4846 printf("FileExp::semantic('%s')\n", toChars());
4847 #endif
4848 UnaExp::semantic(sc);
4849 e1 = resolveProperties(sc, e1);
4850 e1 = e1->optimize(WANTvalue);
4851 if (e1->op != TOKstring)
4852 { error("file name argument must be a string, not (%s)", e1->toChars());
4853 goto Lerror;
4855 se = (StringExp *)e1;
4856 se = se->toUTF8(sc);
4857 name = (char *)se->string;
4859 if (!global.params.fileImppath)
4860 { error("need -Jpath switch to import text file %s", name);
4861 goto Lerror;
4864 if (name != FileName::name(name))
4865 { error("use -Jpath switch to provide path for filename %s", name);
4866 goto Lerror;
4869 name = FileName::searchPath(global.filePath, name, 0);
4870 if (!name)
4871 { error("file %s cannot be found, check -Jpath", se->toChars());
4872 goto Lerror;
4875 if (global.params.verbose)
4876 printf("file %s\t(%s)\n", se->string, name);
4878 { File f(name);
4879 if (f.read())
4880 { error("cannot read file %s", f.toChars());
4881 goto Lerror;
4883 else
4885 f.ref = 1;
4886 se = new StringExp(loc, f.buffer, f.len);
4889 Lret:
4890 return se->semantic(sc);
4892 Lerror:
4893 se = new StringExp(loc, "");
4894 goto Lret;
4897 void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4899 buf->writestring("import(");
4900 expToCBuffer(buf, hgs, e1, PREC_assign);
4901 buf->writeByte(')');
4904 /************************************************************/
4906 AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg)
4907 : UnaExp(loc, TOKassert, sizeof(AssertExp), e)
4909 this->msg = msg;
4912 Expression *AssertExp::syntaxCopy()
4914 AssertExp *ae = new AssertExp(loc, e1->syntaxCopy(),
4915 msg ? msg->syntaxCopy() : NULL);
4916 return ae;
4919 Expression *AssertExp::semantic(Scope *sc)
4921 #if LOGSEMANTIC
4922 printf("AssertExp::semantic('%s')\n", toChars());
4923 #endif
4924 UnaExp::semantic(sc);
4925 e1 = resolveProperties(sc, e1);
4926 // BUG: see if we can do compile time elimination of the Assert
4927 e1 = e1->optimize(WANTvalue);
4928 e1 = e1->checkToBoolean();
4929 if (msg)
4931 msg = msg->semantic(sc);
4932 msg = resolveProperties(sc, msg);
4933 msg = msg->implicitCastTo(sc, Type::tchar->constOf()->arrayOf());
4934 msg = msg->optimize(WANTvalue);
4936 if (e1->isBool(FALSE))
4938 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
4939 fd->hasReturnExp |= 4;
4941 if (!global.params.useAssert)
4942 { Expression *e = new HaltExp(loc);
4943 e = e->semantic(sc);
4944 return e;
4947 type = Type::tvoid;
4948 return this;
4951 int AssertExp::checkSideEffect(int flag)
4953 return 1;
4956 int AssertExp::canThrow()
4958 return (global.params.useAssert != 0);
4961 void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4963 buf->writestring("assert(");
4964 expToCBuffer(buf, hgs, e1, PREC_assign);
4965 if (msg)
4967 buf->writeByte(',');
4968 expToCBuffer(buf, hgs, msg, PREC_assign);
4970 buf->writeByte(')');
4973 /************************************************************/
4975 DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident)
4976 : UnaExp(loc, TOKdot, sizeof(DotIdExp), e)
4978 this->ident = ident;
4981 Expression *DotIdExp::semantic(Scope *sc)
4982 { Expression *e;
4983 Expression *eleft;
4984 Expression *eright;
4986 #if LOGSEMANTIC
4987 printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars());
4988 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
4989 #endif
4991 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
4993 #if 0
4994 /* Don't do semantic analysis if we'll be converting
4995 * it to a string.
4997 if (ident == Id::stringof)
4998 { char *s = e1->toChars();
4999 e = new StringExp(loc, s, strlen(s), 'c');
5000 e = e->semantic(sc);
5001 return e;
5003 #endif
5005 /* Special case: rewrite this.id and super.id
5006 * to be classtype.id and baseclasstype.id
5007 * if we have no this pointer.
5009 if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc))
5010 { ClassDeclaration *cd;
5011 StructDeclaration *sd;
5012 AggregateDeclaration *ad;
5014 ad = sc->getStructClassScope();
5015 if (ad)
5017 cd = ad->isClassDeclaration();
5018 if (cd)
5020 if (e1->op == TOKthis)
5022 e = new TypeDotIdExp(loc, cd->type, ident);
5023 return e->semantic(sc);
5025 else if (cd->baseClass && e1->op == TOKsuper)
5027 e = new TypeDotIdExp(loc, cd->baseClass->type, ident);
5028 return e->semantic(sc);
5031 else
5033 sd = ad->isStructDeclaration();
5034 if (sd)
5036 if (e1->op == TOKthis)
5038 e = new TypeDotIdExp(loc, sd->type, ident);
5039 return e->semantic(sc);
5046 UnaExp::semantic(sc);
5048 if (e1->op == TOKdotexp)
5050 DotExp *de = (DotExp *)e1;
5051 eleft = de->e1;
5052 eright = de->e2;
5054 else
5056 e1 = resolveProperties(sc, e1);
5057 eleft = NULL;
5058 eright = e1;
5061 if (e1->op == TOKtuple && ident == Id::offsetof)
5062 { /* 'distribute' the .offsetof to each of the tuple elements.
5064 TupleExp *te = (TupleExp *)e1;
5065 Expressions *exps = new Expressions();
5066 exps->setDim(te->exps->dim);
5067 for (int i = 0; i < exps->dim; i++)
5068 { Expression *e = (Expression *)te->exps->data[i];
5069 e = e->semantic(sc);
5070 e = new DotIdExp(e->loc, e, Id::offsetof);
5071 exps->data[i] = (void *)e;
5073 e = new TupleExp(loc, exps);
5074 e = e->semantic(sc);
5075 return e;
5078 if (e1->op == TOKtuple && ident == Id::length)
5080 TupleExp *te = (TupleExp *)e1;
5081 e = new IntegerExp(loc, te->exps->dim, Type::tsize_t);
5082 return e;
5085 if (eright->op == TOKimport) // also used for template alias's
5087 Dsymbol *s;
5088 ScopeExp *ie = (ScopeExp *)eright;
5090 s = ie->sds->search(loc, ident, 0);
5091 if (s)
5093 s = s->toAlias();
5094 checkDeprecated(sc, s);
5096 EnumMember *em = s->isEnumMember();
5097 if (em)
5099 e = em->value;
5100 e = e->semantic(sc);
5101 return e;
5104 VarDeclaration *v = s->isVarDeclaration();
5105 if (v)
5107 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
5108 if (v->inuse)
5110 error("circular reference to '%s'", v->toChars());
5111 type = Type::tint32;
5112 return this;
5114 type = v->type;
5115 #if 0
5116 if (v->isConst() || v->isInvariant())
5118 if (v->init)
5120 ExpInitializer *ei = v->init->isExpInitializer();
5121 if (ei)
5123 //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars());
5124 //ei->exp = ei->exp->semantic(sc);
5125 if (ei->exp->type == type)
5127 e = ei->exp->copy(); // make copy so we can change loc
5128 e->loc = loc;
5129 return e;
5133 else if (type->isscalar())
5135 e = type->defaultInit();
5136 e->loc = loc;
5137 return e;
5140 #endif
5141 if (v->needThis())
5143 if (!eleft)
5144 eleft = new ThisExp(loc);
5145 e = new DotVarExp(loc, eleft, v);
5146 e = e->semantic(sc);
5148 else
5150 e = new VarExp(loc, v);
5151 if (eleft)
5152 { e = new CommaExp(loc, eleft, e);
5153 e->type = v->type;
5156 return e->deref();
5159 FuncDeclaration *f = s->isFuncDeclaration();
5160 if (f)
5162 //printf("it's a function\n");
5163 if (f->needThis())
5165 if (!eleft)
5166 eleft = new ThisExp(loc);
5167 e = new DotVarExp(loc, eleft, f);
5168 e = e->semantic(sc);
5170 else
5172 e = new VarExp(loc, f, 1);
5173 if (eleft)
5174 { e = new CommaExp(loc, eleft, e);
5175 e->type = f->type;
5178 return e;
5181 Type *t = s->getType();
5182 if (t)
5184 return new TypeExp(loc, t);
5187 TupleDeclaration *tup = s->isTupleDeclaration();
5188 if (tup)
5190 if (eleft)
5191 error("cannot have e.tuple");
5192 e = new TupleExp(loc, tup);
5193 e = e->semantic(sc);
5194 return e;
5197 ScopeDsymbol *sds = s->isScopeDsymbol();
5198 if (sds)
5200 //printf("it's a ScopeDsymbol\n");
5201 e = new ScopeExp(loc, sds);
5202 e = e->semantic(sc);
5203 if (eleft)
5204 e = new DotExp(loc, eleft, e);
5205 return e;
5208 Import *imp = s->isImport();
5209 if (imp)
5211 ScopeExp *ie;
5213 ie = new ScopeExp(loc, imp->pkg);
5214 return ie->semantic(sc);
5217 // BUG: handle other cases like in IdentifierExp::semantic()
5218 #ifdef DEBUG
5219 printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind());
5220 #endif
5221 assert(0);
5223 else if (ident == Id::stringof)
5224 { char *s = ie->toChars();
5225 e = new StringExp(loc, s, strlen(s), 'c');
5226 e = e->semantic(sc);
5227 return e;
5229 error("undefined identifier %s", toChars());
5230 type = Type::tvoid;
5231 return this;
5233 else if (e1->type->ty == Tpointer &&
5234 ident != Id::init && ident != Id::__sizeof &&
5235 ident != Id::alignof && ident != Id::offsetof &&
5236 ident != Id::mangleof && ident != Id::stringof)
5238 e = new PtrExp(loc, e1);
5239 e->type = ((TypePointer *)e1->type)->next;
5240 return e->type->dotExp(sc, e, ident);
5242 else
5244 e = e1->type->dotExp(sc, e1, ident);
5245 e = e->semantic(sc);
5246 return e;
5250 void DotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5252 //printf("DotIdExp::toCBuffer()\n");
5253 expToCBuffer(buf, hgs, e1, PREC_primary);
5254 buf->writeByte('.');
5255 buf->writestring(ident->toChars());
5258 /********************** DotTemplateExp ***********************************/
5260 // Mainly just a placeholder
5262 DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td)
5263 : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e)
5266 this->td = td;
5269 void DotTemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5271 expToCBuffer(buf, hgs, e1, PREC_primary);
5272 buf->writeByte('.');
5273 buf->writestring(td->toChars());
5277 /************************************************************/
5279 DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v, int hasOverloads)
5280 : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e)
5282 //printf("DotVarExp()\n");
5283 this->var = v;
5284 this->hasOverloads = hasOverloads;
5287 Expression *DotVarExp::semantic(Scope *sc)
5289 #if LOGSEMANTIC
5290 printf("DotVarExp::semantic('%s')\n", toChars());
5291 #endif
5292 if (!type)
5294 var = var->toAlias()->isDeclaration();
5296 TupleDeclaration *tup = var->isTupleDeclaration();
5297 if (tup)
5298 { /* Replace:
5299 * e1.tuple(a, b, c)
5300 * with:
5301 * tuple(e1.a, e1.b, e1.c)
5303 Expressions *exps = new Expressions;
5305 exps->reserve(tup->objects->dim);
5306 for (size_t i = 0; i < tup->objects->dim; i++)
5307 { Object *o = (Object *)tup->objects->data[i];
5308 if (o->dyncast() != DYNCAST_EXPRESSION)
5310 error("%s is not an expression", o->toChars());
5312 else
5314 Expression *e = (Expression *)o;
5315 if (e->op != TOKdsymbol)
5316 error("%s is not a member", e->toChars());
5317 else
5318 { DsymbolExp *ve = (DsymbolExp *)e;
5320 e = new DotVarExp(loc, e1, ve->s->isDeclaration());
5321 exps->push(e);
5325 Expression *e = new TupleExp(loc, exps);
5326 e = e->semantic(sc);
5327 return e;
5330 e1 = e1->semantic(sc);
5332 type = var->type;
5333 if (!type && global.errors)
5334 { // var is goofed up, just return 0
5335 return new IntegerExp(0);
5337 assert(type);
5339 if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution
5341 Type *t1 = e1->type;
5342 if (t1->ty == Tpointer)
5343 t1 = t1->nextOf();
5344 if (t1->isConst())
5345 type = type->constOf();
5346 else if (t1->isInvariant())
5347 type = type->invariantOf();
5349 AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration();
5350 e1 = getRightThis(loc, sc, ad, e1, var);
5351 if (!sc->noaccesscheck)
5352 accessCheck(loc, sc, e1, var);
5355 //printf("-DotVarExp::semantic('%s')\n", toChars());
5356 return this;
5359 Expression *DotVarExp::toLvalue(Scope *sc, Expression *e)
5361 //printf("DotVarExp::toLvalue(%s)\n", toChars());
5362 return this;
5365 Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
5367 #if 0
5368 printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
5369 printf("e1->type = %s\n", e1->type->toChars());
5370 printf("var->type = %s\n", var->type->toChars());
5371 #endif
5373 // Also need this for non-null fields.
5374 VarDeclaration *v = var->isVarDeclaration();
5375 if (v) // When is it not a VarDeclaration?
5376 v->ctorinit = 1;
5377 else
5378 error("Just curious");
5380 if (var->isCtorinit())
5381 { // It's only modifiable if inside the right constructor
5382 Dsymbol *s = sc->func;
5383 while (1)
5385 FuncDeclaration *fd = NULL;
5386 if (s)
5387 fd = s->isFuncDeclaration();
5388 if (fd &&
5389 ((fd->isCtorDeclaration() && var->storage_class & STCfield) ||
5390 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) &&
5391 fd->toParent() == var->toParent() &&
5392 e1->op == TOKthis
5395 VarDeclaration *v = var->isVarDeclaration();
5396 assert(v);
5397 v->ctorinit = 1;
5398 //printf("setting ctorinit\n");
5400 else
5402 if (s)
5403 { s = s->toParent2();
5404 continue;
5406 else
5408 const char *p = var->isStatic() ? "static " : "";
5409 error("can only initialize %sconst member %s inside %sconstructor",
5410 p, var->toChars(), p);
5413 break;
5416 else
5418 Type *t1 = e1->type->toBasetype();
5420 if (!t1->isMutable() ||
5421 (t1->ty == Tpointer && !t1->nextOf()->isMutable()) ||
5422 !var->type->isMutable() ||
5423 !var->type->isAssignable() ||
5424 var->storage_class & STCmanifest
5426 error("cannot modify const/invariant %s", toChars());
5428 return this;
5431 void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5433 expToCBuffer(buf, hgs, e1, PREC_primary);
5434 buf->writeByte('.');
5435 buf->writestring(var->toChars());
5438 /************************************************************/
5440 /* Things like:
5441 * foo.bar!(args)
5444 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti)
5445 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e)
5447 //printf("DotTemplateInstanceExp()\n");
5448 this->ti = ti;
5451 Expression *DotTemplateInstanceExp::syntaxCopy()
5453 DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc,
5454 e1->syntaxCopy(),
5455 (TemplateInstance *)ti->syntaxCopy(NULL));
5456 return de;
5459 Expression *DotTemplateInstanceExp::semantic(Scope *sc)
5460 { Dsymbol *s;
5461 Dsymbol *s2;
5462 TemplateDeclaration *td;
5463 Expression *e;
5464 Identifier *id;
5465 Type *t1;
5466 Expression *eleft = NULL;
5467 Expression *eright;
5469 #if LOGSEMANTIC
5470 printf("DotTemplateInstanceExp::semantic('%s')\n", toChars());
5471 #endif
5472 //e1->print();
5473 //print();
5474 e1 = e1->semantic(sc);
5475 t1 = e1->type;
5476 if (t1)
5477 t1 = t1->toBasetype();
5478 //t1->print();
5480 /* Extract the following from e1:
5481 * s: the symbol which ti should be a member of
5482 * eleft: if not NULL, it is the 'this' pointer for ti
5485 if (e1->op == TOKdotexp)
5486 { DotExp *de = (DotExp *)e1;
5487 eleft = de->e1;
5488 eright = de->e2;
5490 else
5491 { eleft = NULL;
5492 eright = e1;
5494 if (eright->op == TOKimport)
5496 s = ((ScopeExp *)eright)->sds;
5498 else if (e1->op == TOKtype)
5500 s = t1->isClassHandle();
5501 if (!s)
5502 { if (t1->ty == Tstruct)
5503 s = ((TypeStruct *)t1)->sym;
5504 else
5505 goto L1;
5508 else if (t1 && (t1->ty == Tstruct || t1->ty == Tclass))
5510 s = t1->toDsymbol(sc);
5511 eleft = e1;
5513 else if (t1 && t1->ty == Tpointer)
5515 t1 = ((TypePointer *)t1)->next->toBasetype();
5516 if (t1->ty != Tstruct)
5517 goto L1;
5518 s = t1->toDsymbol(sc);
5519 eleft = e1;
5521 else
5524 error("template %s is not a member of %s", ti->toChars(), e1->toChars());
5525 goto Lerr;
5528 assert(s);
5529 id = ti->name;
5530 s2 = s->search(loc, id, 0);
5531 if (!s2)
5532 { error("template identifier %s is not a member of %s %s", id->toChars(), s->kind(), s->ident->toChars());
5533 goto Lerr;
5535 s = s2;
5536 s->semantic(sc);
5537 s = s->toAlias();
5538 td = s->isTemplateDeclaration();
5539 if (!td)
5541 error("%s is not a template", id->toChars());
5542 goto Lerr;
5544 if (global.errors)
5545 goto Lerr;
5547 ti->tempdecl = td;
5549 if (eleft)
5550 { Declaration *v;
5552 ti->semantic(sc);
5553 s = ti->inst->toAlias();
5554 v = s->isDeclaration();
5555 if (v)
5556 { e = new DotVarExp(loc, eleft, v);
5557 e = e->semantic(sc);
5558 return e;
5562 e = new ScopeExp(loc, ti);
5563 if (eleft)
5565 e = new DotExp(loc, eleft, e);
5567 e = e->semantic(sc);
5568 return e;
5570 Lerr:
5571 return new IntegerExp(0);
5574 void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5576 expToCBuffer(buf, hgs, e1, PREC_primary);
5577 buf->writeByte('.');
5578 ti->toCBuffer(buf, hgs);
5581 /************************************************************/
5583 DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f, int hasOverloads)
5584 : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
5586 this->func = f;
5587 this->hasOverloads = hasOverloads;
5590 Expression *DelegateExp::semantic(Scope *sc)
5592 #if LOGSEMANTIC
5593 printf("DelegateExp::semantic('%s')\n", toChars());
5594 #endif
5595 if (!type)
5597 e1 = e1->semantic(sc);
5598 type = new TypeDelegate(func->type);
5599 type = type->semantic(loc, sc);
5600 AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration();
5601 if (func->needThis())
5602 e1 = getRightThis(loc, sc, ad, e1, func);
5604 return this;
5607 void DelegateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5609 buf->writeByte('&');
5610 if (!func->isNested())
5612 expToCBuffer(buf, hgs, e1, PREC_primary);
5613 buf->writeByte('.');
5615 buf->writestring(func->toChars());
5618 /************************************************************/
5620 DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s)
5621 : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e)
5623 this->sym = s;
5624 this->type = s->getType();
5627 Expression *DotTypeExp::semantic(Scope *sc)
5629 #if LOGSEMANTIC
5630 printf("DotTypeExp::semantic('%s')\n", toChars());
5631 #endif
5632 UnaExp::semantic(sc);
5633 return this;
5636 void DotTypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5638 expToCBuffer(buf, hgs, e1, PREC_primary);
5639 buf->writeByte('.');
5640 buf->writestring(sym->toChars());
5643 /************************************************************/
5645 CallExp::CallExp(Loc loc, Expression *e, Expressions *exps)
5646 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5648 this->arguments = exps;
5651 CallExp::CallExp(Loc loc, Expression *e)
5652 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5654 this->arguments = NULL;
5657 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1)
5658 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5660 Expressions *arguments = new Expressions();
5661 arguments->setDim(1);
5662 arguments->data[0] = (void *)earg1;
5664 this->arguments = arguments;
5667 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2)
5668 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5670 Expressions *arguments = new Expressions();
5671 arguments->setDim(2);
5672 arguments->data[0] = (void *)earg1;
5673 arguments->data[1] = (void *)earg2;
5675 this->arguments = arguments;
5678 Expression *CallExp::syntaxCopy()
5680 return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
5684 Expression *CallExp::semantic(Scope *sc)
5686 TypeFunction *tf;
5687 FuncDeclaration *f;
5688 int i;
5689 Type *t1;
5690 int istemp;
5691 Objects *targsi = NULL; // initial list of template arguments
5693 #if LOGSEMANTIC
5694 printf("CallExp::semantic() %s\n", toChars());
5695 e1->dump(0);
5696 #endif
5697 if (type)
5698 return this; // semantic() already run
5699 #if 0
5700 if (arguments && arguments->dim)
5702 Expression *earg = (Expression *)arguments->data[0];
5703 earg->print();
5704 if (earg->type) earg->type->print();
5706 #endif
5708 if (e1->op == TOKdelegate)
5709 { DelegateExp *de = (DelegateExp *)e1;
5711 e1 = new DotVarExp(de->loc, de->e1, de->func);
5712 return semantic(sc);
5715 /* Transform:
5716 * array.id(args) into id(array,args)
5717 * aa.remove(arg) into delete aa[arg]
5719 if (e1->op == TOKdot)
5721 // BUG: we should handle array.a.b.c.e(args) too
5723 DotIdExp *dotid = (DotIdExp *)(e1);
5724 dotid->e1 = dotid->e1->semantic(sc);
5725 assert(dotid->e1);
5726 if (dotid->e1->type)
5728 TY e1ty = dotid->e1->type->toBasetype()->ty;
5729 if (e1ty == Taarray && dotid->ident == Id::remove)
5731 if (!arguments || arguments->dim != 1)
5732 { error("expected key as argument to aa.remove()");
5733 goto Lagain;
5735 Expression *key = (Expression *)arguments->data[0];
5736 key = key->semantic(sc);
5737 key = resolveProperties(sc, key);
5738 key->rvalue();
5740 TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype();
5741 key = key->implicitCastTo(sc, taa->index);
5743 return new RemoveExp(loc, dotid->e1, key);
5745 else if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray)
5747 if (!arguments)
5748 arguments = new Expressions();
5749 arguments->shift(dotid->e1);
5750 e1 = new IdentifierExp(dotid->loc, dotid->ident);
5755 /* This recognizes:
5756 * foo!(tiargs)(funcargs)
5758 if (e1->op == TOKimport && !e1->type)
5759 { ScopeExp *se = (ScopeExp *)e1;
5760 TemplateInstance *ti = se->sds->isTemplateInstance();
5761 if (ti && !ti->semanticdone)
5763 /* Attempt to instantiate ti. If that works, go with it.
5764 * If not, go with partial explicit specialization.
5766 unsigned errors = global.errors;
5767 global.gag++;
5768 ti->semantic(sc);
5769 global.gag--;
5770 if (errors != global.errors)
5772 global.errors = errors;
5773 targsi = ti->tiargs;
5774 e1 = new IdentifierExp(loc, ti->name);
5779 /* This recognizes:
5780 * expr.foo!(tiargs)(funcargs)
5782 if (e1->op == TOKdotti && !e1->type)
5783 { DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1;
5784 TemplateInstance *ti = se->ti;
5785 if (!ti->semanticdone)
5787 /* Attempt to instantiate ti. If that works, go with it.
5788 * If not, go with partial explicit specialization.
5790 Expression *etmp;
5791 unsigned errors = global.errors;
5792 global.gag++;
5793 etmp = e1->semantic(sc);
5794 global.gag--;
5795 if (errors != global.errors)
5797 global.errors = errors;
5798 targsi = ti->tiargs;
5799 e1 = new DotIdExp(loc, se->e1, ti->name);
5801 else
5802 e1 = etmp;
5806 istemp = 0;
5807 Lagain:
5808 //printf("Lagain: %s\n", toChars());
5809 f = NULL;
5810 if (e1->op == TOKthis || e1->op == TOKsuper)
5812 // semantic() run later for these
5814 else
5816 UnaExp::semantic(sc);
5818 /* Look for e1 being a lazy parameter
5820 if (e1->op == TOKvar)
5821 { VarExp *ve = (VarExp *)e1;
5823 if (ve->var->storage_class & STClazy)
5825 TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd);
5826 TypeDelegate *t = new TypeDelegate(tf);
5827 ve->type = t->semantic(loc, sc);
5831 if (e1->op == TOKimport)
5832 { // Perhaps this should be moved to ScopeExp::semantic()
5833 ScopeExp *se = (ScopeExp *)e1;
5834 e1 = new DsymbolExp(loc, se->sds);
5835 e1 = e1->semantic(sc);
5837 #if 1 // patch for #540 by Oskar Linde
5838 else if (e1->op == TOKdotexp)
5840 DotExp *de = (DotExp *) e1;
5842 if (de->e2->op == TOKimport)
5843 { // This should *really* be moved to ScopeExp::semantic()
5844 ScopeExp *se = (ScopeExp *)de->e2;
5845 de->e2 = new DsymbolExp(loc, se->sds);
5846 de->e2 = de->e2->semantic(sc);
5849 if (de->e2->op == TOKtemplate)
5850 { TemplateExp *te = (TemplateExp *) de->e2;
5851 e1 = new DotTemplateExp(loc,de->e1,te->td);
5854 #endif
5857 if (e1->op == TOKcomma)
5859 CommaExp *ce = (CommaExp *)e1;
5861 e1 = ce->e2;
5862 e1->type = ce->type;
5863 ce->e2 = this;
5864 ce->type = NULL;
5865 return ce->semantic(sc);
5868 t1 = NULL;
5869 if (e1->type)
5870 t1 = e1->type->toBasetype();
5872 // Check for call operator overload
5873 if (t1)
5874 { AggregateDeclaration *ad;
5876 if (t1->ty == Tstruct)
5878 ad = ((TypeStruct *)t1)->sym;
5879 if (search_function(ad, Id::call))
5880 goto L1; // overload of opCall, therefore it's a call
5882 if (e1->op != TOKtype)
5883 error("%s %s does not overload ()", ad->kind(), ad->toChars());
5884 /* It's a struct literal
5886 Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments);
5887 e = e->semantic(sc);
5888 e->type = e1->type; // in case e1->type was a typedef
5889 return e;
5891 else if (t1->ty == Tclass)
5893 ad = ((TypeClass *)t1)->sym;
5894 goto L1;
5896 // Rewrite as e1.call(arguments)
5897 Expression *e = new DotIdExp(loc, e1, Id::call);
5898 e = new CallExp(loc, e, arguments);
5899 e = e->semantic(sc);
5900 return e;
5904 arrayExpressionSemantic(arguments, sc);
5905 preFunctionArguments(loc, sc, arguments);
5907 if (e1->op == TOKdotvar && t1->ty == Tfunction ||
5908 e1->op == TOKdottd)
5910 DotVarExp *dve;
5911 DotTemplateExp *dte;
5912 AggregateDeclaration *ad;
5913 UnaExp *ue = (UnaExp *)(e1);
5915 if (e1->op == TOKdotvar)
5916 { // Do overload resolution
5917 dve = (DotVarExp *)(e1);
5919 f = dve->var->isFuncDeclaration();
5920 assert(f);
5921 f = f->overloadResolve(loc, ue->e1, arguments);
5923 ad = f->toParent()->isAggregateDeclaration();
5925 else
5926 { dte = (DotTemplateExp *)(e1);
5927 TemplateDeclaration *td = dte->td;
5928 assert(td);
5929 if (!arguments)
5930 // Should fix deduceFunctionTemplate() so it works on NULL argument
5931 arguments = new Expressions();
5932 f = td->deduceFunctionTemplate(sc, loc, targsi, ue->e1, arguments);
5933 if (!f)
5934 { type = Type::terror;
5935 return this;
5937 ad = td->toParent()->isAggregateDeclaration();
5939 if (f->needThis())
5940 ue->e1 = getRightThis(loc, sc, ad, ue->e1, f);
5942 checkDeprecated(sc, f);
5943 accessCheck(loc, sc, ue->e1, f);
5944 if (!f->needThis())
5946 VarExp *ve = new VarExp(loc, f);
5947 e1 = new CommaExp(loc, ue->e1, ve);
5948 e1->type = f->type;
5950 else
5952 if (e1->op == TOKdotvar)
5953 dve->var = f;
5954 else
5955 e1 = new DotVarExp(loc, dte->e1, f);
5956 e1->type = f->type;
5957 #if 0
5958 printf("ue->e1 = %s\n", ue->e1->toChars());
5959 printf("f = %s\n", f->toChars());
5960 printf("t = %s\n", t->toChars());
5961 printf("e1 = %s\n", e1->toChars());
5962 printf("e1->type = %s\n", e1->type->toChars());
5963 #endif
5964 // Const member function can take const/invariant/mutable this
5965 if (!(f->type->isConst()))
5967 // Check for const/invariant compatibility
5968 Type *tthis = ue->e1->type->toBasetype();
5969 if (tthis->ty == Tpointer)
5970 tthis = tthis->nextOf()->toBasetype();
5971 if (f->type->isInvariant())
5973 if (tthis->mod != MODinvariant)
5974 error("%s can only be called on an invariant object", e1->toChars());
5976 else
5978 if (tthis->mod != 0)
5979 { //printf("mod = %x\n", tthis->mod);
5980 error("%s can only be called on a mutable object, not %s", e1->toChars(), tthis->toChars());
5984 /* Cannot call mutable method on a final struct
5986 if (tthis->ty == Tstruct &&
5987 ue->e1->op == TOKvar)
5988 { VarExp *v = (VarExp *)ue->e1;
5989 if (v->var->storage_class & STCfinal)
5990 error("cannot call mutable method on final struct");
5994 // See if we need to adjust the 'this' pointer
5995 AggregateDeclaration *ad = f->isThis();
5996 ClassDeclaration *cd = ue->e1->type->isClassHandle();
5997 if (ad && cd && ad->isClassDeclaration() && ad != cd &&
5998 ue->e1->op != TOKsuper)
6000 ue->e1 = ue->e1->castTo(sc, ad->type); //new CastExp(loc, ue->e1, ad->type);
6001 ue->e1 = ue->e1->semantic(sc);
6004 t1 = e1->type;
6006 else if (e1->op == TOKsuper)
6008 // Base class constructor call
6009 ClassDeclaration *cd = NULL;
6011 if (sc->func)
6012 cd = sc->func->toParent()->isClassDeclaration();
6013 if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration())
6015 error("super class constructor call must be in a constructor");
6016 type = Type::terror;
6017 return this;
6019 else
6021 f = cd->baseClass->ctor;
6022 if (!f)
6023 { error("no super class constructor for %s", cd->baseClass->toChars());
6024 type = Type::terror;
6025 return this;
6027 else
6029 #if 0
6030 if (sc->callSuper & (CSXthis | CSXsuper))
6031 error("reference to this before super()");
6032 #endif
6033 if (sc->noctor || sc->callSuper & CSXlabel)
6034 error("constructor calls not allowed in loops or after labels");
6035 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
6036 error("multiple constructor calls");
6037 sc->callSuper |= CSXany_ctor | CSXsuper_ctor;
6039 f = f->overloadResolve(loc, NULL, arguments);
6040 checkDeprecated(sc, f);
6041 e1 = new DotVarExp(e1->loc, e1, f);
6042 e1 = e1->semantic(sc);
6043 t1 = e1->type;
6047 else if (e1->op == TOKthis)
6049 // same class constructor call
6050 ClassDeclaration *cd = NULL;
6052 if (sc->func)
6053 cd = sc->func->toParent()->isClassDeclaration();
6054 if (!cd || !sc->func->isCtorDeclaration())
6056 error("class constructor call must be in a constructor");
6057 type = Type::terror;
6058 return this;
6060 else
6062 #if 0
6063 if (sc->callSuper & (CSXthis | CSXsuper))
6064 error("reference to this before super()");
6065 #endif
6066 if (sc->noctor || sc->callSuper & CSXlabel)
6067 error("constructor calls not allowed in loops or after labels");
6068 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
6069 error("multiple constructor calls");
6070 sc->callSuper |= CSXany_ctor | CSXthis_ctor;
6072 f = cd->ctor;
6073 f = f->overloadResolve(loc, NULL, arguments);
6074 checkDeprecated(sc, f);
6075 e1 = new DotVarExp(e1->loc, e1, f);
6076 e1 = e1->semantic(sc);
6077 t1 = e1->type;
6079 // BUG: this should really be done by checking the static
6080 // call graph
6081 if (f == sc->func)
6082 error("cyclic constructor call");
6085 else if (e1->op == TOKoverloadset)
6087 OverExp *eo = (OverExp *)e1;
6088 FuncDeclaration *f = NULL;
6089 for (int i = 0; i < eo->vars->a.dim; i++)
6090 { Dsymbol *s = (Dsymbol *)eo->vars->a.data[i];
6091 FuncDeclaration *f2 = s->isFuncDeclaration();
6092 if (f2)
6094 f2 = f2->overloadResolve(loc, NULL, arguments, 1);
6096 else
6097 { TemplateDeclaration *td = s->isTemplateDeclaration();
6098 assert(td);
6099 f2 = td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments, 1);
6101 if (f2)
6102 { if (f)
6103 /* Error if match in more than one overload set,
6104 * even if one is a 'better' match than the other.
6106 ScopeDsymbol::multiplyDefined(loc, f, f2);
6107 else
6108 f = f2;
6111 if (!f)
6112 { /* No overload matches, just set f and rely on error
6113 * message being generated later.
6115 f = (FuncDeclaration *)eo->vars->a.data[0];
6117 e1 = new VarExp(loc, f);
6118 goto Lagain;
6120 else if (!t1)
6122 error("function expected before (), not '%s'", e1->toChars());
6123 type = Type::terror;
6124 return this;
6126 else if (t1->ty != Tfunction)
6128 if (t1->ty == Tdelegate)
6129 { TypeDelegate *td = (TypeDelegate *)t1;
6130 assert(td->next->ty == Tfunction);
6131 tf = (TypeFunction *)(td->next);
6132 goto Lcheckargs;
6134 else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction)
6135 { Expression *e;
6137 e = new PtrExp(loc, e1);
6138 t1 = ((TypePointer *)t1)->next;
6139 e->type = t1;
6140 e1 = e;
6142 else if (e1->op == TOKtemplate)
6144 TemplateExp *te = (TemplateExp *)e1;
6145 f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments);
6146 if (!f)
6147 { type = Type::terror;
6148 return this;
6150 if (f->needThis() && hasThis(sc))
6152 // Supply an implicit 'this', as in
6153 // this.ident
6155 e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td);
6156 goto Lagain;
6159 e1 = new VarExp(loc, f);
6160 goto Lagain;
6162 else
6163 { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars());
6164 type = Type::terror;
6165 return this;
6168 else if (e1->op == TOKvar)
6170 // Do overload resolution
6171 VarExp *ve = (VarExp *)e1;
6173 f = ve->var->isFuncDeclaration();
6174 assert(f);
6176 if (ve->hasOverloads)
6177 f = f->overloadResolve(loc, NULL, arguments);
6178 checkDeprecated(sc, f);
6180 if (f->needThis() && hasThis(sc))
6182 // Supply an implicit 'this', as in
6183 // this.ident
6185 e1 = new DotVarExp(loc, new ThisExp(loc), f);
6186 goto Lagain;
6189 accessCheck(loc, sc, NULL, f);
6191 ve->var = f;
6192 // ve->hasOverloads = 0;
6193 ve->type = f->type;
6194 t1 = f->type;
6196 assert(t1->ty == Tfunction);
6197 tf = (TypeFunction *)(t1);
6199 Lcheckargs:
6200 assert(tf->ty == Tfunction);
6201 type = tf->next;
6203 if (!arguments)
6204 arguments = new Expressions();
6205 functionArguments(loc, sc, tf, arguments);
6207 assert(type);
6209 if (f && f->tintro)
6211 Type *t = type;
6212 target_ptrdiff_t offset = 0;
6213 TypeFunction *tf = (TypeFunction *)f->tintro;
6215 if (tf->next->isBaseOf(t, &offset) && offset)
6217 type = tf->next;
6218 return castTo(sc, t);
6222 return this;
6225 int CallExp::checkSideEffect(int flag)
6227 return 1;
6230 int CallExp::canThrow()
6232 return 1;
6235 Expression *CallExp::toLvalue(Scope *sc, Expression *e)
6237 if (type->toBasetype()->ty == Tstruct)
6238 return this;
6239 else
6240 return Expression::toLvalue(sc, e);
6243 void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6244 { int i;
6246 expToCBuffer(buf, hgs, e1, precedence[op]);
6247 buf->writeByte('(');
6248 argsToCBuffer(buf, arguments, hgs);
6249 buf->writeByte(')');
6253 /************************************************************/
6255 AddrExp::AddrExp(Loc loc, Expression *e)
6256 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e)
6260 Expression *AddrExp::semantic(Scope *sc)
6262 #if LOGSEMANTIC
6263 printf("AddrExp::semantic('%s')\n", toChars());
6264 #endif
6265 if (!type)
6267 UnaExp::semantic(sc);
6268 e1 = e1->toLvalue(sc, NULL);
6269 if (!e1->type)
6271 error("cannot take address of %s", e1->toChars());
6272 type = Type::tint32;
6273 return this;
6275 type = e1->type->pointerTo();
6277 // See if this should really be a delegate
6278 if (e1->op == TOKdotvar)
6280 DotVarExp *dve = (DotVarExp *)e1;
6282 FuncDeclaration *f = dve->var->isFuncDeclaration();
6284 if (f)
6286 if (!dve->hasOverloads)
6287 f->tookAddressOf = 1;
6288 Expression *e = new DelegateExp(loc, dve->e1, f, dve->hasOverloads);
6289 e = e->semantic(sc);
6290 return e;
6293 else if (e1->op == TOKvar)
6295 VarExp *ve = (VarExp *)e1;
6297 VarDeclaration *v = ve->var->isVarDeclaration();
6298 if (v && !v->canTakeAddressOf())
6299 error("cannot take address of %s", e1->toChars());
6301 FuncDeclaration *f = ve->var->isFuncDeclaration();
6303 if (f)
6305 if (!ve->hasOverloads)
6306 f->tookAddressOf = 1;
6307 if (f->isNested())
6309 Expression *e = new DelegateExp(loc, e1, f, ve->hasOverloads);
6310 e = e->semantic(sc);
6311 return e;
6313 if (f->needThis() && hasThis(sc))
6315 /* Should probably supply 'this' after overload resolution,
6316 * not before.
6318 Expression *ethis = new ThisExp(loc);
6319 Expression *e = new DelegateExp(loc, ethis, f, ve->hasOverloads);
6320 e = e->semantic(sc);
6321 return e;
6325 return optimize(WANTvalue);
6327 return this;
6330 /************************************************************/
6332 PtrExp::PtrExp(Loc loc, Expression *e)
6333 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
6335 if (e->type)
6336 type = ((TypePointer *)e->type)->next;
6339 PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
6340 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
6342 type = t;
6345 Expression *PtrExp::semantic(Scope *sc)
6346 { Type *tb;
6348 #if LOGSEMANTIC
6349 printf("PtrExp::semantic('%s')\n", toChars());
6350 #endif
6351 if (!type)
6353 UnaExp::semantic(sc);
6354 e1 = resolveProperties(sc, e1);
6355 if (!e1->type)
6356 printf("PtrExp::semantic('%s')\n", toChars());
6357 Expression *e = op_overload(sc);
6358 if (e)
6359 return e;
6360 tb = e1->type->toBasetype();
6361 switch (tb->ty)
6363 case Tpointer:
6364 type = ((TypePointer *)tb)->next;
6365 break;
6367 case Tsarray:
6368 case Tarray:
6369 type = ((TypeArray *)tb)->next;
6370 e1 = e1->castTo(sc, type->pointerTo());
6371 break;
6373 default:
6374 error("can only * a pointer, not a '%s'", e1->type->toChars());
6375 type = Type::tint32;
6376 break;
6378 rvalue();
6380 return this;
6383 Expression *PtrExp::toLvalue(Scope *sc, Expression *e)
6385 #if 0
6386 tym = tybasic(e1->ET->Tty);
6387 if (!(tyscalar(tym) ||
6388 tym == TYstruct ||
6389 tym == TYarray && e->Eoper == TOKaddr))
6390 synerr(EM_lvalue); // lvalue expected
6391 #endif
6392 return this;
6395 Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e)
6397 //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
6399 if (e1->op == TOKsymoff)
6400 { SymOffExp *se = (SymOffExp *)e1;
6401 se->var->checkModify(loc, sc, type);
6402 //return toLvalue(sc, e);
6405 return Expression::modifiableLvalue(sc, e);
6409 void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6411 buf->writeByte('*');
6412 expToCBuffer(buf, hgs, e1, precedence[op]);
6415 /************************************************************/
6417 NegExp::NegExp(Loc loc, Expression *e)
6418 : UnaExp(loc, TOKneg, sizeof(NegExp), e)
6422 Expression *NegExp::semantic(Scope *sc)
6423 { Expression *e;
6425 #if LOGSEMANTIC
6426 printf("NegExp::semantic('%s')\n", toChars());
6427 #endif
6428 if (!type)
6430 UnaExp::semantic(sc);
6431 e1 = resolveProperties(sc, e1);
6432 e = op_overload(sc);
6433 if (e)
6434 return e;
6436 e1->checkNoBool();
6437 e1->checkArithmetic();
6438 type = e1->type;
6440 return this;
6443 /************************************************************/
6445 UAddExp::UAddExp(Loc loc, Expression *e)
6446 : UnaExp(loc, TOKuadd, sizeof(UAddExp), e)
6450 Expression *UAddExp::semantic(Scope *sc)
6451 { Expression *e;
6453 #if LOGSEMANTIC
6454 printf("UAddExp::semantic('%s')\n", toChars());
6455 #endif
6456 assert(!type);
6457 UnaExp::semantic(sc);
6458 e1 = resolveProperties(sc, e1);
6459 e = op_overload(sc);
6460 if (e)
6461 return e;
6462 e1->checkNoBool();
6463 e1->checkArithmetic();
6464 return e1;
6467 /************************************************************/
6469 ComExp::ComExp(Loc loc, Expression *e)
6470 : UnaExp(loc, TOKtilde, sizeof(ComExp), e)
6474 Expression *ComExp::semantic(Scope *sc)
6475 { Expression *e;
6477 if (!type)
6479 UnaExp::semantic(sc);
6480 e1 = resolveProperties(sc, e1);
6481 e = op_overload(sc);
6482 if (e)
6483 return e;
6485 e1->checkNoBool();
6486 e1 = e1->checkIntegral();
6487 type = e1->type;
6489 return this;
6492 /************************************************************/
6494 NotExp::NotExp(Loc loc, Expression *e)
6495 : UnaExp(loc, TOKnot, sizeof(NotExp), e)
6499 Expression *NotExp::semantic(Scope *sc)
6501 UnaExp::semantic(sc);
6502 e1 = resolveProperties(sc, e1);
6503 e1 = e1->checkToBoolean();
6504 type = Type::tboolean;
6505 return this;
6508 int NotExp::isBit()
6510 return TRUE;
6515 /************************************************************/
6517 BoolExp::BoolExp(Loc loc, Expression *e, Type *t)
6518 : UnaExp(loc, TOKtobool, sizeof(BoolExp), e)
6520 type = t;
6523 Expression *BoolExp::semantic(Scope *sc)
6525 UnaExp::semantic(sc);
6526 e1 = resolveProperties(sc, e1);
6527 e1 = e1->checkToBoolean();
6528 type = Type::tboolean;
6529 return this;
6532 int BoolExp::isBit()
6534 return TRUE;
6537 /************************************************************/
6539 DeleteExp::DeleteExp(Loc loc, Expression *e)
6540 : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e)
6544 Expression *DeleteExp::semantic(Scope *sc)
6546 Type *tb;
6548 UnaExp::semantic(sc);
6549 e1 = resolveProperties(sc, e1);
6550 e1 = e1->toLvalue(sc, NULL);
6551 type = Type::tvoid;
6553 tb = e1->type->toBasetype();
6554 switch (tb->ty)
6555 { case Tclass:
6556 { TypeClass *tc = (TypeClass *)tb;
6557 ClassDeclaration *cd = tc->sym;
6559 if (cd->isCOMinterface())
6560 { /* Because COM classes are deleted by IUnknown.Release()
6562 error("cannot delete instance of COM interface %s", cd->toChars());
6564 break;
6566 case Tpointer:
6567 tb = ((TypePointer *)tb)->next->toBasetype();
6568 if (tb->ty == Tstruct)
6570 TypeStruct *ts = (TypeStruct *)tb;
6571 StructDeclaration *sd = ts->sym;
6572 FuncDeclaration *f = sd->aggDelete;
6573 FuncDeclaration *fd = sd->dtor;
6575 if (!f && !fd)
6576 break;
6578 /* Construct:
6579 * ea = copy e1 to a tmp to do side effects only once
6580 * eb = call destructor
6581 * ec = call deallocator
6583 Expression *ea = NULL;
6584 Expression *eb = NULL;
6585 Expression *ec = NULL;
6586 VarDeclaration *v;
6588 if (fd && f)
6589 { Identifier *id = Lexer::idPool("__tmp");
6590 v = new VarDeclaration(loc, e1->type, id, new ExpInitializer(loc, e1));
6591 v->semantic(sc);
6592 v->parent = sc->parent;
6593 ea = new DeclarationExp(loc, v);
6594 ea->type = v->type;
6597 if (fd)
6598 { Expression *e = ea ? new VarExp(loc, v) : e1;
6599 e = new DotVarExp(0, e, fd, 0);
6600 eb = new CallExp(loc, e);
6601 eb = eb->semantic(sc);
6604 if (f)
6606 Type *tpv = Type::tvoid->pointerTo();
6607 Expression *e = ea ? new VarExp(loc, v) : e1->castTo(sc, tpv);
6608 e = new CallExp(loc, new VarExp(loc, f), e);
6609 ec = e->semantic(sc);
6611 ea = combine(ea, eb);
6612 ea = combine(ea, ec);
6613 assert(ea);
6614 return ea;
6616 break;
6618 case Tarray:
6619 /* BUG: look for deleting arrays of structs with dtors.
6621 break;
6623 default:
6624 if (e1->op == TOKindex)
6626 IndexExp *ae = (IndexExp *)(e1);
6627 Type *tb1 = ae->e1->type->toBasetype();
6628 if (tb1->ty == Taarray)
6629 break;
6631 error("cannot delete type %s", e1->type->toChars());
6632 break;
6635 if (e1->op == TOKindex)
6637 IndexExp *ae = (IndexExp *)(e1);
6638 Type *tb1 = ae->e1->type->toBasetype();
6639 if (tb1->ty == Taarray)
6640 { if (!global.params.useDeprecated)
6641 error("delete aa[key] deprecated, use aa.remove(key)");
6645 return this;
6648 int DeleteExp::checkSideEffect(int flag)
6650 return 1;
6653 Expression *DeleteExp::checkToBoolean()
6655 error("delete does not give a boolean result");
6656 return this;
6659 void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6661 buf->writestring("delete ");
6662 expToCBuffer(buf, hgs, e1, precedence[op]);
6665 /************************************************************/
6667 CastExp::CastExp(Loc loc, Expression *e, Type *t)
6668 : UnaExp(loc, TOKcast, sizeof(CastExp), e)
6670 to = t;
6671 this->tok = TOKreserved;
6674 /* For cast(const) and cast(invariant)
6676 CastExp::CastExp(Loc loc, Expression *e, enum TOK tok)
6677 : UnaExp(loc, TOKcast, sizeof(CastExp), e)
6679 to = NULL;
6680 this->tok = tok;
6683 Expression *CastExp::syntaxCopy()
6685 return to ? new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy())
6686 : new CastExp(loc, e1->syntaxCopy(), tok);
6690 Expression *CastExp::semantic(Scope *sc)
6691 { Expression *e;
6692 BinExp *b;
6693 UnaExp *u;
6695 #if LOGSEMANTIC
6696 printf("CastExp::semantic('%s')\n", toChars());
6697 #endif
6699 //static int x; assert(++x < 10);
6701 if (type)
6702 return this;
6703 UnaExp::semantic(sc);
6704 if (e1->type) // if not a tuple
6706 e1 = resolveProperties(sc, e1);
6708 /* Handle cast(const) and cast(invariant)
6710 if (!to)
6711 { if (tok == TOKconst)
6712 to = e1->type->constOf();
6713 else if (tok == TOKinvariant)
6714 to = e1->type->invariantOf();
6715 else
6716 assert(0);
6718 else
6719 to = to->semantic(loc, sc);
6721 e = op_overload(sc);
6722 if (e)
6724 return e->implicitCastTo(sc, to);
6727 Type *tob = to->toBasetype();
6728 if (tob->ty == Tstruct &&
6729 !tob->equals(e1->type->toBasetype()) &&
6730 ((TypeStruct *)to)->sym->search(0, Id::call, 0)
6733 /* Look to replace:
6734 * cast(S)t
6735 * with:
6736 * S(t)
6739 // Rewrite as to.call(e1)
6740 e = new TypeExp(loc, to);
6741 e = new DotIdExp(loc, e, Id::call);
6742 e = new CallExp(loc, e, e1);
6743 e = e->semantic(sc);
6744 return e;
6747 else if (!to)
6748 { error("cannot cast tuple");
6749 to = Type::terror;
6751 if (sc->fromDcode || to->ty != Tclass)
6752 e = e1->castTo(sc, to);
6753 else
6755 // Result is null if "e1" is not an instance of "to"
6756 e = e1->castTo(sc, to->maybe(true));
6758 return e;
6761 int CastExp::checkSideEffect(int flag)
6763 /* if not:
6764 * cast(void)
6765 * cast(classtype)func()
6767 if (!to->equals(Type::tvoid) &&
6768 !(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass))
6769 return Expression::checkSideEffect(flag);
6770 return 1;
6773 void CastExp::checkEscape()
6774 { Type *tb = type->toBasetype();
6775 if (tb->ty == Tarray && e1->op == TOKvar &&
6776 e1->type->toBasetype()->ty == Tsarray)
6777 { VarExp *ve = (VarExp *)e1;
6778 VarDeclaration *v = ve->var->isVarDeclaration();
6779 if (v)
6781 if (!v->isDataseg() && !v->isParameter())
6782 error("escaping reference to local %s", v->toChars());
6787 void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6789 buf->writestring("cast(");
6790 if (to)
6791 to->toCBuffer(buf, NULL, hgs);
6792 else
6793 buf->writestring(Token::tochars[tok]);
6794 buf->writeByte(')');
6795 expToCBuffer(buf, hgs, e1, precedence[op]);
6799 /************************************************************/
6801 SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr)
6802 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1)
6804 this->upr = upr;
6805 this->lwr = lwr;
6806 lengthVar = NULL;
6809 Expression *SliceExp::syntaxCopy()
6811 Expression *lwr = NULL;
6812 if (this->lwr)
6813 lwr = this->lwr->syntaxCopy();
6815 Expression *upr = NULL;
6816 if (this->upr)
6817 upr = this->upr->syntaxCopy();
6819 return new SliceExp(loc, e1->syntaxCopy(), lwr, upr);
6822 Expression *SliceExp::semantic(Scope *sc)
6823 { Expression *e;
6824 AggregateDeclaration *ad;
6825 //FuncDeclaration *fd;
6826 ScopeDsymbol *sym;
6828 #if LOGSEMANTIC
6829 printf("SliceExp::semantic('%s')\n", toChars());
6830 #endif
6831 if (type)
6832 return this;
6834 UnaExp::semantic(sc);
6835 e1 = resolveProperties(sc, e1);
6837 e = this;
6839 Type *t = e1->type->toBasetype();
6840 if (t->ty == Tpointer)
6842 if (!lwr || !upr)
6843 error("need upper and lower bound to slice pointer");
6845 else if (t->ty == Tarray)
6848 else if (t->ty == Tsarray)
6851 else if (t->ty == Tclass)
6853 ad = ((TypeClass *)t)->sym;
6854 goto L1;
6856 else if (t->ty == Tstruct)
6858 ad = ((TypeStruct *)t)->sym;
6861 if (search_function(ad, Id::slice))
6863 // Rewrite as e1.slice(lwr, upr)
6864 e = new DotIdExp(loc, e1, Id::slice);
6866 if (lwr)
6868 assert(upr);
6869 e = new CallExp(loc, e, lwr, upr);
6871 else
6872 { assert(!upr);
6873 e = new CallExp(loc, e);
6875 e = e->semantic(sc);
6876 return e;
6878 goto Lerror;
6880 else if (t->ty == Ttuple)
6882 if (!lwr && !upr)
6883 return e1;
6884 if (!lwr || !upr)
6885 { error("need upper and lower bound to slice tuple");
6886 goto Lerror;
6889 else
6890 goto Lerror;
6892 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
6894 sym = new ArrayScopeSymbol(sc, this);
6895 sym->loc = loc;
6896 sym->parent = sc->scopesym;
6897 sc = sc->push(sym);
6900 if (lwr)
6901 { lwr = lwr->semantic(sc);
6902 lwr = resolveProperties(sc, lwr);
6903 lwr = lwr->implicitCastTo(sc, Type::tsize_t);
6905 if (upr)
6906 { upr = upr->semantic(sc);
6907 upr = resolveProperties(sc, upr);
6908 upr = upr->implicitCastTo(sc, Type::tsize_t);
6911 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
6912 sc->pop();
6914 if (t->ty == Ttuple)
6916 lwr = lwr->optimize(WANTvalue);
6917 upr = upr->optimize(WANTvalue);
6918 uinteger_t i1 = lwr->toUInteger();
6919 uinteger_t i2 = upr->toUInteger();
6921 size_t length;
6922 TupleExp *te;
6923 TypeTuple *tup;
6925 if (e1->op == TOKtuple) // slicing an expression tuple
6926 { te = (TupleExp *)e1;
6927 length = te->exps->dim;
6929 else if (e1->op == TOKtype) // slicing a type tuple
6930 { tup = (TypeTuple *)t;
6931 length = Argument::dim(tup->arguments);
6933 else
6934 assert(0);
6936 if (i1 <= i2 && i2 <= length)
6937 { size_t j1 = (size_t) i1;
6938 size_t j2 = (size_t) i2;
6940 if (e1->op == TOKtuple)
6941 { Expressions *exps = new Expressions;
6942 exps->setDim(j2 - j1);
6943 for (size_t i = 0; i < j2 - j1; i++)
6944 { Expression *e = (Expression *)te->exps->data[j1 + i];
6945 exps->data[i] = (void *)e;
6947 e = new TupleExp(loc, exps);
6949 else
6950 { Arguments *args = new Arguments;
6951 args->reserve(j2 - j1);
6952 for (size_t i = j1; i < j2; i++)
6953 { Argument *arg = Argument::getNth(tup->arguments, i);
6954 args->push(arg);
6956 e = new TypeExp(e1->loc, new TypeTuple(args));
6958 e = e->semantic(sc);
6960 else
6962 error("string slice [%"PRIuMAX" .. %"PRIuMAX"] is out of bounds", i1, i2);
6963 e = e1;
6965 return e;
6968 type = t->nextOf()->arrayOf();
6969 return e;
6971 Lerror:
6972 char *s;
6973 if (t->ty == Tvoid)
6974 s = e1->toChars();
6975 else
6976 s = t->toChars();
6977 error("%s cannot be sliced with []", s);
6978 type = Type::terror;
6979 return e;
6982 void SliceExp::checkEscape()
6984 e1->checkEscape();
6987 Expression *SliceExp::toLvalue(Scope *sc, Expression *e)
6989 return this;
6992 Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e)
6994 error("slice expression %s is not a modifiable lvalue", toChars());
6995 return this;
6998 void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7000 expToCBuffer(buf, hgs, e1, precedence[op]);
7001 buf->writeByte('[');
7002 if (upr || lwr)
7004 if (lwr)
7005 expToCBuffer(buf, hgs, lwr, PREC_assign);
7006 else
7007 buf->writeByte('0');
7008 buf->writestring("..");
7009 if (upr)
7010 expToCBuffer(buf, hgs, upr, PREC_assign);
7011 else
7012 buf->writestring("length"); // BUG: should be array.length
7014 buf->writeByte(']');
7017 /********************** ArrayLength **************************************/
7019 ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1)
7020 : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1)
7024 Expression *ArrayLengthExp::semantic(Scope *sc)
7025 { Expression *e;
7027 #if LOGSEMANTIC
7028 printf("ArrayLengthExp::semantic('%s')\n", toChars());
7029 #endif
7030 if (!type)
7032 UnaExp::semantic(sc);
7033 e1 = resolveProperties(sc, e1);
7035 type = Type::tsize_t;
7037 return this;
7040 void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7042 expToCBuffer(buf, hgs, e1, PREC_primary);
7043 buf->writestring(".length");
7046 /*********************** ArrayExp *************************************/
7048 // e1 [ i1, i2, i3, ... ]
7050 ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args)
7051 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1)
7053 arguments = args;
7056 Expression *ArrayExp::syntaxCopy()
7058 return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
7061 Expression *ArrayExp::semantic(Scope *sc)
7062 { Expression *e;
7063 Type *t1;
7065 #if LOGSEMANTIC
7066 printf("ArrayExp::semantic('%s')\n", toChars());
7067 #endif
7068 UnaExp::semantic(sc);
7069 e1 = resolveProperties(sc, e1);
7071 t1 = e1->type->toBasetype();
7072 if (t1->ty != Tclass && t1->ty != Tstruct)
7073 { // Convert to IndexExp
7074 if (arguments->dim != 1)
7075 error("only one index allowed to index %s", t1->toChars());
7076 e = new IndexExp(loc, e1, (Expression *)arguments->data[0]);
7077 return e->semantic(sc);
7080 // Run semantic() on each argument
7081 for (size_t i = 0; i < arguments->dim; i++)
7082 { e = (Expression *)arguments->data[i];
7084 e = e->semantic(sc);
7085 if (!e->type)
7086 error("%s has no value", e->toChars());
7087 arguments->data[i] = (void *)e;
7090 expandTuples(arguments);
7091 assert(arguments && arguments->dim);
7093 e = op_overload(sc);
7094 if (!e)
7095 { error("no [] operator overload for type %s", e1->type->toChars());
7096 e = e1;
7098 return e;
7102 Expression *ArrayExp::toLvalue(Scope *sc, Expression *e)
7104 if (type && type->toBasetype()->ty == Tvoid)
7105 error("voids have no value");
7106 return this;
7110 void ArrayExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7111 { int i;
7113 expToCBuffer(buf, hgs, e1, PREC_primary);
7114 buf->writeByte('[');
7115 argsToCBuffer(buf, arguments, hgs);
7116 buf->writeByte(']');
7119 /************************* DotExp ***********************************/
7121 DotExp::DotExp(Loc loc, Expression *e1, Expression *e2)
7122 : BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2)
7126 Expression *DotExp::semantic(Scope *sc)
7128 #if LOGSEMANTIC
7129 printf("DotExp::semantic('%s')\n", toChars());
7130 if (type) printf("\ttype = %s\n", type->toChars());
7131 #endif
7132 e1 = e1->semantic(sc);
7133 e2 = e2->semantic(sc);
7134 if (e2->op == TOKimport)
7136 ScopeExp *se = (ScopeExp *)e2;
7137 TemplateDeclaration *td = se->sds->isTemplateDeclaration();
7138 if (td)
7139 { Expression *e = new DotTemplateExp(loc, e1, td);
7140 e = e->semantic(sc);
7141 return e;
7144 if (!type)
7145 type = e2->type;
7146 return this;
7150 /************************* CommaExp ***********************************/
7152 CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2)
7153 : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2)
7157 Expression *CommaExp::semantic(Scope *sc)
7159 if (!type)
7160 { BinExp::semanticp(sc);
7161 type = e2->type;
7163 return this;
7166 void CommaExp::checkEscape()
7168 e2->checkEscape();
7171 Expression *CommaExp::toLvalue(Scope *sc, Expression *e)
7173 e2 = e2->toLvalue(sc, NULL);
7174 return this;
7177 Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e)
7179 e2 = e2->modifiableLvalue(sc, e);
7180 return this;
7183 int CommaExp::isBool(int result)
7185 return e2->isBool(result);
7188 int CommaExp::checkSideEffect(int flag)
7190 if (flag == 2)
7191 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
7192 else
7194 // Don't check e1 until we cast(void) the a,b code generation
7195 return e2->checkSideEffect(flag);
7199 /************************** IndexExp **********************************/
7201 // e1 [ e2 ]
7203 IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2)
7204 : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2)
7206 //printf("IndexExp::IndexExp('%s')\n", toChars());
7207 lengthVar = NULL;
7208 modifiable = 0; // assume it is an rvalue
7211 Expression *IndexExp::semantic(Scope *sc)
7212 { Expression *e;
7213 BinExp *b;
7214 UnaExp *u;
7215 Type *t1;
7216 ScopeDsymbol *sym;
7218 #if LOGSEMANTIC
7219 printf("IndexExp::semantic('%s')\n", toChars());
7220 #endif
7221 if (type)
7222 return this;
7223 if (!e1->type)
7224 e1 = e1->semantic(sc);
7225 assert(e1->type); // semantic() should already be run on it
7226 e = this;
7228 if (e1->type->ty == Tmaybe)
7229 error("Attempt to index %s of type %s, which may be null", e1->toChars(), e1->type->toChars());
7231 // Note that unlike C we do not implement the int[ptr]
7233 t1 = e1->type->toBasetype();
7235 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
7236 { // Create scope for 'length' variable
7237 sym = new ArrayScopeSymbol(sc, this);
7238 sym->loc = loc;
7239 sym->parent = sc->scopesym;
7240 sc = sc->push(sym);
7243 e2 = e2->semantic(sc);
7244 if (!e2->type)
7246 error("%s has no value", e2->toChars());
7247 e2->type = Type::terror;
7249 e2 = resolveProperties(sc, e2);
7251 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
7252 sc = sc->pop();
7254 switch (t1->ty)
7256 case Tpointer:
7257 case Tarray:
7258 e2 = e2->implicitCastTo(sc, Type::tsize_t);
7259 e->type = ((TypeNext *)t1)->next;
7260 break;
7262 case Tsarray:
7264 e2 = e2->implicitCastTo(sc, Type::tsize_t);
7266 TypeSArray *tsa = (TypeSArray *)t1;
7268 #if 0 // Don't do now, because it might be short-circuit evaluated
7269 // Do compile time array bounds checking if possible
7270 e2 = e2->optimize(WANTvalue);
7271 if (e2->op == TOKint64)
7273 integer_t index = e2->toInteger();
7274 integer_t length = tsa->dim->toInteger();
7275 if (index < 0 || index >= length)
7276 error("array index [%lld] is outside array bounds [0 .. %lld]",
7277 index, length);
7279 #endif
7280 e->type = t1->nextOf();
7281 break;
7284 case Taarray:
7285 { TypeAArray *taa = (TypeAArray *)t1;
7287 e2 = e2->implicitCastTo(sc, taa->index); // type checking
7288 type = taa->next;
7289 break;
7292 case Ttuple:
7294 e2 = e2->implicitCastTo(sc, Type::tsize_t);
7295 e2 = e2->optimize(WANTvalue | WANTinterpret);
7296 uinteger_t index = e2->toUInteger();
7297 size_t length;
7298 TupleExp *te;
7299 TypeTuple *tup;
7301 if (e1->op == TOKtuple)
7302 { te = (TupleExp *)e1;
7303 length = te->exps->dim;
7305 else if (e1->op == TOKtype)
7307 tup = (TypeTuple *)t1;
7308 length = Argument::dim(tup->arguments);
7310 else
7311 assert(0);
7313 if (index < length)
7316 if (e1->op == TOKtuple)
7317 e = (Expression *)te->exps->data[(size_t)index];
7318 else
7319 e = new TypeExp(e1->loc, Argument::getNth(tup->arguments, (size_t)index)->type);
7321 else
7323 error("array index [%"PRIuMAX"] is outside array bounds [0 .. %"PRIuSIZE"]",
7324 index, length);
7325 e = e1;
7327 break;
7330 default:
7331 error("%s must be an array or pointer type, not %s",
7332 e1->toChars(), e1->type->toChars());
7333 type = Type::tint32;
7334 break;
7336 return e;
7339 Expression *IndexExp::toLvalue(Scope *sc, Expression *e)
7341 // if (type && type->toBasetype()->ty == Tvoid)
7342 // error("voids have no value");
7343 return this;
7346 Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
7348 //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
7349 modifiable = 1;
7350 if (e1->op == TOKstring)
7351 error("string literals are immutable");
7352 if (type && !type->isMutable())
7353 error("%s isn't mutable", e->toChars());
7354 if (e1->type->toBasetype()->ty == Taarray)
7355 e1 = e1->modifiableLvalue(sc, e1);
7356 return toLvalue(sc, e);
7359 void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7361 expToCBuffer(buf, hgs, e1, PREC_primary);
7362 buf->writeByte('[');
7363 expToCBuffer(buf, hgs, e2, PREC_assign);
7364 buf->writeByte(']');
7368 /************************* PostExp ***********************************/
7370 PostExp::PostExp(enum TOK op, Loc loc, Expression *e)
7371 : BinExp(loc, op, sizeof(PostExp), e,
7372 new IntegerExp(loc, 1, Type::tint32))
7376 Expression *PostExp::semantic(Scope *sc)
7377 { Expression *e = this;
7379 if (!type)
7381 BinExp::semantic(sc);
7382 e2 = resolveProperties(sc, e2);
7384 e = op_overload(sc);
7385 if (e)
7386 return e;
7388 e = this;
7389 e1 = e1->modifiableLvalue(sc, e1);
7390 e1->checkScalar();
7391 e1->checkNoBool();
7392 if (e1->type->ty == Tpointer)
7393 e = scaleFactor(sc);
7394 else
7395 e2 = e2->castTo(sc, e1->type);
7396 e->type = e1->type;
7398 return e;
7401 void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7403 expToCBuffer(buf, hgs, e1, precedence[op]);
7404 buf->writestring((op == TOKplusplus) ? (char *)"++" : (char *)"--");
7407 /************************************************************/
7409 /* op can be TOKassign, TOKconstruct, or TOKblit */
7411 AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2)
7412 : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2)
7414 ismemset = 0;
7417 Expression *AssignExp::semantic(Scope *sc)
7419 Expression *e1old = e1;
7421 #if LOGSEMANTIC
7422 printf("AssignExp::semantic('%s')\n", toChars());
7423 #endif
7424 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
7425 //printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op));
7427 if (type)
7428 return this;
7430 if (e2->op == TOKcomma)
7431 { /* Rewrite to get rid of the comma from rvalue
7433 AssignExp *ea = new AssignExp(loc, e1, ((CommaExp *)e2)->e2);
7434 ea->op = op;
7435 Expression *e = new CommaExp(loc, ((CommaExp *)e2)->e1, ea);
7436 return e->semantic(sc);
7439 /* Look for operator overloading of a[i]=value.
7440 * Do it before semantic() otherwise the a[i] will have been
7441 * converted to a.opIndex() already.
7443 if (e1->op == TOKarray)
7445 ArrayExp *ae = (ArrayExp *)e1;
7446 AggregateDeclaration *ad;
7447 Identifier *id = Id::index;
7449 ae->e1 = ae->e1->semantic(sc);
7450 Type *t1 = ae->e1->type->toBasetype();
7451 if (t1->ty == Tstruct)
7453 ad = ((TypeStruct *)t1)->sym;
7454 goto L1;
7456 else if (t1->ty == Tclass)
7458 ad = ((TypeClass *)t1)->sym;
7460 // Rewrite (a[i] = value) to (a.opIndexAssign(value, i))
7461 if (search_function(ad, Id::indexass))
7462 { Expression *e = new DotIdExp(loc, ae->e1, Id::indexass);
7463 Expressions *a = (Expressions *)ae->arguments->copy();
7465 a->insert(0, e2);
7466 e = new CallExp(loc, e, a);
7467 e = e->semantic(sc);
7468 return e;
7470 else
7472 // Rewrite (a[i] = value) to (a.opIndex(i, value))
7473 if (search_function(ad, id))
7474 { Expression *e = new DotIdExp(loc, ae->e1, id);
7476 if (1 || !global.params.useDeprecated)
7477 error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
7479 e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2);
7480 e = e->semantic(sc);
7481 return e;
7486 /* Look for operator overloading of a[i..j]=value.
7487 * Do it before semantic() otherwise the a[i..j] will have been
7488 * converted to a.opSlice() already.
7490 if (e1->op == TOKslice)
7491 { Type *t1;
7492 SliceExp *ae = (SliceExp *)e1;
7493 AggregateDeclaration *ad;
7494 Identifier *id = Id::index;
7496 ae->e1 = ae->e1->semantic(sc);
7497 ae->e1 = resolveProperties(sc, ae->e1);
7498 t1 = ae->e1->type->toBasetype();
7499 if (t1->ty == Tstruct)
7501 ad = ((TypeStruct *)t1)->sym;
7502 goto L2;
7504 else if (t1->ty == Tclass)
7506 ad = ((TypeClass *)t1)->sym;
7508 // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j))
7509 if (search_function(ad, Id::sliceass))
7510 { Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass);
7511 Expressions *a = new Expressions();
7513 a->push(e2);
7514 if (ae->lwr)
7515 { a->push(ae->lwr);
7516 assert(ae->upr);
7517 a->push(ae->upr);
7519 else
7520 assert(!ae->upr);
7521 e = new CallExp(loc, e, a);
7522 e = e->semantic(sc);
7523 return e;
7528 BinExp::semantic(sc);
7529 e2 = resolveProperties(sc, e2);
7530 assert(e1->type);
7532 /* Rewrite tuple assignment as a tuple of assignments.
7534 if (e1->op == TOKtuple && e2->op == TOKtuple)
7535 { TupleExp *tup1 = (TupleExp *)e1;
7536 TupleExp *tup2 = (TupleExp *)e2;
7537 size_t dim = tup1->exps->dim;
7538 if (dim != tup2->exps->dim)
7540 error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim);
7542 else
7543 { Expressions *exps = new Expressions;
7544 exps->setDim(dim);
7546 for (int i = 0; i < dim; i++)
7547 { Expression *ex1 = (Expression *)tup1->exps->data[i];
7548 Expression *ex2 = (Expression *)tup2->exps->data[i];
7549 exps->data[i] = (void *) new AssignExp(loc, ex1, ex2);
7551 Expression *e = new TupleExp(loc, exps);
7552 e = e->semantic(sc);
7553 return e;
7557 Type *t1 = e1->type->toBasetype();
7559 if (t1->ty == Tfunction)
7560 { // Rewrite f=value to f(value)
7561 Expression *e;
7563 e = new CallExp(loc, e1, e2);
7564 e = e->semantic(sc);
7565 return e;
7568 /* If it is an assignment from a 'foreign' type,
7569 * check for operator overloading.
7571 if (t1->ty == Tstruct)
7573 StructDeclaration *sd = ((TypeStruct *)t1)->sym;
7574 if (op == TOKassign)
7576 Expression *e = op_overload(sc);
7577 if (e)
7578 return e;
7580 else if (op == TOKconstruct)
7581 { Type *t2 = e2->type->toBasetype();
7582 if (t2->ty == Tstruct &&
7583 sd == ((TypeStruct *)t2)->sym &&
7584 sd->cpctor)
7585 { /* We have a copy constructor for this
7587 if (e2->op == TOKvar || e2->op == TOKstar)
7588 { /* Write as:
7589 * e1.cpctor(e2);
7591 Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0);
7592 e = new CallExp(loc, e, e2);
7593 return e->semantic(sc);
7595 else if (e2->op == TOKquestion)
7596 { /* Write as:
7597 * a ? e1 = b : e1 = c;
7599 CondExp *ec = (CondExp *)e2;
7600 AssignExp *ea1 = new AssignExp(ec->e1->loc, e1, ec->e1);
7601 ea1->op = op;
7602 AssignExp *ea2 = new AssignExp(ec->e1->loc, e1, ec->e2);
7603 ea2->op = op;
7604 Expression *e = new CondExp(loc, ec->econd, ea1, ea2);
7605 return e->semantic(sc);
7610 else if (t1->ty == Tclass)
7611 { // Disallow assignment operator overloads for same type
7612 if (!e2->type->implicitConvTo(e1->type))
7614 Expression *e = op_overload(sc);
7615 if (e)
7616 return e;
7620 if (t1->ty == Tsarray)
7622 Expression *e = new SliceExp(e1->loc, e1, NULL, NULL);
7623 e1 = e->semantic(sc);
7624 t1 = e1->type->toBasetype();
7627 e2->rvalue();
7629 if (e1->op == TOKarraylength)
7631 // e1 is not an lvalue, but we let code generator handle it
7632 ArrayLengthExp *ale = (ArrayLengthExp *)e1;
7634 ale->e1 = ale->e1->modifiableLvalue(sc, e1);
7636 else if (e1->op == TOKslice)
7638 Type *tn = e1->type->nextOf();
7639 if (tn && !tn->isMutable() && op != TOKconstruct)
7640 error("slice %s is not mutable", e1->toChars());
7642 else
7643 { // Try to do a decent error message with the expression
7644 // before it got constant folded
7645 if (e1->op != TOKvar)
7646 e1 = e1->optimize(WANTvalue);
7647 if (op != TOKconstruct)
7648 e1 = e1->modifiableLvalue(sc, e1old);
7651 Type *t2 = e2->type;
7652 if (e1->op == TOKslice &&
7653 t1->nextOf() &&
7654 e2->implicitConvTo(t1->nextOf())
7656 { // memset
7657 ismemset = 1; // make it easy for back end to tell what this is
7658 e2 = e2->implicitCastTo(sc, t1->nextOf());
7660 else if (t1->ty == Tsarray)
7662 /* Should have already converted e1 => e1[]
7664 assert(0);
7665 //error("cannot assign to static array %s", e1->toChars());
7667 else if (e1->op == TOKslice)
7669 e2 = e2->implicitCastTo(sc, e1->type->constOf());
7671 else
7673 e2 = e2->implicitCastTo(sc, e1->type);
7675 type = e1->type;
7676 assert(type);
7677 return this;
7680 Expression *AssignExp::checkToBoolean()
7682 // Things like:
7683 // if (a = b) ...
7684 // are usually mistakes.
7686 error("'=' does not give a boolean result");
7687 return this;
7690 /************************************************************/
7692 /* Allow pointer arithmetic on e1? */
7693 static bool allowPtrArith(Scope *sc, Expression *e1)
7695 if (e1->type->ty == Tpointer)
7696 return true;
7697 else if (e1->type->ty == Tmaybe && e1->type->nextOf()->ty == Tpointer)
7699 if (!sc->fromDcode)
7700 e1->error("Can't do pointer arithmetic on pointer ('%s') that could be null",
7701 e1->toChars());
7702 return true;
7704 return false;
7707 AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
7708 : BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
7712 Expression *AddAssignExp::semantic(Scope *sc)
7713 { Expression *e;
7715 if (type)
7716 return this;
7718 BinExp::semantic(sc);
7719 e2 = resolveProperties(sc, e2);
7721 e = op_overload(sc);
7722 if (e)
7723 return e;
7725 e1 = e1->modifiableLvalue(sc, e1);
7727 Type *tb1 = e1->type->toBasetype();
7728 Type *tb2 = e2->type->toBasetype();
7730 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
7731 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
7732 tb1->nextOf()->equals(tb2->nextOf())
7735 type = e1->type;
7736 e = this;
7738 else
7740 e1->checkScalar();
7741 e1->checkNoBool();
7742 if (allowPtrArith(sc, e1) && tb2->isintegral())
7743 e = scaleFactor(sc);
7744 else if (tb1->ty == Tbit || tb1->ty == Tbool)
7746 #if 0
7747 // Need to rethink this
7748 if (e1->op != TOKvar)
7749 { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2
7750 VarDeclaration *v;
7751 Expression *ea;
7752 Expression *ex;
7754 Identifier *id = Lexer::uniqueId("__name");
7756 v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL);
7757 v->semantic(sc);
7758 if (!sc->insert(v))
7759 assert(0);
7760 v->parent = sc->func;
7762 ea = new AddrExp(loc, e1);
7763 ea = new AssignExp(loc, new VarExp(loc, v), ea);
7765 ex = new VarExp(loc, v);
7766 ex = new PtrExp(loc, ex);
7767 e = new AddExp(loc, ex, e2);
7768 e = new CastExp(loc, e, e1->type);
7769 e = new AssignExp(loc, ex->syntaxCopy(), e);
7771 e = new CommaExp(loc, ea, e);
7773 else
7774 #endif
7775 { // Rewrite e1+=e2 to e1=e1+e2
7776 // BUG: doesn't account for side effects in e1
7777 // BUG: other assignment operators for bits aren't handled at all
7778 e = new AddExp(loc, e1, e2);
7779 e = new CastExp(loc, e, e1->type);
7780 e = new AssignExp(loc, e1->syntaxCopy(), e);
7782 e = e->semantic(sc);
7784 else
7786 type = e1->type;
7787 typeCombine(sc);
7788 e1->checkArithmetic();
7789 e2->checkArithmetic();
7790 if (type->isreal() || type->isimaginary())
7792 assert(global.errors || e2->type->isfloating());
7793 e2 = e2->castTo(sc, e1->type);
7795 e = this;
7798 return e;
7801 /************************************************************/
7803 MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
7804 : BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
7808 Expression *MinAssignExp::semantic(Scope *sc)
7809 { Expression *e;
7811 if (type)
7812 return this;
7814 BinExp::semantic(sc);
7815 e2 = resolveProperties(sc, e2);
7817 e = op_overload(sc);
7818 if (e)
7819 return e;
7821 e1 = e1->modifiableLvalue(sc, e1);
7822 e1->checkScalar();
7823 e1->checkNoBool();
7825 if (allowPtrArith(sc, e1) && e2->type->isintegral())
7826 e = scaleFactor(sc);
7827 else
7829 e1 = e1->checkArithmetic();
7830 e2 = e2->checkArithmetic();
7831 type = e1->type;
7832 typeCombine(sc);
7833 if (type->isreal() || type->isimaginary())
7835 assert(e2->type->isfloating());
7836 e2 = e2->castTo(sc, e1->type);
7838 e = this;
7840 return e;
7843 /************************************************************/
7845 CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
7846 : BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
7850 Expression *CatAssignExp::semantic(Scope *sc)
7851 { Expression *e;
7853 BinExp::semantic(sc);
7854 e2 = resolveProperties(sc, e2);
7856 e = op_overload(sc);
7857 if (e)
7858 return e;
7860 if (e1->op == TOKslice)
7861 { SliceExp *se = (SliceExp *)e1;
7863 if (se->e1->type->toBasetype()->ty == Tsarray)
7864 error("cannot append to static array %s", se->e1->type->toChars());
7867 e1 = e1->modifiableLvalue(sc, e1);
7869 Type *tb1 = e1->type->toBasetype();
7870 Type *tb2 = e2->type->toBasetype();
7872 e2->rvalue();
7874 if ((tb1->ty == Tarray) &&
7875 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
7876 (e2->implicitConvTo(e1->type) ||
7877 tb2->nextOf()->implicitConvTo(tb1->nextOf()))
7879 { // Append array
7880 e2 = e2->castTo(sc, e1->type);
7881 type = e1->type;
7882 e = this;
7884 else if ((tb1->ty == Tarray) &&
7885 e2->implicitConvTo(tb1->nextOf())
7887 { // Append element
7888 e2 = e2->castTo(sc, tb1->nextOf());
7889 type = e1->type;
7890 e = this;
7892 else
7894 error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars());
7895 type = Type::tint32;
7896 e = this;
7898 return e;
7901 /************************************************************/
7903 MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
7904 : BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
7908 Expression *MulAssignExp::semantic(Scope *sc)
7909 { Expression *e;
7911 BinExp::semantic(sc);
7912 e2 = resolveProperties(sc, e2);
7914 e = op_overload(sc);
7915 if (e)
7916 return e;
7918 e1 = e1->modifiableLvalue(sc, e1);
7919 e1->checkScalar();
7920 e1->checkNoBool();
7921 type = e1->type;
7922 typeCombine(sc);
7923 e1->checkArithmetic();
7924 e2->checkArithmetic();
7925 if (e2->type->isfloating())
7926 { Type *t1;
7927 Type *t2;
7929 t1 = e1->type;
7930 t2 = e2->type;
7931 if (t1->isreal())
7933 if (t2->isimaginary() || t2->iscomplex())
7935 e2 = e2->castTo(sc, t1);
7938 else if (t1->isimaginary())
7940 if (t2->isimaginary() || t2->iscomplex())
7942 switch (t1->ty)
7944 case Timaginary32: t2 = Type::tfloat32; break;
7945 case Timaginary64: t2 = Type::tfloat64; break;
7946 case Timaginary80: t2 = Type::tfloat80; break;
7947 default:
7948 assert(0);
7950 e2 = e2->castTo(sc, t2);
7954 return this;
7957 /************************************************************/
7959 DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
7960 : BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
7964 Expression *DivAssignExp::semantic(Scope *sc)
7965 { Expression *e;
7967 BinExp::semantic(sc);
7968 e2 = resolveProperties(sc, e2);
7970 e = op_overload(sc);
7971 if (e)
7972 return e;
7974 e1 = e1->modifiableLvalue(sc, e1);
7975 e1->checkScalar();
7976 e1->checkNoBool();
7977 type = e1->type;
7978 typeCombine(sc);
7979 e1->checkArithmetic();
7980 e2->checkArithmetic();
7981 if (e2->type->isimaginary())
7982 { Type *t1;
7983 Type *t2;
7985 t1 = e1->type;
7986 if (t1->isreal())
7987 { // x/iv = i(-x/v)
7988 // Therefore, the result is 0
7989 e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1));
7990 e2->type = t1;
7991 e = new AssignExp(loc, e1, e2);
7992 e->type = t1;
7993 return e;
7995 else if (t1->isimaginary())
7996 { Expression *e;
7998 switch (t1->ty)
8000 case Timaginary32: t2 = Type::tfloat32; break;
8001 case Timaginary64: t2 = Type::tfloat64; break;
8002 case Timaginary80: t2 = Type::tfloat80; break;
8003 default:
8004 assert(0);
8006 e2 = e2->castTo(sc, t2);
8007 e = new AssignExp(loc, e1, e2);
8008 e->type = t1;
8009 return e;
8012 return this;
8015 /************************************************************/
8017 ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
8018 : BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
8022 Expression *ModAssignExp::semantic(Scope *sc)
8024 return commonSemanticAssign(sc);
8027 /************************************************************/
8029 ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
8030 : BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
8034 Expression *ShlAssignExp::semantic(Scope *sc)
8035 { Expression *e;
8037 //printf("ShlAssignExp::semantic()\n");
8038 BinExp::semantic(sc);
8039 e2 = resolveProperties(sc, e2);
8041 e = op_overload(sc);
8042 if (e)
8043 return e;
8045 e1 = e1->modifiableLvalue(sc, e1);
8046 e1->checkScalar();
8047 e1->checkNoBool();
8048 type = e1->type;
8049 typeCombine(sc);
8050 e1->checkIntegral();
8051 e2 = e2->checkIntegral();
8052 e2 = e2->castTo(sc, Type::tshiftcnt);
8053 return this;
8056 /************************************************************/
8058 ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
8059 : BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
8063 Expression *ShrAssignExp::semantic(Scope *sc)
8064 { Expression *e;
8066 BinExp::semantic(sc);
8067 e2 = resolveProperties(sc, e2);
8069 e = op_overload(sc);
8070 if (e)
8071 return e;
8073 e1 = e1->modifiableLvalue(sc, e1);
8074 e1->checkScalar();
8075 e1->checkNoBool();
8076 type = e1->type;
8077 typeCombine(sc);
8078 e1->checkIntegral();
8079 e2 = e2->checkIntegral();
8080 e2 = e2->castTo(sc, Type::tshiftcnt);
8081 return this;
8084 /************************************************************/
8086 UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
8087 : BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
8091 Expression *UshrAssignExp::semantic(Scope *sc)
8092 { Expression *e;
8094 BinExp::semantic(sc);
8095 e2 = resolveProperties(sc, e2);
8097 e = op_overload(sc);
8098 if (e)
8099 return e;
8101 e1 = e1->modifiableLvalue(sc, e1);
8102 e1->checkScalar();
8103 e1->checkNoBool();
8104 type = e1->type;
8105 typeCombine(sc);
8106 e1->checkIntegral();
8107 e2 = e2->checkIntegral();
8108 e2 = e2->castTo(sc, Type::tshiftcnt);
8109 return this;
8112 /************************************************************/
8114 AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
8115 : BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
8119 Expression *AndAssignExp::semantic(Scope *sc)
8121 return commonSemanticAssignIntegral(sc);
8124 /************************************************************/
8126 OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
8127 : BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
8131 Expression *OrAssignExp::semantic(Scope *sc)
8133 return commonSemanticAssignIntegral(sc);
8136 /************************************************************/
8138 XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
8139 : BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
8143 Expression *XorAssignExp::semantic(Scope *sc)
8145 return commonSemanticAssignIntegral(sc);
8148 /************************* AddExp *****************************/
8150 AddExp::AddExp(Loc loc, Expression *e1, Expression *e2)
8151 : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2)
8155 Expression *AddExp::semantic(Scope *sc)
8156 { Expression *e;
8158 #if LOGSEMANTIC
8159 printf("AddExp::semantic('%s')\n", toChars());
8160 #endif
8161 if (!type)
8163 BinExp::semanticp(sc);
8165 e = op_overload(sc);
8166 if (e)
8167 return e;
8169 Type *tb1 = e1->type->toBasetype();
8170 Type *tb2 = e2->type->toBasetype();
8172 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
8173 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
8174 tb1->nextOf()->equals(tb2->nextOf())
8177 type = e1->type;
8178 e = this;
8180 else if (tb1->ty == Tpointer && e2->type->isintegral() ||
8181 tb2->ty == Tpointer && e1->type->isintegral())
8182 e = scaleFactor(sc);
8183 else if (tb1->ty == Tpointer && tb2->ty == Tpointer)
8185 incompatibleTypes();
8186 type = e1->type;
8187 e = this;
8189 else
8191 typeCombine(sc);
8192 if ((e1->type->isreal() && e2->type->isimaginary()) ||
8193 (e1->type->isimaginary() && e2->type->isreal()))
8195 switch (type->toBasetype()->ty)
8197 case Tfloat32:
8198 case Timaginary32:
8199 type = Type::tcomplex32;
8200 break;
8202 case Tfloat64:
8203 case Timaginary64:
8204 type = Type::tcomplex64;
8205 break;
8207 case Tfloat80:
8208 case Timaginary80:
8209 type = Type::tcomplex80;
8210 break;
8212 default:
8213 assert(0);
8216 e = this;
8218 return e;
8220 return this;
8223 /************************************************************/
8225 MinExp::MinExp(Loc loc, Expression *e1, Expression *e2)
8226 : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2)
8230 Expression *MinExp::semantic(Scope *sc)
8231 { Expression *e;
8232 Type *t1;
8233 Type *t2;
8235 #if LOGSEMANTIC
8236 printf("MinExp::semantic('%s')\n", toChars());
8237 #endif
8238 if (type)
8239 return this;
8241 BinExp::semanticp(sc);
8243 e = op_overload(sc);
8244 if (e)
8245 return e;
8247 e = this;
8248 t1 = e1->type->toBasetype();
8249 t2 = e2->type->toBasetype();
8250 if (t1->ty == Tpointer)
8252 if (t2->ty == Tpointer)
8253 { // Need to divide the result by the stride
8254 // Replace (ptr - ptr) with (ptr - ptr) / stride
8255 d_int64 stride;
8256 Expression *e;
8258 typeCombine(sc); // make sure pointer types are compatible
8259 type = Type::tptrdiff_t;
8260 stride = t2->nextOf()->size();
8261 e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
8262 e->type = Type::tptrdiff_t;
8263 return e;
8265 else if (t2->isintegral())
8266 e = scaleFactor(sc);
8267 else
8268 { error("incompatible types for -");
8269 return new IntegerExp(0);
8272 else if (t2->ty == Tpointer)
8274 type = e2->type;
8275 error("can't subtract pointer from %s", e1->type->toChars());
8276 return new IntegerExp(0);
8278 else
8280 typeCombine(sc);
8281 t1 = e1->type->toBasetype();
8282 t2 = e2->type->toBasetype();
8283 if ((t1->isreal() && t2->isimaginary()) ||
8284 (t1->isimaginary() && t2->isreal()))
8286 switch (type->ty)
8288 case Tfloat32:
8289 case Timaginary32:
8290 type = Type::tcomplex32;
8291 break;
8293 case Tfloat64:
8294 case Timaginary64:
8295 type = Type::tcomplex64;
8296 break;
8298 case Tfloat80:
8299 case Timaginary80:
8300 type = Type::tcomplex80;
8301 break;
8303 default:
8304 assert(0);
8308 return e;
8311 /************************* CatExp *****************************/
8313 CatExp::CatExp(Loc loc, Expression *e1, Expression *e2)
8314 : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2)
8318 Expression *CatExp::semantic(Scope *sc)
8319 { Expression *e;
8321 //printf("CatExp::semantic() %s\n", toChars());
8322 if (!type)
8324 BinExp::semanticp(sc);
8325 e = op_overload(sc);
8326 if (e)
8327 return e;
8329 Type *tb1 = e1->type->toBasetype();
8330 Type *tb2 = e2->type->toBasetype();
8333 /* BUG: Should handle things like:
8334 * char c;
8335 * c ~ ' '
8336 * ' ' ~ c;
8339 #if 0
8340 e1->type->print();
8341 e2->type->print();
8342 #endif
8343 if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
8344 e2->type->implicitConvTo(tb1->nextOf()) >= MATCHconst)
8346 type = tb1->nextOf()->arrayOf();
8347 if (tb2->ty == Tarray)
8348 { // Make e2 into [e2]
8349 e2 = new ArrayLiteralExp(e2->loc, e2);
8350 e2->type = type;
8352 return this;
8354 else if ((tb2->ty == Tsarray || tb2->ty == Tarray) &&
8355 e1->type->implicitConvTo(tb2->nextOf()) >= MATCHconst)
8357 type = tb2->nextOf()->arrayOf();
8358 if (tb1->ty == Tarray)
8359 { // Make e1 into [e1]
8360 e1 = new ArrayLiteralExp(e1->loc, e1);
8361 e1->type = type;
8363 return this;
8366 typeCombine(sc);
8367 if (type->ty == Tmaybe)
8368 error("Cannot join arrays that may be null (%s)", toChars());
8370 type = type->toHeadMutable();
8372 Type *tb = type->toBasetype();
8373 if (tb->ty == Tsarray)
8374 type = tb->nextOf()->arrayOf();
8375 if (type->ty == Tarray && tb1->nextOf() && tb2->nextOf() &&
8376 tb1->nextOf()->mod != tb2->nextOf()->mod)
8377 type = type->nextOf()->toHeadMutable()->arrayOf();
8378 #if 0
8379 e1->type->print();
8380 e2->type->print();
8381 type->print();
8382 print();
8383 #endif
8384 Type *t1 = e1->type->toBasetype();
8385 Type *t2 = e2->type->toBasetype();
8386 if (e1->op == TOKstring && e2->op == TOKstring)
8387 e = optimize(WANTvalue);
8388 else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
8389 (t2->ty == Tarray || t2->ty == Tsarray))
8391 e = this;
8393 else
8395 //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars());
8396 error("Can only concatenate arrays, not (%s ~ %s)",
8397 e1->type->toChars(), e2->type->toChars());
8398 type = Type::tint32;
8399 e = this;
8401 e->type = e->type->semantic(loc, sc);
8402 return e;
8404 return this;
8407 /************************************************************/
8409 MulExp::MulExp(Loc loc, Expression *e1, Expression *e2)
8410 : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2)
8414 Expression *MulExp::semantic(Scope *sc)
8415 { Expression *e;
8417 #if 0
8418 printf("MulExp::semantic() %s\n", toChars());
8419 #endif
8420 if (type)
8422 return this;
8425 BinExp::semanticp(sc);
8426 e = op_overload(sc);
8427 if (e)
8428 return e;
8430 typeCombine(sc);
8431 e1->checkArithmetic();
8432 e2->checkArithmetic();
8433 if (type->isfloating())
8434 { Type *t1 = e1->type;
8435 Type *t2 = e2->type;
8437 if (t1->isreal())
8439 type = t2;
8441 else if (t2->isreal())
8443 type = t1;
8445 else if (t1->isimaginary())
8447 if (t2->isimaginary())
8448 { Expression *e;
8450 switch (t1->ty)
8452 case Timaginary32: type = Type::tfloat32; break;
8453 case Timaginary64: type = Type::tfloat64; break;
8454 case Timaginary80: type = Type::tfloat80; break;
8455 default: assert(0);
8458 // iy * iv = -yv
8459 e1->type = type;
8460 e2->type = type;
8461 e = new NegExp(loc, this);
8462 e = e->semantic(sc);
8463 return e;
8465 else
8466 type = t2; // t2 is complex
8468 else if (t2->isimaginary())
8470 type = t1; // t1 is complex
8473 return this;
8476 /************************************************************/
8478 DivExp::DivExp(Loc loc, Expression *e1, Expression *e2)
8479 : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2)
8483 Expression *DivExp::semantic(Scope *sc)
8484 { Expression *e;
8486 if (type)
8487 return this;
8489 BinExp::semanticp(sc);
8490 e = op_overload(sc);
8491 if (e)
8492 return e;
8494 typeCombine(sc);
8495 e1->checkArithmetic();
8496 e2->checkArithmetic();
8497 if (type->isfloating())
8498 { Type *t1 = e1->type;
8499 Type *t2 = e2->type;
8501 if (t1->isreal())
8503 type = t2;
8504 if (t2->isimaginary())
8505 { Expression *e;
8507 // x/iv = i(-x/v)
8508 e2->type = t1;
8509 e = new NegExp(loc, this);
8510 e = e->semantic(sc);
8511 return e;
8514 else if (t2->isreal())
8516 type = t1;
8518 else if (t1->isimaginary())
8520 if (t2->isimaginary())
8522 switch (t1->ty)
8524 case Timaginary32: type = Type::tfloat32; break;
8525 case Timaginary64: type = Type::tfloat64; break;
8526 case Timaginary80: type = Type::tfloat80; break;
8527 default: assert(0);
8530 else
8531 type = t2; // t2 is complex
8533 else if (t2->isimaginary())
8535 type = t1; // t1 is complex
8538 return this;
8541 /************************************************************/
8543 ModExp::ModExp(Loc loc, Expression *e1, Expression *e2)
8544 : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2)
8548 Expression *ModExp::semantic(Scope *sc)
8549 { Expression *e;
8551 if (type)
8552 return this;
8554 BinExp::semanticp(sc);
8555 e = op_overload(sc);
8556 if (e)
8557 return e;
8559 typeCombine(sc);
8560 e1->checkArithmetic();
8561 e2->checkArithmetic();
8562 if (type->isfloating())
8563 { type = e1->type;
8564 if (e2->type->iscomplex())
8565 { error("cannot perform modulo complex arithmetic");
8566 return new IntegerExp(0);
8569 return this;
8572 /************************************************************/
8574 ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2)
8575 : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2)
8579 Expression *ShlExp::semantic(Scope *sc)
8580 { Expression *e;
8582 //printf("ShlExp::semantic(), type = %p\n", type);
8583 if (!type)
8584 { BinExp::semanticp(sc);
8585 e = op_overload(sc);
8586 if (e)
8587 return e;
8588 e1 = e1->checkIntegral();
8589 e2 = e2->checkIntegral();
8590 e1 = e1->integralPromotions(sc);
8591 e2 = e2->castTo(sc, Type::tshiftcnt);
8592 type = e1->type;
8594 return this;
8597 /************************************************************/
8599 ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2)
8600 : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2)
8604 Expression *ShrExp::semantic(Scope *sc)
8605 { Expression *e;
8607 if (!type)
8608 { BinExp::semanticp(sc);
8609 e = op_overload(sc);
8610 if (e)
8611 return e;
8612 e1 = e1->checkIntegral();
8613 e2 = e2->checkIntegral();
8614 e1 = e1->integralPromotions(sc);
8615 e2 = e2->castTo(sc, Type::tshiftcnt);
8616 type = e1->type;
8618 return this;
8621 /************************************************************/
8623 UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2)
8624 : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2)
8628 Expression *UshrExp::semantic(Scope *sc)
8629 { Expression *e;
8631 if (!type)
8632 { BinExp::semanticp(sc);
8633 e = op_overload(sc);
8634 if (e)
8635 return e;
8636 e1 = e1->checkIntegral();
8637 e2 = e2->checkIntegral();
8638 e1 = e1->integralPromotions(sc);
8639 e2 = e2->castTo(sc, Type::tshiftcnt);
8640 type = e1->type;
8642 return this;
8645 /************************************************************/
8647 AndExp::AndExp(Loc loc, Expression *e1, Expression *e2)
8648 : BinExp(loc, TOKand, sizeof(AndExp), e1, e2)
8652 Expression *AndExp::semantic(Scope *sc)
8653 { Expression *e;
8655 if (!type)
8656 { BinExp::semanticp(sc);
8657 e = op_overload(sc);
8658 if (e)
8659 return e;
8660 if (e1->type->toBasetype()->ty == Tbool &&
8661 e2->type->toBasetype()->ty == Tbool)
8663 type = e1->type;
8664 e = this;
8666 else
8668 typeCombine(sc);
8669 e1->checkIntegral();
8670 e2->checkIntegral();
8673 return this;
8676 /************************************************************/
8678 OrExp::OrExp(Loc loc, Expression *e1, Expression *e2)
8679 : BinExp(loc, TOKor, sizeof(OrExp), e1, e2)
8683 Expression *OrExp::semantic(Scope *sc)
8684 { Expression *e;
8686 if (!type)
8687 { BinExp::semanticp(sc);
8688 e = op_overload(sc);
8689 if (e)
8690 return e;
8691 if (e1->type->toBasetype()->ty == Tbool &&
8692 e2->type->toBasetype()->ty == Tbool)
8694 type = e1->type;
8695 e = this;
8697 else
8699 typeCombine(sc);
8700 e1->checkIntegral();
8701 e2->checkIntegral();
8704 return this;
8707 /************************************************************/
8709 XorExp::XorExp(Loc loc, Expression *e1, Expression *e2)
8710 : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2)
8714 Expression *XorExp::semantic(Scope *sc)
8715 { Expression *e;
8717 if (!type)
8718 { BinExp::semanticp(sc);
8719 e = op_overload(sc);
8720 if (e)
8721 return e;
8722 if (e1->type->toBasetype()->ty == Tbool &&
8723 e2->type->toBasetype()->ty == Tbool)
8725 type = e1->type;
8726 e = this;
8728 else
8730 typeCombine(sc);
8731 e1->checkIntegral();
8732 e2->checkIntegral();
8735 return this;
8739 /************************************************************/
8741 OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2)
8742 : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2)
8746 Expression *OrOrExp::semantic(Scope *sc)
8748 unsigned cs1;
8750 // same as for AndAnd
8751 e1 = e1->semantic(sc);
8752 e1 = resolveProperties(sc, e1);
8753 e1 = e1->checkToPointer();
8754 e1 = e1->checkToBoolean();
8755 cs1 = sc->callSuper;
8757 if (sc->flags & SCOPEstaticif)
8759 /* If in static if, don't evaluate e2 if we don't have to.
8761 e1 = e1->optimize(WANTflags);
8762 if (e1->isBool(TRUE))
8764 return new IntegerExp(loc, 1, Type::tboolean);
8768 e2 = e2->semantic(sc);
8769 sc->mergeCallSuper(loc, cs1);
8770 e2 = resolveProperties(sc, e2);
8771 e2 = e2->checkToPointer();
8773 type = Type::tboolean;
8774 if (e1->type->ty == Tvoid)
8775 type = Type::tvoid;
8776 if (e2->op == TOKtype || e2->op == TOKimport)
8777 error("%s is not an expression", e2->toChars());
8778 return this;
8781 Expression *OrOrExp::checkToBoolean()
8783 e2 = e2->checkToBoolean();
8784 return this;
8787 int OrOrExp::isBit()
8789 return TRUE;
8792 int OrOrExp::checkSideEffect(int flag)
8794 if (flag == 2)
8796 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
8798 else
8799 { e1->checkSideEffect(1);
8800 return e2->checkSideEffect(flag);
8804 /************************************************************/
8806 AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2)
8807 : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2)
8811 Expression *AndAndExp::semantic(Scope *sc)
8813 unsigned cs1;
8815 // same as for OrOr
8816 e1 = e1->semantic(sc);
8817 e1 = resolveProperties(sc, e1);
8818 e1 = e1->checkToPointer();
8819 e1 = e1->checkToBoolean();
8820 cs1 = sc->callSuper;
8822 if (sc->flags & SCOPEstaticif)
8824 /* If in static if, don't evaluate e2 if we don't have to.
8826 e1 = e1->optimize(WANTflags);
8827 if (e1->isBool(FALSE))
8829 return new IntegerExp(loc, 0, Type::tboolean);
8833 e2 = e2->semantic(sc);
8834 sc->mergeCallSuper(loc, cs1);
8835 e2 = resolveProperties(sc, e2);
8836 e2 = e2->checkToPointer();
8838 type = Type::tboolean;
8839 if (e1->type->ty == Tvoid)
8840 type = Type::tvoid;
8841 if (e2->op == TOKtype || e2->op == TOKimport)
8842 error("%s is not an expression", e2->toChars());
8843 return this;
8846 Expression *AndAndExp::checkToBoolean()
8848 e2 = e2->checkToBoolean();
8849 return this;
8852 int AndAndExp::isBit()
8854 return TRUE;
8857 int AndAndExp::checkSideEffect(int flag)
8859 if (flag == 2)
8861 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
8863 else
8865 e1->checkSideEffect(1);
8866 return e2->checkSideEffect(flag);
8870 /************************************************************/
8872 InExp::InExp(Loc loc, Expression *e1, Expression *e2)
8873 : BinExp(loc, TOKin, sizeof(InExp), e1, e2)
8877 Expression *InExp::semantic(Scope *sc)
8878 { Expression *e;
8880 if (type)
8881 return this;
8883 BinExp::semanticp(sc);
8884 e = op_overload(sc);
8885 if (e)
8886 return e;
8888 //type = Type::tboolean;
8889 Type *t2b = e2->type->toBasetype();
8890 if (t2b->ty != Taarray)
8892 error("rvalue of in expression must be an associative array, not %s", e2->type->toChars());
8893 type = Type::terror;
8895 else
8897 TypeAArray *ta = (TypeAArray *)t2b;
8899 // Convert key to type of key
8900 e1 = e1->implicitCastTo(sc, ta->index);
8902 // Return type is pointer to value
8903 type = ta->nextOf()->pointerTo();
8904 if (!sc->fromDcode)
8905 type = type->maybe(true);
8907 return this;
8910 int InExp::isBit()
8912 return FALSE;
8916 /************************************************************/
8918 /* This deletes the key e1 from the associative array e2
8921 RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2)
8922 : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2)
8924 type = Type::tvoid;
8927 /************************************************************/
8929 CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
8930 : BinExp(loc, op, sizeof(CmpExp), e1, e2)
8934 Expression *CmpExp::semantic(Scope *sc)
8935 { Expression *e;
8936 Type *t1;
8937 Type *t2;
8939 #if LOGSEMANTIC
8940 printf("CmpExp::semantic('%s')\n", toChars());
8941 #endif
8942 if (type)
8943 return this;
8945 BinExp::semanticp(sc);
8947 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
8948 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
8950 error("do not use null when comparing class types");
8953 e = op_overload(sc);
8954 if (e)
8956 e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32));
8957 e = e->semantic(sc);
8958 return e;
8961 typeCombine(sc);
8962 type = Type::tboolean;
8964 // Special handling for array comparisons
8965 t1 = e1->type->toBasetype();
8966 t2 = e2->type->toBasetype();
8967 if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
8968 (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
8970 if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
8971 t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
8972 (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
8973 error("array comparison type mismatch, %s vs %s", t1->nextOf()->toChars(), t2->nextOf()->toChars());
8974 e = this;
8976 else if (t1->ty == Tstruct || t2->ty == Tstruct ||
8977 (t1->ty == Tclass && t2->ty == Tclass))
8979 if (t2->ty == Tstruct)
8980 error("need member function opCmp() for %s %s to compare", t2->toDsymbol(sc)->kind(), t2->toChars());
8981 else
8982 error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars());
8983 e = this;
8985 #if 1
8986 else if (t1->iscomplex() || t2->iscomplex())
8988 error("compare not defined for complex operands");
8989 e = new IntegerExp(0);
8991 #endif
8992 else
8993 e = this;
8994 //printf("CmpExp: %s\n", e->toChars());
8995 return e;
8998 int CmpExp::isBit()
9000 return TRUE;
9004 /************************************************************/
9006 EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
9007 : BinExp(loc, op, sizeof(EqualExp), e1, e2)
9009 assert(op == TOKequal || op == TOKnotequal);
9012 Expression *EqualExp::semantic(Scope *sc)
9013 { Expression *e;
9014 Type *t1;
9015 Type *t2;
9017 //printf("EqualExp::semantic('%s')\n", toChars());
9018 if (type)
9019 return this;
9021 BinExp::semanticp(sc);
9023 /* Before checking for operator overloading, check to see if we're
9024 * comparing the addresses of two statics. If so, we can just see
9025 * if they are the same symbol.
9027 if (e1->op == TOKaddress && e2->op == TOKaddress)
9028 { AddrExp *ae1 = (AddrExp *)e1;
9029 AddrExp *ae2 = (AddrExp *)e2;
9031 if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar)
9032 { VarExp *ve1 = (VarExp *)ae1->e1;
9033 VarExp *ve2 = (VarExp *)ae2->e1;
9035 if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/)
9037 // They are the same, result is 'true' for ==, 'false' for !=
9038 e = new IntegerExp(loc, (op == TOKequal), Type::tboolean);
9039 return e;
9044 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
9045 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
9047 error("use '%s' instead of '%s' when comparing with null",
9048 Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity),
9049 Token::toChars(op));
9052 //if (e2->op != TOKnull)
9054 e = op_overload(sc);
9055 if (e)
9057 if (op == TOKnotequal)
9059 e = new NotExp(e->loc, e);
9060 e = e->semantic(sc);
9062 return e;
9066 e = typeCombine(sc);
9067 type = Type::tboolean;
9069 // Special handling for array comparisons
9070 t1 = e1->type->toBasetype();
9071 t2 = e2->type->toBasetype();
9073 if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
9074 (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
9076 if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
9077 t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
9078 (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
9079 error("array equality comparison type mismatch, %s vs %s", t1->toChars(), t2->toChars());
9081 else
9083 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
9085 // Cast both to complex
9086 e1 = e1->castTo(sc, Type::tcomplex80);
9087 e2 = e2->castTo(sc, Type::tcomplex80);
9090 return e;
9093 int EqualExp::isBit()
9095 return TRUE;
9100 /************************************************************/
9102 IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
9103 : BinExp(loc, op, sizeof(IdentityExp), e1, e2)
9107 Expression *IdentityExp::semantic(Scope *sc)
9109 if (type)
9110 return this;
9112 BinExp::semanticp(sc);
9113 type = Type::tboolean;
9114 typeCombine(sc);
9115 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
9117 // Cast both to complex
9118 e1 = e1->castTo(sc, Type::tcomplex80);
9119 e2 = e2->castTo(sc, Type::tcomplex80);
9121 return this;
9124 int IdentityExp::isBit()
9126 return TRUE;
9130 /****************************************************************/
9132 CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2)
9133 : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2)
9135 this->econd = econd;
9138 Expression *CondExp::syntaxCopy()
9140 return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy());
9144 Expression *CondExp::semantic(Scope *sc)
9145 { Type *t1;
9146 Type *t2;
9147 unsigned cs0;
9148 unsigned cs1;
9150 #if LOGSEMANTIC
9151 printf("CondExp::semantic('%s')\n", toChars());
9152 #endif
9153 if (type)
9154 return this;
9156 econd = econd->semantic(sc);
9157 econd = resolveProperties(sc, econd);
9158 econd = econd->checkToPointer();
9159 econd = econd->checkToBoolean();
9161 #if 0 /* this cannot work right because the types of e1 and e2
9162 * both contribute to the type of the result.
9164 if (sc->flags & SCOPEstaticif)
9166 /* If in static if, don't evaluate what we don't have to.
9168 econd = econd->optimize(WANTflags);
9169 if (econd->isBool(TRUE))
9171 e1 = e1->semantic(sc);
9172 e1 = resolveProperties(sc, e1);
9173 return e1;
9175 else if (econd->isBool(FALSE))
9177 e2 = e2->semantic(sc);
9178 e2 = resolveProperties(sc, e2);
9179 return e2;
9182 #endif
9185 cs0 = sc->callSuper;
9186 e1 = e1->semantic(sc);
9187 e1 = resolveProperties(sc, e1);
9188 cs1 = sc->callSuper;
9189 sc->callSuper = cs0;
9190 e2 = e2->semantic(sc);
9191 e2 = resolveProperties(sc, e2);
9192 sc->mergeCallSuper(loc, cs1);
9195 // If either operand is void, the result is void
9196 t1 = e1->type;
9197 t2 = e2->type;
9198 if (t1->ty == Tvoid || t2->ty == Tvoid)
9199 type = Type::tvoid;
9200 else if (t1 == t2)
9201 type = t1;
9202 else
9204 typeCombine(sc);
9205 switch (e1->type->toBasetype()->ty)
9207 case Tcomplex32:
9208 case Tcomplex64:
9209 case Tcomplex80:
9210 e2 = e2->castTo(sc, e1->type);
9211 break;
9213 switch (e2->type->toBasetype()->ty)
9215 case Tcomplex32:
9216 case Tcomplex64:
9217 case Tcomplex80:
9218 e1 = e1->castTo(sc, e2->type);
9219 break;
9221 if (type->toBasetype()->ty == Tarray)
9223 e1 = e1->castTo(sc, type);
9224 e2 = e2->castTo(sc, type);
9227 #if 0
9228 printf("res: %s\n", type->toChars());
9229 printf("e1 : %s\n", e1->type->toChars());
9230 printf("e2 : %s\n", e2->type->toChars());
9231 #endif
9232 return this;
9235 Expression *CondExp::toLvalue(Scope *sc, Expression *ex)
9237 PtrExp *e;
9239 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
9240 e = new PtrExp(loc, this, type);
9242 e1 = e1->addressOf(sc);
9243 //e1 = e1->toLvalue(sc, NULL);
9245 e2 = e2->addressOf(sc);
9246 //e2 = e2->toLvalue(sc, NULL);
9248 typeCombine(sc);
9250 type = e2->type;
9251 return e;
9254 Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e)
9256 error("conditional expression %s is not a modifiable lvalue", toChars());
9257 return this;
9260 void CondExp::checkEscape()
9262 e1->checkEscape();
9263 e2->checkEscape();
9267 Expression *CondExp::checkToBoolean()
9269 e1 = e1->checkToBoolean();
9270 e2 = e2->checkToBoolean();
9271 return this;
9274 int CondExp::checkSideEffect(int flag)
9276 if (flag == 2)
9278 return econd->checkSideEffect(2) ||
9279 e1->checkSideEffect(2) ||
9280 e2->checkSideEffect(2);
9282 else
9284 econd->checkSideEffect(1);
9285 e1->checkSideEffect(flag);
9286 return e2->checkSideEffect(flag);
9290 int CondExp::canThrow()
9292 return econd->canThrow() || e1->canThrow() || e2->canThrow();
9296 void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
9298 expToCBuffer(buf, hgs, econd, PREC_oror);
9299 buf->writestring(" ? ");
9300 expToCBuffer(buf, hgs, e1, PREC_expr);
9301 buf->writestring(" : ");
9302 expToCBuffer(buf, hgs, e2, PREC_cond);
9306 /****************************************************************/
9308 DefaultInitExp::DefaultInitExp(Loc loc, enum TOK subop, int size)
9309 : Expression(loc, TOKdefault, size)
9311 this->subop = subop;
9314 void DefaultInitExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
9316 buf->writestring(Token::toChars(subop));
9319 /****************************************************************/
9321 FileInitExp::FileInitExp(Loc loc)
9322 : DefaultInitExp(loc, TOKfile, sizeof(FileInitExp))
9326 Expression *FileInitExp::semantic(Scope *sc)
9328 //printf("FileInitExp::semantic()\n");
9329 type = Type::tchar->invariantOf()->arrayOf();
9330 return this;
9333 Expression *FileInitExp::resolve(Loc loc, Scope *sc)
9335 //printf("FileInitExp::resolve() %s\n", toChars());
9336 char *s = loc.filename ? loc.filename : sc->module->ident->toChars();
9337 Expression *e = new StringExp(loc, s);
9338 e = e->semantic(sc);
9339 e = e->castTo(sc, type);
9340 return e;
9343 /****************************************************************/
9345 LineInitExp::LineInitExp(Loc loc)
9346 : DefaultInitExp(loc, TOKline, sizeof(LineInitExp))
9350 Expression *LineInitExp::semantic(Scope *sc)
9352 type = Type::tint32;
9353 return this;
9356 Expression *LineInitExp::resolve(Loc loc, Scope *sc)
9358 Expression *e = new IntegerExp(loc, loc.linnum, Type::tint32);
9359 e = e->castTo(sc, type);
9360 return e;