Warn about "assert X,Y"
[delight/core.git] / dmd2 / expression.c
blob1adbbd22ae619f2b792fc1e655c18847c3d8d015
2 // Compiler implementation of the D programming language
3 // Copyright (c) 1999-2008 by Digital Mars
4 // All Rights Reserved
5 // written by Walter Bright
6 // http://www.digitalmars.com
7 // License for redistribution is by either the Artistic License
8 // in artistic.txt, or the GNU General Public License in gnu.txt.
9 // See the included readme.txt for details.
11 /* NOTE: This file has been patched from the original DMD distribution to
12 work with the GDC compiler.
14 Modified by David Friedman, December 2006
17 // Issues with using -include total.h (defines integer_t) and then complex.h fails...
18 #undef integer_t
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <ctype.h>
23 #include <assert.h>
24 #include <complex.h>
25 #include <math.h>
27 #ifdef __APPLE__
28 #define integer_t dmd_integer_t
29 #endif
31 #if _WIN32 && __DMC__
32 extern "C" char * __cdecl __locale_decpoint;
33 #endif
35 #if IN_GCC
36 #include "mem.h"
37 #elif _WIN32
38 #include "..\root\mem.h"
39 #elif linux
40 #include "../root/mem.h"
41 #endif
42 //#include "port.h"
43 #include "mtype.h"
44 #include "init.h"
45 #include "expression.h"
46 #include "template.h"
47 #include "utf.h"
48 #include "enum.h"
49 #include "scope.h"
50 #include "statement.h"
51 #include "declaration.h"
52 #include "aggregate.h"
53 #include "import.h"
54 #include "id.h"
55 #include "dsymbol.h"
56 #include "module.h"
57 #include "attrib.h"
58 #include "hdrgen.h"
59 #include "parse.h"
61 Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim);
63 #define LOGSEMANTIC 0
65 /**********************************
66 * Set operator precedence for each operator.
69 // Operator precedence - greater values are higher precedence
71 enum PREC
73 PREC_zero,
74 PREC_expr,
75 PREC_assign,
76 PREC_cond,
77 PREC_oror,
78 PREC_andand,
79 PREC_or,
80 PREC_xor,
81 PREC_and,
82 PREC_equal,
83 PREC_rel,
84 PREC_shift,
85 PREC_add,
86 PREC_mul,
87 PREC_unary,
88 PREC_primary,
91 enum PREC precedence[TOKMAX];
93 void initPrecedence()
95 precedence[TOKdotvar] = PREC_primary;
96 precedence[TOKimport] = PREC_primary;
97 precedence[TOKidentifier] = PREC_primary;
98 precedence[TOKthis] = PREC_primary;
99 precedence[TOKsuper] = PREC_primary;
100 precedence[TOKint64] = PREC_primary;
101 precedence[TOKfloat64] = PREC_primary;
102 precedence[TOKnull] = PREC_primary;
103 precedence[TOKstring] = PREC_primary;
104 precedence[TOKarrayliteral] = PREC_primary;
105 precedence[TOKtypedot] = PREC_primary;
106 precedence[TOKtypeid] = PREC_primary;
107 precedence[TOKis] = PREC_primary;
108 precedence[TOKassert] = PREC_primary;
109 precedence[TOKfunction] = PREC_primary;
110 precedence[TOKvar] = PREC_primary;
111 precedence[TOKdefault] = PREC_primary;
113 // post
114 precedence[TOKdotti] = PREC_primary;
115 precedence[TOKdot] = PREC_primary;
116 // precedence[TOKarrow] = PREC_primary;
117 precedence[TOKplusplus] = PREC_primary;
118 precedence[TOKminusminus] = PREC_primary;
119 precedence[TOKcall] = PREC_primary;
120 precedence[TOKslice] = PREC_primary;
121 precedence[TOKarray] = PREC_primary;
123 precedence[TOKaddress] = PREC_unary;
124 precedence[TOKstar] = PREC_unary;
125 precedence[TOKneg] = PREC_unary;
126 precedence[TOKuadd] = PREC_unary;
127 precedence[TOKnot] = PREC_unary;
128 precedence[TOKtobool] = PREC_add;
129 precedence[TOKtilde] = PREC_unary;
130 precedence[TOKdelete] = PREC_unary;
131 precedence[TOKnew] = PREC_unary;
132 precedence[TOKcast] = PREC_unary;
134 precedence[TOKmul] = PREC_mul;
135 precedence[TOKdiv] = PREC_mul;
136 precedence[TOKmod] = PREC_mul;
138 precedence[TOKadd] = PREC_add;
139 precedence[TOKmin] = PREC_add;
140 precedence[TOKcat] = PREC_add;
142 precedence[TOKshl] = PREC_shift;
143 precedence[TOKshr] = PREC_shift;
144 precedence[TOKushr] = PREC_shift;
146 precedence[TOKlt] = PREC_rel;
147 precedence[TOKle] = PREC_rel;
148 precedence[TOKgt] = PREC_rel;
149 precedence[TOKge] = PREC_rel;
150 precedence[TOKunord] = PREC_rel;
151 precedence[TOKlg] = PREC_rel;
152 precedence[TOKleg] = PREC_rel;
153 precedence[TOKule] = PREC_rel;
154 precedence[TOKul] = PREC_rel;
155 precedence[TOKuge] = PREC_rel;
156 precedence[TOKug] = PREC_rel;
157 precedence[TOKue] = PREC_rel;
158 precedence[TOKin] = PREC_rel;
160 precedence[TOKequal] = PREC_equal;
161 precedence[TOKnotequal] = PREC_equal;
162 precedence[TOKidentity] = PREC_equal;
163 precedence[TOKnotidentity] = PREC_equal;
165 precedence[TOKand] = PREC_and;
167 precedence[TOKxor] = PREC_xor;
169 precedence[TOKor] = PREC_or;
171 precedence[TOKandand] = PREC_andand;
173 precedence[TOKoror] = PREC_oror;
175 precedence[TOKquestion] = PREC_cond;
177 precedence[TOKassign] = PREC_assign;
178 precedence[TOKconstruct] = PREC_assign;
179 precedence[TOKblit] = PREC_assign;
180 precedence[TOKaddass] = PREC_assign;
181 precedence[TOKminass] = PREC_assign;
182 precedence[TOKcatass] = PREC_assign;
183 precedence[TOKmulass] = PREC_assign;
184 precedence[TOKdivass] = PREC_assign;
185 precedence[TOKmodass] = PREC_assign;
186 precedence[TOKshlass] = PREC_assign;
187 precedence[TOKshrass] = PREC_assign;
188 precedence[TOKushrass] = PREC_assign;
189 precedence[TOKandass] = PREC_assign;
190 precedence[TOKorass] = PREC_assign;
191 precedence[TOKxorass] = PREC_assign;
193 precedence[TOKcomma] = PREC_expr;
196 /*************************************************************
197 * Given var, we need to get the
198 * right 'this' pointer if var is in an outer class, but our
199 * existing 'this' pointer is in an inner class.
200 * Input:
201 * e1 existing 'this'
202 * ad struct or class we need the correct 'this' for
203 * var the specific member of ad we're accessing
206 Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
207 Expression *e1, Declaration *var)
210 Type *t = e1->type->toBasetype();
212 /* If e1 is not the 'this' pointer for ad
214 if (ad &&
215 !(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
216 ((TypeStruct *)t->nextOf())->sym == ad)
218 !(t->ty == Tstruct &&
219 ((TypeStruct *)t)->sym == ad)
222 ClassDeclaration *cd = ad->isClassDeclaration();
223 ClassDeclaration *tcd = t->isClassHandle();
225 /* e1 is the right this if ad is a base class of e1
227 if (!cd || !tcd ||
228 !(tcd == cd || cd->isBaseOf(tcd, NULL))
231 /* Only classes can be inner classes with an 'outer'
232 * member pointing to the enclosing class instance
234 if (tcd && tcd->isNested())
235 { /* e1 is the 'this' pointer for an inner class.
236 * Rewrite it as the 'this' pointer for the outer class.
239 e1 = new DotVarExp(loc, e1, tcd->vthis);
240 e1 = e1->semantic(sc);
242 // Skip up over nested functions, and get the enclosing
243 // class type.
244 Dsymbol *s;
245 for (s = tcd->toParent();
246 s && s->isFuncDeclaration();
247 s = s->toParent())
248 { FuncDeclaration *f = s->isFuncDeclaration();
249 if (f->vthis)
251 e1 = new VarExp(loc, f->vthis);
254 if (s && s->isClassDeclaration())
255 e1->type = s->isClassDeclaration()->type;
256 e1 = e1->semantic(sc);
257 goto L1;
260 /* Can't find a path from e1 to ad
262 error("this for %s needs to be type %s not type %s",
263 var->toChars(), ad->toChars(), t->toChars());
266 return e1;
269 /*****************************************
270 * Determine if 'this' is available.
271 * If it is, return the FuncDeclaration that has it.
274 FuncDeclaration *hasThis(Scope *sc)
275 { FuncDeclaration *fd;
276 FuncDeclaration *fdthis;
278 //printf("hasThis()\n");
279 fdthis = sc->parent->isFuncDeclaration();
280 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : "");
282 // Go upwards until we find the enclosing member function
283 fd = fdthis;
284 while (1)
286 if (!fd)
288 goto Lno;
290 if (!fd->isNested())
291 break;
293 Dsymbol *parent = fd->parent;
294 while (parent)
296 TemplateInstance *ti = parent->isTemplateInstance();
297 if (ti)
298 parent = ti->parent;
299 else
300 break;
303 fd = fd->parent->isFuncDeclaration();
306 if (!fd->isThis())
307 { //printf("test '%s'\n", fd->toChars());
308 goto Lno;
311 assert(fd->vthis);
312 return fd;
314 Lno:
315 return NULL; // don't have 'this' available
319 /***************************************
320 * Pull out any properties.
323 Expression *resolveProperties(Scope *sc, Expression *e)
325 //printf("resolveProperties(%s)\n", e->toChars());
326 if (e->type)
328 Type *t = e->type->toBasetype();
330 if (t->ty == Tfunction || e->op == TOKoverloadset)
332 e = new CallExp(e->loc, e);
333 e = e->semantic(sc);
336 /* Look for e being a lazy parameter; rewrite as delegate call
338 else if (e->op == TOKvar)
339 { VarExp *ve = (VarExp *)e;
341 if (ve->var->storage_class & STClazy)
343 e = new CallExp(e->loc, e);
344 e = e->semantic(sc);
348 else if (e->op == TOKdotexp)
350 e->error("expression has no value");
354 return e;
357 /******************************
358 * Perform semantic() on an array of Expressions.
361 void arrayExpressionSemantic(Expressions *exps, Scope *sc)
363 if (exps)
365 for (size_t i = 0; i < exps->dim; i++)
366 { Expression *e = (Expression *)exps->data[i];
368 e = e->semantic(sc);
369 exps->data[i] = (void *)e;
375 /******************************
376 * Perform canThrow() on an array of Expressions.
379 int arrayExpressionCanThrow(Expressions *exps)
381 if (exps)
383 for (size_t i = 0; i < exps->dim; i++)
384 { Expression *e = (Expression *)exps->data[i];
385 if (e && e->canThrow())
386 return 1;
389 return 0;
393 /****************************************
394 * Expand tuples.
397 void expandTuples(Expressions *exps)
399 //printf("expandTuples()\n");
400 if (exps)
402 for (size_t i = 0; i < exps->dim; i++)
403 { Expression *arg = (Expression *)exps->data[i];
404 if (!arg)
405 continue;
407 // Look for tuple with 0 members
408 if (arg->op == TOKtype)
409 { TypeExp *e = (TypeExp *)arg;
410 if (e->type->toBasetype()->ty == Ttuple)
411 { TypeTuple *tt = (TypeTuple *)e->type->toBasetype();
413 if (!tt->arguments || tt->arguments->dim == 0)
415 exps->remove(i);
416 if (i == exps->dim)
417 return;
418 i--;
419 continue;
424 // Inline expand all the tuples
425 while (arg->op == TOKtuple)
426 { TupleExp *te = (TupleExp *)arg;
428 exps->remove(i); // remove arg
429 exps->insert(i, te->exps); // replace with tuple contents
430 if (i == exps->dim)
431 return; // empty tuple, no more arguments
432 arg = (Expression *)exps->data[i];
438 /****************************************
439 * Preprocess arguments to function.
442 void preFunctionArguments(Loc loc, Scope *sc, Expressions *exps)
444 if (exps)
446 expandTuples(exps);
448 for (size_t i = 0; i < exps->dim; i++)
449 { Expression *arg = (Expression *)exps->data[i];
451 if (!arg->type)
453 #ifdef DEBUG
454 if (!global.gag)
455 printf("1: \n");
456 #endif
457 arg->error("%s is not an expression", arg->toChars());
458 arg = new IntegerExp(arg->loc, 0, Type::tint32);
461 arg = resolveProperties(sc, arg);
462 exps->data[i] = (void *) arg;
464 //arg->rvalue();
465 #if 0
466 if (arg->type->ty == Tfunction)
468 arg = new AddrExp(arg->loc, arg);
469 arg = arg->semantic(sc);
470 exps->data[i] = (void *) arg;
472 #endif
477 /*********************************************
478 * Call copy constructor for struct value argument.
481 Expression *callCpCtor(Loc loc, Scope *sc, Expression *e)
483 Type *tb = e->type->toBasetype();
484 assert(tb->ty == Tstruct);
485 StructDeclaration *sd = ((TypeStruct *)tb)->sym;
486 if (sd->cpctor)
488 /* Create a variable tmp, and replace the argument e with:
489 * (tmp = e),tmp
490 * and let AssignExp() handle the construction.
491 * This is not the most efficent, ideally tmp would be constructed
492 * directly onto the stack.
494 Identifier *idtmp = Lexer::uniqueId("__tmp");
495 VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e));
496 Expression *ae = new DeclarationExp(loc, tmp);
497 e = new CommaExp(loc, ae, new VarExp(loc, tmp));
498 e = e->semantic(sc);
500 return e;
503 /****************************************
504 * Now that we know the exact type of the function we're calling,
505 * the arguments[] need to be adjusted:
506 * 1. implicitly convert argument to the corresponding parameter type
507 * 2. add default arguments for any missing arguments
508 * 3. do default promotions on arguments corresponding to ...
509 * 4. add hidden _arguments[] argument
510 * 5. call copy constructor for struct value arguments
513 void functionArguments(Loc loc, Scope *sc, TypeFunction *tf, Expressions *arguments)
515 unsigned n;
517 //printf("functionArguments()\n");
518 assert(arguments);
519 size_t nargs = arguments ? arguments->dim : 0;
520 size_t nparams = Argument::dim(tf->parameters);
522 if (nargs > nparams && tf->varargs == 0)
523 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
525 n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
527 int done = 0;
528 for (size_t i = 0; i < n; i++)
530 Expression *arg;
532 if (i < nargs)
533 arg = (Expression *)arguments->data[i];
534 else
535 arg = NULL;
536 Type *tb;
538 if (i < nparams)
540 Argument *p = Argument::getNth(tf->parameters, i);
542 if (!arg)
544 if (!p->defaultArg)
546 if (tf->varargs == 2 && i + 1 == nparams)
547 goto L2;
548 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
549 break;
551 arg = p->defaultArg;
552 if (arg->op == TOKdefault)
553 { DefaultInitExp *de = (DefaultInitExp *)arg;
554 arg = de->resolve(loc, sc);
556 else
557 arg = arg->copy();
558 arguments->push(arg);
559 nargs++;
562 if (tf->varargs == 2 && i + 1 == nparams)
564 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
565 if (arg->implicitConvTo(p->type))
567 if (nargs != nparams)
568 error(loc, "expected %"PRIuSIZE" arguments, not %"PRIuSIZE, nparams, nargs);
569 goto L1;
572 Type *tb = p->type->toBasetype();
573 Type *tret = p->isLazyArray();
574 switch (tb->ty)
576 case Tsarray:
577 case Tarray:
578 { // Create a static array variable v of type arg->type
579 #ifdef IN_GCC
580 /* GCC 4.0 does not like zero length arrays used like
581 this; pass a null array value instead. Could also
582 just make a one-element array. */
583 if (nargs - i == 0)
585 arg = new NullExp(loc);
586 break;
588 #endif
589 Identifier *id = Lexer::uniqueId("__arrayArg");
590 Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i));
591 t = t->semantic(loc, sc);
592 VarDeclaration *v = new VarDeclaration(loc, t, id, new VoidInitializer(loc));
593 v->semantic(sc);
594 v->parent = sc->parent;
595 //sc->insert(v);
597 Expression *c = new DeclarationExp(0, v);
598 c->type = v->type;
600 for (size_t u = i; u < nargs; u++)
601 { Expression *a = (Expression *)arguments->data[u];
602 if (tret && !((TypeArray *)tb)->next->equals(a->type))
603 a = a->toDelegate(sc, tret);
605 Expression *e = new VarExp(loc, v);
606 e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
607 AssignExp *ae = new AssignExp(loc, e, a);
608 ae->op = TOKconstruct;
609 if (c)
610 c = new CommaExp(loc, c, ae);
611 else
612 c = ae;
614 arg = new VarExp(loc, v);
615 if (c)
616 arg = new CommaExp(loc, c, arg);
617 break;
619 case Tclass:
620 { /* Set arg to be:
621 * new Tclass(arg0, arg1, ..., argn)
623 Expressions *args = new Expressions();
624 args->setDim(nargs - i);
625 for (size_t u = i; u < nargs; u++)
626 args->data[u - i] = arguments->data[u];
627 arg = new NewExp(loc, NULL, NULL, p->type, args);
628 break;
630 default:
631 if (!arg)
632 { error(loc, "not enough arguments");
633 return;
635 break;
637 arg = arg->semantic(sc);
638 //printf("\targ = '%s'\n", arg->toChars());
639 arguments->setDim(i + 1);
640 done = 1;
644 if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
646 if (p->type != arg->type)
648 //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
649 arg = arg->implicitCastTo(sc, p->type);
650 arg = arg->optimize(WANTvalue);
653 if (p->storageClass & STCref)
655 arg = arg->toLvalue(sc, arg);
657 else if (p->storageClass & STCout)
659 arg = arg->modifiableLvalue(sc, arg);
662 // Convert static arrays to pointers
663 tb = arg->type->toBasetype();
664 if (tb->ty == Tsarray)
666 arg = arg->checkToPointer();
669 if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
671 arg = callCpCtor(loc, sc, arg);
674 // Convert lazy argument to a delegate
675 if (p->storageClass & STClazy)
677 arg = arg->toDelegate(sc, p->type);
680 else
683 // If not D linkage, do promotions
684 if (tf->linkage != LINKd)
686 // Promote bytes, words, etc., to ints
687 arg = arg->integralPromotions(sc);
689 // Promote floats to doubles
690 switch (arg->type->ty)
692 case Tfloat32:
693 arg = arg->castTo(sc, Type::tfloat64);
694 break;
696 case Timaginary32:
697 arg = arg->castTo(sc, Type::timaginary64);
698 break;
702 // Convert static arrays to dynamic arrays
703 tb = arg->type->toBasetype();
704 if (tb->ty == Tsarray)
705 { TypeSArray *ts = (TypeSArray *)tb;
706 Type *ta = ts->next->arrayOf();
707 if (ts->size(arg->loc) == 0)
708 { arg = new NullExp(arg->loc);
709 arg->type = ta;
711 else
712 arg = arg->castTo(sc, ta);
715 if (tb->ty == Tstruct)
717 arg = callCpCtor(loc, sc, arg);
720 // Give error for overloaded function addresses
721 if (arg->op == TOKsymoff)
722 { SymOffExp *se = (SymOffExp *)arg;
723 if (se->hasOverloads && !se->var->isFuncDeclaration()->isUnique())
724 arg->error("function %s is overloaded", arg->toChars());
726 arg->rvalue();
729 arg = arg->optimize(WANTvalue);
730 arguments->data[i] = (void *) arg;
731 if (done)
732 break;
735 // If D linkage and variadic, add _arguments[] as first argument
736 if (tf->linkage == LINKd && tf->varargs == 1)
738 Expression *e;
740 e = createTypeInfoArray(sc, (Expression **)&arguments->data[nparams],
741 arguments->dim - nparams);
742 arguments->insert(0, e);
746 /**************************************************
747 * Write expression out to buf, but wrap it
748 * in ( ) if its precedence is less than pr.
751 void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr)
753 //if (precedence[e->op] == 0) e->dump(0);
754 if (precedence[e->op] < pr)
756 buf->writeByte('(');
757 e->toCBuffer(buf, hgs);
758 buf->writeByte(')');
760 else
761 e->toCBuffer(buf, hgs);
764 /**************************************************
765 * Write out argument list to buf.
768 void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
770 if (arguments)
772 for (size_t i = 0; i < arguments->dim; i++)
773 { Expression *arg = (Expression *)arguments->data[i];
775 if (arg)
776 { if (i)
777 buf->writeByte(',');
778 expToCBuffer(buf, hgs, arg, PREC_assign);
784 /**************************************************
785 * Write out argument types to buf.
788 void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
790 if (arguments)
791 { OutBuffer argbuf;
793 for (size_t i = 0; i < arguments->dim; i++)
794 { Expression *arg = (Expression *)arguments->data[i];
796 if (i)
797 buf->writeByte(',');
798 argbuf.reset();
799 arg->type->toCBuffer2(&argbuf, hgs, 0);
800 buf->write(&argbuf);
805 /******************************** Expression **************************/
807 Expression::Expression(Loc loc, enum TOK op, int size)
808 : loc(loc)
810 this->loc = loc;
811 this->op = op;
812 this->size = size;
813 type = NULL;
816 Expression *Expression::syntaxCopy()
818 //printf("Expression::syntaxCopy()\n");
819 //dump(0);
820 return copy();
823 /*********************************
824 * Does *not* do a deep copy.
827 Expression *Expression::copy()
829 Expression *e;
830 if (!size)
832 #ifdef DEBUG
833 fprintf(stdmsg, "No expression copy for: %s\n", toChars());
834 printf("op = %d\n", op);
835 dump(0);
836 #endif
837 assert(0);
839 e = (Expression *)mem.malloc(size);
840 return (Expression *)memcpy(e, this, size);
843 /**************************
844 * Semantically analyze Expression.
845 * Determine types, fold constants, etc.
848 Expression *Expression::semantic(Scope *sc)
850 #if LOGSEMANTIC
851 printf("Expression::semantic() %s\n", toChars());
852 #endif
853 if (type)
854 type = type->semantic(loc, sc);
855 else
856 type = Type::tvoid;
857 return this;
860 void Expression::print()
862 fprintf(stdmsg, "%s\n", toChars());
863 fflush(stdmsg);
866 char *Expression::toChars()
867 { OutBuffer *buf;
868 HdrGenState hgs;
870 memset(&hgs, 0, sizeof(hgs));
871 buf = new OutBuffer();
872 toCBuffer(buf, &hgs);
873 return buf->toChars();
876 void Expression::error(const char *format, ...)
878 va_list ap;
879 va_start(ap, format);
880 ::verror(loc, format, ap);
881 va_end( ap );
884 void Expression::rvalue()
886 if (type && type->toBasetype()->ty == Tvoid)
887 { error("expression %s is void and has no value", toChars());
888 #if 0
889 dump(0);
890 halt();
891 #endif
892 type = Type::tint32;
896 Expression *Expression::combine(Expression *e1, Expression *e2)
898 if (e1)
900 if (e2)
902 e1 = new CommaExp(e1->loc, e1, e2);
903 e1->type = e2->type;
906 else
907 e1 = e2;
908 return e1;
911 integer_t Expression::toInteger()
913 //printf("Expression %s\n", Token::toChars(op));
914 error("Integer constant expression expected instead of %s", toChars());
915 return 0;
918 uinteger_t Expression::toUInteger()
920 //printf("Expression %s\n", Token::toChars(op));
921 return (uinteger_t)toInteger();
924 real_t Expression::toReal()
926 error("Floating point constant expression expected instead of %s", toChars());
927 return 0;
930 real_t Expression::toImaginary()
932 error("Floating point constant expression expected instead of %s", toChars());
933 return 0;
936 complex_t Expression::toComplex()
938 error("Floating point constant expression expected instead of %s", toChars());
939 #ifdef IN_GCC
940 return complex_t(real_t(0)); // %% nicer
941 #else
942 return 0;
943 #endif
946 void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
948 buf->writestring(Token::toChars(op));
951 void Expression::toMangleBuffer(OutBuffer *buf)
953 error("expression %s is not a valid template value argument", toChars());
956 /*******************************
957 * Give error if we're not an lvalue.
958 * If we can, convert expression to be an lvalue.
961 Expression *Expression::toLvalue(Scope *sc, Expression *e)
963 if (!e)
964 e = this;
965 else if (!loc.filename)
966 loc = e->loc;
967 error("%s is not an lvalue", e->toChars());
968 return this;
971 Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
973 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
975 // See if this expression is a modifiable lvalue (i.e. not const)
976 if (type && (!type->isMutable() || !type->isAssignable()))
977 error("%s is not mutable", e->toChars());
979 return toLvalue(sc, e);
982 /************************************
983 * Detect cases where pointers to the stack can 'escape' the
984 * lifetime of the stack frame.
987 void Expression::checkEscape()
991 void Expression::checkScalar()
993 if (!type->isscalar())
994 error("'%s' is not a scalar, it is a %s", toChars(), type->toChars());
997 void Expression::checkNoBool()
999 if (type->toBasetype()->ty == Tbool)
1000 error("operation not allowed on bool '%s'", toChars());
1003 Expression *Expression::checkIntegral()
1005 if (!type->isintegral())
1006 { error("'%s' is not of integral type, it is a %s", toChars(), type->toChars());
1007 return new IntegerExp(0);
1009 return this;
1012 Expression *Expression::checkArithmetic()
1014 if (!type->isintegral() && !type->isfloating())
1015 { error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
1016 return new IntegerExp(0);
1018 return this;
1021 void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
1023 s->checkDeprecated(loc, sc);
1026 /********************************
1027 * Check for expressions that have no use.
1028 * Input:
1029 * flag 0 not going to use the result, so issue error message if no
1030 * side effects
1031 * 1 the result of the expression is used, but still check
1032 * for useless subexpressions
1033 * 2 do not issue error messages, just return !=0 if expression
1034 * has side effects
1037 int Expression::checkSideEffect(int flag)
1039 if (flag == 0)
1040 { if (op == TOKimport)
1042 error("%s has no effect", toChars());
1044 else
1045 error("%s has no effect in expression (%s)",
1046 Token::toChars(op), toChars());
1048 return 0;
1051 /*****************************
1052 * Check that expression can be tested for true or false.
1055 Expression *Expression::checkToBoolean()
1057 // Default is 'yes' - do nothing
1059 #ifdef DEBUG
1060 if (!type)
1061 dump(0);
1062 #endif
1064 if (!type->checkBoolean())
1066 error("expression %s of type %s does not have a boolean value", toChars(), type->toChars());
1068 return this;
1071 /****************************
1074 Expression *Expression::checkToPointer()
1076 Expression *e;
1077 Type *tb;
1079 //printf("Expression::checkToPointer()\n");
1080 e = this;
1082 // If C static array, convert to pointer
1083 tb = type->toBasetype();
1084 if (tb->ty == Tsarray)
1085 { TypeSArray *ts = (TypeSArray *)tb;
1086 if (ts->size(loc) == 0)
1087 e = new NullExp(loc);
1088 else
1089 e = new AddrExp(loc, this);
1090 e->type = ts->next->pointerTo();
1092 return e;
1095 /******************************
1096 * Take address of expression.
1099 Expression *Expression::addressOf(Scope *sc)
1101 Expression *e;
1103 //printf("Expression::addressOf()\n");
1104 e = toLvalue(sc, NULL);
1105 e = new AddrExp(loc, e);
1106 e->type = type->pointerTo();
1107 return e;
1110 /******************************
1111 * If this is a reference, dereference it.
1114 Expression *Expression::deref()
1116 //printf("Expression::deref()\n");
1117 if (type->ty == Treference)
1118 { Expression *e;
1120 e = new PtrExp(loc, this);
1121 e->type = ((TypeReference *)type)->next;
1122 return e;
1124 return this;
1127 /********************************
1128 * Does this expression statically evaluate to a boolean TRUE or FALSE?
1131 int Expression::isBool(int result)
1133 return FALSE;
1136 /********************************
1137 * Does this expression result in either a 1 or a 0?
1140 int Expression::isBit()
1142 return FALSE;
1145 /********************************
1146 * Can this expression throw an exception?
1147 * Valid only after semantic() pass.
1150 int Expression::canThrow()
1152 return FALSE;
1157 Expressions *Expression::arraySyntaxCopy(Expressions *exps)
1158 { Expressions *a = NULL;
1160 if (exps)
1162 a = new Expressions();
1163 a->setDim(exps->dim);
1164 for (int i = 0; i < a->dim; i++)
1165 { Expression *e = (Expression *)exps->data[i];
1167 e = e->syntaxCopy();
1168 a->data[i] = e;
1171 return a;
1174 /******************************** IntegerExp **************************/
1176 IntegerExp::IntegerExp(Loc loc, integer_t value, Type *type)
1177 : Expression(loc, TOKint64, sizeof(IntegerExp))
1179 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
1180 if (type && !type->isscalar())
1182 //printf("%s, loc = %d\n", toChars(), loc.linnum);
1183 error("integral constant must be scalar type, not %s", type->toChars());
1184 type = Type::terror;
1186 this->type = type;
1187 this->value = value;
1190 IntegerExp::IntegerExp(integer_t value)
1191 : Expression(0, TOKint64, sizeof(IntegerExp))
1193 this->type = Type::tint32;
1194 this->value = value;
1197 int IntegerExp::equals(Object *o)
1198 { IntegerExp *ne;
1200 if (this == o ||
1201 (((Expression *)o)->op == TOKint64 &&
1202 ((ne = (IntegerExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
1203 value == ne->value))
1204 return 1;
1205 return 0;
1208 char *IntegerExp::toChars()
1210 #if 1
1211 return Expression::toChars();
1212 #else
1213 static char buffer[sizeof(value) * 3 + 1];
1215 sprintf(buffer, "%"PRIdMAX, value);
1216 return buffer;
1217 #endif
1220 integer_t IntegerExp::toInteger()
1221 { Type *t;
1223 t = type;
1224 while (t)
1226 switch (t->ty)
1228 case Tbit:
1229 case Tbool: value = (value != 0); break;
1230 case Tint8: value = (d_int8) value; break;
1231 case Tchar:
1232 case Tuns8: value = (d_uns8) value; break;
1233 case Tint16: value = (d_int16) value; break;
1234 case Twchar:
1235 case Tuns16: value = (d_uns16) value; break;
1236 case Tint32: value = (d_int32) value; break;
1237 case Tdchar:
1238 case Tuns32: value = (d_uns32) value; break;
1239 case Tint64: value = (d_int64) value; break;
1240 case Tuns64: value = (d_uns64) value; break;
1242 case Tpointer:
1243 switch (PTRSIZE)
1245 case 4: value = (d_uns32) value; break;
1246 case 8: value = (d_uns64) value; break;
1247 default:
1248 assert(PTRSIZE == 4 || PTRSIZE == 8);
1250 break;
1252 case Tenum:
1254 TypeEnum *te = (TypeEnum *)t;
1255 t = te->sym->memtype;
1256 continue;
1259 case Ttypedef:
1261 TypeTypedef *tt = (TypeTypedef *)t;
1262 t = tt->sym->basetype;
1263 continue;
1266 default:
1267 type->print();
1268 assert(0);
1269 break;
1271 break;
1273 return value;
1276 real_t IntegerExp::toReal()
1278 Type *t;
1280 toInteger();
1281 t = type->toBasetype();
1282 if (t->ty == Tuns64)
1283 return (real_t)(d_uns64)value;
1284 else
1285 return (real_t)(d_int64)value;
1288 real_t IntegerExp::toImaginary()
1290 return (real_t) 0;
1293 complex_t IntegerExp::toComplex()
1295 return toReal();
1298 int IntegerExp::isBool(int result)
1300 return result ? value != 0 : value == 0;
1303 Expression *IntegerExp::semantic(Scope *sc)
1305 if (!type)
1307 // Determine what the type of this number is
1308 integer_t number = value;
1310 if (number & 0x8000000000000000LL)
1311 type = Type::tuns64;
1312 else if (number & 0xFFFFFFFF80000000LL)
1313 type = Type::tint64;
1314 else
1315 type = Type::tint32;
1317 else
1318 { if (!type->deco)
1319 type = type->semantic(loc, sc);
1321 return this;
1324 Expression *IntegerExp::toLvalue(Scope *sc, Expression *e)
1326 if (!e)
1327 e = this;
1328 else if (!loc.filename)
1329 loc = e->loc;
1330 e->error("constant %s is not an lvalue", e->toChars());
1331 return this;
1334 void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1336 integer_t v = toInteger();
1338 if (type)
1339 { Type *t = type;
1342 switch (t->ty)
1344 case Tenum:
1345 { TypeEnum *te = (TypeEnum *)t;
1346 buf->printf("cast(%s)", te->sym->toChars());
1347 t = te->sym->memtype;
1348 goto L1;
1351 case Ttypedef:
1352 { TypeTypedef *tt = (TypeTypedef *)t;
1353 buf->printf("cast(%s)", tt->sym->toChars());
1354 t = tt->sym->basetype;
1355 goto L1;
1358 case Twchar: // BUG: need to cast(wchar)
1359 case Tdchar: // BUG: need to cast(dchar)
1360 if ((uinteger_t)v > 0xFF)
1362 buf->printf("'\\U%08x'", v);
1363 break;
1365 case Tchar:
1366 if (v == '\'')
1367 buf->writestring("'\\''");
1368 else if (isprint(v) && v != '\\')
1369 buf->printf("'%c'", (int)v);
1370 else
1371 buf->printf("'\\x%02x'", (int)v);
1372 break;
1374 case Tint8:
1375 buf->writestring("cast(byte)");
1376 goto L2;
1378 case Tint16:
1379 buf->writestring("cast(short)");
1380 goto L2;
1382 case Tint32:
1384 buf->printf("%d", (int)v);
1385 break;
1387 case Tuns8:
1388 buf->writestring("cast(ubyte)");
1389 goto L3;
1391 case Tuns16:
1392 buf->writestring("cast(ushort)");
1393 goto L3;
1395 case Tuns32:
1397 buf->printf("%du", (unsigned)v);
1398 break;
1400 case Tint64:
1401 buf->printf("%"PRIdMAX"L", v);
1402 break;
1404 case Tuns64:
1405 buf->printf("%"PRIuMAX"LU", v);
1406 break;
1408 case Tbit:
1409 case Tbool:
1410 buf->writestring((char *)(v ? "true" : "false"));
1411 break;
1413 case Tpointer:
1414 buf->writestring("cast(");
1415 buf->writestring(t->toChars());
1416 buf->writeByte(')');
1417 goto L3;
1419 default:
1420 #ifdef DEBUG
1421 t->print();
1422 #endif
1423 assert(0);
1426 else if (v & 0x8000000000000000LL)
1427 buf->printf("0x%"PRIxMAX, v);
1428 else
1429 buf->printf("%"PRIdMAX, v);
1432 void IntegerExp::toMangleBuffer(OutBuffer *buf)
1434 if ((sinteger_t)value < 0)
1435 buf->printf("N%"PRIdMAX, -value);
1436 else
1437 buf->printf("%"PRIdMAX, value);
1440 /******************************** RealExp **************************/
1442 RealExp::RealExp(Loc loc, real_t value, Type *type)
1443 : Expression(loc, TOKfloat64, sizeof(RealExp))
1445 //printf("RealExp::RealExp(%Lg)\n", value);
1446 this->value = value;
1447 this->type = type;
1450 char *RealExp::toChars()
1452 char buffer[sizeof(value) * 3 + 8 + 1 + 1];
1454 #ifdef IN_GCC
1455 value.format(buffer, sizeof(buffer));
1456 if (type->isimaginary())
1457 strcat(buffer, "i");
1458 #else
1459 sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value);
1460 #endif
1461 assert(strlen(buffer) < sizeof(buffer));
1462 return mem.strdup(buffer);
1465 integer_t RealExp::toInteger()
1467 #ifdef IN_GCC
1468 return (d_int64) toReal().toInt();
1469 #else
1470 return (sinteger_t) toReal();
1471 #endif
1474 uinteger_t RealExp::toUInteger()
1476 #ifdef IN_GCC
1477 return (uinteger_t) toReal().toInt();
1478 #else
1479 return (uinteger_t) toReal();
1480 #endif
1483 real_t RealExp::toReal()
1485 return type->isreal() ? value : 0;
1488 real_t RealExp::toImaginary()
1490 return type->isreal() ? 0 : value;
1493 complex_t RealExp::toComplex()
1495 #ifdef __DMC__
1496 return toReal() + toImaginary() * I;
1497 #else
1498 return complex_t(toReal(), toImaginary());
1499 #endif
1502 /********************************
1503 * Test to see if two reals are the same.
1504 * Regard NaN's as equivalent.
1505 * Regard +0 and -0 as different.
1508 int RealEquals(real_t x1, real_t x2)
1510 #ifndef IN_GCC
1511 return (isnan(x1) && isnan(x2)) ||
1512 /* In some cases, the REALPAD bytes get garbage in them,
1513 * so be sure and ignore them.
1515 memcmp(&x1, &x2, REALSIZE - REALPAD) == 0;
1516 #else
1517 return (x1.isNan() && x2.isNan()) || x1.isIdenticalTo(x2);
1518 #endif
1521 int RealExp::equals(Object *o)
1522 { RealExp *ne;
1524 if (this == o ||
1525 (((Expression *)o)->op == TOKfloat64 &&
1526 ((ne = (RealExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
1527 RealEquals(value, ne->value)
1530 return 1;
1531 return 0;
1534 Expression *RealExp::semantic(Scope *sc)
1536 if (!type)
1537 type = Type::tfloat64;
1538 else
1539 type = type->semantic(loc, sc);
1540 return this;
1543 int RealExp::isBool(int result)
1545 #ifdef IN_GCC
1546 return result ? (! value.isZero()) : (value.isZero());
1547 #else
1548 return result ? (value != 0)
1549 : (value == 0);
1550 #endif
1553 void floatToBuffer(OutBuffer *buf, Type *type, const real_t & value)
1555 /* In order to get an exact representation, try converting it
1556 * to decimal then back again. If it matches, use it.
1557 * If it doesn't, fall back to hex, which is
1558 * always exact.
1560 char buffer[48];
1561 #ifdef IN_GCC
1562 real_t parsed_value;
1564 value.format(buffer, sizeof(buffer));
1565 parsed_value = real_t::parse(buffer, real_t::LongDouble);
1566 if (parsed_value.isIdenticalTo( value ))
1567 buf->writestring(buffer);
1568 else
1570 value.formatHex(buffer, sizeof(buffer));
1571 buf->writestring(buffer);
1573 #else
1574 sprintf(buffer, "%Lg", value);
1575 assert(strlen(buffer) < sizeof(buffer));
1576 #if _WIN32 && __DMC__
1577 char *save = __locale_decpoint;
1578 __locale_decpoint = ".";
1579 real_t r = strtold(buffer, NULL);
1580 __locale_decpoint = save;
1581 #else
1582 real_t r = strtold(buffer, NULL);
1583 #endif
1584 if (r == value) // if exact duplication
1585 buf->writestring(buffer);
1586 else
1587 buf->printf("%La", value); // ensure exact duplication
1588 #endif
1590 if (type)
1592 Type *t = type->toBasetype();
1593 switch (t->ty)
1595 case Tfloat32:
1596 case Timaginary32:
1597 case Tcomplex32:
1598 buf->writeByte('F');
1599 break;
1601 case Tfloat80:
1602 case Timaginary80:
1603 case Tcomplex80:
1604 buf->writeByte('L');
1605 break;
1607 default:
1608 break;
1610 if (t->isimaginary())
1611 buf->writeByte('i');
1615 void RealExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1617 floatToBuffer(buf, type, value);
1620 void realToMangleBuffer(OutBuffer *buf, real_t value)
1622 /* Rely on %A to get portable mangling.
1623 * Must munge result to get only identifier characters.
1625 * Possible values from %A => mangled result
1626 * NAN => NAN
1627 * -INF => NINF
1628 * INF => INF
1629 * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79
1630 * 0X1.9P+2 => 19P2
1633 #ifdef IN_GCC
1634 if (value.isNan())
1635 buf->writestring("NAN"); // no -NAN bugs
1636 else if (value.isInf())
1637 buf->writestring(value.isNegative()?"NINF":"INF");
1638 #else
1639 if (isnan(value))
1640 buf->writestring("NAN"); // no -NAN bugs
1641 #endif
1642 else
1644 char buffer[64];
1645 #ifdef IN_GCC
1646 value.formatHex(buffer, sizeof(buffer));
1647 int n = strlen(buffer);
1648 #else
1649 int n = sprintf(buffer, "%LA", value);
1650 assert(n > 0 && n < sizeof(buffer));
1651 #endif
1652 for (int i = 0; i < n; i++)
1653 { char c = buffer[i];
1655 switch (c)
1657 case '-':
1658 buf->writeByte('N');
1659 break;
1661 case '+':
1662 case 'x':
1663 case 'X':
1664 case '.':
1665 break;
1667 case '0':
1668 if (i < 2)
1669 break; // skip leading 0X
1670 default:
1671 buf->writeByte(c);
1672 break;
1678 void RealExp::toMangleBuffer(OutBuffer *buf)
1680 buf->writeByte('e');
1681 realToMangleBuffer(buf, value);
1685 /******************************** ComplexExp **************************/
1687 ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type)
1688 : Expression(loc, TOKcomplex80, sizeof(ComplexExp))
1690 this->value = value;
1691 this->type = type;
1692 //printf("ComplexExp::ComplexExp(%s)\n", toChars());
1695 char *ComplexExp::toChars()
1697 char buffer[sizeof(value) * 3 + 8 + 1];
1699 #ifdef IN_GCC
1700 char buf1[sizeof(value) * 3 + 8 + 1];
1701 char buf2[sizeof(value) * 3 + 8 + 1];
1702 creall(value).format(buf1, sizeof(buf1));
1703 cimagl(value).format(buf2, sizeof(buf2));
1704 sprintf(buffer, "(%s+%si)", buf1, buf2);
1705 #else
1706 sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value));
1707 assert(strlen(buffer) < sizeof(buffer));
1708 #endif
1709 return mem.strdup(buffer);
1712 integer_t ComplexExp::toInteger()
1714 #ifdef IN_GCC
1715 return (d_int64) toReal().toInt();
1716 #else
1717 return (sinteger_t) toReal();
1718 #endif
1721 uinteger_t ComplexExp::toUInteger()
1723 #ifdef IN_GCC
1724 return (uinteger_t) toReal().toInt();
1725 #else
1726 return (uinteger_t) toReal();
1727 #endif
1730 real_t ComplexExp::toReal()
1732 return creall(value);
1735 real_t ComplexExp::toImaginary()
1737 return cimagl(value);
1740 complex_t ComplexExp::toComplex()
1742 return value;
1745 int ComplexExp::equals(Object *o)
1746 { ComplexExp *ne;
1748 if (this == o ||
1749 (((Expression *)o)->op == TOKcomplex80 &&
1750 ((ne = (ComplexExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
1751 #ifndef IN_GCC
1752 RealEquals(creall(value), creall(ne->value)) &&
1753 RealEquals(cimagl(value), cimagl(ne->value))
1754 #else
1755 RealEquals(value.re, ne->value.re) &&
1756 RealEquals(value.im, ne->value.im)
1757 #endif
1760 return 1;
1761 return 0;
1764 Expression *ComplexExp::semantic(Scope *sc)
1766 if (!type)
1767 type = Type::tcomplex80;
1768 else
1769 type = type->semantic(loc, sc);
1770 return this;
1773 int ComplexExp::isBool(int result)
1775 if (result)
1776 return (bool)(value);
1777 else
1778 return !value;
1781 void ComplexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1783 /* Print as:
1784 * (re+imi)
1786 #ifdef IN_GCC
1787 char buf1[sizeof(value) * 3 + 8 + 1];
1788 char buf2[sizeof(value) * 3 + 8 + 1];
1789 creall(value).format(buf1, sizeof(buf1));
1790 cimagl(value).format(buf2, sizeof(buf2));
1791 buf->printf("(%s+%si)", buf1, buf2);
1792 #else
1793 buf->writeByte('(');
1794 floatToBuffer(buf, type, creall(value));
1795 buf->writeByte('+');
1796 floatToBuffer(buf, type, cimagl(value));
1797 buf->writestring("i)");
1798 #endif
1801 void ComplexExp::toMangleBuffer(OutBuffer *buf)
1803 buf->writeByte('c');
1804 real_t r = toReal();
1805 realToMangleBuffer(buf, r);
1806 buf->writeByte('c'); // separate the two
1807 r = toImaginary();
1808 realToMangleBuffer(buf, r);
1811 /******************************** IdentifierExp **************************/
1813 IdentifierExp::IdentifierExp(Loc loc, Identifier *ident)
1814 : Expression(loc, TOKidentifier, sizeof(IdentifierExp))
1816 this->ident = ident;
1819 Expression *IdentifierExp::semantic(Scope *sc)
1821 Dsymbol *s;
1822 Dsymbol *scopesym;
1824 #if LOGSEMANTIC
1825 printf("IdentifierExp::semantic('%s')\n", ident->toChars());
1826 #endif
1827 s = sc->search(loc, ident, &scopesym);
1828 if (s)
1829 { Expression *e;
1830 WithScopeSymbol *withsym;
1832 /* See if the symbol was a member of an enclosing 'with'
1834 withsym = scopesym->isWithScopeSymbol();
1835 if (withsym)
1837 s = s->toAlias();
1839 // Same as wthis.ident
1840 if (s->needThis() || s->isTemplateDeclaration())
1842 e = new VarExp(loc, withsym->withstate->wthis);
1843 e = new DotIdExp(loc, e, ident);
1845 else
1846 { Type *t = withsym->withstate->wthis->type;
1847 if (t->ty == Tpointer)
1848 t = ((TypePointer *)t)->next;
1849 e = new TypeDotIdExp(loc, t, ident);
1852 else
1854 /* If f is really a function template,
1855 * then replace f with the function template declaration.
1857 FuncDeclaration *f = s->isFuncDeclaration();
1858 if (f && f->parent)
1859 { TemplateInstance *ti = f->parent->isTemplateInstance();
1861 if (ti &&
1862 !ti->isTemplateMixin() &&
1863 (ti->name == f->ident ||
1864 ti->toAlias()->ident == f->ident)
1866 ti->tempdecl && ti->tempdecl->onemember)
1868 TemplateDeclaration *tempdecl = ti->tempdecl;
1869 if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's
1870 tempdecl = tempdecl->overroot; // then get the start
1871 e = new TemplateExp(loc, tempdecl);
1872 e = e->semantic(sc);
1873 return e;
1876 // Haven't done overload resolution yet, so pass 1
1877 e = new DsymbolExp(loc, s, 1);
1879 return e->semantic(sc);
1881 error("undefined identifier %s", ident->toChars());
1882 type = Type::terror;
1883 return this;
1886 char *IdentifierExp::toChars()
1888 return ident->toChars();
1891 void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1893 if (hgs->hdrgen)
1894 buf->writestring(ident->toHChars2());
1895 else
1896 buf->writestring(ident->toChars());
1899 Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e)
1901 #if 0
1902 tym = tybasic(e1->ET->Tty);
1903 if (!(tyscalar(tym) ||
1904 tym == TYstruct ||
1905 tym == TYarray && e->Eoper == TOKaddr))
1906 synerr(EM_lvalue); // lvalue expected
1907 #endif
1908 return this;
1911 /******************************** DollarExp **************************/
1913 DollarExp::DollarExp(Loc loc)
1914 : IdentifierExp(loc, Id::dollar)
1918 /******************************** DsymbolExp **************************/
1920 DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, int hasOverloads)
1921 : Expression(loc, TOKdsymbol, sizeof(DsymbolExp))
1923 this->s = s;
1924 this->hasOverloads = hasOverloads;
1927 Expression *DsymbolExp::semantic(Scope *sc)
1929 #if LOGSEMANTIC
1930 printf("DsymbolExp::semantic('%s')\n", s->toChars());
1931 #endif
1933 Lagain:
1934 EnumMember *em;
1935 Expression *e;
1936 VarDeclaration *v;
1937 FuncDeclaration *f;
1938 FuncLiteralDeclaration *fld;
1939 OverloadSet *o;
1940 Declaration *d;
1941 ClassDeclaration *cd;
1942 ClassDeclaration *thiscd = NULL;
1943 Import *imp;
1944 Package *pkg;
1945 Type *t;
1947 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
1948 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
1949 if (type)
1950 return this;
1951 if (!s->isFuncDeclaration()) // functions are checked after overloading
1952 checkDeprecated(sc, s);
1953 s = s->toAlias();
1954 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
1955 if (!s->isFuncDeclaration())
1956 checkDeprecated(sc, s);
1958 if (sc->func)
1959 thiscd = sc->func->parent->isClassDeclaration();
1961 // BUG: This should happen after overload resolution for functions, not before
1962 if (s->needThis())
1964 if (hasThis(sc) && !s->isFuncDeclaration())
1966 // Supply an implicit 'this', as in
1967 // this.ident
1969 DotVarExp *de;
1971 de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration());
1972 return de->semantic(sc);
1976 em = s->isEnumMember();
1977 if (em)
1979 e = em->value;
1980 e = e->semantic(sc);
1981 return e;
1983 v = s->isVarDeclaration();
1984 if (v)
1986 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
1987 if (!type)
1988 { type = v->type;
1989 if (!v->type)
1990 { error("forward reference of %s", v->toChars());
1991 type = Type::terror;
1994 e = new VarExp(loc, v);
1995 e->type = type;
1996 e = e->semantic(sc);
1997 return e->deref();
1999 fld = s->isFuncLiteralDeclaration();
2000 if (fld)
2001 { //printf("'%s' is a function literal\n", fld->toChars());
2002 e = new FuncExp(loc, fld);
2003 return e->semantic(sc);
2005 f = s->isFuncDeclaration();
2006 if (f)
2007 { //printf("'%s' is a function\n", f->toChars());
2008 return new VarExp(loc, f, hasOverloads);
2010 o = s->isOverloadSet();
2011 if (o)
2012 { //printf("'%s' is an overload set\n", o->toChars());
2013 return new OverExp(o);
2015 cd = s->isClassDeclaration();
2016 if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis())
2018 // We need to add an implicit 'this' if cd is this class or a base class.
2019 DotTypeExp *dte;
2021 dte = new DotTypeExp(loc, new ThisExp(loc), s);
2022 return dte->semantic(sc);
2024 imp = s->isImport();
2025 if (imp)
2027 ScopeExp *ie;
2029 ie = new ScopeExp(loc, imp->pkg);
2030 return ie->semantic(sc);
2032 pkg = s->isPackage();
2033 if (pkg)
2035 ScopeExp *ie;
2037 ie = new ScopeExp(loc, pkg);
2038 return ie->semantic(sc);
2040 Module *mod = s->isModule();
2041 if (mod)
2043 ScopeExp *ie;
2045 ie = new ScopeExp(loc, mod);
2046 return ie->semantic(sc);
2049 t = s->getType();
2050 if (t)
2052 return new TypeExp(loc, t);
2055 TupleDeclaration *tup = s->isTupleDeclaration();
2056 if (tup)
2058 e = new TupleExp(loc, tup);
2059 e = e->semantic(sc);
2060 return e;
2063 TemplateInstance *ti = s->isTemplateInstance();
2064 if (ti && !global.errors)
2065 { if (!ti->semanticdone)
2066 ti->semantic(sc);
2067 s = ti->inst->toAlias();
2068 if (!s->isTemplateInstance())
2069 goto Lagain;
2070 e = new ScopeExp(loc, ti);
2071 e = e->semantic(sc);
2072 return e;
2075 TemplateDeclaration *td = s->isTemplateDeclaration();
2076 if (td)
2078 e = new TemplateExp(loc, td);
2079 e = e->semantic(sc);
2080 return e;
2083 Lerr:
2084 error("%s '%s' is not a variable", s->kind(), s->toChars());
2085 type = Type::terror;
2086 return this;
2089 char *DsymbolExp::toChars()
2091 return s->toChars();
2094 void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2096 buf->writestring(s->toChars());
2099 Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e)
2101 #if 0
2102 tym = tybasic(e1->ET->Tty);
2103 if (!(tyscalar(tym) ||
2104 tym == TYstruct ||
2105 tym == TYarray && e->Eoper == TOKaddr))
2106 synerr(EM_lvalue); // lvalue expected
2107 #endif
2108 return this;
2111 /******************************** ThisExp **************************/
2113 ThisExp::ThisExp(Loc loc)
2114 : Expression(loc, TOKthis, sizeof(ThisExp))
2116 var = NULL;
2119 Expression *ThisExp::semantic(Scope *sc)
2120 { FuncDeclaration *fd;
2121 FuncDeclaration *fdthis;
2122 int nested = 0;
2124 #if LOGSEMANTIC
2125 printf("ThisExp::semantic()\n");
2126 #endif
2127 if (type)
2128 { //assert(global.errors || var);
2129 return this;
2132 /* Special case for typeof(this) and typeof(super) since both
2133 * should work even if they are not inside a non-static member function
2135 if (sc->intypeof)
2137 // Find enclosing struct or class
2138 for (Dsymbol *s = sc->parent; 1; s = s->parent)
2140 ClassDeclaration *cd;
2141 StructDeclaration *sd;
2143 if (!s)
2145 error("%s is not in a struct or class scope", toChars());
2146 goto Lerr;
2148 cd = s->isClassDeclaration();
2149 if (cd)
2151 type = cd->type;
2152 return this;
2154 sd = s->isStructDeclaration();
2155 if (sd)
2157 type = sd->type->pointerTo();
2158 return this;
2163 fdthis = sc->parent->isFuncDeclaration();
2164 fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2165 if (!fd)
2166 goto Lerr;
2168 assert(fd->vthis);
2169 var = fd->vthis;
2170 assert(var->parent);
2171 type = var->type;
2172 var->isVarDeclaration()->checkNestedReference(sc, loc);
2173 sc->callSuper |= CSXthis;
2174 return this;
2176 Lerr:
2177 error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars());
2178 type = Type::terror;
2179 return this;
2182 int ThisExp::isBool(int result)
2184 return result ? TRUE : FALSE;
2187 void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2189 buf->writestring("this");
2192 Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
2194 return this;
2197 /******************************** SuperExp **************************/
2199 SuperExp::SuperExp(Loc loc)
2200 : ThisExp(loc)
2202 op = TOKsuper;
2205 Expression *SuperExp::semantic(Scope *sc)
2206 { FuncDeclaration *fd;
2207 FuncDeclaration *fdthis;
2208 ClassDeclaration *cd;
2209 Dsymbol *s;
2211 #if LOGSEMANTIC
2212 printf("SuperExp::semantic('%s')\n", toChars());
2213 #endif
2214 if (type)
2215 return this;
2217 /* Special case for typeof(this) and typeof(super) since both
2218 * should work even if they are not inside a non-static member function
2220 if (sc->intypeof)
2222 // Find enclosing class
2223 for (Dsymbol *s = sc->parent; 1; s = s->parent)
2225 ClassDeclaration *cd;
2227 if (!s)
2229 error("%s is not in a class scope", toChars());
2230 goto Lerr;
2232 cd = s->isClassDeclaration();
2233 if (cd)
2235 cd = cd->baseClass;
2236 if (!cd)
2237 { error("class %s has no 'super'", s->toChars());
2238 goto Lerr;
2240 type = cd->type;
2241 return this;
2246 fdthis = sc->parent->isFuncDeclaration();
2247 fd = hasThis(sc);
2248 if (!fd)
2249 goto Lerr;
2250 assert(fd->vthis);
2251 var = fd->vthis;
2252 assert(var->parent);
2254 s = fd->toParent();
2255 while (s && s->isTemplateInstance())
2256 s = s->toParent();
2257 assert(s);
2258 cd = s->isClassDeclaration();
2259 //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
2260 if (!cd)
2261 goto Lerr;
2262 if (!cd->baseClass)
2264 error("no base class for %s", cd->toChars());
2265 type = fd->vthis->type;
2267 else
2269 type = cd->baseClass->type;
2272 var->isVarDeclaration()->checkNestedReference(sc, loc);
2274 sc->callSuper |= CSXsuper;
2275 return this;
2278 Lerr:
2279 error("'super' is only allowed in non-static class member functions");
2280 type = Type::tint32;
2281 return this;
2284 void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2286 buf->writestring("super");
2290 /******************************** NullExp **************************/
2292 NullExp::NullExp(Loc loc)
2293 : Expression(loc, TOKnull, sizeof(NullExp))
2295 committed = 0;
2298 Expression *NullExp::semantic(Scope *sc)
2300 #if LOGSEMANTIC
2301 printf("NullExp::semantic('%s')\n", toChars());
2302 #endif
2303 // NULL is the same as (void *)0
2304 if (!type)
2305 type = Type::tvoid->pointerTo();
2306 return this;
2309 int NullExp::isBool(int result)
2311 return result ? FALSE : TRUE;
2314 void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2316 buf->writestring("null");
2319 void NullExp::toMangleBuffer(OutBuffer *buf)
2321 buf->writeByte('n');
2324 /******************************** StringExp **************************/
2326 StringExp::StringExp(Loc loc, char *string)
2327 : Expression(loc, TOKstring, sizeof(StringExp))
2329 this->string = string;
2330 this->len = strlen(string);
2331 this->sz = 1;
2332 this->committed = 0;
2333 this->postfix = 0;
2336 StringExp::StringExp(Loc loc, void *string, size_t len)
2337 : Expression(loc, TOKstring, sizeof(StringExp))
2339 this->string = string;
2340 this->len = len;
2341 this->sz = 1;
2342 this->committed = 0;
2343 this->postfix = 0;
2346 StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix)
2347 : Expression(loc, TOKstring, sizeof(StringExp))
2349 this->string = string;
2350 this->len = len;
2351 this->sz = 1;
2352 this->committed = 0;
2353 this->postfix = postfix;
2356 #if 0
2357 Expression *StringExp::syntaxCopy()
2359 printf("StringExp::syntaxCopy() %s\n", toChars());
2360 return copy();
2362 #endif
2364 int StringExp::equals(Object *o)
2366 //printf("StringExp::equals('%s')\n", o->toChars());
2367 if (o && o->dyncast() == DYNCAST_EXPRESSION)
2368 { Expression *e = (Expression *)o;
2370 if (e->op == TOKstring)
2372 return compare(o) == 0;
2375 return FALSE;
2378 char *StringExp::toChars()
2380 OutBuffer buf;
2381 HdrGenState hgs;
2382 char *p;
2384 memset(&hgs, 0, sizeof(hgs));
2385 toCBuffer(&buf, &hgs);
2386 buf.writeByte(0);
2387 p = (char *)buf.data;
2388 buf.data = NULL;
2389 return p;
2392 Expression *StringExp::semantic(Scope *sc)
2394 #if LOGSEMANTIC
2395 printf("StringExp::semantic() %s\n", toChars());
2396 #endif
2397 if (!type)
2398 { OutBuffer buffer;
2399 size_t newlen = 0;
2400 char *p;
2401 size_t u;
2402 unsigned c;
2404 switch (postfix)
2406 case 'd':
2407 for (u = 0; u < len;)
2409 p = utf_decodeChar((unsigned char *)string, len, &u, &c);
2410 if (p)
2411 { error("%s", p);
2412 break;
2414 else
2415 { buffer.write4(c);
2416 newlen++;
2419 buffer.write4(0);
2420 string = buffer.extractData();
2421 len = newlen;
2422 sz = 4;
2423 type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex));
2424 committed = 1;
2425 break;
2427 case 'w':
2428 for (u = 0; u < len;)
2430 p = utf_decodeChar((unsigned char *)string, len, &u, &c);
2431 if (p)
2432 { error("%s", p);
2433 break;
2435 else
2436 { buffer.writeUTF16(c);
2437 newlen++;
2438 if (c >= 0x10000)
2439 newlen++;
2442 buffer.writeUTF16(0);
2443 string = buffer.extractData();
2444 len = newlen;
2445 sz = 2;
2446 type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex));
2447 committed = 1;
2448 break;
2450 case 'c':
2451 committed = 1;
2452 default:
2453 type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex));
2454 break;
2456 type = type->semantic(loc, sc);
2457 type = type->invariantOf();
2458 //printf("type = %s\n", type->toChars());
2460 return this;
2463 /****************************************
2464 * Convert string to char[].
2467 StringExp *StringExp::toUTF8(Scope *sc)
2469 if (sz != 1)
2470 { // Convert to UTF-8 string
2471 committed = 0;
2472 Expression *e = castTo(sc, Type::tchar->arrayOf());
2473 e = e->optimize(WANTvalue);
2474 assert(e->op == TOKstring);
2475 StringExp *se = (StringExp *)e;
2476 assert(se->sz == 1);
2477 return se;
2479 return this;
2482 int StringExp::compare(Object *obj)
2484 // Used to sort case statement expressions so we can do an efficient lookup
2485 StringExp *se2 = (StringExp *)(obj);
2487 // This is a kludge so isExpression() in template.c will return 5
2488 // for StringExp's.
2489 if (!se2)
2490 return 5;
2492 assert(se2->op == TOKstring);
2494 int len1 = len;
2495 int len2 = se2->len;
2497 if (len1 == len2)
2499 switch (sz)
2501 case 1:
2502 return strcmp((char *)string, (char *)se2->string);
2504 case 2:
2505 { unsigned u;
2506 d_wchar *s1 = (d_wchar *)string;
2507 d_wchar *s2 = (d_wchar *)se2->string;
2509 for (u = 0; u < len; u++)
2511 if (s1[u] != s2[u])
2512 return s1[u] - s2[u];
2516 case 4:
2517 { unsigned u;
2518 d_dchar *s1 = (d_dchar *)string;
2519 d_dchar *s2 = (d_dchar *)se2->string;
2521 for (u = 0; u < len; u++)
2523 if (s1[u] != s2[u])
2524 return s1[u] - s2[u];
2527 break;
2529 default:
2530 assert(0);
2533 return len1 - len2;
2536 int StringExp::isBool(int result)
2538 return result ? TRUE : FALSE;
2541 unsigned StringExp::charAt(size_t i)
2542 { unsigned value;
2544 switch (sz)
2546 case 1:
2547 value = ((unsigned char *)string)[i];
2548 break;
2550 case 2:
2551 value = ((unsigned short *)string)[i];
2552 break;
2554 case 4:
2555 value = ((unsigned int *)string)[i];
2556 break;
2558 default:
2559 assert(0);
2560 break;
2562 return value;
2565 void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2567 buf->writeByte('"');
2568 for (size_t i = 0; i < len; i++)
2569 { unsigned c = charAt(i);
2571 switch (c)
2573 case '"':
2574 case '\\':
2575 if (!hgs->console)
2576 buf->writeByte('\\');
2577 default:
2578 if (c <= 0xFF)
2579 { if (c <= 0x7F && (isprint(c) || hgs->console))
2580 buf->writeByte(c);
2581 else
2582 buf->printf("\\x%02x", c);
2584 else if (c <= 0xFFFF)
2585 buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8);
2586 else
2587 buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
2588 c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24);
2589 break;
2592 buf->writeByte('"');
2593 if (postfix)
2594 buf->writeByte(postfix);
2597 void StringExp::toMangleBuffer(OutBuffer *buf)
2598 { char m;
2599 OutBuffer tmp;
2600 char *p;
2601 dchar_t c;
2602 size_t u;
2603 unsigned char *q;
2604 unsigned qlen;
2606 /* Write string in UTF-8 format
2608 switch (sz)
2609 { case 1:
2610 m = 'a';
2611 q = (unsigned char *)string;
2612 qlen = len;
2613 break;
2614 case 2:
2615 m = 'w';
2616 for (u = 0; u < len; )
2618 p = utf_decodeWchar((unsigned short *)string, len, &u, &c);
2619 if (p)
2620 error("%s", p);
2621 else
2622 tmp.writeUTF8(c);
2624 q = tmp.data;
2625 qlen = tmp.offset;
2626 break;
2627 case 4:
2628 m = 'd';
2629 for (u = 0; u < len; u++)
2631 c = ((unsigned *)string)[u];
2632 if (!utf_isValidDchar(c))
2633 error("invalid UCS-32 char \\U%08x", c);
2634 else
2635 tmp.writeUTF8(c);
2637 q = tmp.data;
2638 qlen = tmp.offset;
2639 break;
2640 default:
2641 assert(0);
2643 buf->writeByte(m);
2644 buf->printf("%d_", qlen);
2645 for (size_t i = 0; i < qlen; i++)
2646 buf->printf("%02x", q[i]);
2649 /************************ ArrayLiteralExp ************************************/
2651 // [ e1, e2, e3, ... ]
2653 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements)
2654 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
2656 this->elements = elements;
2659 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e)
2660 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
2662 elements = new Expressions;
2663 elements->push(e);
2666 Expression *ArrayLiteralExp::syntaxCopy()
2668 return new ArrayLiteralExp(loc, arraySyntaxCopy(elements));
2671 Expression *ArrayLiteralExp::semantic(Scope *sc)
2672 { Expression *e;
2673 Type *t0 = NULL;
2675 #if LOGSEMANTIC
2676 printf("ArrayLiteralExp::semantic('%s')\n", toChars());
2677 #endif
2678 if (type)
2679 return this;
2681 // Run semantic() on each element
2682 for (int i = 0; i < elements->dim; i++)
2683 { e = (Expression *)elements->data[i];
2684 e = e->semantic(sc);
2685 elements->data[i] = (void *)e;
2687 expandTuples(elements);
2688 for (int i = 0; i < elements->dim; i++)
2689 { e = (Expression *)elements->data[i];
2691 if (!e->type)
2692 error("%s has no value", e->toChars());
2693 e = resolveProperties(sc, e);
2695 unsigned char committed = 1;
2696 if (e->op == TOKstring)
2697 committed = ((StringExp *)e)->committed;
2699 if (!t0)
2700 { t0 = e->type;
2701 // Convert any static arrays to dynamic arrays
2702 if (t0->ty == Tsarray)
2704 t0 = ((TypeSArray *)t0)->next->arrayOf();
2705 e = e->implicitCastTo(sc, t0);
2708 else
2709 e = e->implicitCastTo(sc, t0);
2710 if (!committed && e->op == TOKstring)
2711 { StringExp *se = (StringExp *)e;
2712 se->committed = 0;
2714 elements->data[i] = (void *)e;
2717 if (!t0)
2718 t0 = Type::tvoid;
2719 type = new TypeSArray(t0, new IntegerExp(elements->dim));
2720 type = type->semantic(loc, sc);
2721 return this;
2724 int ArrayLiteralExp::checkSideEffect(int flag)
2725 { int f = 0;
2727 for (size_t i = 0; i < elements->dim; i++)
2728 { Expression *e = (Expression *)elements->data[i];
2730 f |= e->checkSideEffect(2);
2732 if (flag == 0 && f == 0)
2733 Expression::checkSideEffect(0);
2734 return f;
2737 int ArrayLiteralExp::isBool(int result)
2739 size_t dim = elements ? elements->dim : 0;
2740 return result ? (dim != 0) : (dim == 0);
2743 int ArrayLiteralExp::canThrow()
2745 return 1; // because it can fail allocating memory
2748 void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2750 buf->writeByte('[');
2751 argsToCBuffer(buf, elements, hgs);
2752 buf->writeByte(']');
2755 void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
2757 size_t dim = elements ? elements->dim : 0;
2758 buf->printf("A%"PRIuSIZE, dim);
2759 for (size_t i = 0; i < dim; i++)
2760 { Expression *e = (Expression *)elements->data[i];
2761 e->toMangleBuffer(buf);
2765 /************************ AssocArrayLiteralExp ************************************/
2767 // [ key0 : value0, key1 : value1, ... ]
2769 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc,
2770 Expressions *keys, Expressions *values)
2771 : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp))
2773 assert(keys->dim == values->dim);
2774 this->keys = keys;
2775 this->values = values;
2778 Expression *AssocArrayLiteralExp::syntaxCopy()
2780 return new AssocArrayLiteralExp(loc,
2781 arraySyntaxCopy(keys), arraySyntaxCopy(values));
2784 Expression *AssocArrayLiteralExp::semantic(Scope *sc)
2785 { Expression *e;
2786 Type *tkey = NULL;
2787 Type *tvalue = NULL;
2789 #if LOGSEMANTIC
2790 printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
2791 #endif
2793 // Run semantic() on each element
2794 for (size_t i = 0; i < keys->dim; i++)
2795 { Expression *key = (Expression *)keys->data[i];
2796 Expression *value = (Expression *)values->data[i];
2798 key = key->semantic(sc);
2799 value = value->semantic(sc);
2801 keys->data[i] = (void *)key;
2802 values->data[i] = (void *)value;
2804 expandTuples(keys);
2805 expandTuples(values);
2806 if (keys->dim != values->dim)
2808 error("number of keys is %u, must match number of values %u", keys->dim, values->dim);
2809 keys->setDim(0);
2810 values->setDim(0);
2812 for (size_t i = 0; i < keys->dim; i++)
2813 { Expression *key = (Expression *)keys->data[i];
2814 Expression *value = (Expression *)values->data[i];
2816 if (!key->type)
2817 error("%s has no value", key->toChars());
2818 if (!value->type)
2819 error("%s has no value", value->toChars());
2820 key = resolveProperties(sc, key);
2821 value = resolveProperties(sc, value);
2823 if (!tkey)
2824 tkey = key->type;
2825 else
2826 key = key->implicitCastTo(sc, tkey);
2827 keys->data[i] = (void *)key;
2829 if (!tvalue)
2830 tvalue = value->type;
2831 else
2832 value = value->implicitCastTo(sc, tvalue);
2833 values->data[i] = (void *)value;
2836 if (!tkey)
2837 tkey = Type::tvoid;
2838 if (!tvalue)
2839 tvalue = Type::tvoid;
2840 type = new TypeAArray(tvalue, tkey);
2841 type = type->semantic(loc, sc);
2842 return this;
2845 int AssocArrayLiteralExp::checkSideEffect(int flag)
2846 { int f = 0;
2848 for (size_t i = 0; i < keys->dim; i++)
2849 { Expression *key = (Expression *)keys->data[i];
2850 Expression *value = (Expression *)values->data[i];
2852 f |= key->checkSideEffect(2);
2853 f |= value->checkSideEffect(2);
2855 if (flag == 0 && f == 0)
2856 Expression::checkSideEffect(0);
2857 return f;
2860 int AssocArrayLiteralExp::isBool(int result)
2862 size_t dim = keys->dim;
2863 return result ? (dim != 0) : (dim == 0);
2866 int AssocArrayLiteralExp::canThrow()
2868 return 1;
2871 void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2873 buf->writeByte('[');
2874 for (size_t i = 0; i < keys->dim; i++)
2875 { Expression *key = (Expression *)keys->data[i];
2876 Expression *value = (Expression *)values->data[i];
2878 if (i)
2879 buf->writeByte(',');
2880 expToCBuffer(buf, hgs, key, PREC_assign);
2881 buf->writeByte(':');
2882 expToCBuffer(buf, hgs, value, PREC_assign);
2884 buf->writeByte(']');
2887 void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
2889 size_t dim = keys->dim;
2890 buf->printf("A%u", dim);
2891 for (size_t i = 0; i < dim; i++)
2892 { Expression *key = (Expression *)keys->data[i];
2893 Expression *value = (Expression *)values->data[i];
2895 key->toMangleBuffer(buf);
2896 value->toMangleBuffer(buf);
2900 /************************ StructLiteralExp ************************************/
2902 // sd( e1, e2, e3, ... )
2904 StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements)
2905 : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp))
2907 this->sd = sd;
2908 this->elements = elements;
2909 this->sym = NULL;
2910 this->soffset = 0;
2911 this->fillHoles = 1;
2914 Expression *StructLiteralExp::syntaxCopy()
2916 return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements));
2919 Expression *StructLiteralExp::semantic(Scope *sc)
2920 { Expression *e;
2922 #if LOGSEMANTIC
2923 printf("StructLiteralExp::semantic('%s')\n", toChars());
2924 #endif
2925 if (type)
2926 return this;
2928 // Run semantic() on each element
2929 for (size_t i = 0; i < elements->dim; i++)
2930 { e = (Expression *)elements->data[i];
2931 if (!e)
2932 continue;
2933 e = e->semantic(sc);
2934 elements->data[i] = (void *)e;
2936 expandTuples(elements);
2937 size_t offset = 0;
2938 for (size_t i = 0; i < elements->dim; i++)
2939 { e = (Expression *)elements->data[i];
2940 if (!e)
2941 continue;
2943 if (!e->type)
2944 error("%s has no value", e->toChars());
2945 e = resolveProperties(sc, e);
2946 if (i >= sd->fields.dim)
2947 { error("more initializers than fields of %s", sd->toChars());
2948 break;
2950 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
2951 VarDeclaration *v = s->isVarDeclaration();
2952 assert(v);
2953 if (v->offset < offset)
2954 error("overlapping initialization for %s", v->toChars());
2955 offset = v->offset + v->type->size();
2957 Type *telem = v->type;
2958 while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray)
2959 { /* Static array initialization, as in:
2960 * T[3][5] = e;
2962 telem = telem->toBasetype()->nextOf();
2965 e = e->implicitCastTo(sc, telem);
2967 elements->data[i] = (void *)e;
2970 /* Fill out remainder of elements[] with default initializers for fields[]
2972 for (size_t i = elements->dim; i < sd->fields.dim; i++)
2973 { Dsymbol *s = (Dsymbol *)sd->fields.data[i];
2974 VarDeclaration *v = s->isVarDeclaration();
2975 assert(v);
2977 if (v->offset < offset)
2978 { e = NULL;
2979 sd->hasUnions = 1;
2981 else
2983 if (v->init)
2984 { e = v->init->toExpression();
2985 if (!e)
2986 error("cannot make expression out of initializer for %s", v->toChars());
2988 else
2989 { e = v->type->defaultInit();
2990 e->loc = loc;
2992 offset = v->offset + v->type->size();
2994 elements->push(e);
2997 type = sd->type;
2998 return this;
3001 /**************************************
3002 * Gets expression at offset of type.
3003 * Returns NULL if not found.
3006 Expression *StructLiteralExp::getField(Type *type, unsigned offset)
3008 //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
3009 // /*toChars()*/"", type->toChars(), offset);
3010 Expression *e = NULL;
3011 int i = getFieldIndex(type, offset);
3013 if (i != -1)
3015 //printf("\ti = %d\n", i);
3016 assert(i < elements->dim);
3017 e = (Expression *)elements->data[i];
3018 if (e)
3020 e = e->copy();
3021 e->type = type;
3024 return e;
3027 /************************************
3028 * Get index of field.
3029 * Returns -1 if not found.
3032 int StructLiteralExp::getFieldIndex(Type *type, unsigned offset)
3034 /* Find which field offset is by looking at the field offsets
3036 for (size_t i = 0; i < sd->fields.dim; i++)
3038 Dsymbol *s = (Dsymbol *)sd->fields.data[i];
3039 VarDeclaration *v = s->isVarDeclaration();
3040 assert(v);
3042 if (offset == v->offset &&
3043 type->size() == v->type->size())
3044 { Expression *e = (Expression *)elements->data[i];
3045 if (e)
3047 return i;
3049 break;
3052 return -1;
3056 Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e)
3058 return this;
3062 int StructLiteralExp::checkSideEffect(int flag)
3063 { int f = 0;
3065 for (size_t i = 0; i < elements->dim; i++)
3066 { Expression *e = (Expression *)elements->data[i];
3067 if (!e)
3068 continue;
3070 f |= e->checkSideEffect(2);
3072 if (flag == 0 && f == 0)
3073 Expression::checkSideEffect(0);
3074 return f;
3077 int StructLiteralExp::canThrow()
3079 return arrayExpressionCanThrow(elements);
3082 void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3084 buf->writestring(sd->toChars());
3085 buf->writeByte('(');
3086 argsToCBuffer(buf, elements, hgs);
3087 buf->writeByte(')');
3090 void StructLiteralExp::toMangleBuffer(OutBuffer *buf)
3092 size_t dim = elements ? elements->dim : 0;
3093 buf->printf("S%u", dim);
3094 for (size_t i = 0; i < dim; i++)
3095 { Expression *e = (Expression *)elements->data[i];
3096 if (e)
3097 e->toMangleBuffer(buf);
3098 else
3099 buf->writeByte('v'); // 'v' for void
3103 /************************ TypeDotIdExp ************************************/
3105 /* Things like:
3106 * int.size
3107 * foo.size
3108 * (foo).size
3109 * cast(foo).size
3112 TypeDotIdExp::TypeDotIdExp(Loc loc, Type *type, Identifier *ident)
3113 : Expression(loc, TOKtypedot, sizeof(TypeDotIdExp))
3115 this->type = type;
3116 this->ident = ident;
3119 Expression *TypeDotIdExp::syntaxCopy()
3121 TypeDotIdExp *te = new TypeDotIdExp(loc, type->syntaxCopy(), ident);
3122 return te;
3125 Expression *TypeDotIdExp::semantic(Scope *sc)
3126 { Expression *e;
3128 #if LOGSEMANTIC
3129 printf("TypeDotIdExp::semantic()\n");
3130 #endif
3131 e = new DotIdExp(loc, new TypeExp(loc, type), ident);
3132 e = e->semantic(sc);
3133 return e;
3136 void TypeDotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3138 buf->writeByte('(');
3139 type->toCBuffer(buf, NULL, hgs);
3140 buf->writeByte(')');
3141 buf->writeByte('.');
3142 buf->writestring(ident->toChars());
3145 /************************************************************/
3147 // Mainly just a placeholder
3149 TypeExp::TypeExp(Loc loc, Type *type)
3150 : Expression(loc, TOKtype, sizeof(TypeExp))
3152 //printf("TypeExp::TypeExp(%s)\n", type->toChars());
3153 this->type = type;
3156 Expression *TypeExp::semantic(Scope *sc)
3158 //printf("TypeExp::semantic(%s)\n", type->toChars());
3159 type = type->semantic(loc, sc);
3160 return this;
3163 void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3165 type->toCBuffer(buf, NULL, hgs);
3168 /************************************************************/
3170 // Mainly just a placeholder
3172 ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg)
3173 : Expression(loc, TOKimport, sizeof(ScopeExp))
3175 //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars());
3176 //static int count; if (++count == 38) *(char*)0=0;
3177 this->sds = pkg;
3180 Expression *ScopeExp::syntaxCopy()
3182 ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL));
3183 return se;
3186 Expression *ScopeExp::semantic(Scope *sc)
3188 TemplateInstance *ti;
3189 ScopeDsymbol *sds2;
3191 #if LOGSEMANTIC
3192 printf("+ScopeExp::semantic('%s')\n", toChars());
3193 #endif
3194 Lagain:
3195 ti = sds->isTemplateInstance();
3196 if (ti && !global.errors)
3197 { Dsymbol *s;
3198 if (!ti->semanticdone)
3199 ti->semantic(sc);
3200 s = ti->inst->toAlias();
3201 sds2 = s->isScopeDsymbol();
3202 if (!sds2)
3203 { Expression *e;
3205 //printf("s = %s, '%s'\n", s->kind(), s->toChars());
3206 if (ti->withsym)
3208 // Same as wthis.s
3209 e = new VarExp(loc, ti->withsym->withstate->wthis);
3210 e = new DotVarExp(loc, e, s->isDeclaration());
3212 else
3213 e = new DsymbolExp(loc, s);
3214 e = e->semantic(sc);
3215 //printf("-1ScopeExp::semantic()\n");
3216 return e;
3218 if (sds2 != sds)
3220 sds = sds2;
3221 goto Lagain;
3223 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3225 else
3227 //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3228 //printf("\tparent = '%s'\n", sds->parent->toChars());
3229 sds->semantic(sc);
3231 type = Type::tvoid;
3232 //printf("-2ScopeExp::semantic() %s\n", toChars());
3233 return this;
3236 void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3238 if (sds->isTemplateInstance())
3240 sds->toCBuffer(buf, hgs);
3242 else
3244 buf->writestring(sds->kind());
3245 buf->writestring(" ");
3246 buf->writestring(sds->toChars());
3250 /********************** TemplateExp **************************************/
3252 // Mainly just a placeholder
3254 TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td)
3255 : Expression(loc, TOKtemplate, sizeof(TemplateExp))
3257 //printf("TemplateExp(): %s\n", td->toChars());
3258 this->td = td;
3261 void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3263 buf->writestring(td->toChars());
3266 void TemplateExp::rvalue()
3268 error("template %s has no value", toChars());
3271 /********************** NewExp **************************************/
3273 NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
3274 Type *newtype, Expressions *arguments)
3275 : Expression(loc, TOKnew, sizeof(NewExp))
3277 this->thisexp = thisexp;
3278 this->newargs = newargs;
3279 this->newtype = newtype;
3280 this->arguments = arguments;
3281 member = NULL;
3282 allocator = NULL;
3283 onstack = 0;
3286 Expression *NewExp::syntaxCopy()
3288 return new NewExp(loc,
3289 thisexp ? thisexp->syntaxCopy() : NULL,
3290 arraySyntaxCopy(newargs),
3291 newtype->syntaxCopy(), arraySyntaxCopy(arguments));
3295 Expression *NewExp::semantic(Scope *sc)
3296 { int i;
3297 Type *tb;
3298 ClassDeclaration *cdthis = NULL;
3300 #if LOGSEMANTIC
3301 printf("NewExp::semantic() %s\n", toChars());
3302 if (thisexp)
3303 printf("\tthisexp = %s\n", thisexp->toChars());
3304 printf("\tnewtype: %s\n", newtype->toChars());
3305 #endif
3306 if (type) // if semantic() already run
3307 return this;
3309 Lagain:
3310 if (thisexp)
3311 { thisexp = thisexp->semantic(sc);
3312 cdthis = thisexp->type->isClassHandle();
3313 if (cdthis)
3315 sc = sc->push(cdthis);
3316 type = newtype->semantic(loc, sc);
3317 sc = sc->pop();
3319 else
3321 error("'this' for nested class must be a class type, not %s", thisexp->type->toChars());
3322 type = newtype->semantic(loc, sc);
3325 else
3326 type = newtype->semantic(loc, sc);
3327 newtype = type; // in case type gets cast to something else
3328 tb = type->toBasetype();
3329 //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco);
3331 arrayExpressionSemantic(newargs, sc);
3332 preFunctionArguments(loc, sc, newargs);
3333 arrayExpressionSemantic(arguments, sc);
3334 preFunctionArguments(loc, sc, arguments);
3336 if (thisexp && tb->ty != Tclass)
3337 error("e.new is only for allocating nested classes, not %s", tb->toChars());
3339 if (tb->ty == Tclass)
3340 { TypeFunction *tf;
3342 TypeClass *tc = (TypeClass *)(tb);
3343 ClassDeclaration *cd = tc->sym->isClassDeclaration();
3344 if (cd->isInterfaceDeclaration())
3345 error("cannot create instance of interface %s", cd->toChars());
3346 else if (cd->isAbstract())
3347 { error("cannot create instance of abstract class %s", cd->toChars());
3348 for (int i = 0; i < cd->vtbl.dim; i++)
3349 { FuncDeclaration *fd = ((Dsymbol *)cd->vtbl.data[i])->isFuncDeclaration();
3350 if (fd && fd->isAbstract())
3351 error("function %s is abstract", fd->toChars());
3354 checkDeprecated(sc, cd);
3355 if (cd->isNested())
3356 { /* We need a 'this' pointer for the nested class.
3357 * Ensure we have the right one.
3359 Dsymbol *s = cd->toParent2();
3360 ClassDeclaration *cdn = s->isClassDeclaration();
3361 FuncDeclaration *fdn = s->isFuncDeclaration();
3363 //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
3364 if (cdn)
3366 if (!cdthis)
3368 // Supply an implicit 'this' and try again
3369 thisexp = new ThisExp(loc);
3370 for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
3371 { if (!sp)
3373 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
3374 break;
3376 ClassDeclaration *cdp = sp->isClassDeclaration();
3377 if (!cdp)
3378 continue;
3379 if (cdp == cdn || cdn->isBaseOf(cdp, NULL))
3380 break;
3381 // Add a '.outer' and try again
3382 thisexp = new DotIdExp(loc, thisexp, Id::outer);
3384 if (!global.errors)
3385 goto Lagain;
3387 if (cdthis)
3389 //printf("cdthis = %s\n", cdthis->toChars());
3390 if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL))
3391 error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars());
3393 #if 0
3394 else
3396 for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration())
3398 if (!sf)
3400 error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
3401 break;
3403 printf("sf = %s\n", sf->toChars());
3404 AggregateDeclaration *ad = sf->isThis();
3405 if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL)))
3406 break;
3409 #endif
3411 else if (fdn)
3412 { /* The nested class cd is nested inside a function,
3413 * we'll let getEthis() look for errors.
3415 //printf("nested class %s is nested inside function %s, we're in %s\n", cd->toChars(), fdn->toChars(), sc->func->toChars());
3416 if (thisexp)
3417 // Because thisexp cannot be a function frame pointer
3418 error("e.new is only for allocating nested classes");
3420 else
3421 assert(0);
3423 else if (thisexp)
3424 error("e.new is only for allocating nested classes");
3426 FuncDeclaration *f = cd->ctor;
3427 if (f)
3429 assert(f);
3430 f = f->overloadResolve(loc, NULL, arguments);
3431 checkDeprecated(sc, f);
3432 member = f->isCtorDeclaration();
3433 assert(member);
3435 cd->accessCheck(loc, sc, member);
3437 tf = (TypeFunction *)f->type;
3438 // type = tf->next;
3440 if (!arguments)
3441 arguments = new Expressions();
3442 functionArguments(loc, sc, tf, arguments);
3444 else
3446 if (arguments && arguments->dim)
3447 error("no constructor for %s", cd->toChars());
3450 if (cd->aggNew)
3451 { Expression *e;
3453 f = cd->aggNew;
3455 // Prepend the uint size argument to newargs[]
3456 e = new IntegerExp(loc, cd->size(loc), Type::tsize_t);
3457 if (!newargs)
3458 newargs = new Expressions();
3459 newargs->shift(e);
3461 f = f->overloadResolve(loc, NULL, newargs);
3462 allocator = f->isNewDeclaration();
3463 assert(allocator);
3465 tf = (TypeFunction *)f->type;
3466 functionArguments(loc, sc, tf, newargs);
3468 else
3470 if (newargs && newargs->dim)
3471 error("no allocator for %s", cd->toChars());
3475 else if (tb->ty == Tstruct)
3477 TypeStruct *ts = (TypeStruct *)tb;
3478 StructDeclaration *sd = ts->sym;
3479 FuncDeclaration *f = sd->aggNew;
3480 TypeFunction *tf;
3482 if (arguments && arguments->dim)
3483 error("no constructor for %s", type->toChars());
3485 if (f)
3487 Expression *e;
3489 // Prepend the uint size argument to newargs[]
3490 e = new IntegerExp(loc, sd->size(loc), Type::tsize_t);
3491 if (!newargs)
3492 newargs = new Expressions();
3493 newargs->shift(e);
3495 f = f->overloadResolve(loc, NULL, newargs);
3496 allocator = f->isNewDeclaration();
3497 assert(allocator);
3499 tf = (TypeFunction *)f->type;
3500 functionArguments(loc, sc, tf, newargs);
3502 e = new VarExp(loc, f);
3503 e = new CallExp(loc, e, newargs);
3504 e = e->semantic(sc);
3505 e->type = type->pointerTo();
3506 return e;
3509 type = type->pointerTo();
3511 else if (tb->ty == Tarray && (arguments && arguments->dim))
3513 for (size_t i = 0; i < arguments->dim; i++)
3515 if (tb->ty != Tarray)
3516 { error("too many arguments for array");
3517 arguments->dim = i;
3518 break;
3521 Expression *arg = (Expression *)arguments->data[i];
3522 arg = resolveProperties(sc, arg);
3523 arg = arg->implicitCastTo(sc, Type::tsize_t);
3524 arg = arg->optimize(WANTvalue);
3525 if (arg->op == TOKint64 && (long long)arg->toInteger() < 0)
3526 error("negative array index %s", arg->toChars());
3527 arguments->data[i] = (void *) arg;
3528 tb = ((TypeDArray *)tb)->next->toBasetype();
3531 else if (tb->isscalar())
3533 if (arguments && arguments->dim)
3534 error("no constructor for %s", type->toChars());
3536 type = type->pointerTo();
3538 else
3540 error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars());
3541 type = type->pointerTo();
3544 //printf("NewExp: '%s'\n", toChars());
3545 //printf("NewExp:type '%s'\n", type->toChars());
3547 return this;
3550 int NewExp::checkSideEffect(int flag)
3552 return 1;
3555 int NewExp::canThrow()
3557 return 1;
3560 void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3561 { int i;
3563 if (thisexp)
3564 { expToCBuffer(buf, hgs, thisexp, PREC_primary);
3565 buf->writeByte('.');
3567 buf->writestring("new ");
3568 if (newargs && newargs->dim)
3570 buf->writeByte('(');
3571 argsToCBuffer(buf, newargs, hgs);
3572 buf->writeByte(')');
3574 newtype->toCBuffer(buf, NULL, hgs);
3575 if (arguments && arguments->dim)
3577 buf->writeByte('(');
3578 argsToCBuffer(buf, arguments, hgs);
3579 buf->writeByte(')');
3583 /********************** NewAnonClassExp **************************************/
3585 NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp,
3586 Expressions *newargs, ClassDeclaration *cd, Expressions *arguments)
3587 : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp))
3589 this->thisexp = thisexp;
3590 this->newargs = newargs;
3591 this->cd = cd;
3592 this->arguments = arguments;
3595 Expression *NewAnonClassExp::syntaxCopy()
3597 return new NewAnonClassExp(loc,
3598 thisexp ? thisexp->syntaxCopy() : NULL,
3599 arraySyntaxCopy(newargs),
3600 (ClassDeclaration *)cd->syntaxCopy(NULL),
3601 arraySyntaxCopy(arguments));
3605 Expression *NewAnonClassExp::semantic(Scope *sc)
3607 #if LOGSEMANTIC
3608 printf("NewAnonClassExp::semantic() %s\n", toChars());
3609 //printf("type: %s\n", type->toChars());
3610 #endif
3612 Expression *d = new DeclarationExp(loc, cd);
3613 d = d->semantic(sc);
3615 Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments);
3617 Expression *c = new CommaExp(loc, d, n);
3618 return c->semantic(sc);
3621 int NewAnonClassExp::checkSideEffect(int flag)
3623 return 1;
3626 int NewAnonClassExp::canThrow()
3628 return 1;
3631 void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3632 { int i;
3634 if (thisexp)
3635 { expToCBuffer(buf, hgs, thisexp, PREC_primary);
3636 buf->writeByte('.');
3638 buf->writestring("new");
3639 if (newargs && newargs->dim)
3641 buf->writeByte('(');
3642 argsToCBuffer(buf, newargs, hgs);
3643 buf->writeByte(')');
3645 buf->writestring(" class ");
3646 if (arguments && arguments->dim)
3648 buf->writeByte('(');
3649 argsToCBuffer(buf, arguments, hgs);
3650 buf->writeByte(')');
3652 //buf->writestring(" { }");
3653 if (cd)
3655 cd->toCBuffer(buf, hgs);
3659 /********************** SymOffExp **************************************/
3661 SymbolExp::SymbolExp(Loc loc, enum TOK op, int size, Declaration *var, int hasOverloads)
3662 : Expression(loc, op, size)
3664 assert(var);
3665 this->var = var;
3666 this->hasOverloads = hasOverloads;
3669 /********************** SymOffExp **************************************/
3671 SymOffExp::SymOffExp(Loc loc, Declaration *var, target_size_t offset, int hasOverloads)
3672 : SymbolExp(loc, TOKsymoff, sizeof(SymOffExp), var, hasOverloads)
3674 this->offset = offset;
3676 VarDeclaration *v = var->isVarDeclaration();
3677 if (v && v->needThis())
3678 error("need 'this' for address of %s", v->toChars());
3681 Expression *SymOffExp::semantic(Scope *sc)
3683 #if LOGSEMANTIC
3684 printf("SymOffExp::semantic('%s')\n", toChars());
3685 #endif
3686 //var->semantic(sc);
3687 if (!type)
3688 type = var->type->pointerTo();
3689 VarDeclaration *v = var->isVarDeclaration();
3690 if (v)
3691 v->checkNestedReference(sc, loc);
3692 return this;
3695 int SymOffExp::isBool(int result)
3697 return result ? TRUE : FALSE;
3700 void SymOffExp::checkEscape()
3702 VarDeclaration *v = var->isVarDeclaration();
3703 if (v)
3705 if (!v->isDataseg())
3706 error("escaping reference to local variable %s", v->toChars());
3710 void SymOffExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3712 if (offset)
3713 buf->printf("(& %s+%"PRIuTSIZE")", var->toChars(), offset);
3714 else
3715 buf->printf("& %s", var->toChars());
3718 /******************************** VarExp **************************/
3720 VarExp::VarExp(Loc loc, Declaration *var, int hasOverloads)
3721 : SymbolExp(loc, TOKvar, sizeof(VarExp), var, hasOverloads)
3723 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
3724 //if (strcmp(var->ident->toChars(), "func") == 0) halt();
3725 this->type = var->type;
3728 int VarExp::equals(Object *o)
3729 { VarExp *ne;
3731 if (this == o ||
3732 (((Expression *)o)->op == TOKvar &&
3733 ((ne = (VarExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
3734 var == ne->var))
3735 return 1;
3736 return 0;
3739 Expression *VarExp::semantic(Scope *sc)
3740 { FuncLiteralDeclaration *fd;
3742 #if LOGSEMANTIC
3743 printf("VarExp::semantic(%s)\n", toChars());
3744 #endif
3745 if (!type)
3746 { type = var->type;
3747 #if 0
3748 if (var->storage_class & STClazy)
3750 TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd);
3751 type = new TypeDelegate(tf);
3752 type = type->semantic(loc, sc);
3754 #endif
3757 VarDeclaration *v = var->isVarDeclaration();
3758 if (v)
3760 #if 0
3761 if ((v->isConst() || v->isInvariant()) &&
3762 type->toBasetype()->ty != Tsarray && v->init)
3764 ExpInitializer *ei = v->init->isExpInitializer();
3765 if (ei)
3767 //ei->exp->implicitCastTo(sc, type)->print();
3768 return ei->exp->implicitCastTo(sc, type);
3771 #endif
3772 v->checkNestedReference(sc, loc);
3774 #if 0
3775 else if ((fd = var->isFuncLiteralDeclaration()) != NULL)
3776 { Expression *e;
3777 e = new FuncExp(loc, fd);
3778 e->type = type;
3779 return e;
3781 #endif
3782 return this;
3785 char *VarExp::toChars()
3787 return var->toChars();
3790 void VarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3792 buf->writestring(var->toChars());
3795 void VarExp::checkEscape()
3797 VarDeclaration *v = var->isVarDeclaration();
3798 if (v)
3799 { Type *tb = v->type->toBasetype();
3800 // if reference type
3801 if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass)
3803 if ((v->isAuto() || v->isScope()) && !v->noauto)
3804 error("escaping reference to auto local %s", v->toChars());
3805 else if (v->storage_class & STCvariadic)
3806 error("escaping reference to variadic parameter %s", v->toChars());
3811 Expression *VarExp::toLvalue(Scope *sc, Expression *e)
3813 #if 0
3814 tym = tybasic(e1->ET->Tty);
3815 if (!(tyscalar(tym) ||
3816 tym == TYstruct ||
3817 tym == TYarray && e->Eoper == TOKaddr))
3818 synerr(EM_lvalue); // lvalue expected
3819 #endif
3820 if (var->storage_class & STClazy)
3821 error("lazy variables cannot be lvalues");
3822 return this;
3825 Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
3827 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
3828 if (type && type->toBasetype()->ty == Tsarray)
3829 error("cannot change reference to static array '%s'", var->toChars());
3831 var->checkModify(loc, sc, type);
3833 // See if this expression is a modifiable lvalue (i.e. not const)
3834 return toLvalue(sc, e);
3838 /******************************** OverExp **************************/
3840 OverExp::OverExp(OverloadSet *s)
3841 : Expression(loc, TOKoverloadset, sizeof(OverExp))
3843 //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
3844 vars = s;
3845 type = Type::tvoid;
3848 Expression *OverExp::toLvalue(Scope *sc, Expression *e)
3850 return this;
3854 /******************************** TupleExp **************************/
3856 TupleExp::TupleExp(Loc loc, Expressions *exps)
3857 : Expression(loc, TOKtuple, sizeof(TupleExp))
3859 //printf("TupleExp(this = %p)\n", this);
3860 this->exps = exps;
3861 this->type = NULL;
3865 TupleExp::TupleExp(Loc loc, TupleDeclaration *tup)
3866 : Expression(loc, TOKtuple, sizeof(TupleExp))
3868 exps = new Expressions();
3869 type = NULL;
3871 exps->reserve(tup->objects->dim);
3872 for (size_t i = 0; i < tup->objects->dim; i++)
3873 { Object *o = (Object *)tup->objects->data[i];
3874 if (o->dyncast() == DYNCAST_EXPRESSION)
3876 Expression *e = (Expression *)o;
3877 e = e->syntaxCopy();
3878 exps->push(e);
3880 else if (o->dyncast() == DYNCAST_DSYMBOL)
3882 Dsymbol *s = (Dsymbol *)o;
3883 Expression *e = new DsymbolExp(loc, s);
3884 exps->push(e);
3886 else if (o->dyncast() == DYNCAST_TYPE)
3888 Type *t = (Type *)o;
3889 Expression *e = new TypeExp(loc, t);
3890 exps->push(e);
3892 else
3894 error("%s is not an expression", o->toChars());
3899 int TupleExp::equals(Object *o)
3900 { TupleExp *ne;
3902 if (this == o)
3903 return 1;
3904 if (((Expression *)o)->op == TOKtuple)
3906 TupleExp *te = (TupleExp *)o;
3907 if (exps->dim != te->exps->dim)
3908 return 0;
3909 for (size_t i = 0; i < exps->dim; i++)
3910 { Expression *e1 = (Expression *)exps->data[i];
3911 Expression *e2 = (Expression *)te->exps->data[i];
3913 if (!e1->equals(e2))
3914 return 0;
3916 return 1;
3918 return 0;
3921 Expression *TupleExp::syntaxCopy()
3923 return new TupleExp(loc, arraySyntaxCopy(exps));
3926 Expression *TupleExp::semantic(Scope *sc)
3928 #if LOGSEMANTIC
3929 printf("+TupleExp::semantic(%s)\n", toChars());
3930 #endif
3931 if (type)
3932 return this;
3934 // Run semantic() on each argument
3935 for (size_t i = 0; i < exps->dim; i++)
3936 { Expression *e = (Expression *)exps->data[i];
3938 e = e->semantic(sc);
3939 if (!e->type)
3940 { error("%s has no value", e->toChars());
3941 e->type = Type::terror;
3943 exps->data[i] = (void *)e;
3946 expandTuples(exps);
3947 if (0 && exps->dim == 1)
3949 return (Expression *)exps->data[0];
3951 type = new TypeTuple(exps);
3952 //printf("-TupleExp::semantic(%s)\n", toChars());
3953 return this;
3956 void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3958 buf->writestring("tuple(");
3959 argsToCBuffer(buf, exps, hgs);
3960 buf->writeByte(')');
3963 int TupleExp::checkSideEffect(int flag)
3964 { int f = 0;
3966 for (int i = 0; i < exps->dim; i++)
3967 { Expression *e = (Expression *)exps->data[i];
3969 f |= e->checkSideEffect(2);
3971 if (flag == 0 && f == 0)
3972 Expression::checkSideEffect(0);
3973 return f;
3976 int TupleExp::canThrow()
3978 return arrayExpressionCanThrow(exps);
3981 void TupleExp::checkEscape()
3983 for (size_t i = 0; i < exps->dim; i++)
3984 { Expression *e = (Expression *)exps->data[i];
3985 e->checkEscape();
3989 /******************************** FuncExp *********************************/
3991 FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd)
3992 : Expression(loc, TOKfunction, sizeof(FuncExp))
3994 this->fd = fd;
3997 Expression *FuncExp::syntaxCopy()
3999 return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL));
4002 Expression *FuncExp::semantic(Scope *sc)
4004 #if LOGSEMANTIC
4005 printf("FuncExp::semantic(%s)\n", toChars());
4006 #endif
4007 if (!type)
4009 fd->semantic(sc);
4010 fd->parent = sc->parent;
4011 if (global.errors)
4014 else
4016 fd->semantic2(sc);
4017 if (!global.errors)
4019 fd->semantic3(sc);
4021 if (!global.errors && global.params.useInline)
4022 fd->inlineScan();
4026 // Type is a "delegate to" or "pointer to" the function literal
4027 if (fd->isNested())
4029 type = new TypeDelegate(fd->type);
4030 type = type->semantic(loc, sc);
4032 else
4034 type = fd->type->pointerTo();
4036 fd->tookAddressOf++;
4038 return this;
4041 char *FuncExp::toChars()
4043 return fd->toChars();
4046 void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4048 buf->writestring(fd->toChars());
4052 /******************************** DeclarationExp **************************/
4054 DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration)
4055 : Expression(loc, TOKdeclaration, sizeof(DeclarationExp))
4057 this->declaration = declaration;
4060 Expression *DeclarationExp::syntaxCopy()
4062 return new DeclarationExp(loc, declaration->syntaxCopy(NULL));
4065 Expression *DeclarationExp::semantic(Scope *sc)
4067 if (type)
4068 return this;
4070 #if LOGSEMANTIC
4071 printf("DeclarationExp::semantic() %s\n", toChars());
4072 #endif
4074 /* This is here to support extern(linkage) declaration,
4075 * where the extern(linkage) winds up being an AttribDeclaration
4076 * wrapper.
4078 Dsymbol *s = declaration;
4080 AttribDeclaration *ad = declaration->isAttribDeclaration();
4081 if (ad)
4083 if (ad->decl && ad->decl->dim == 1)
4084 s = (Dsymbol *)ad->decl->data[0];
4087 if (s->isVarDeclaration())
4088 { // Do semantic() on initializer first, so:
4089 // int a = a;
4090 // will be illegal.
4091 declaration->semantic(sc);
4092 s->parent = sc->parent;
4095 //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc);
4096 // Insert into both local scope and function scope.
4097 // Must be unique in both.
4098 if (s->ident)
4100 if (!sc->insert(s))
4101 error("declaration %s is already defined", s->toPrettyChars());
4102 else if (sc->func)
4103 { VarDeclaration *v = s->isVarDeclaration();
4104 if (s->isFuncDeclaration() &&
4105 !sc->func->localsymtab->insert(s))
4106 error("declaration %s is already defined in another scope in %s", s->toPrettyChars(), sc->func->toChars());
4107 else if (!global.params.useDeprecated)
4108 { // Disallow shadowing
4110 for (Scope *scx = sc->enclosing; scx && scx->func == sc->func; scx = scx->enclosing)
4111 { Dsymbol *s2;
4113 if (scx->scopesym && scx->scopesym->symtab &&
4114 (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL &&
4115 s != s2)
4117 error("shadowing declaration %s is deprecated", s->toPrettyChars());
4123 if (!s->isVarDeclaration())
4125 declaration->semantic(sc);
4126 s->parent = sc->parent;
4128 if (!global.errors)
4130 declaration->semantic2(sc);
4131 if (!global.errors)
4133 declaration->semantic3(sc);
4135 if (!global.errors && global.params.useInline)
4136 declaration->inlineScan();
4140 type = Type::tvoid;
4141 return this;
4144 int DeclarationExp::checkSideEffect(int flag)
4146 return 1;
4149 int DeclarationExp::canThrow()
4151 VarDeclaration *v = declaration->isVarDeclaration();
4152 if (v && v->init)
4153 { ExpInitializer *ie = v->init->isExpInitializer();
4154 return ie && ie->exp->canThrow();
4156 return 0;
4159 void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4161 declaration->toCBuffer(buf, hgs);
4165 /************************ TypeidExp ************************************/
4168 * typeid(int)
4171 TypeidExp::TypeidExp(Loc loc, Type *typeidType)
4172 : Expression(loc, TOKtypeid, sizeof(TypeidExp))
4174 this->typeidType = typeidType;
4178 Expression *TypeidExp::syntaxCopy()
4180 return new TypeidExp(loc, typeidType->syntaxCopy());
4184 Expression *TypeidExp::semantic(Scope *sc)
4185 { Expression *e;
4187 #if LOGSEMANTIC
4188 printf("TypeidExp::semantic()\n");
4189 #endif
4190 typeidType = typeidType->semantic(loc, sc);
4191 e = typeidType->getTypeInfo(sc);
4192 return e;
4195 void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4197 buf->writestring("typeid(");
4198 typeidType->toCBuffer(buf, NULL, hgs);
4199 buf->writeByte(')');
4202 /************************ TraitsExp ************************************/
4205 * __traits(identifier, args...)
4208 TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args)
4209 : Expression(loc, TOKtraits, sizeof(TraitsExp))
4211 this->ident = ident;
4212 this->args = args;
4216 Expression *TraitsExp::syntaxCopy()
4218 return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args));
4222 void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4224 buf->writestring("__traits(");
4225 buf->writestring(ident->toChars());
4226 if (args)
4228 for (int i = 0; i < args->dim; i++)
4230 buf->writeByte(',');
4231 Object *oarg = (Object *)args->data[i];
4232 ObjectToCBuffer(buf, hgs, oarg);
4235 buf->writeByte(')');
4238 /************************************************************/
4240 HaltExp::HaltExp(Loc loc)
4241 : Expression(loc, TOKhalt, sizeof(HaltExp))
4245 Expression *HaltExp::semantic(Scope *sc)
4247 #if LOGSEMANTIC
4248 printf("HaltExp::semantic()\n");
4249 #endif
4250 type = Type::tvoid;
4251 return this;
4254 int HaltExp::checkSideEffect(int flag)
4256 return 1;
4259 void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4261 buf->writestring("halt");
4264 /************************************************************/
4266 IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
4267 Type *tspec, enum TOK tok2, TemplateParameters *parameters)
4268 : Expression(loc, TOKis, sizeof(IsExp))
4270 this->targ = targ;
4271 this->id = id;
4272 this->tok = tok;
4273 this->tspec = tspec;
4274 this->tok2 = tok2;
4275 this->parameters = parameters;
4278 Expression *IsExp::syntaxCopy()
4280 // This section is identical to that in TemplateDeclaration::syntaxCopy()
4281 TemplateParameters *p = NULL;
4282 if (parameters)
4284 p = new TemplateParameters();
4285 p->setDim(parameters->dim);
4286 for (int i = 0; i < p->dim; i++)
4287 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
4288 p->data[i] = (void *)tp->syntaxCopy();
4292 return new IsExp(loc,
4293 targ->syntaxCopy(),
4295 tok,
4296 tspec ? tspec->syntaxCopy() : NULL,
4297 tok2,
4301 Expression *IsExp::semantic(Scope *sc)
4302 { Type *tded;
4304 /* is(targ id tok tspec)
4305 * is(targ id == tok2)
4308 //printf("IsExp::semantic(%s)\n", toChars());
4309 if (id && !(sc->flags & SCOPEstaticif))
4310 error("can only declare type aliases within static if conditionals");
4312 unsigned errors_save = global.errors;
4313 global.errors = 0;
4314 global.gag++; // suppress printing of error messages
4315 targ = targ->semantic(loc, sc);
4316 global.gag--;
4317 unsigned gerrors = global.errors;
4318 global.errors = errors_save;
4320 if (gerrors) // if any errors happened
4321 { // then condition is false
4322 goto Lno;
4324 else if (tok2 != TOKreserved)
4326 switch (tok2)
4328 case TOKtypedef:
4329 if (targ->ty != Ttypedef)
4330 goto Lno;
4331 tded = ((TypeTypedef *)targ)->sym->basetype;
4332 break;
4334 case TOKstruct:
4335 if (targ->ty != Tstruct)
4336 goto Lno;
4337 if (((TypeStruct *)targ)->sym->isUnionDeclaration())
4338 goto Lno;
4339 tded = targ;
4340 break;
4342 case TOKunion:
4343 if (targ->ty != Tstruct)
4344 goto Lno;
4345 if (!((TypeStruct *)targ)->sym->isUnionDeclaration())
4346 goto Lno;
4347 tded = targ;
4348 break;
4350 case TOKclass:
4351 if (targ->ty != Tclass)
4352 goto Lno;
4353 if (((TypeClass *)targ)->sym->isInterfaceDeclaration())
4354 goto Lno;
4355 tded = targ;
4356 break;
4358 case TOKinterface:
4359 if (targ->ty != Tclass)
4360 goto Lno;
4361 if (!((TypeClass *)targ)->sym->isInterfaceDeclaration())
4362 goto Lno;
4363 tded = targ;
4364 break;
4366 #if V2
4367 case TOKconst:
4368 if (!targ->isConst())
4369 goto Lno;
4370 tded = targ;
4371 break;
4373 case TOKinvariant:
4374 if (!targ->isInvariant())
4375 goto Lno;
4376 tded = targ;
4377 break;
4378 #endif
4380 case TOKsuper:
4381 // If class or interface, get the base class and interfaces
4382 if (targ->ty != Tclass)
4383 goto Lno;
4384 else
4385 { ClassDeclaration *cd = ((TypeClass *)targ)->sym;
4386 Arguments *args = new Arguments;
4387 args->reserve(cd->baseclasses.dim);
4388 for (size_t i = 0; i < cd->baseclasses.dim; i++)
4389 { BaseClass *b = (BaseClass *)cd->baseclasses.data[i];
4390 args->push(new Argument(STCin, b->type, NULL, NULL));
4392 tded = new TypeTuple(args);
4394 break;
4396 case TOKenum:
4397 if (targ->ty != Tenum)
4398 goto Lno;
4399 tded = ((TypeEnum *)targ)->sym->memtype;
4400 break;
4402 case TOKdelegate:
4403 if (targ->ty != Tdelegate)
4404 goto Lno;
4405 tded = ((TypeDelegate *)targ)->next; // the underlying function type
4406 break;
4408 case TOKfunction:
4410 if (targ->ty != Tfunction)
4411 goto Lno;
4412 tded = targ;
4414 /* Generate tuple from function parameter types.
4416 assert(tded->ty == Tfunction);
4417 Arguments *params = ((TypeFunction *)tded)->parameters;
4418 size_t dim = Argument::dim(params);
4419 Arguments *args = new Arguments;
4420 args->reserve(dim);
4421 for (size_t i = 0; i < dim; i++)
4422 { Argument *arg = Argument::getNth(params, i);
4423 assert(arg && arg->type);
4424 args->push(new Argument(arg->storageClass, arg->type, NULL, NULL));
4426 tded = new TypeTuple(args);
4427 break;
4429 case TOKreturn:
4430 /* Get the 'return type' for the function,
4431 * delegate, or pointer to function.
4433 if (targ->ty == Tfunction)
4434 tded = ((TypeFunction *)targ)->next;
4435 else if (targ->ty == Tdelegate)
4436 { tded = ((TypeDelegate *)targ)->next;
4437 tded = ((TypeFunction *)tded)->next;
4439 else if (targ->ty == Tpointer &&
4440 ((TypePointer *)targ)->next->ty == Tfunction)
4441 { tded = ((TypePointer *)targ)->next;
4442 tded = ((TypeFunction *)tded)->next;
4444 else
4445 goto Lno;
4446 break;
4448 default:
4449 assert(0);
4451 goto Lyes;
4453 else if (id && tspec)
4455 /* Evaluate to TRUE if targ matches tspec.
4456 * If TRUE, declare id as an alias for the specialized type.
4459 MATCH m;
4460 assert(parameters && parameters->dim);
4462 Objects dedtypes;
4463 dedtypes.setDim(parameters->dim);
4464 dedtypes.zero();
4466 m = targ->deduceType(NULL, tspec, parameters, &dedtypes);
4467 if (m == MATCHnomatch ||
4468 (m != MATCHexact && tok == TOKequal))
4469 goto Lno;
4470 else
4472 tded = (Type *)dedtypes.data[0];
4473 if (!tded)
4474 tded = targ;
4476 Objects tiargs;
4477 tiargs.setDim(1);
4478 tiargs.data[0] = (void *)targ;
4480 for (int i = 1; i < parameters->dim; i++)
4481 { TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
4482 Declaration *s;
4484 m = tp->matchArg(sc, &tiargs, i, parameters, &dedtypes, &s);
4485 if (m == MATCHnomatch)
4486 goto Lno;
4487 s->semantic(sc);
4488 if (!sc->insert(s))
4489 error("declaration %s is already defined", s->toChars());
4490 #if 0
4491 Object *o = (Object *)dedtypes.data[i];
4492 Dsymbol *s = TemplateDeclaration::declareParameter(loc, sc, tp, o);
4493 #endif
4494 if (sc->sd)
4495 s->addMember(sc, sc->sd, 1);
4498 goto Lyes;
4501 else if (id)
4503 /* Declare id as an alias for type targ. Evaluate to TRUE
4505 tded = targ;
4506 goto Lyes;
4508 else if (tspec)
4510 /* Evaluate to TRUE if targ matches tspec
4512 tspec = tspec->semantic(loc, sc);
4513 //printf("targ = %s\n", targ->toChars());
4514 //printf("tspec = %s\n", tspec->toChars());
4515 if (tok == TOKcolon)
4516 { if (targ->implicitConvTo(tspec))
4517 goto Lyes;
4518 else
4519 goto Lno;
4521 else /* == */
4522 { if (targ->equals(tspec))
4523 goto Lyes;
4524 else
4525 goto Lno;
4529 Lyes:
4530 if (id)
4532 Dsymbol *s = new AliasDeclaration(loc, id, tded);
4533 s->semantic(sc);
4534 if (!sc->insert(s))
4535 error("declaration %s is already defined", s->toChars());
4536 if (sc->sd)
4537 s->addMember(sc, sc->sd, 1);
4539 return new IntegerExp(loc, 1, Type::tbool);
4541 Lno:
4542 return new IntegerExp(loc, 0, Type::tbool);
4545 void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4547 buf->writestring("is(");
4548 targ->toCBuffer(buf, id, hgs);
4549 if (tok2 != TOKreserved)
4551 buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2));
4553 else if (tspec)
4555 if (tok == TOKcolon)
4556 buf->writestring(" : ");
4557 else
4558 buf->writestring(" == ");
4559 tspec->toCBuffer(buf, NULL, hgs);
4561 if (parameters)
4562 { // First parameter is already output, so start with second
4563 for (int i = 1; i < parameters->dim; i++)
4565 buf->writeByte(',');
4566 TemplateParameter *tp = (TemplateParameter *)parameters->data[i];
4567 tp->toCBuffer(buf, hgs);
4570 buf->writeByte(')');
4574 /************************************************************/
4576 UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1)
4577 : Expression(loc, op, size)
4579 this->e1 = e1;
4582 Expression *UnaExp::syntaxCopy()
4583 { UnaExp *e;
4585 e = (UnaExp *)copy();
4586 e->type = NULL;
4587 e->e1 = e->e1->syntaxCopy();
4588 return e;
4591 Expression *UnaExp::semantic(Scope *sc)
4593 #if LOGSEMANTIC
4594 printf("UnaExp::semantic('%s')\n", toChars());
4595 #endif
4596 e1 = e1->semantic(sc);
4597 // if (!e1->type)
4598 // error("%s has no value", e1->toChars());
4599 return this;
4602 int UnaExp::canThrow()
4604 return e1->canThrow();
4607 void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4609 buf->writestring(Token::toChars(op));
4610 expToCBuffer(buf, hgs, e1, precedence[op]);
4613 /************************************************************/
4615 BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2)
4616 : Expression(loc, op, size)
4618 this->e1 = e1;
4619 this->e2 = e2;
4622 Expression *BinExp::syntaxCopy()
4623 { BinExp *e;
4625 e = (BinExp *)copy();
4626 e->type = NULL;
4627 e->e1 = e->e1->syntaxCopy();
4628 e->e2 = e->e2->syntaxCopy();
4629 return e;
4632 Expression *BinExp::semantic(Scope *sc)
4634 #if LOGSEMANTIC
4635 printf("BinExp::semantic('%s')\n", toChars());
4636 #endif
4637 e1 = e1->semantic(sc);
4638 if (!e1->type)
4640 error("%s has no value", e1->toChars());
4641 e1->type = Type::terror;
4643 e2 = e2->semantic(sc);
4644 if (!e2->type)
4646 error("%s has no value", e2->toChars());
4647 e2->type = Type::terror;
4649 assert(e1->type);
4650 return this;
4653 Expression *BinExp::semanticp(Scope *sc)
4655 BinExp::semantic(sc);
4656 e1 = resolveProperties(sc, e1);
4657 e2 = resolveProperties(sc, e2);
4658 return this;
4661 /***************************
4662 * Common semantic routine for some xxxAssignExp's.
4665 Expression *BinExp::commonSemanticAssign(Scope *sc)
4666 { Expression *e;
4668 if (!type)
4670 BinExp::semantic(sc);
4671 e2 = resolveProperties(sc, e2);
4673 e = op_overload(sc);
4674 if (e)
4675 return e;
4677 e1 = e1->modifiableLvalue(sc, e1);
4678 e1->checkScalar();
4679 type = e1->type;
4680 if (type->toBasetype()->ty == Tbool)
4682 error("operator not allowed on bool expression %s", toChars());
4684 typeCombine(sc);
4685 e1->checkArithmetic();
4686 e2->checkArithmetic();
4688 if (op == TOKmodass && e2->type->iscomplex())
4689 { error("cannot perform modulo complex arithmetic");
4690 return new IntegerExp(0);
4693 return this;
4696 Expression *BinExp::commonSemanticAssignIntegral(Scope *sc)
4697 { Expression *e;
4699 if (!type)
4701 BinExp::semantic(sc);
4702 e2 = resolveProperties(sc, e2);
4704 e = op_overload(sc);
4705 if (e)
4706 return e;
4708 e1 = e1->modifiableLvalue(sc, e1);
4709 e1->checkScalar();
4710 type = e1->type;
4711 if (type->toBasetype()->ty == Tbool)
4713 e2 = e2->implicitCastTo(sc, type);
4716 typeCombine(sc);
4717 e1->checkIntegral();
4718 e2->checkIntegral();
4720 return this;
4723 int BinExp::checkSideEffect(int flag)
4725 if (op == TOKplusplus ||
4726 op == TOKminusminus ||
4727 op == TOKassign ||
4728 op == TOKconstruct ||
4729 op == TOKblit ||
4730 op == TOKaddass ||
4731 op == TOKminass ||
4732 op == TOKcatass ||
4733 op == TOKmulass ||
4734 op == TOKdivass ||
4735 op == TOKmodass ||
4736 op == TOKshlass ||
4737 op == TOKshrass ||
4738 op == TOKushrass ||
4739 op == TOKandass ||
4740 op == TOKorass ||
4741 op == TOKxorass ||
4742 op == TOKin ||
4743 op == TOKremove)
4744 return 1;
4745 return Expression::checkSideEffect(flag);
4748 void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4750 expToCBuffer(buf, hgs, e1, precedence[op]);
4751 buf->writeByte(' ');
4752 buf->writestring(Token::toChars(op));
4753 buf->writeByte(' ');
4754 expToCBuffer(buf, hgs, e2, (enum PREC)(precedence[op] + 1));
4757 int BinExp::isunsigned()
4759 return e1->type->isunsigned() || e2->type->isunsigned();
4762 int BinExp::canThrow()
4764 return e1->canThrow() || e2->canThrow();
4767 void BinExp::incompatibleTypes()
4769 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
4770 e1->toChars(), Token::toChars(op), e2->toChars(),
4771 e1->type->toChars(), e2->type->toChars());
4774 /************************************************************/
4776 CompileExp::CompileExp(Loc loc, Expression *e)
4777 : UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
4781 Expression *CompileExp::semantic(Scope *sc)
4783 #if LOGSEMANTIC
4784 printf("CompileExp::semantic('%s')\n", toChars());
4785 #endif
4786 UnaExp::semantic(sc);
4787 e1 = resolveProperties(sc, e1);
4788 e1 = e1->optimize(WANTvalue | WANTinterpret);
4789 if (e1->op != TOKstring)
4790 { error("argument to mixin must be a string, not (%s)", e1->toChars());
4791 type = Type::terror;
4792 return this;
4794 StringExp *se = (StringExp *)e1;
4795 se = se->toUTF8(sc);
4796 Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
4797 p.loc = loc;
4798 p.nextToken();
4799 //printf("p.loc.linnum = %d\n", p.loc.linnum);
4800 Expression *e = p.parseExpression();
4801 if (p.token.value != TOKeof)
4802 error("incomplete mixin expression (%s)", se->toChars());
4803 return e->semantic(sc);
4806 void CompileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4808 buf->writestring("mixin(");
4809 expToCBuffer(buf, hgs, e1, PREC_assign);
4810 buf->writeByte(')');
4813 /************************************************************/
4815 FileExp::FileExp(Loc loc, Expression *e)
4816 : UnaExp(loc, TOKmixin, sizeof(FileExp), e)
4820 Expression *FileExp::semantic(Scope *sc)
4821 { char *name;
4822 StringExp *se;
4824 #if LOGSEMANTIC
4825 printf("FileExp::semantic('%s')\n", toChars());
4826 #endif
4827 UnaExp::semantic(sc);
4828 e1 = resolveProperties(sc, e1);
4829 e1 = e1->optimize(WANTvalue);
4830 if (e1->op != TOKstring)
4831 { error("file name argument must be a string, not (%s)", e1->toChars());
4832 goto Lerror;
4834 se = (StringExp *)e1;
4835 se = se->toUTF8(sc);
4836 name = (char *)se->string;
4838 if (!global.params.fileImppath)
4839 { error("need -Jpath switch to import text file %s", name);
4840 goto Lerror;
4843 if (name != FileName::name(name))
4844 { error("use -Jpath switch to provide path for filename %s", name);
4845 goto Lerror;
4848 name = FileName::searchPath(global.filePath, name, 0);
4849 if (!name)
4850 { error("file %s cannot be found, check -Jpath", se->toChars());
4851 goto Lerror;
4854 if (global.params.verbose)
4855 printf("file %s\t(%s)\n", se->string, name);
4857 { File f(name);
4858 if (f.read())
4859 { error("cannot read file %s", f.toChars());
4860 goto Lerror;
4862 else
4864 f.ref = 1;
4865 se = new StringExp(loc, f.buffer, f.len);
4868 Lret:
4869 return se->semantic(sc);
4871 Lerror:
4872 se = new StringExp(loc, "");
4873 goto Lret;
4876 void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4878 buf->writestring("import(");
4879 expToCBuffer(buf, hgs, e1, PREC_assign);
4880 buf->writeByte(')');
4883 /************************************************************/
4885 AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg)
4886 : UnaExp(loc, TOKassert, sizeof(AssertExp), e)
4888 this->msg = msg;
4891 Expression *AssertExp::syntaxCopy()
4893 AssertExp *ae = new AssertExp(loc, e1->syntaxCopy(),
4894 msg ? msg->syntaxCopy() : NULL);
4895 return ae;
4898 Expression *AssertExp::semantic(Scope *sc)
4900 #if LOGSEMANTIC
4901 printf("AssertExp::semantic('%s')\n", toChars());
4902 #endif
4903 UnaExp::semantic(sc);
4904 e1 = resolveProperties(sc, e1);
4905 // BUG: see if we can do compile time elimination of the Assert
4906 e1 = e1->optimize(WANTvalue);
4907 e1 = e1->checkToBoolean();
4908 if (msg)
4910 msg = msg->semantic(sc);
4911 msg = resolveProperties(sc, msg);
4912 msg = msg->implicitCastTo(sc, Type::tchar->constOf()->arrayOf());
4913 msg = msg->optimize(WANTvalue);
4915 if (e1->isBool(FALSE))
4917 FuncDeclaration *fd = sc->parent->isFuncDeclaration();
4918 fd->hasReturnExp |= 4;
4920 if (!global.params.useAssert)
4921 { Expression *e = new HaltExp(loc);
4922 e = e->semantic(sc);
4923 return e;
4926 type = Type::tvoid;
4927 return this;
4930 int AssertExp::checkSideEffect(int flag)
4932 return 1;
4935 int AssertExp::canThrow()
4937 return (global.params.useAssert != 0);
4940 void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4942 buf->writestring("assert(");
4943 expToCBuffer(buf, hgs, e1, PREC_assign);
4944 if (msg)
4946 buf->writeByte(',');
4947 expToCBuffer(buf, hgs, msg, PREC_assign);
4949 buf->writeByte(')');
4952 /************************************************************/
4954 DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident)
4955 : UnaExp(loc, TOKdot, sizeof(DotIdExp), e)
4957 this->ident = ident;
4960 Expression *DotIdExp::semantic(Scope *sc)
4961 { Expression *e;
4962 Expression *eleft;
4963 Expression *eright;
4965 #if LOGSEMANTIC
4966 printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars());
4967 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
4968 #endif
4970 //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
4972 #if 0
4973 /* Don't do semantic analysis if we'll be converting
4974 * it to a string.
4976 if (ident == Id::stringof)
4977 { char *s = e1->toChars();
4978 e = new StringExp(loc, s, strlen(s), 'c');
4979 e = e->semantic(sc);
4980 return e;
4982 #endif
4984 /* Special case: rewrite this.id and super.id
4985 * to be classtype.id and baseclasstype.id
4986 * if we have no this pointer.
4988 if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc))
4989 { ClassDeclaration *cd;
4990 StructDeclaration *sd;
4991 AggregateDeclaration *ad;
4993 ad = sc->getStructClassScope();
4994 if (ad)
4996 cd = ad->isClassDeclaration();
4997 if (cd)
4999 if (e1->op == TOKthis)
5001 e = new TypeDotIdExp(loc, cd->type, ident);
5002 return e->semantic(sc);
5004 else if (cd->baseClass && e1->op == TOKsuper)
5006 e = new TypeDotIdExp(loc, cd->baseClass->type, ident);
5007 return e->semantic(sc);
5010 else
5012 sd = ad->isStructDeclaration();
5013 if (sd)
5015 if (e1->op == TOKthis)
5017 e = new TypeDotIdExp(loc, sd->type, ident);
5018 return e->semantic(sc);
5025 UnaExp::semantic(sc);
5027 if (e1->op == TOKdotexp)
5029 DotExp *de = (DotExp *)e1;
5030 eleft = de->e1;
5031 eright = de->e2;
5033 else
5035 e1 = resolveProperties(sc, e1);
5036 eleft = NULL;
5037 eright = e1;
5040 if (e1->op == TOKtuple && ident == Id::offsetof)
5041 { /* 'distribute' the .offsetof to each of the tuple elements.
5043 TupleExp *te = (TupleExp *)e1;
5044 Expressions *exps = new Expressions();
5045 exps->setDim(te->exps->dim);
5046 for (int i = 0; i < exps->dim; i++)
5047 { Expression *e = (Expression *)te->exps->data[i];
5048 e = e->semantic(sc);
5049 e = new DotIdExp(e->loc, e, Id::offsetof);
5050 exps->data[i] = (void *)e;
5052 e = new TupleExp(loc, exps);
5053 e = e->semantic(sc);
5054 return e;
5057 if (e1->op == TOKtuple && ident == Id::length)
5059 TupleExp *te = (TupleExp *)e1;
5060 e = new IntegerExp(loc, te->exps->dim, Type::tsize_t);
5061 return e;
5064 if (eright->op == TOKimport) // also used for template alias's
5066 Dsymbol *s;
5067 ScopeExp *ie = (ScopeExp *)eright;
5069 s = ie->sds->search(loc, ident, 0);
5070 if (s)
5072 s = s->toAlias();
5073 checkDeprecated(sc, s);
5075 EnumMember *em = s->isEnumMember();
5076 if (em)
5078 e = em->value;
5079 e = e->semantic(sc);
5080 return e;
5083 VarDeclaration *v = s->isVarDeclaration();
5084 if (v)
5086 //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
5087 if (v->inuse)
5089 error("circular reference to '%s'", v->toChars());
5090 type = Type::tint32;
5091 return this;
5093 type = v->type;
5094 #if 0
5095 if (v->isConst() || v->isInvariant())
5097 if (v->init)
5099 ExpInitializer *ei = v->init->isExpInitializer();
5100 if (ei)
5102 //printf("\tei: %p (%s)\n", ei->exp, ei->exp->toChars());
5103 //ei->exp = ei->exp->semantic(sc);
5104 if (ei->exp->type == type)
5106 e = ei->exp->copy(); // make copy so we can change loc
5107 e->loc = loc;
5108 return e;
5112 else if (type->isscalar())
5114 e = type->defaultInit();
5115 e->loc = loc;
5116 return e;
5119 #endif
5120 if (v->needThis())
5122 if (!eleft)
5123 eleft = new ThisExp(loc);
5124 e = new DotVarExp(loc, eleft, v);
5125 e = e->semantic(sc);
5127 else
5129 e = new VarExp(loc, v);
5130 if (eleft)
5131 { e = new CommaExp(loc, eleft, e);
5132 e->type = v->type;
5135 return e->deref();
5138 FuncDeclaration *f = s->isFuncDeclaration();
5139 if (f)
5141 //printf("it's a function\n");
5142 if (f->needThis())
5144 if (!eleft)
5145 eleft = new ThisExp(loc);
5146 e = new DotVarExp(loc, eleft, f);
5147 e = e->semantic(sc);
5149 else
5151 e = new VarExp(loc, f, 1);
5152 if (eleft)
5153 { e = new CommaExp(loc, eleft, e);
5154 e->type = f->type;
5157 return e;
5160 Type *t = s->getType();
5161 if (t)
5163 return new TypeExp(loc, t);
5166 TupleDeclaration *tup = s->isTupleDeclaration();
5167 if (tup)
5169 if (eleft)
5170 error("cannot have e.tuple");
5171 e = new TupleExp(loc, tup);
5172 e = e->semantic(sc);
5173 return e;
5176 ScopeDsymbol *sds = s->isScopeDsymbol();
5177 if (sds)
5179 //printf("it's a ScopeDsymbol\n");
5180 e = new ScopeExp(loc, sds);
5181 e = e->semantic(sc);
5182 if (eleft)
5183 e = new DotExp(loc, eleft, e);
5184 return e;
5187 Import *imp = s->isImport();
5188 if (imp)
5190 ScopeExp *ie;
5192 ie = new ScopeExp(loc, imp->pkg);
5193 return ie->semantic(sc);
5196 // BUG: handle other cases like in IdentifierExp::semantic()
5197 #ifdef DEBUG
5198 printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind());
5199 #endif
5200 assert(0);
5202 else if (ident == Id::stringof)
5203 { char *s = ie->toChars();
5204 e = new StringExp(loc, s, strlen(s), 'c');
5205 e = e->semantic(sc);
5206 return e;
5208 error("undefined identifier %s", toChars());
5209 type = Type::tvoid;
5210 return this;
5212 else if (e1->type->ty == Tpointer &&
5213 ident != Id::init && ident != Id::__sizeof &&
5214 ident != Id::alignof && ident != Id::offsetof &&
5215 ident != Id::mangleof && ident != Id::stringof)
5217 e = new PtrExp(loc, e1);
5218 e->type = ((TypePointer *)e1->type)->next;
5219 return e->type->dotExp(sc, e, ident);
5221 else
5223 e = e1->type->dotExp(sc, e1, ident);
5224 e = e->semantic(sc);
5225 return e;
5229 void DotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5231 //printf("DotIdExp::toCBuffer()\n");
5232 expToCBuffer(buf, hgs, e1, PREC_primary);
5233 buf->writeByte('.');
5234 buf->writestring(ident->toChars());
5237 /********************** DotTemplateExp ***********************************/
5239 // Mainly just a placeholder
5241 DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td)
5242 : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e)
5245 this->td = td;
5248 void DotTemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5250 expToCBuffer(buf, hgs, e1, PREC_primary);
5251 buf->writeByte('.');
5252 buf->writestring(td->toChars());
5256 /************************************************************/
5258 DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v, int hasOverloads)
5259 : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e)
5261 //printf("DotVarExp()\n");
5262 this->var = v;
5263 this->hasOverloads = hasOverloads;
5266 Expression *DotVarExp::semantic(Scope *sc)
5268 #if LOGSEMANTIC
5269 printf("DotVarExp::semantic('%s')\n", toChars());
5270 #endif
5271 if (!type)
5273 var = var->toAlias()->isDeclaration();
5275 TupleDeclaration *tup = var->isTupleDeclaration();
5276 if (tup)
5277 { /* Replace:
5278 * e1.tuple(a, b, c)
5279 * with:
5280 * tuple(e1.a, e1.b, e1.c)
5282 Expressions *exps = new Expressions;
5284 exps->reserve(tup->objects->dim);
5285 for (size_t i = 0; i < tup->objects->dim; i++)
5286 { Object *o = (Object *)tup->objects->data[i];
5287 if (o->dyncast() != DYNCAST_EXPRESSION)
5289 error("%s is not an expression", o->toChars());
5291 else
5293 Expression *e = (Expression *)o;
5294 if (e->op != TOKdsymbol)
5295 error("%s is not a member", e->toChars());
5296 else
5297 { DsymbolExp *ve = (DsymbolExp *)e;
5299 e = new DotVarExp(loc, e1, ve->s->isDeclaration());
5300 exps->push(e);
5304 Expression *e = new TupleExp(loc, exps);
5305 e = e->semantic(sc);
5306 return e;
5309 e1 = e1->semantic(sc);
5311 type = var->type;
5312 if (!type && global.errors)
5313 { // var is goofed up, just return 0
5314 return new IntegerExp(0);
5316 assert(type);
5318 if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution
5320 Type *t1 = e1->type;
5321 if (t1->ty == Tpointer)
5322 t1 = t1->nextOf();
5323 if (t1->isConst())
5324 type = type->constOf();
5325 else if (t1->isInvariant())
5326 type = type->invariantOf();
5328 AggregateDeclaration *ad = var->toParent()->isAggregateDeclaration();
5329 e1 = getRightThis(loc, sc, ad, e1, var);
5330 if (!sc->noaccesscheck)
5331 accessCheck(loc, sc, e1, var);
5334 //printf("-DotVarExp::semantic('%s')\n", toChars());
5335 return this;
5338 Expression *DotVarExp::toLvalue(Scope *sc, Expression *e)
5340 //printf("DotVarExp::toLvalue(%s)\n", toChars());
5341 return this;
5344 Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
5346 #if 0
5347 printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
5348 printf("e1->type = %s\n", e1->type->toChars());
5349 printf("var->type = %s\n", var->type->toChars());
5350 #endif
5352 if (var->isCtorinit())
5353 { // It's only modifiable if inside the right constructor
5354 Dsymbol *s = sc->func;
5355 while (1)
5357 FuncDeclaration *fd = NULL;
5358 if (s)
5359 fd = s->isFuncDeclaration();
5360 if (fd &&
5361 ((fd->isCtorDeclaration() && var->storage_class & STCfield) ||
5362 (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) &&
5363 fd->toParent() == var->toParent() &&
5364 e1->op == TOKthis
5367 VarDeclaration *v = var->isVarDeclaration();
5368 assert(v);
5369 v->ctorinit = 1;
5370 //printf("setting ctorinit\n");
5372 else
5374 if (s)
5375 { s = s->toParent2();
5376 continue;
5378 else
5380 const char *p = var->isStatic() ? "static " : "";
5381 error("can only initialize %sconst member %s inside %sconstructor",
5382 p, var->toChars(), p);
5385 break;
5388 else
5390 Type *t1 = e1->type->toBasetype();
5392 if (!t1->isMutable() ||
5393 (t1->ty == Tpointer && !t1->nextOf()->isMutable()) ||
5394 !var->type->isMutable() ||
5395 !var->type->isAssignable() ||
5396 var->storage_class & STCmanifest
5398 error("cannot modify const/invariant %s", toChars());
5400 return this;
5403 void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5405 expToCBuffer(buf, hgs, e1, PREC_primary);
5406 buf->writeByte('.');
5407 buf->writestring(var->toChars());
5410 /************************************************************/
5412 /* Things like:
5413 * foo.bar!(args)
5416 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti)
5417 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e)
5419 //printf("DotTemplateInstanceExp()\n");
5420 this->ti = ti;
5423 Expression *DotTemplateInstanceExp::syntaxCopy()
5425 DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc,
5426 e1->syntaxCopy(),
5427 (TemplateInstance *)ti->syntaxCopy(NULL));
5428 return de;
5431 Expression *DotTemplateInstanceExp::semantic(Scope *sc)
5432 { Dsymbol *s;
5433 Dsymbol *s2;
5434 TemplateDeclaration *td;
5435 Expression *e;
5436 Identifier *id;
5437 Type *t1;
5438 Expression *eleft = NULL;
5439 Expression *eright;
5441 #if LOGSEMANTIC
5442 printf("DotTemplateInstanceExp::semantic('%s')\n", toChars());
5443 #endif
5444 //e1->print();
5445 //print();
5446 e1 = e1->semantic(sc);
5447 t1 = e1->type;
5448 if (t1)
5449 t1 = t1->toBasetype();
5450 //t1->print();
5452 /* Extract the following from e1:
5453 * s: the symbol which ti should be a member of
5454 * eleft: if not NULL, it is the 'this' pointer for ti
5457 if (e1->op == TOKdotexp)
5458 { DotExp *de = (DotExp *)e1;
5459 eleft = de->e1;
5460 eright = de->e2;
5462 else
5463 { eleft = NULL;
5464 eright = e1;
5466 if (eright->op == TOKimport)
5468 s = ((ScopeExp *)eright)->sds;
5470 else if (e1->op == TOKtype)
5472 s = t1->isClassHandle();
5473 if (!s)
5474 { if (t1->ty == Tstruct)
5475 s = ((TypeStruct *)t1)->sym;
5476 else
5477 goto L1;
5480 else if (t1 && (t1->ty == Tstruct || t1->ty == Tclass))
5482 s = t1->toDsymbol(sc);
5483 eleft = e1;
5485 else if (t1 && t1->ty == Tpointer)
5487 t1 = ((TypePointer *)t1)->next->toBasetype();
5488 if (t1->ty != Tstruct)
5489 goto L1;
5490 s = t1->toDsymbol(sc);
5491 eleft = e1;
5493 else
5496 error("template %s is not a member of %s", ti->toChars(), e1->toChars());
5497 goto Lerr;
5500 assert(s);
5501 id = ti->name;
5502 s2 = s->search(loc, id, 0);
5503 if (!s2)
5504 { error("template identifier %s is not a member of %s %s", id->toChars(), s->kind(), s->ident->toChars());
5505 goto Lerr;
5507 s = s2;
5508 s->semantic(sc);
5509 s = s->toAlias();
5510 td = s->isTemplateDeclaration();
5511 if (!td)
5513 error("%s is not a template", id->toChars());
5514 goto Lerr;
5516 if (global.errors)
5517 goto Lerr;
5519 ti->tempdecl = td;
5521 if (eleft)
5522 { Declaration *v;
5524 ti->semantic(sc);
5525 s = ti->inst->toAlias();
5526 v = s->isDeclaration();
5527 if (v)
5528 { e = new DotVarExp(loc, eleft, v);
5529 e = e->semantic(sc);
5530 return e;
5534 e = new ScopeExp(loc, ti);
5535 if (eleft)
5537 e = new DotExp(loc, eleft, e);
5539 e = e->semantic(sc);
5540 return e;
5542 Lerr:
5543 return new IntegerExp(0);
5546 void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5548 expToCBuffer(buf, hgs, e1, PREC_primary);
5549 buf->writeByte('.');
5550 ti->toCBuffer(buf, hgs);
5553 /************************************************************/
5555 DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f, int hasOverloads)
5556 : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
5558 this->func = f;
5559 this->hasOverloads = hasOverloads;
5562 Expression *DelegateExp::semantic(Scope *sc)
5564 #if LOGSEMANTIC
5565 printf("DelegateExp::semantic('%s')\n", toChars());
5566 #endif
5567 if (!type)
5569 e1 = e1->semantic(sc);
5570 type = new TypeDelegate(func->type);
5571 type = type->semantic(loc, sc);
5572 AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration();
5573 if (func->needThis())
5574 e1 = getRightThis(loc, sc, ad, e1, func);
5576 return this;
5579 void DelegateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5581 buf->writeByte('&');
5582 if (!func->isNested())
5584 expToCBuffer(buf, hgs, e1, PREC_primary);
5585 buf->writeByte('.');
5587 buf->writestring(func->toChars());
5590 /************************************************************/
5592 DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s)
5593 : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e)
5595 this->sym = s;
5596 this->type = s->getType();
5599 Expression *DotTypeExp::semantic(Scope *sc)
5601 #if LOGSEMANTIC
5602 printf("DotTypeExp::semantic('%s')\n", toChars());
5603 #endif
5604 UnaExp::semantic(sc);
5605 return this;
5608 void DotTypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5610 expToCBuffer(buf, hgs, e1, PREC_primary);
5611 buf->writeByte('.');
5612 buf->writestring(sym->toChars());
5615 /************************************************************/
5617 CallExp::CallExp(Loc loc, Expression *e, Expressions *exps)
5618 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5620 this->arguments = exps;
5623 CallExp::CallExp(Loc loc, Expression *e)
5624 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5626 this->arguments = NULL;
5629 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1)
5630 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5632 Expressions *arguments = new Expressions();
5633 arguments->setDim(1);
5634 arguments->data[0] = (void *)earg1;
5636 this->arguments = arguments;
5639 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2)
5640 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5642 Expressions *arguments = new Expressions();
5643 arguments->setDim(2);
5644 arguments->data[0] = (void *)earg1;
5645 arguments->data[1] = (void *)earg2;
5647 this->arguments = arguments;
5650 Expression *CallExp::syntaxCopy()
5652 return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
5656 Expression *CallExp::semantic(Scope *sc)
5658 TypeFunction *tf;
5659 FuncDeclaration *f;
5660 int i;
5661 Type *t1;
5662 int istemp;
5663 Objects *targsi = NULL; // initial list of template arguments
5665 #if LOGSEMANTIC
5666 printf("CallExp::semantic() %s\n", toChars());
5667 e1->dump(0);
5668 #endif
5669 if (type)
5670 return this; // semantic() already run
5671 #if 0
5672 if (arguments && arguments->dim)
5674 Expression *earg = (Expression *)arguments->data[0];
5675 earg->print();
5676 if (earg->type) earg->type->print();
5678 #endif
5680 if (e1->op == TOKdelegate)
5681 { DelegateExp *de = (DelegateExp *)e1;
5683 e1 = new DotVarExp(de->loc, de->e1, de->func);
5684 return semantic(sc);
5687 /* Transform:
5688 * array.id(args) into id(array,args)
5689 * aa.remove(arg) into delete aa[arg]
5691 if (e1->op == TOKdot)
5693 // BUG: we should handle array.a.b.c.e(args) too
5695 DotIdExp *dotid = (DotIdExp *)(e1);
5696 dotid->e1 = dotid->e1->semantic(sc);
5697 assert(dotid->e1);
5698 if (dotid->e1->type)
5700 TY e1ty = dotid->e1->type->toBasetype()->ty;
5701 if (e1ty == Taarray && dotid->ident == Id::remove)
5703 if (!arguments || arguments->dim != 1)
5704 { error("expected key as argument to aa.remove()");
5705 goto Lagain;
5707 Expression *key = (Expression *)arguments->data[0];
5708 key = key->semantic(sc);
5709 key = resolveProperties(sc, key);
5710 key->rvalue();
5712 TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype();
5713 key = key->implicitCastTo(sc, taa->index);
5715 return new RemoveExp(loc, dotid->e1, key);
5717 else if (e1ty == Tarray || e1ty == Tsarray || e1ty == Taarray)
5719 if (!arguments)
5720 arguments = new Expressions();
5721 arguments->shift(dotid->e1);
5722 e1 = new IdentifierExp(dotid->loc, dotid->ident);
5727 /* This recognizes:
5728 * foo!(tiargs)(funcargs)
5730 if (e1->op == TOKimport && !e1->type)
5731 { ScopeExp *se = (ScopeExp *)e1;
5732 TemplateInstance *ti = se->sds->isTemplateInstance();
5733 if (ti && !ti->semanticdone)
5735 /* Attempt to instantiate ti. If that works, go with it.
5736 * If not, go with partial explicit specialization.
5738 unsigned errors = global.errors;
5739 global.gag++;
5740 ti->semantic(sc);
5741 global.gag--;
5742 if (errors != global.errors)
5744 global.errors = errors;
5745 targsi = ti->tiargs;
5746 e1 = new IdentifierExp(loc, ti->name);
5751 /* This recognizes:
5752 * expr.foo!(tiargs)(funcargs)
5754 if (e1->op == TOKdotti && !e1->type)
5755 { DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1;
5756 TemplateInstance *ti = se->ti;
5757 if (!ti->semanticdone)
5759 /* Attempt to instantiate ti. If that works, go with it.
5760 * If not, go with partial explicit specialization.
5762 Expression *etmp;
5763 unsigned errors = global.errors;
5764 global.gag++;
5765 etmp = e1->semantic(sc);
5766 global.gag--;
5767 if (errors != global.errors)
5769 global.errors = errors;
5770 targsi = ti->tiargs;
5771 e1 = new DotIdExp(loc, se->e1, ti->name);
5773 else
5774 e1 = etmp;
5778 istemp = 0;
5779 Lagain:
5780 //printf("Lagain: %s\n", toChars());
5781 f = NULL;
5782 if (e1->op == TOKthis || e1->op == TOKsuper)
5784 // semantic() run later for these
5786 else
5788 UnaExp::semantic(sc);
5790 /* Look for e1 being a lazy parameter
5792 if (e1->op == TOKvar)
5793 { VarExp *ve = (VarExp *)e1;
5795 if (ve->var->storage_class & STClazy)
5797 TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd);
5798 TypeDelegate *t = new TypeDelegate(tf);
5799 ve->type = t->semantic(loc, sc);
5803 if (e1->op == TOKimport)
5804 { // Perhaps this should be moved to ScopeExp::semantic()
5805 ScopeExp *se = (ScopeExp *)e1;
5806 e1 = new DsymbolExp(loc, se->sds);
5807 e1 = e1->semantic(sc);
5809 #if 1 // patch for #540 by Oskar Linde
5810 else if (e1->op == TOKdotexp)
5812 DotExp *de = (DotExp *) e1;
5814 if (de->e2->op == TOKimport)
5815 { // This should *really* be moved to ScopeExp::semantic()
5816 ScopeExp *se = (ScopeExp *)de->e2;
5817 de->e2 = new DsymbolExp(loc, se->sds);
5818 de->e2 = de->e2->semantic(sc);
5821 if (de->e2->op == TOKtemplate)
5822 { TemplateExp *te = (TemplateExp *) de->e2;
5823 e1 = new DotTemplateExp(loc,de->e1,te->td);
5826 #endif
5829 if (e1->op == TOKcomma)
5831 CommaExp *ce = (CommaExp *)e1;
5833 e1 = ce->e2;
5834 e1->type = ce->type;
5835 ce->e2 = this;
5836 ce->type = NULL;
5837 return ce->semantic(sc);
5840 t1 = NULL;
5841 if (e1->type)
5842 t1 = e1->type->toBasetype();
5844 // Check for call operator overload
5845 if (t1)
5846 { AggregateDeclaration *ad;
5848 if (t1->ty == Tstruct)
5850 ad = ((TypeStruct *)t1)->sym;
5851 if (search_function(ad, Id::call))
5852 goto L1; // overload of opCall, therefore it's a call
5854 if (e1->op != TOKtype)
5855 error("%s %s does not overload ()", ad->kind(), ad->toChars());
5856 /* It's a struct literal
5858 Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments);
5859 e = e->semantic(sc);
5860 e->type = e1->type; // in case e1->type was a typedef
5861 return e;
5863 else if (t1->ty == Tclass)
5865 ad = ((TypeClass *)t1)->sym;
5866 goto L1;
5868 // Rewrite as e1.call(arguments)
5869 Expression *e = new DotIdExp(loc, e1, Id::call);
5870 e = new CallExp(loc, e, arguments);
5871 e = e->semantic(sc);
5872 return e;
5876 arrayExpressionSemantic(arguments, sc);
5877 preFunctionArguments(loc, sc, arguments);
5879 if (e1->op == TOKdotvar && t1->ty == Tfunction ||
5880 e1->op == TOKdottd)
5882 DotVarExp *dve;
5883 DotTemplateExp *dte;
5884 AggregateDeclaration *ad;
5885 UnaExp *ue = (UnaExp *)(e1);
5887 if (e1->op == TOKdotvar)
5888 { // Do overload resolution
5889 dve = (DotVarExp *)(e1);
5891 f = dve->var->isFuncDeclaration();
5892 assert(f);
5893 f = f->overloadResolve(loc, ue->e1, arguments);
5895 ad = f->toParent()->isAggregateDeclaration();
5897 else
5898 { dte = (DotTemplateExp *)(e1);
5899 TemplateDeclaration *td = dte->td;
5900 assert(td);
5901 if (!arguments)
5902 // Should fix deduceFunctionTemplate() so it works on NULL argument
5903 arguments = new Expressions();
5904 f = td->deduceFunctionTemplate(sc, loc, targsi, ue->e1, arguments);
5905 if (!f)
5906 { type = Type::terror;
5907 return this;
5909 ad = td->toParent()->isAggregateDeclaration();
5911 if (f->needThis())
5912 ue->e1 = getRightThis(loc, sc, ad, ue->e1, f);
5914 checkDeprecated(sc, f);
5915 accessCheck(loc, sc, ue->e1, f);
5916 if (!f->needThis())
5918 VarExp *ve = new VarExp(loc, f);
5919 e1 = new CommaExp(loc, ue->e1, ve);
5920 e1->type = f->type;
5922 else
5924 if (e1->op == TOKdotvar)
5925 dve->var = f;
5926 else
5927 e1 = new DotVarExp(loc, dte->e1, f);
5928 e1->type = f->type;
5929 #if 0
5930 printf("ue->e1 = %s\n", ue->e1->toChars());
5931 printf("f = %s\n", f->toChars());
5932 printf("t = %s\n", t->toChars());
5933 printf("e1 = %s\n", e1->toChars());
5934 printf("e1->type = %s\n", e1->type->toChars());
5935 #endif
5936 // Const member function can take const/invariant/mutable this
5937 if (!(f->type->isConst()))
5939 // Check for const/invariant compatibility
5940 Type *tthis = ue->e1->type->toBasetype();
5941 if (tthis->ty == Tpointer)
5942 tthis = tthis->nextOf()->toBasetype();
5943 if (f->type->isInvariant())
5945 if (tthis->mod != MODinvariant)
5946 error("%s can only be called on an invariant object", e1->toChars());
5948 else
5950 if (tthis->mod != 0)
5951 { //printf("mod = %x\n", tthis->mod);
5952 error("%s can only be called on a mutable object, not %s", e1->toChars(), tthis->toChars());
5956 /* Cannot call mutable method on a final struct
5958 if (tthis->ty == Tstruct &&
5959 ue->e1->op == TOKvar)
5960 { VarExp *v = (VarExp *)ue->e1;
5961 if (v->var->storage_class & STCfinal)
5962 error("cannot call mutable method on final struct");
5966 // See if we need to adjust the 'this' pointer
5967 AggregateDeclaration *ad = f->isThis();
5968 ClassDeclaration *cd = ue->e1->type->isClassHandle();
5969 if (ad && cd && ad->isClassDeclaration() && ad != cd &&
5970 ue->e1->op != TOKsuper)
5972 ue->e1 = ue->e1->castTo(sc, ad->type); //new CastExp(loc, ue->e1, ad->type);
5973 ue->e1 = ue->e1->semantic(sc);
5976 t1 = e1->type;
5978 else if (e1->op == TOKsuper)
5980 // Base class constructor call
5981 ClassDeclaration *cd = NULL;
5983 if (sc->func)
5984 cd = sc->func->toParent()->isClassDeclaration();
5985 if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration())
5987 error("super class constructor call must be in a constructor");
5988 type = Type::terror;
5989 return this;
5991 else
5993 f = cd->baseClass->ctor;
5994 if (!f)
5995 { error("no super class constructor for %s", cd->baseClass->toChars());
5996 type = Type::terror;
5997 return this;
5999 else
6001 #if 0
6002 if (sc->callSuper & (CSXthis | CSXsuper))
6003 error("reference to this before super()");
6004 #endif
6005 if (sc->noctor || sc->callSuper & CSXlabel)
6006 error("constructor calls not allowed in loops or after labels");
6007 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
6008 error("multiple constructor calls");
6009 sc->callSuper |= CSXany_ctor | CSXsuper_ctor;
6011 f = f->overloadResolve(loc, NULL, arguments);
6012 checkDeprecated(sc, f);
6013 e1 = new DotVarExp(e1->loc, e1, f);
6014 e1 = e1->semantic(sc);
6015 t1 = e1->type;
6019 else if (e1->op == TOKthis)
6021 // same class constructor call
6022 ClassDeclaration *cd = NULL;
6024 if (sc->func)
6025 cd = sc->func->toParent()->isClassDeclaration();
6026 if (!cd || !sc->func->isCtorDeclaration())
6028 error("class constructor call must be in a constructor");
6029 type = Type::terror;
6030 return this;
6032 else
6034 #if 0
6035 if (sc->callSuper & (CSXthis | CSXsuper))
6036 error("reference to this before super()");
6037 #endif
6038 if (sc->noctor || sc->callSuper & CSXlabel)
6039 error("constructor calls not allowed in loops or after labels");
6040 if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
6041 error("multiple constructor calls");
6042 sc->callSuper |= CSXany_ctor | CSXthis_ctor;
6044 f = cd->ctor;
6045 f = f->overloadResolve(loc, NULL, arguments);
6046 checkDeprecated(sc, f);
6047 e1 = new DotVarExp(e1->loc, e1, f);
6048 e1 = e1->semantic(sc);
6049 t1 = e1->type;
6051 // BUG: this should really be done by checking the static
6052 // call graph
6053 if (f == sc->func)
6054 error("cyclic constructor call");
6057 else if (e1->op == TOKoverloadset)
6059 OverExp *eo = (OverExp *)e1;
6060 FuncDeclaration *f = NULL;
6061 for (int i = 0; i < eo->vars->a.dim; i++)
6062 { Dsymbol *s = (Dsymbol *)eo->vars->a.data[i];
6063 FuncDeclaration *f2 = s->isFuncDeclaration();
6064 if (f2)
6066 f2 = f2->overloadResolve(loc, NULL, arguments, 1);
6068 else
6069 { TemplateDeclaration *td = s->isTemplateDeclaration();
6070 assert(td);
6071 f2 = td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments, 1);
6073 if (f2)
6074 { if (f)
6075 /* Error if match in more than one overload set,
6076 * even if one is a 'better' match than the other.
6078 ScopeDsymbol::multiplyDefined(loc, f, f2);
6079 else
6080 f = f2;
6083 if (!f)
6084 { /* No overload matches, just set f and rely on error
6085 * message being generated later.
6087 f = (FuncDeclaration *)eo->vars->a.data[0];
6089 e1 = new VarExp(loc, f);
6090 goto Lagain;
6092 else if (!t1)
6094 error("function expected before (), not '%s'", e1->toChars());
6095 type = Type::terror;
6096 return this;
6098 else if (t1->ty != Tfunction)
6100 if (t1->ty == Tdelegate)
6101 { TypeDelegate *td = (TypeDelegate *)t1;
6102 assert(td->next->ty == Tfunction);
6103 tf = (TypeFunction *)(td->next);
6104 goto Lcheckargs;
6106 else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction)
6107 { Expression *e;
6109 e = new PtrExp(loc, e1);
6110 t1 = ((TypePointer *)t1)->next;
6111 e->type = t1;
6112 e1 = e;
6114 else if (e1->op == TOKtemplate)
6116 TemplateExp *te = (TemplateExp *)e1;
6117 f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments);
6118 if (!f)
6119 { type = Type::terror;
6120 return this;
6122 if (f->needThis() && hasThis(sc))
6124 // Supply an implicit 'this', as in
6125 // this.ident
6127 e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td);
6128 goto Lagain;
6131 e1 = new VarExp(loc, f);
6132 goto Lagain;
6134 else
6135 { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars());
6136 type = Type::terror;
6137 return this;
6140 else if (e1->op == TOKvar)
6142 // Do overload resolution
6143 VarExp *ve = (VarExp *)e1;
6145 f = ve->var->isFuncDeclaration();
6146 assert(f);
6148 if (ve->hasOverloads)
6149 f = f->overloadResolve(loc, NULL, arguments);
6150 checkDeprecated(sc, f);
6152 if (f->needThis() && hasThis(sc))
6154 // Supply an implicit 'this', as in
6155 // this.ident
6157 e1 = new DotVarExp(loc, new ThisExp(loc), f);
6158 goto Lagain;
6161 accessCheck(loc, sc, NULL, f);
6163 ve->var = f;
6164 // ve->hasOverloads = 0;
6165 ve->type = f->type;
6166 t1 = f->type;
6168 assert(t1->ty == Tfunction);
6169 tf = (TypeFunction *)(t1);
6171 Lcheckargs:
6172 assert(tf->ty == Tfunction);
6173 type = tf->next;
6175 if (!arguments)
6176 arguments = new Expressions();
6177 functionArguments(loc, sc, tf, arguments);
6179 assert(type);
6181 if (f && f->tintro)
6183 Type *t = type;
6184 target_ptrdiff_t offset = 0;
6185 TypeFunction *tf = (TypeFunction *)f->tintro;
6187 if (tf->next->isBaseOf(t, &offset) && offset)
6189 type = tf->next;
6190 return castTo(sc, t);
6194 return this;
6197 int CallExp::checkSideEffect(int flag)
6199 return 1;
6202 int CallExp::canThrow()
6204 return 1;
6207 Expression *CallExp::toLvalue(Scope *sc, Expression *e)
6209 if (type->toBasetype()->ty == Tstruct)
6210 return this;
6211 else
6212 return Expression::toLvalue(sc, e);
6215 void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6216 { int i;
6218 expToCBuffer(buf, hgs, e1, precedence[op]);
6219 buf->writeByte('(');
6220 argsToCBuffer(buf, arguments, hgs);
6221 buf->writeByte(')');
6225 /************************************************************/
6227 AddrExp::AddrExp(Loc loc, Expression *e)
6228 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e)
6232 Expression *AddrExp::semantic(Scope *sc)
6234 #if LOGSEMANTIC
6235 printf("AddrExp::semantic('%s')\n", toChars());
6236 #endif
6237 if (!type)
6239 UnaExp::semantic(sc);
6240 e1 = e1->toLvalue(sc, NULL);
6241 if (!e1->type)
6243 error("cannot take address of %s", e1->toChars());
6244 type = Type::tint32;
6245 return this;
6247 type = e1->type->pointerTo();
6249 // See if this should really be a delegate
6250 if (e1->op == TOKdotvar)
6252 DotVarExp *dve = (DotVarExp *)e1;
6254 FuncDeclaration *f = dve->var->isFuncDeclaration();
6256 if (f)
6258 if (!dve->hasOverloads)
6259 f->tookAddressOf = 1;
6260 Expression *e = new DelegateExp(loc, dve->e1, f, dve->hasOverloads);
6261 e = e->semantic(sc);
6262 return e;
6265 else if (e1->op == TOKvar)
6267 VarExp *ve = (VarExp *)e1;
6269 VarDeclaration *v = ve->var->isVarDeclaration();
6270 if (v && !v->canTakeAddressOf())
6271 error("cannot take address of %s", e1->toChars());
6273 FuncDeclaration *f = ve->var->isFuncDeclaration();
6275 if (f)
6277 if (!ve->hasOverloads)
6278 f->tookAddressOf = 1;
6279 if (f->isNested())
6281 Expression *e = new DelegateExp(loc, e1, f, ve->hasOverloads);
6282 e = e->semantic(sc);
6283 return e;
6285 if (f->needThis() && hasThis(sc))
6287 /* Should probably supply 'this' after overload resolution,
6288 * not before.
6290 Expression *ethis = new ThisExp(loc);
6291 Expression *e = new DelegateExp(loc, ethis, f, ve->hasOverloads);
6292 e = e->semantic(sc);
6293 return e;
6297 return optimize(WANTvalue);
6299 return this;
6302 /************************************************************/
6304 PtrExp::PtrExp(Loc loc, Expression *e)
6305 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
6307 if (e->type)
6308 type = ((TypePointer *)e->type)->next;
6311 PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
6312 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
6314 type = t;
6317 Expression *PtrExp::semantic(Scope *sc)
6318 { Type *tb;
6320 #if LOGSEMANTIC
6321 printf("PtrExp::semantic('%s')\n", toChars());
6322 #endif
6323 if (!type)
6325 UnaExp::semantic(sc);
6326 e1 = resolveProperties(sc, e1);
6327 if (!e1->type)
6328 printf("PtrExp::semantic('%s')\n", toChars());
6329 Expression *e = op_overload(sc);
6330 if (e)
6331 return e;
6332 tb = e1->type->toBasetype();
6333 switch (tb->ty)
6335 case Tpointer:
6336 type = ((TypePointer *)tb)->next;
6337 break;
6339 case Tsarray:
6340 case Tarray:
6341 type = ((TypeArray *)tb)->next;
6342 e1 = e1->castTo(sc, type->pointerTo());
6343 break;
6345 default:
6346 error("can only * a pointer, not a '%s'", e1->type->toChars());
6347 type = Type::tint32;
6348 break;
6350 rvalue();
6352 return this;
6355 Expression *PtrExp::toLvalue(Scope *sc, Expression *e)
6357 #if 0
6358 tym = tybasic(e1->ET->Tty);
6359 if (!(tyscalar(tym) ||
6360 tym == TYstruct ||
6361 tym == TYarray && e->Eoper == TOKaddr))
6362 synerr(EM_lvalue); // lvalue expected
6363 #endif
6364 return this;
6367 Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e)
6369 //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
6371 if (e1->op == TOKsymoff)
6372 { SymOffExp *se = (SymOffExp *)e1;
6373 se->var->checkModify(loc, sc, type);
6374 //return toLvalue(sc, e);
6377 return Expression::modifiableLvalue(sc, e);
6381 void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6383 buf->writeByte('*');
6384 expToCBuffer(buf, hgs, e1, precedence[op]);
6387 /************************************************************/
6389 NegExp::NegExp(Loc loc, Expression *e)
6390 : UnaExp(loc, TOKneg, sizeof(NegExp), e)
6394 Expression *NegExp::semantic(Scope *sc)
6395 { Expression *e;
6397 #if LOGSEMANTIC
6398 printf("NegExp::semantic('%s')\n", toChars());
6399 #endif
6400 if (!type)
6402 UnaExp::semantic(sc);
6403 e1 = resolveProperties(sc, e1);
6404 e = op_overload(sc);
6405 if (e)
6406 return e;
6408 e1->checkNoBool();
6409 e1->checkArithmetic();
6410 type = e1->type;
6412 return this;
6415 /************************************************************/
6417 UAddExp::UAddExp(Loc loc, Expression *e)
6418 : UnaExp(loc, TOKuadd, sizeof(UAddExp), e)
6422 Expression *UAddExp::semantic(Scope *sc)
6423 { Expression *e;
6425 #if LOGSEMANTIC
6426 printf("UAddExp::semantic('%s')\n", toChars());
6427 #endif
6428 assert(!type);
6429 UnaExp::semantic(sc);
6430 e1 = resolveProperties(sc, e1);
6431 e = op_overload(sc);
6432 if (e)
6433 return e;
6434 e1->checkNoBool();
6435 e1->checkArithmetic();
6436 return e1;
6439 /************************************************************/
6441 ComExp::ComExp(Loc loc, Expression *e)
6442 : UnaExp(loc, TOKtilde, sizeof(ComExp), e)
6446 Expression *ComExp::semantic(Scope *sc)
6447 { Expression *e;
6449 if (!type)
6451 UnaExp::semantic(sc);
6452 e1 = resolveProperties(sc, e1);
6453 e = op_overload(sc);
6454 if (e)
6455 return e;
6457 e1->checkNoBool();
6458 e1 = e1->checkIntegral();
6459 type = e1->type;
6461 return this;
6464 /************************************************************/
6466 NotExp::NotExp(Loc loc, Expression *e)
6467 : UnaExp(loc, TOKnot, sizeof(NotExp), e)
6471 Expression *NotExp::semantic(Scope *sc)
6473 UnaExp::semantic(sc);
6474 e1 = resolveProperties(sc, e1);
6475 e1 = e1->checkToBoolean();
6476 type = Type::tboolean;
6477 return this;
6480 int NotExp::isBit()
6482 return TRUE;
6487 /************************************************************/
6489 BoolExp::BoolExp(Loc loc, Expression *e, Type *t)
6490 : UnaExp(loc, TOKtobool, sizeof(BoolExp), e)
6492 type = t;
6495 Expression *BoolExp::semantic(Scope *sc)
6497 UnaExp::semantic(sc);
6498 e1 = resolveProperties(sc, e1);
6499 e1 = e1->checkToBoolean();
6500 type = Type::tboolean;
6501 return this;
6504 int BoolExp::isBit()
6506 return TRUE;
6509 /************************************************************/
6511 DeleteExp::DeleteExp(Loc loc, Expression *e)
6512 : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e)
6516 Expression *DeleteExp::semantic(Scope *sc)
6518 Type *tb;
6520 UnaExp::semantic(sc);
6521 e1 = resolveProperties(sc, e1);
6522 e1 = e1->toLvalue(sc, NULL);
6523 type = Type::tvoid;
6525 tb = e1->type->toBasetype();
6526 switch (tb->ty)
6527 { case Tclass:
6528 { TypeClass *tc = (TypeClass *)tb;
6529 ClassDeclaration *cd = tc->sym;
6531 if (cd->isCOMinterface())
6532 { /* Because COM classes are deleted by IUnknown.Release()
6534 error("cannot delete instance of COM interface %s", cd->toChars());
6536 break;
6538 case Tpointer:
6539 tb = ((TypePointer *)tb)->next->toBasetype();
6540 if (tb->ty == Tstruct)
6542 TypeStruct *ts = (TypeStruct *)tb;
6543 StructDeclaration *sd = ts->sym;
6544 FuncDeclaration *f = sd->aggDelete;
6545 FuncDeclaration *fd = sd->dtor;
6547 if (!f && !fd)
6548 break;
6550 /* Construct:
6551 * ea = copy e1 to a tmp to do side effects only once
6552 * eb = call destructor
6553 * ec = call deallocator
6555 Expression *ea = NULL;
6556 Expression *eb = NULL;
6557 Expression *ec = NULL;
6558 VarDeclaration *v;
6560 if (fd && f)
6561 { Identifier *id = Lexer::idPool("__tmp");
6562 v = new VarDeclaration(loc, e1->type, id, new ExpInitializer(loc, e1));
6563 v->semantic(sc);
6564 v->parent = sc->parent;
6565 ea = new DeclarationExp(loc, v);
6566 ea->type = v->type;
6569 if (fd)
6570 { Expression *e = ea ? new VarExp(loc, v) : e1;
6571 e = new DotVarExp(0, e, fd, 0);
6572 eb = new CallExp(loc, e);
6573 eb = eb->semantic(sc);
6576 if (f)
6578 Type *tpv = Type::tvoid->pointerTo();
6579 Expression *e = ea ? new VarExp(loc, v) : e1->castTo(sc, tpv);
6580 e = new CallExp(loc, new VarExp(loc, f), e);
6581 ec = e->semantic(sc);
6583 ea = combine(ea, eb);
6584 ea = combine(ea, ec);
6585 assert(ea);
6586 return ea;
6588 break;
6590 case Tarray:
6591 /* BUG: look for deleting arrays of structs with dtors.
6593 break;
6595 default:
6596 if (e1->op == TOKindex)
6598 IndexExp *ae = (IndexExp *)(e1);
6599 Type *tb1 = ae->e1->type->toBasetype();
6600 if (tb1->ty == Taarray)
6601 break;
6603 error("cannot delete type %s", e1->type->toChars());
6604 break;
6607 if (e1->op == TOKindex)
6609 IndexExp *ae = (IndexExp *)(e1);
6610 Type *tb1 = ae->e1->type->toBasetype();
6611 if (tb1->ty == Taarray)
6612 { if (!global.params.useDeprecated)
6613 error("delete aa[key] deprecated, use aa.remove(key)");
6617 return this;
6620 int DeleteExp::checkSideEffect(int flag)
6622 return 1;
6625 Expression *DeleteExp::checkToBoolean()
6627 error("delete does not give a boolean result");
6628 return this;
6631 void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6633 buf->writestring("delete ");
6634 expToCBuffer(buf, hgs, e1, precedence[op]);
6637 /************************************************************/
6639 CastExp::CastExp(Loc loc, Expression *e, Type *t)
6640 : UnaExp(loc, TOKcast, sizeof(CastExp), e)
6642 to = t;
6643 this->tok = TOKreserved;
6646 /* For cast(const) and cast(invariant)
6648 CastExp::CastExp(Loc loc, Expression *e, enum TOK tok)
6649 : UnaExp(loc, TOKcast, sizeof(CastExp), e)
6651 to = NULL;
6652 this->tok = tok;
6655 Expression *CastExp::syntaxCopy()
6657 return to ? new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy())
6658 : new CastExp(loc, e1->syntaxCopy(), tok);
6662 Expression *CastExp::semantic(Scope *sc)
6663 { Expression *e;
6664 BinExp *b;
6665 UnaExp *u;
6667 #if LOGSEMANTIC
6668 printf("CastExp::semantic('%s')\n", toChars());
6669 #endif
6671 //static int x; assert(++x < 10);
6673 if (type)
6674 return this;
6675 UnaExp::semantic(sc);
6676 if (e1->type) // if not a tuple
6678 e1 = resolveProperties(sc, e1);
6680 /* Handle cast(const) and cast(invariant)
6682 if (!to)
6683 { if (tok == TOKconst)
6684 to = e1->type->constOf();
6685 else if (tok == TOKinvariant)
6686 to = e1->type->invariantOf();
6687 else
6688 assert(0);
6690 else
6691 to = to->semantic(loc, sc);
6693 e = op_overload(sc);
6694 if (e)
6696 return e->implicitCastTo(sc, to);
6699 Type *tob = to->toBasetype();
6700 if (tob->ty == Tstruct &&
6701 !tob->equals(e1->type->toBasetype()) &&
6702 ((TypeStruct *)to)->sym->search(0, Id::call, 0)
6705 /* Look to replace:
6706 * cast(S)t
6707 * with:
6708 * S(t)
6711 // Rewrite as to.call(e1)
6712 e = new TypeExp(loc, to);
6713 e = new DotIdExp(loc, e, Id::call);
6714 e = new CallExp(loc, e, e1);
6715 e = e->semantic(sc);
6716 return e;
6719 else if (!to)
6720 { error("cannot cast tuple");
6721 to = Type::terror;
6723 e = e1->castTo(sc, to);
6724 return e;
6727 int CastExp::checkSideEffect(int flag)
6729 /* if not:
6730 * cast(void)
6731 * cast(classtype)func()
6733 if (!to->equals(Type::tvoid) &&
6734 !(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass))
6735 return Expression::checkSideEffect(flag);
6736 return 1;
6739 void CastExp::checkEscape()
6740 { Type *tb = type->toBasetype();
6741 if (tb->ty == Tarray && e1->op == TOKvar &&
6742 e1->type->toBasetype()->ty == Tsarray)
6743 { VarExp *ve = (VarExp *)e1;
6744 VarDeclaration *v = ve->var->isVarDeclaration();
6745 if (v)
6747 if (!v->isDataseg() && !v->isParameter())
6748 error("escaping reference to local %s", v->toChars());
6753 void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6755 buf->writestring("cast(");
6756 if (to)
6757 to->toCBuffer(buf, NULL, hgs);
6758 else
6759 buf->writestring(Token::tochars[tok]);
6760 buf->writeByte(')');
6761 expToCBuffer(buf, hgs, e1, precedence[op]);
6765 /************************************************************/
6767 SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr)
6768 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1)
6770 this->upr = upr;
6771 this->lwr = lwr;
6772 lengthVar = NULL;
6775 Expression *SliceExp::syntaxCopy()
6777 Expression *lwr = NULL;
6778 if (this->lwr)
6779 lwr = this->lwr->syntaxCopy();
6781 Expression *upr = NULL;
6782 if (this->upr)
6783 upr = this->upr->syntaxCopy();
6785 return new SliceExp(loc, e1->syntaxCopy(), lwr, upr);
6788 Expression *SliceExp::semantic(Scope *sc)
6789 { Expression *e;
6790 AggregateDeclaration *ad;
6791 //FuncDeclaration *fd;
6792 ScopeDsymbol *sym;
6794 #if LOGSEMANTIC
6795 printf("SliceExp::semantic('%s')\n", toChars());
6796 #endif
6797 if (type)
6798 return this;
6800 UnaExp::semantic(sc);
6801 e1 = resolveProperties(sc, e1);
6803 e = this;
6805 Type *t = e1->type->toBasetype();
6806 if (t->ty == Tpointer)
6808 if (!lwr || !upr)
6809 error("need upper and lower bound to slice pointer");
6811 else if (t->ty == Tarray)
6814 else if (t->ty == Tsarray)
6817 else if (t->ty == Tclass)
6819 ad = ((TypeClass *)t)->sym;
6820 goto L1;
6822 else if (t->ty == Tstruct)
6824 ad = ((TypeStruct *)t)->sym;
6827 if (search_function(ad, Id::slice))
6829 // Rewrite as e1.slice(lwr, upr)
6830 e = new DotIdExp(loc, e1, Id::slice);
6832 if (lwr)
6834 assert(upr);
6835 e = new CallExp(loc, e, lwr, upr);
6837 else
6838 { assert(!upr);
6839 e = new CallExp(loc, e);
6841 e = e->semantic(sc);
6842 return e;
6844 goto Lerror;
6846 else if (t->ty == Ttuple)
6848 if (!lwr && !upr)
6849 return e1;
6850 if (!lwr || !upr)
6851 { error("need upper and lower bound to slice tuple");
6852 goto Lerror;
6855 else
6856 goto Lerror;
6858 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
6860 sym = new ArrayScopeSymbol(sc, this);
6861 sym->loc = loc;
6862 sym->parent = sc->scopesym;
6863 sc = sc->push(sym);
6866 if (lwr)
6867 { lwr = lwr->semantic(sc);
6868 lwr = resolveProperties(sc, lwr);
6869 lwr = lwr->implicitCastTo(sc, Type::tsize_t);
6871 if (upr)
6872 { upr = upr->semantic(sc);
6873 upr = resolveProperties(sc, upr);
6874 upr = upr->implicitCastTo(sc, Type::tsize_t);
6877 if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
6878 sc->pop();
6880 if (t->ty == Ttuple)
6882 lwr = lwr->optimize(WANTvalue);
6883 upr = upr->optimize(WANTvalue);
6884 uinteger_t i1 = lwr->toUInteger();
6885 uinteger_t i2 = upr->toUInteger();
6887 size_t length;
6888 TupleExp *te;
6889 TypeTuple *tup;
6891 if (e1->op == TOKtuple) // slicing an expression tuple
6892 { te = (TupleExp *)e1;
6893 length = te->exps->dim;
6895 else if (e1->op == TOKtype) // slicing a type tuple
6896 { tup = (TypeTuple *)t;
6897 length = Argument::dim(tup->arguments);
6899 else
6900 assert(0);
6902 if (i1 <= i2 && i2 <= length)
6903 { size_t j1 = (size_t) i1;
6904 size_t j2 = (size_t) i2;
6906 if (e1->op == TOKtuple)
6907 { Expressions *exps = new Expressions;
6908 exps->setDim(j2 - j1);
6909 for (size_t i = 0; i < j2 - j1; i++)
6910 { Expression *e = (Expression *)te->exps->data[j1 + i];
6911 exps->data[i] = (void *)e;
6913 e = new TupleExp(loc, exps);
6915 else
6916 { Arguments *args = new Arguments;
6917 args->reserve(j2 - j1);
6918 for (size_t i = j1; i < j2; i++)
6919 { Argument *arg = Argument::getNth(tup->arguments, i);
6920 args->push(arg);
6922 e = new TypeExp(e1->loc, new TypeTuple(args));
6924 e = e->semantic(sc);
6926 else
6928 error("string slice [%"PRIuMAX" .. %"PRIuMAX"] is out of bounds", i1, i2);
6929 e = e1;
6931 return e;
6934 type = t->nextOf()->arrayOf();
6935 return e;
6937 Lerror:
6938 char *s;
6939 if (t->ty == Tvoid)
6940 s = e1->toChars();
6941 else
6942 s = t->toChars();
6943 error("%s cannot be sliced with []", s);
6944 type = Type::terror;
6945 return e;
6948 void SliceExp::checkEscape()
6950 e1->checkEscape();
6953 Expression *SliceExp::toLvalue(Scope *sc, Expression *e)
6955 return this;
6958 Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e)
6960 error("slice expression %s is not a modifiable lvalue", toChars());
6961 return this;
6964 void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6966 expToCBuffer(buf, hgs, e1, precedence[op]);
6967 buf->writeByte('[');
6968 if (upr || lwr)
6970 if (lwr)
6971 expToCBuffer(buf, hgs, lwr, PREC_assign);
6972 else
6973 buf->writeByte('0');
6974 buf->writestring("..");
6975 if (upr)
6976 expToCBuffer(buf, hgs, upr, PREC_assign);
6977 else
6978 buf->writestring("length"); // BUG: should be array.length
6980 buf->writeByte(']');
6983 /********************** ArrayLength **************************************/
6985 ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1)
6986 : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1)
6990 Expression *ArrayLengthExp::semantic(Scope *sc)
6991 { Expression *e;
6993 #if LOGSEMANTIC
6994 printf("ArrayLengthExp::semantic('%s')\n", toChars());
6995 #endif
6996 if (!type)
6998 UnaExp::semantic(sc);
6999 e1 = resolveProperties(sc, e1);
7001 type = Type::tsize_t;
7003 return this;
7006 void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7008 expToCBuffer(buf, hgs, e1, PREC_primary);
7009 buf->writestring(".length");
7012 /*********************** ArrayExp *************************************/
7014 // e1 [ i1, i2, i3, ... ]
7016 ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args)
7017 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1)
7019 arguments = args;
7022 Expression *ArrayExp::syntaxCopy()
7024 return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
7027 Expression *ArrayExp::semantic(Scope *sc)
7028 { Expression *e;
7029 Type *t1;
7031 #if LOGSEMANTIC
7032 printf("ArrayExp::semantic('%s')\n", toChars());
7033 #endif
7034 UnaExp::semantic(sc);
7035 e1 = resolveProperties(sc, e1);
7037 t1 = e1->type->toBasetype();
7038 if (t1->ty != Tclass && t1->ty != Tstruct)
7039 { // Convert to IndexExp
7040 if (arguments->dim != 1)
7041 error("only one index allowed to index %s", t1->toChars());
7042 e = new IndexExp(loc, e1, (Expression *)arguments->data[0]);
7043 return e->semantic(sc);
7046 // Run semantic() on each argument
7047 for (size_t i = 0; i < arguments->dim; i++)
7048 { e = (Expression *)arguments->data[i];
7050 e = e->semantic(sc);
7051 if (!e->type)
7052 error("%s has no value", e->toChars());
7053 arguments->data[i] = (void *)e;
7056 expandTuples(arguments);
7057 assert(arguments && arguments->dim);
7059 e = op_overload(sc);
7060 if (!e)
7061 { error("no [] operator overload for type %s", e1->type->toChars());
7062 e = e1;
7064 return e;
7068 Expression *ArrayExp::toLvalue(Scope *sc, Expression *e)
7070 if (type && type->toBasetype()->ty == Tvoid)
7071 error("voids have no value");
7072 return this;
7076 void ArrayExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7077 { int i;
7079 expToCBuffer(buf, hgs, e1, PREC_primary);
7080 buf->writeByte('[');
7081 argsToCBuffer(buf, arguments, hgs);
7082 buf->writeByte(']');
7085 /************************* DotExp ***********************************/
7087 DotExp::DotExp(Loc loc, Expression *e1, Expression *e2)
7088 : BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2)
7092 Expression *DotExp::semantic(Scope *sc)
7094 #if LOGSEMANTIC
7095 printf("DotExp::semantic('%s')\n", toChars());
7096 if (type) printf("\ttype = %s\n", type->toChars());
7097 #endif
7098 e1 = e1->semantic(sc);
7099 e2 = e2->semantic(sc);
7100 if (e2->op == TOKimport)
7102 ScopeExp *se = (ScopeExp *)e2;
7103 TemplateDeclaration *td = se->sds->isTemplateDeclaration();
7104 if (td)
7105 { Expression *e = new DotTemplateExp(loc, e1, td);
7106 e = e->semantic(sc);
7107 return e;
7110 if (!type)
7111 type = e2->type;
7112 return this;
7116 /************************* CommaExp ***********************************/
7118 CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2)
7119 : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2)
7123 Expression *CommaExp::semantic(Scope *sc)
7125 if (!type)
7126 { BinExp::semanticp(sc);
7127 type = e2->type;
7129 return this;
7132 void CommaExp::checkEscape()
7134 e2->checkEscape();
7137 Expression *CommaExp::toLvalue(Scope *sc, Expression *e)
7139 e2 = e2->toLvalue(sc, NULL);
7140 return this;
7143 Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e)
7145 e2 = e2->modifiableLvalue(sc, e);
7146 return this;
7149 int CommaExp::isBool(int result)
7151 return e2->isBool(result);
7154 int CommaExp::checkSideEffect(int flag)
7156 if (flag == 2)
7157 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
7158 else
7160 // Don't check e1 until we cast(void) the a,b code generation
7161 return e2->checkSideEffect(flag);
7165 /************************** IndexExp **********************************/
7167 // e1 [ e2 ]
7169 IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2)
7170 : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2)
7172 //printf("IndexExp::IndexExp('%s')\n", toChars());
7173 lengthVar = NULL;
7174 modifiable = 0; // assume it is an rvalue
7177 Expression *IndexExp::semantic(Scope *sc)
7178 { Expression *e;
7179 BinExp *b;
7180 UnaExp *u;
7181 Type *t1;
7182 ScopeDsymbol *sym;
7184 #if LOGSEMANTIC
7185 printf("IndexExp::semantic('%s')\n", toChars());
7186 #endif
7187 if (type)
7188 return this;
7189 if (!e1->type)
7190 e1 = e1->semantic(sc);
7191 assert(e1->type); // semantic() should already be run on it
7192 e = this;
7194 // Note that unlike C we do not implement the int[ptr]
7196 t1 = e1->type->toBasetype();
7198 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
7199 { // Create scope for 'length' variable
7200 sym = new ArrayScopeSymbol(sc, this);
7201 sym->loc = loc;
7202 sym->parent = sc->scopesym;
7203 sc = sc->push(sym);
7206 e2 = e2->semantic(sc);
7207 if (!e2->type)
7209 error("%s has no value", e2->toChars());
7210 e2->type = Type::terror;
7212 e2 = resolveProperties(sc, e2);
7214 if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
7215 sc = sc->pop();
7217 switch (t1->ty)
7219 case Tpointer:
7220 case Tarray:
7221 e2 = e2->implicitCastTo(sc, Type::tsize_t);
7222 e->type = ((TypeNext *)t1)->next;
7223 break;
7225 case Tsarray:
7227 e2 = e2->implicitCastTo(sc, Type::tsize_t);
7229 TypeSArray *tsa = (TypeSArray *)t1;
7231 #if 0 // Don't do now, because it might be short-circuit evaluated
7232 // Do compile time array bounds checking if possible
7233 e2 = e2->optimize(WANTvalue);
7234 if (e2->op == TOKint64)
7236 integer_t index = e2->toInteger();
7237 integer_t length = tsa->dim->toInteger();
7238 if (index < 0 || index >= length)
7239 error("array index [%lld] is outside array bounds [0 .. %lld]",
7240 index, length);
7242 #endif
7243 e->type = t1->nextOf();
7244 break;
7247 case Taarray:
7248 { TypeAArray *taa = (TypeAArray *)t1;
7250 e2 = e2->implicitCastTo(sc, taa->index); // type checking
7251 type = taa->next;
7252 break;
7255 case Ttuple:
7257 e2 = e2->implicitCastTo(sc, Type::tsize_t);
7258 e2 = e2->optimize(WANTvalue | WANTinterpret);
7259 uinteger_t index = e2->toUInteger();
7260 size_t length;
7261 TupleExp *te;
7262 TypeTuple *tup;
7264 if (e1->op == TOKtuple)
7265 { te = (TupleExp *)e1;
7266 length = te->exps->dim;
7268 else if (e1->op == TOKtype)
7270 tup = (TypeTuple *)t1;
7271 length = Argument::dim(tup->arguments);
7273 else
7274 assert(0);
7276 if (index < length)
7279 if (e1->op == TOKtuple)
7280 e = (Expression *)te->exps->data[(size_t)index];
7281 else
7282 e = new TypeExp(e1->loc, Argument::getNth(tup->arguments, (size_t)index)->type);
7284 else
7286 error("array index [%"PRIuMAX"] is outside array bounds [0 .. %"PRIuSIZE"]",
7287 index, length);
7288 e = e1;
7290 break;
7293 default:
7294 error("%s must be an array or pointer type, not %s",
7295 e1->toChars(), e1->type->toChars());
7296 type = Type::tint32;
7297 break;
7299 return e;
7302 Expression *IndexExp::toLvalue(Scope *sc, Expression *e)
7304 // if (type && type->toBasetype()->ty == Tvoid)
7305 // error("voids have no value");
7306 return this;
7309 Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
7311 //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
7312 modifiable = 1;
7313 if (e1->op == TOKstring)
7314 error("string literals are immutable");
7315 if (type && !type->isMutable())
7316 error("%s isn't mutable", e->toChars());
7317 if (e1->type->toBasetype()->ty == Taarray)
7318 e1 = e1->modifiableLvalue(sc, e1);
7319 return toLvalue(sc, e);
7322 void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7324 expToCBuffer(buf, hgs, e1, PREC_primary);
7325 buf->writeByte('[');
7326 expToCBuffer(buf, hgs, e2, PREC_assign);
7327 buf->writeByte(']');
7331 /************************* PostExp ***********************************/
7333 PostExp::PostExp(enum TOK op, Loc loc, Expression *e)
7334 : BinExp(loc, op, sizeof(PostExp), e,
7335 new IntegerExp(loc, 1, Type::tint32))
7339 Expression *PostExp::semantic(Scope *sc)
7340 { Expression *e = this;
7342 if (!type)
7344 BinExp::semantic(sc);
7345 e2 = resolveProperties(sc, e2);
7347 e = op_overload(sc);
7348 if (e)
7349 return e;
7351 e = this;
7352 e1 = e1->modifiableLvalue(sc, e1);
7353 e1->checkScalar();
7354 e1->checkNoBool();
7355 if (e1->type->ty == Tpointer)
7356 e = scaleFactor(sc);
7357 else
7358 e2 = e2->castTo(sc, e1->type);
7359 e->type = e1->type;
7361 return e;
7364 void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7366 expToCBuffer(buf, hgs, e1, precedence[op]);
7367 buf->writestring((op == TOKplusplus) ? (char *)"++" : (char *)"--");
7370 /************************************************************/
7372 /* op can be TOKassign, TOKconstruct, or TOKblit */
7374 AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2)
7375 : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2)
7377 ismemset = 0;
7380 Expression *AssignExp::semantic(Scope *sc)
7382 Expression *e1old = e1;
7384 #if LOGSEMANTIC
7385 printf("AssignExp::semantic('%s')\n", toChars());
7386 #endif
7387 //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
7388 //printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op));
7390 if (type)
7391 return this;
7393 if (e2->op == TOKcomma)
7394 { /* Rewrite to get rid of the comma from rvalue
7396 AssignExp *ea = new AssignExp(loc, e1, ((CommaExp *)e2)->e2);
7397 ea->op = op;
7398 Expression *e = new CommaExp(loc, ((CommaExp *)e2)->e1, ea);
7399 return e->semantic(sc);
7402 /* Look for operator overloading of a[i]=value.
7403 * Do it before semantic() otherwise the a[i] will have been
7404 * converted to a.opIndex() already.
7406 if (e1->op == TOKarray)
7408 ArrayExp *ae = (ArrayExp *)e1;
7409 AggregateDeclaration *ad;
7410 Identifier *id = Id::index;
7412 ae->e1 = ae->e1->semantic(sc);
7413 Type *t1 = ae->e1->type->toBasetype();
7414 if (t1->ty == Tstruct)
7416 ad = ((TypeStruct *)t1)->sym;
7417 goto L1;
7419 else if (t1->ty == Tclass)
7421 ad = ((TypeClass *)t1)->sym;
7423 // Rewrite (a[i] = value) to (a.opIndexAssign(value, i))
7424 if (search_function(ad, Id::indexass))
7425 { Expression *e = new DotIdExp(loc, ae->e1, Id::indexass);
7426 Expressions *a = (Expressions *)ae->arguments->copy();
7428 a->insert(0, e2);
7429 e = new CallExp(loc, e, a);
7430 e = e->semantic(sc);
7431 return e;
7433 else
7435 // Rewrite (a[i] = value) to (a.opIndex(i, value))
7436 if (search_function(ad, id))
7437 { Expression *e = new DotIdExp(loc, ae->e1, id);
7439 if (1 || !global.params.useDeprecated)
7440 error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
7442 e = new CallExp(loc, e, (Expression *)ae->arguments->data[0], e2);
7443 e = e->semantic(sc);
7444 return e;
7449 /* Look for operator overloading of a[i..j]=value.
7450 * Do it before semantic() otherwise the a[i..j] will have been
7451 * converted to a.opSlice() already.
7453 if (e1->op == TOKslice)
7454 { Type *t1;
7455 SliceExp *ae = (SliceExp *)e1;
7456 AggregateDeclaration *ad;
7457 Identifier *id = Id::index;
7459 ae->e1 = ae->e1->semantic(sc);
7460 ae->e1 = resolveProperties(sc, ae->e1);
7461 t1 = ae->e1->type->toBasetype();
7462 if (t1->ty == Tstruct)
7464 ad = ((TypeStruct *)t1)->sym;
7465 goto L2;
7467 else if (t1->ty == Tclass)
7469 ad = ((TypeClass *)t1)->sym;
7471 // Rewrite (a[i..j] = value) to (a.opIndexAssign(value, i, j))
7472 if (search_function(ad, Id::sliceass))
7473 { Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass);
7474 Expressions *a = new Expressions();
7476 a->push(e2);
7477 if (ae->lwr)
7478 { a->push(ae->lwr);
7479 assert(ae->upr);
7480 a->push(ae->upr);
7482 else
7483 assert(!ae->upr);
7484 e = new CallExp(loc, e, a);
7485 e = e->semantic(sc);
7486 return e;
7491 BinExp::semantic(sc);
7492 e2 = resolveProperties(sc, e2);
7493 assert(e1->type);
7495 /* Rewrite tuple assignment as a tuple of assignments.
7497 if (e1->op == TOKtuple && e2->op == TOKtuple)
7498 { TupleExp *tup1 = (TupleExp *)e1;
7499 TupleExp *tup2 = (TupleExp *)e2;
7500 size_t dim = tup1->exps->dim;
7501 if (dim != tup2->exps->dim)
7503 error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim);
7505 else
7506 { Expressions *exps = new Expressions;
7507 exps->setDim(dim);
7509 for (int i = 0; i < dim; i++)
7510 { Expression *ex1 = (Expression *)tup1->exps->data[i];
7511 Expression *ex2 = (Expression *)tup2->exps->data[i];
7512 exps->data[i] = (void *) new AssignExp(loc, ex1, ex2);
7514 Expression *e = new TupleExp(loc, exps);
7515 e = e->semantic(sc);
7516 return e;
7520 Type *t1 = e1->type->toBasetype();
7522 if (t1->ty == Tfunction)
7523 { // Rewrite f=value to f(value)
7524 Expression *e;
7526 e = new CallExp(loc, e1, e2);
7527 e = e->semantic(sc);
7528 return e;
7531 /* If it is an assignment from a 'foreign' type,
7532 * check for operator overloading.
7534 if (t1->ty == Tstruct)
7536 StructDeclaration *sd = ((TypeStruct *)t1)->sym;
7537 if (op == TOKassign)
7539 Expression *e = op_overload(sc);
7540 if (e)
7541 return e;
7543 else if (op == TOKconstruct)
7544 { Type *t2 = e2->type->toBasetype();
7545 if (t2->ty == Tstruct &&
7546 sd == ((TypeStruct *)t2)->sym &&
7547 sd->cpctor)
7548 { /* We have a copy constructor for this
7550 if (e2->op == TOKvar || e2->op == TOKstar)
7551 { /* Write as:
7552 * e1.cpctor(e2);
7554 Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0);
7555 e = new CallExp(loc, e, e2);
7556 return e->semantic(sc);
7558 else if (e2->op == TOKquestion)
7559 { /* Write as:
7560 * a ? e1 = b : e1 = c;
7562 CondExp *ec = (CondExp *)e2;
7563 AssignExp *ea1 = new AssignExp(ec->e1->loc, e1, ec->e1);
7564 ea1->op = op;
7565 AssignExp *ea2 = new AssignExp(ec->e1->loc, e1, ec->e2);
7566 ea2->op = op;
7567 Expression *e = new CondExp(loc, ec->econd, ea1, ea2);
7568 return e->semantic(sc);
7573 else if (t1->ty == Tclass)
7574 { // Disallow assignment operator overloads for same type
7575 if (!e2->type->implicitConvTo(e1->type))
7577 Expression *e = op_overload(sc);
7578 if (e)
7579 return e;
7583 if (t1->ty == Tsarray)
7585 Expression *e = new SliceExp(e1->loc, e1, NULL, NULL);
7586 e1 = e->semantic(sc);
7587 t1 = e1->type->toBasetype();
7590 e2->rvalue();
7592 if (e1->op == TOKarraylength)
7594 // e1 is not an lvalue, but we let code generator handle it
7595 ArrayLengthExp *ale = (ArrayLengthExp *)e1;
7597 ale->e1 = ale->e1->modifiableLvalue(sc, e1);
7599 else if (e1->op == TOKslice)
7601 Type *tn = e1->type->nextOf();
7602 if (tn && !tn->isMutable() && op != TOKconstruct)
7603 error("slice %s is not mutable", e1->toChars());
7605 else
7606 { // Try to do a decent error message with the expression
7607 // before it got constant folded
7608 if (e1->op != TOKvar)
7609 e1 = e1->optimize(WANTvalue);
7610 if (op != TOKconstruct)
7611 e1 = e1->modifiableLvalue(sc, e1old);
7614 Type *t2 = e2->type;
7615 if (e1->op == TOKslice &&
7616 t1->nextOf() &&
7617 e2->implicitConvTo(t1->nextOf())
7619 { // memset
7620 ismemset = 1; // make it easy for back end to tell what this is
7621 e2 = e2->implicitCastTo(sc, t1->nextOf());
7623 else if (t1->ty == Tsarray)
7625 /* Should have already converted e1 => e1[]
7627 assert(0);
7628 //error("cannot assign to static array %s", e1->toChars());
7630 else if (e1->op == TOKslice)
7632 e2 = e2->implicitCastTo(sc, e1->type->constOf());
7634 else
7636 e2 = e2->implicitCastTo(sc, e1->type);
7638 type = e1->type;
7639 assert(type);
7640 return this;
7643 Expression *AssignExp::checkToBoolean()
7645 // Things like:
7646 // if (a = b) ...
7647 // are usually mistakes.
7649 error("'=' does not give a boolean result");
7650 return this;
7653 /************************************************************/
7655 AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
7656 : BinExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
7660 Expression *AddAssignExp::semantic(Scope *sc)
7661 { Expression *e;
7663 if (type)
7664 return this;
7666 BinExp::semantic(sc);
7667 e2 = resolveProperties(sc, e2);
7669 e = op_overload(sc);
7670 if (e)
7671 return e;
7673 e1 = e1->modifiableLvalue(sc, e1);
7675 Type *tb1 = e1->type->toBasetype();
7676 Type *tb2 = e2->type->toBasetype();
7678 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
7679 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
7680 tb1->nextOf()->equals(tb2->nextOf())
7683 type = e1->type;
7684 e = this;
7686 else
7688 e1->checkScalar();
7689 e1->checkNoBool();
7690 if (tb1->ty == Tpointer && tb2->isintegral())
7691 e = scaleFactor(sc);
7692 else if (tb1->ty == Tbit || tb1->ty == Tbool)
7694 #if 0
7695 // Need to rethink this
7696 if (e1->op != TOKvar)
7697 { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2
7698 VarDeclaration *v;
7699 Expression *ea;
7700 Expression *ex;
7702 Identifier *id = Lexer::uniqueId("__name");
7704 v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL);
7705 v->semantic(sc);
7706 if (!sc->insert(v))
7707 assert(0);
7708 v->parent = sc->func;
7710 ea = new AddrExp(loc, e1);
7711 ea = new AssignExp(loc, new VarExp(loc, v), ea);
7713 ex = new VarExp(loc, v);
7714 ex = new PtrExp(loc, ex);
7715 e = new AddExp(loc, ex, e2);
7716 e = new CastExp(loc, e, e1->type);
7717 e = new AssignExp(loc, ex->syntaxCopy(), e);
7719 e = new CommaExp(loc, ea, e);
7721 else
7722 #endif
7723 { // Rewrite e1+=e2 to e1=e1+e2
7724 // BUG: doesn't account for side effects in e1
7725 // BUG: other assignment operators for bits aren't handled at all
7726 e = new AddExp(loc, e1, e2);
7727 e = new CastExp(loc, e, e1->type);
7728 e = new AssignExp(loc, e1->syntaxCopy(), e);
7730 e = e->semantic(sc);
7732 else
7734 type = e1->type;
7735 typeCombine(sc);
7736 e1->checkArithmetic();
7737 e2->checkArithmetic();
7738 if (type->isreal() || type->isimaginary())
7740 assert(global.errors || e2->type->isfloating());
7741 e2 = e2->castTo(sc, e1->type);
7743 e = this;
7746 return e;
7749 /************************************************************/
7751 MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
7752 : BinExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
7756 Expression *MinAssignExp::semantic(Scope *sc)
7757 { Expression *e;
7759 if (type)
7760 return this;
7762 BinExp::semantic(sc);
7763 e2 = resolveProperties(sc, e2);
7765 e = op_overload(sc);
7766 if (e)
7767 return e;
7769 e1 = e1->modifiableLvalue(sc, e1);
7770 e1->checkScalar();
7771 e1->checkNoBool();
7772 if (e1->type->ty == Tpointer && e2->type->isintegral())
7773 e = scaleFactor(sc);
7774 else
7776 e1 = e1->checkArithmetic();
7777 e2 = e2->checkArithmetic();
7778 type = e1->type;
7779 typeCombine(sc);
7780 if (type->isreal() || type->isimaginary())
7782 assert(e2->type->isfloating());
7783 e2 = e2->castTo(sc, e1->type);
7785 e = this;
7787 return e;
7790 /************************************************************/
7792 CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
7793 : BinExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
7797 Expression *CatAssignExp::semantic(Scope *sc)
7798 { Expression *e;
7800 BinExp::semantic(sc);
7801 e2 = resolveProperties(sc, e2);
7803 e = op_overload(sc);
7804 if (e)
7805 return e;
7807 if (e1->op == TOKslice)
7808 { SliceExp *se = (SliceExp *)e1;
7810 if (se->e1->type->toBasetype()->ty == Tsarray)
7811 error("cannot append to static array %s", se->e1->type->toChars());
7814 e1 = e1->modifiableLvalue(sc, e1);
7816 Type *tb1 = e1->type->toBasetype();
7817 Type *tb2 = e2->type->toBasetype();
7819 e2->rvalue();
7821 if ((tb1->ty == Tarray) &&
7822 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
7823 (e2->implicitConvTo(e1->type) ||
7824 tb2->nextOf()->implicitConvTo(tb1->nextOf()))
7826 { // Append array
7827 e2 = e2->castTo(sc, e1->type);
7828 type = e1->type;
7829 e = this;
7831 else if ((tb1->ty == Tarray) &&
7832 e2->implicitConvTo(tb1->nextOf())
7834 { // Append element
7835 e2 = e2->castTo(sc, tb1->nextOf());
7836 type = e1->type;
7837 e = this;
7839 else
7841 error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars());
7842 type = Type::tint32;
7843 e = this;
7845 return e;
7848 /************************************************************/
7850 MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
7851 : BinExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
7855 Expression *MulAssignExp::semantic(Scope *sc)
7856 { Expression *e;
7858 BinExp::semantic(sc);
7859 e2 = resolveProperties(sc, e2);
7861 e = op_overload(sc);
7862 if (e)
7863 return e;
7865 e1 = e1->modifiableLvalue(sc, e1);
7866 e1->checkScalar();
7867 e1->checkNoBool();
7868 type = e1->type;
7869 typeCombine(sc);
7870 e1->checkArithmetic();
7871 e2->checkArithmetic();
7872 if (e2->type->isfloating())
7873 { Type *t1;
7874 Type *t2;
7876 t1 = e1->type;
7877 t2 = e2->type;
7878 if (t1->isreal())
7880 if (t2->isimaginary() || t2->iscomplex())
7882 e2 = e2->castTo(sc, t1);
7885 else if (t1->isimaginary())
7887 if (t2->isimaginary() || t2->iscomplex())
7889 switch (t1->ty)
7891 case Timaginary32: t2 = Type::tfloat32; break;
7892 case Timaginary64: t2 = Type::tfloat64; break;
7893 case Timaginary80: t2 = Type::tfloat80; break;
7894 default:
7895 assert(0);
7897 e2 = e2->castTo(sc, t2);
7901 return this;
7904 /************************************************************/
7906 DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
7907 : BinExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
7911 Expression *DivAssignExp::semantic(Scope *sc)
7912 { Expression *e;
7914 BinExp::semantic(sc);
7915 e2 = resolveProperties(sc, e2);
7917 e = op_overload(sc);
7918 if (e)
7919 return e;
7921 e1 = e1->modifiableLvalue(sc, e1);
7922 e1->checkScalar();
7923 e1->checkNoBool();
7924 type = e1->type;
7925 typeCombine(sc);
7926 e1->checkArithmetic();
7927 e2->checkArithmetic();
7928 if (e2->type->isimaginary())
7929 { Type *t1;
7930 Type *t2;
7932 t1 = e1->type;
7933 if (t1->isreal())
7934 { // x/iv = i(-x/v)
7935 // Therefore, the result is 0
7936 e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1));
7937 e2->type = t1;
7938 e = new AssignExp(loc, e1, e2);
7939 e->type = t1;
7940 return e;
7942 else if (t1->isimaginary())
7943 { Expression *e;
7945 switch (t1->ty)
7947 case Timaginary32: t2 = Type::tfloat32; break;
7948 case Timaginary64: t2 = Type::tfloat64; break;
7949 case Timaginary80: t2 = Type::tfloat80; break;
7950 default:
7951 assert(0);
7953 e2 = e2->castTo(sc, t2);
7954 e = new AssignExp(loc, e1, e2);
7955 e->type = t1;
7956 return e;
7959 return this;
7962 /************************************************************/
7964 ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
7965 : BinExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
7969 Expression *ModAssignExp::semantic(Scope *sc)
7971 return commonSemanticAssign(sc);
7974 /************************************************************/
7976 ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
7977 : BinExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
7981 Expression *ShlAssignExp::semantic(Scope *sc)
7982 { Expression *e;
7984 //printf("ShlAssignExp::semantic()\n");
7985 BinExp::semantic(sc);
7986 e2 = resolveProperties(sc, e2);
7988 e = op_overload(sc);
7989 if (e)
7990 return e;
7992 e1 = e1->modifiableLvalue(sc, e1);
7993 e1->checkScalar();
7994 e1->checkNoBool();
7995 type = e1->type;
7996 typeCombine(sc);
7997 e1->checkIntegral();
7998 e2 = e2->checkIntegral();
7999 e2 = e2->castTo(sc, Type::tshiftcnt);
8000 return this;
8003 /************************************************************/
8005 ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
8006 : BinExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
8010 Expression *ShrAssignExp::semantic(Scope *sc)
8011 { Expression *e;
8013 BinExp::semantic(sc);
8014 e2 = resolveProperties(sc, e2);
8016 e = op_overload(sc);
8017 if (e)
8018 return e;
8020 e1 = e1->modifiableLvalue(sc, e1);
8021 e1->checkScalar();
8022 e1->checkNoBool();
8023 type = e1->type;
8024 typeCombine(sc);
8025 e1->checkIntegral();
8026 e2 = e2->checkIntegral();
8027 e2 = e2->castTo(sc, Type::tshiftcnt);
8028 return this;
8031 /************************************************************/
8033 UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
8034 : BinExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
8038 Expression *UshrAssignExp::semantic(Scope *sc)
8039 { Expression *e;
8041 BinExp::semantic(sc);
8042 e2 = resolveProperties(sc, e2);
8044 e = op_overload(sc);
8045 if (e)
8046 return e;
8048 e1 = e1->modifiableLvalue(sc, e1);
8049 e1->checkScalar();
8050 e1->checkNoBool();
8051 type = e1->type;
8052 typeCombine(sc);
8053 e1->checkIntegral();
8054 e2 = e2->checkIntegral();
8055 e2 = e2->castTo(sc, Type::tshiftcnt);
8056 return this;
8059 /************************************************************/
8061 AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
8062 : BinExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
8066 Expression *AndAssignExp::semantic(Scope *sc)
8068 return commonSemanticAssignIntegral(sc);
8071 /************************************************************/
8073 OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
8074 : BinExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
8078 Expression *OrAssignExp::semantic(Scope *sc)
8080 return commonSemanticAssignIntegral(sc);
8083 /************************************************************/
8085 XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
8086 : BinExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
8090 Expression *XorAssignExp::semantic(Scope *sc)
8092 return commonSemanticAssignIntegral(sc);
8095 /************************* AddExp *****************************/
8097 AddExp::AddExp(Loc loc, Expression *e1, Expression *e2)
8098 : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2)
8102 Expression *AddExp::semantic(Scope *sc)
8103 { Expression *e;
8105 #if LOGSEMANTIC
8106 printf("AddExp::semantic('%s')\n", toChars());
8107 #endif
8108 if (!type)
8110 BinExp::semanticp(sc);
8112 e = op_overload(sc);
8113 if (e)
8114 return e;
8116 Type *tb1 = e1->type->toBasetype();
8117 Type *tb2 = e2->type->toBasetype();
8119 if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
8120 (tb2->ty == Tarray || tb2->ty == Tsarray) &&
8121 tb1->nextOf()->equals(tb2->nextOf())
8124 type = e1->type;
8125 e = this;
8127 else if (tb1->ty == Tpointer && e2->type->isintegral() ||
8128 tb2->ty == Tpointer && e1->type->isintegral())
8129 e = scaleFactor(sc);
8130 else if (tb1->ty == Tpointer && tb2->ty == Tpointer)
8132 incompatibleTypes();
8133 type = e1->type;
8134 e = this;
8136 else
8138 typeCombine(sc);
8139 if ((e1->type->isreal() && e2->type->isimaginary()) ||
8140 (e1->type->isimaginary() && e2->type->isreal()))
8142 switch (type->toBasetype()->ty)
8144 case Tfloat32:
8145 case Timaginary32:
8146 type = Type::tcomplex32;
8147 break;
8149 case Tfloat64:
8150 case Timaginary64:
8151 type = Type::tcomplex64;
8152 break;
8154 case Tfloat80:
8155 case Timaginary80:
8156 type = Type::tcomplex80;
8157 break;
8159 default:
8160 assert(0);
8163 e = this;
8165 return e;
8167 return this;
8170 /************************************************************/
8172 MinExp::MinExp(Loc loc, Expression *e1, Expression *e2)
8173 : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2)
8177 Expression *MinExp::semantic(Scope *sc)
8178 { Expression *e;
8179 Type *t1;
8180 Type *t2;
8182 #if LOGSEMANTIC
8183 printf("MinExp::semantic('%s')\n", toChars());
8184 #endif
8185 if (type)
8186 return this;
8188 BinExp::semanticp(sc);
8190 e = op_overload(sc);
8191 if (e)
8192 return e;
8194 e = this;
8195 t1 = e1->type->toBasetype();
8196 t2 = e2->type->toBasetype();
8197 if (t1->ty == Tpointer)
8199 if (t2->ty == Tpointer)
8200 { // Need to divide the result by the stride
8201 // Replace (ptr - ptr) with (ptr - ptr) / stride
8202 d_int64 stride;
8203 Expression *e;
8205 typeCombine(sc); // make sure pointer types are compatible
8206 type = Type::tptrdiff_t;
8207 stride = t2->nextOf()->size();
8208 e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
8209 e->type = Type::tptrdiff_t;
8210 return e;
8212 else if (t2->isintegral())
8213 e = scaleFactor(sc);
8214 else
8215 { error("incompatible types for -");
8216 return new IntegerExp(0);
8219 else if (t2->ty == Tpointer)
8221 type = e2->type;
8222 error("can't subtract pointer from %s", e1->type->toChars());
8223 return new IntegerExp(0);
8225 else
8227 typeCombine(sc);
8228 t1 = e1->type->toBasetype();
8229 t2 = e2->type->toBasetype();
8230 if ((t1->isreal() && t2->isimaginary()) ||
8231 (t1->isimaginary() && t2->isreal()))
8233 switch (type->ty)
8235 case Tfloat32:
8236 case Timaginary32:
8237 type = Type::tcomplex32;
8238 break;
8240 case Tfloat64:
8241 case Timaginary64:
8242 type = Type::tcomplex64;
8243 break;
8245 case Tfloat80:
8246 case Timaginary80:
8247 type = Type::tcomplex80;
8248 break;
8250 default:
8251 assert(0);
8255 return e;
8258 /************************* CatExp *****************************/
8260 CatExp::CatExp(Loc loc, Expression *e1, Expression *e2)
8261 : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2)
8265 Expression *CatExp::semantic(Scope *sc)
8266 { Expression *e;
8268 //printf("CatExp::semantic() %s\n", toChars());
8269 if (!type)
8271 BinExp::semanticp(sc);
8272 e = op_overload(sc);
8273 if (e)
8274 return e;
8276 Type *tb1 = e1->type->toBasetype();
8277 Type *tb2 = e2->type->toBasetype();
8280 /* BUG: Should handle things like:
8281 * char c;
8282 * c ~ ' '
8283 * ' ' ~ c;
8286 #if 0
8287 e1->type->print();
8288 e2->type->print();
8289 #endif
8290 if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
8291 e2->type->implicitConvTo(tb1->nextOf()) >= MATCHconst)
8293 type = tb1->nextOf()->arrayOf();
8294 if (tb2->ty == Tarray)
8295 { // Make e2 into [e2]
8296 e2 = new ArrayLiteralExp(e2->loc, e2);
8297 e2->type = type;
8299 return this;
8301 else if ((tb2->ty == Tsarray || tb2->ty == Tarray) &&
8302 e1->type->implicitConvTo(tb2->nextOf()) >= MATCHconst)
8304 type = tb2->nextOf()->arrayOf();
8305 if (tb1->ty == Tarray)
8306 { // Make e1 into [e1]
8307 e1 = new ArrayLiteralExp(e1->loc, e1);
8308 e1->type = type;
8310 return this;
8313 typeCombine(sc);
8314 type = type->toHeadMutable();
8316 Type *tb = type->toBasetype();
8317 if (tb->ty == Tsarray)
8318 type = tb->nextOf()->arrayOf();
8319 if (type->ty == Tarray && tb1->nextOf() && tb2->nextOf() &&
8320 tb1->nextOf()->mod != tb2->nextOf()->mod)
8321 type = type->nextOf()->toHeadMutable()->arrayOf();
8322 #if 0
8323 e1->type->print();
8324 e2->type->print();
8325 type->print();
8326 print();
8327 #endif
8328 Type *t1 = e1->type->toBasetype();
8329 Type *t2 = e2->type->toBasetype();
8330 if (e1->op == TOKstring && e2->op == TOKstring)
8331 e = optimize(WANTvalue);
8332 else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
8333 (t2->ty == Tarray || t2->ty == Tsarray))
8335 e = this;
8337 else
8339 //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars());
8340 error("Can only concatenate arrays, not (%s ~ %s)",
8341 e1->type->toChars(), e2->type->toChars());
8342 type = Type::tint32;
8343 e = this;
8345 e->type = e->type->semantic(loc, sc);
8346 return e;
8348 return this;
8351 /************************************************************/
8353 MulExp::MulExp(Loc loc, Expression *e1, Expression *e2)
8354 : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2)
8358 Expression *MulExp::semantic(Scope *sc)
8359 { Expression *e;
8361 #if 0
8362 printf("MulExp::semantic() %s\n", toChars());
8363 #endif
8364 if (type)
8366 return this;
8369 BinExp::semanticp(sc);
8370 e = op_overload(sc);
8371 if (e)
8372 return e;
8374 typeCombine(sc);
8375 e1->checkArithmetic();
8376 e2->checkArithmetic();
8377 if (type->isfloating())
8378 { Type *t1 = e1->type;
8379 Type *t2 = e2->type;
8381 if (t1->isreal())
8383 type = t2;
8385 else if (t2->isreal())
8387 type = t1;
8389 else if (t1->isimaginary())
8391 if (t2->isimaginary())
8392 { Expression *e;
8394 switch (t1->ty)
8396 case Timaginary32: type = Type::tfloat32; break;
8397 case Timaginary64: type = Type::tfloat64; break;
8398 case Timaginary80: type = Type::tfloat80; break;
8399 default: assert(0);
8402 // iy * iv = -yv
8403 e1->type = type;
8404 e2->type = type;
8405 e = new NegExp(loc, this);
8406 e = e->semantic(sc);
8407 return e;
8409 else
8410 type = t2; // t2 is complex
8412 else if (t2->isimaginary())
8414 type = t1; // t1 is complex
8417 return this;
8420 /************************************************************/
8422 DivExp::DivExp(Loc loc, Expression *e1, Expression *e2)
8423 : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2)
8427 Expression *DivExp::semantic(Scope *sc)
8428 { Expression *e;
8430 if (type)
8431 return this;
8433 BinExp::semanticp(sc);
8434 e = op_overload(sc);
8435 if (e)
8436 return e;
8438 typeCombine(sc);
8439 e1->checkArithmetic();
8440 e2->checkArithmetic();
8441 if (type->isfloating())
8442 { Type *t1 = e1->type;
8443 Type *t2 = e2->type;
8445 if (t1->isreal())
8447 type = t2;
8448 if (t2->isimaginary())
8449 { Expression *e;
8451 // x/iv = i(-x/v)
8452 e2->type = t1;
8453 e = new NegExp(loc, this);
8454 e = e->semantic(sc);
8455 return e;
8458 else if (t2->isreal())
8460 type = t1;
8462 else if (t1->isimaginary())
8464 if (t2->isimaginary())
8466 switch (t1->ty)
8468 case Timaginary32: type = Type::tfloat32; break;
8469 case Timaginary64: type = Type::tfloat64; break;
8470 case Timaginary80: type = Type::tfloat80; break;
8471 default: assert(0);
8474 else
8475 type = t2; // t2 is complex
8477 else if (t2->isimaginary())
8479 type = t1; // t1 is complex
8482 return this;
8485 /************************************************************/
8487 ModExp::ModExp(Loc loc, Expression *e1, Expression *e2)
8488 : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2)
8492 Expression *ModExp::semantic(Scope *sc)
8493 { Expression *e;
8495 if (type)
8496 return this;
8498 BinExp::semanticp(sc);
8499 e = op_overload(sc);
8500 if (e)
8501 return e;
8503 typeCombine(sc);
8504 e1->checkArithmetic();
8505 e2->checkArithmetic();
8506 if (type->isfloating())
8507 { type = e1->type;
8508 if (e2->type->iscomplex())
8509 { error("cannot perform modulo complex arithmetic");
8510 return new IntegerExp(0);
8513 return this;
8516 /************************************************************/
8518 ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2)
8519 : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2)
8523 Expression *ShlExp::semantic(Scope *sc)
8524 { Expression *e;
8526 //printf("ShlExp::semantic(), type = %p\n", type);
8527 if (!type)
8528 { BinExp::semanticp(sc);
8529 e = op_overload(sc);
8530 if (e)
8531 return e;
8532 e1 = e1->checkIntegral();
8533 e2 = e2->checkIntegral();
8534 e1 = e1->integralPromotions(sc);
8535 e2 = e2->castTo(sc, Type::tshiftcnt);
8536 type = e1->type;
8538 return this;
8541 /************************************************************/
8543 ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2)
8544 : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2)
8548 Expression *ShrExp::semantic(Scope *sc)
8549 { Expression *e;
8551 if (!type)
8552 { BinExp::semanticp(sc);
8553 e = op_overload(sc);
8554 if (e)
8555 return e;
8556 e1 = e1->checkIntegral();
8557 e2 = e2->checkIntegral();
8558 e1 = e1->integralPromotions(sc);
8559 e2 = e2->castTo(sc, Type::tshiftcnt);
8560 type = e1->type;
8562 return this;
8565 /************************************************************/
8567 UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2)
8568 : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2)
8572 Expression *UshrExp::semantic(Scope *sc)
8573 { Expression *e;
8575 if (!type)
8576 { BinExp::semanticp(sc);
8577 e = op_overload(sc);
8578 if (e)
8579 return e;
8580 e1 = e1->checkIntegral();
8581 e2 = e2->checkIntegral();
8582 e1 = e1->integralPromotions(sc);
8583 e2 = e2->castTo(sc, Type::tshiftcnt);
8584 type = e1->type;
8586 return this;
8589 /************************************************************/
8591 AndExp::AndExp(Loc loc, Expression *e1, Expression *e2)
8592 : BinExp(loc, TOKand, sizeof(AndExp), e1, e2)
8596 Expression *AndExp::semantic(Scope *sc)
8597 { Expression *e;
8599 if (!type)
8600 { BinExp::semanticp(sc);
8601 e = op_overload(sc);
8602 if (e)
8603 return e;
8604 if (e1->type->toBasetype()->ty == Tbool &&
8605 e2->type->toBasetype()->ty == Tbool)
8607 type = e1->type;
8608 e = this;
8610 else
8612 typeCombine(sc);
8613 e1->checkIntegral();
8614 e2->checkIntegral();
8617 return this;
8620 /************************************************************/
8622 OrExp::OrExp(Loc loc, Expression *e1, Expression *e2)
8623 : BinExp(loc, TOKor, sizeof(OrExp), e1, e2)
8627 Expression *OrExp::semantic(Scope *sc)
8628 { Expression *e;
8630 if (!type)
8631 { BinExp::semanticp(sc);
8632 e = op_overload(sc);
8633 if (e)
8634 return e;
8635 if (e1->type->toBasetype()->ty == Tbool &&
8636 e2->type->toBasetype()->ty == Tbool)
8638 type = e1->type;
8639 e = this;
8641 else
8643 typeCombine(sc);
8644 e1->checkIntegral();
8645 e2->checkIntegral();
8648 return this;
8651 /************************************************************/
8653 XorExp::XorExp(Loc loc, Expression *e1, Expression *e2)
8654 : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2)
8658 Expression *XorExp::semantic(Scope *sc)
8659 { Expression *e;
8661 if (!type)
8662 { BinExp::semanticp(sc);
8663 e = op_overload(sc);
8664 if (e)
8665 return e;
8666 if (e1->type->toBasetype()->ty == Tbool &&
8667 e2->type->toBasetype()->ty == Tbool)
8669 type = e1->type;
8670 e = this;
8672 else
8674 typeCombine(sc);
8675 e1->checkIntegral();
8676 e2->checkIntegral();
8679 return this;
8683 /************************************************************/
8685 OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2)
8686 : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2)
8690 Expression *OrOrExp::semantic(Scope *sc)
8692 unsigned cs1;
8694 // same as for AndAnd
8695 e1 = e1->semantic(sc);
8696 e1 = resolveProperties(sc, e1);
8697 e1 = e1->checkToPointer();
8698 e1 = e1->checkToBoolean();
8699 cs1 = sc->callSuper;
8701 if (sc->flags & SCOPEstaticif)
8703 /* If in static if, don't evaluate e2 if we don't have to.
8705 e1 = e1->optimize(WANTflags);
8706 if (e1->isBool(TRUE))
8708 return new IntegerExp(loc, 1, Type::tboolean);
8712 e2 = e2->semantic(sc);
8713 sc->mergeCallSuper(loc, cs1);
8714 e2 = resolveProperties(sc, e2);
8715 e2 = e2->checkToPointer();
8717 type = Type::tboolean;
8718 if (e1->type->ty == Tvoid)
8719 type = Type::tvoid;
8720 if (e2->op == TOKtype || e2->op == TOKimport)
8721 error("%s is not an expression", e2->toChars());
8722 return this;
8725 Expression *OrOrExp::checkToBoolean()
8727 e2 = e2->checkToBoolean();
8728 return this;
8731 int OrOrExp::isBit()
8733 return TRUE;
8736 int OrOrExp::checkSideEffect(int flag)
8738 if (flag == 2)
8740 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
8742 else
8743 { e1->checkSideEffect(1);
8744 return e2->checkSideEffect(flag);
8748 /************************************************************/
8750 AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2)
8751 : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2)
8755 Expression *AndAndExp::semantic(Scope *sc)
8757 unsigned cs1;
8759 // same as for OrOr
8760 e1 = e1->semantic(sc);
8761 e1 = resolveProperties(sc, e1);
8762 e1 = e1->checkToPointer();
8763 e1 = e1->checkToBoolean();
8764 cs1 = sc->callSuper;
8766 if (sc->flags & SCOPEstaticif)
8768 /* If in static if, don't evaluate e2 if we don't have to.
8770 e1 = e1->optimize(WANTflags);
8771 if (e1->isBool(FALSE))
8773 return new IntegerExp(loc, 0, Type::tboolean);
8777 e2 = e2->semantic(sc);
8778 sc->mergeCallSuper(loc, cs1);
8779 e2 = resolveProperties(sc, e2);
8780 e2 = e2->checkToPointer();
8782 type = Type::tboolean;
8783 if (e1->type->ty == Tvoid)
8784 type = Type::tvoid;
8785 if (e2->op == TOKtype || e2->op == TOKimport)
8786 error("%s is not an expression", e2->toChars());
8787 return this;
8790 Expression *AndAndExp::checkToBoolean()
8792 e2 = e2->checkToBoolean();
8793 return this;
8796 int AndAndExp::isBit()
8798 return TRUE;
8801 int AndAndExp::checkSideEffect(int flag)
8803 if (flag == 2)
8805 return e1->checkSideEffect(2) || e2->checkSideEffect(2);
8807 else
8809 e1->checkSideEffect(1);
8810 return e2->checkSideEffect(flag);
8814 /************************************************************/
8816 InExp::InExp(Loc loc, Expression *e1, Expression *e2)
8817 : BinExp(loc, TOKin, sizeof(InExp), e1, e2)
8821 Expression *InExp::semantic(Scope *sc)
8822 { Expression *e;
8824 if (type)
8825 return this;
8827 BinExp::semanticp(sc);
8828 e = op_overload(sc);
8829 if (e)
8830 return e;
8832 //type = Type::tboolean;
8833 Type *t2b = e2->type->toBasetype();
8834 if (t2b->ty != Taarray)
8836 error("rvalue of in expression must be an associative array, not %s", e2->type->toChars());
8837 type = Type::terror;
8839 else
8841 TypeAArray *ta = (TypeAArray *)t2b;
8843 // Convert key to type of key
8844 e1 = e1->implicitCastTo(sc, ta->index);
8846 // Return type is pointer to value
8847 type = ta->nextOf()->pointerTo();
8849 return this;
8852 int InExp::isBit()
8854 return FALSE;
8858 /************************************************************/
8860 /* This deletes the key e1 from the associative array e2
8863 RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2)
8864 : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2)
8866 type = Type::tvoid;
8869 /************************************************************/
8871 CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
8872 : BinExp(loc, op, sizeof(CmpExp), e1, e2)
8876 Expression *CmpExp::semantic(Scope *sc)
8877 { Expression *e;
8878 Type *t1;
8879 Type *t2;
8881 #if LOGSEMANTIC
8882 printf("CmpExp::semantic('%s')\n", toChars());
8883 #endif
8884 if (type)
8885 return this;
8887 BinExp::semanticp(sc);
8889 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
8890 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
8892 error("do not use null when comparing class types");
8895 e = op_overload(sc);
8896 if (e)
8898 e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32));
8899 e = e->semantic(sc);
8900 return e;
8903 typeCombine(sc);
8904 type = Type::tboolean;
8906 // Special handling for array comparisons
8907 t1 = e1->type->toBasetype();
8908 t2 = e2->type->toBasetype();
8909 if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
8910 (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
8912 if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
8913 t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
8914 (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
8915 error("array comparison type mismatch, %s vs %s", t1->nextOf()->toChars(), t2->nextOf()->toChars());
8916 e = this;
8918 else if (t1->ty == Tstruct || t2->ty == Tstruct ||
8919 (t1->ty == Tclass && t2->ty == Tclass))
8921 if (t2->ty == Tstruct)
8922 error("need member function opCmp() for %s %s to compare", t2->toDsymbol(sc)->kind(), t2->toChars());
8923 else
8924 error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars());
8925 e = this;
8927 #if 1
8928 else if (t1->iscomplex() || t2->iscomplex())
8930 error("compare not defined for complex operands");
8931 e = new IntegerExp(0);
8933 #endif
8934 else
8935 e = this;
8936 //printf("CmpExp: %s\n", e->toChars());
8937 return e;
8940 int CmpExp::isBit()
8942 return TRUE;
8946 /************************************************************/
8948 EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
8949 : BinExp(loc, op, sizeof(EqualExp), e1, e2)
8951 assert(op == TOKequal || op == TOKnotequal);
8954 Expression *EqualExp::semantic(Scope *sc)
8955 { Expression *e;
8956 Type *t1;
8957 Type *t2;
8959 //printf("EqualExp::semantic('%s')\n", toChars());
8960 if (type)
8961 return this;
8963 BinExp::semanticp(sc);
8965 /* Before checking for operator overloading, check to see if we're
8966 * comparing the addresses of two statics. If so, we can just see
8967 * if they are the same symbol.
8969 if (e1->op == TOKaddress && e2->op == TOKaddress)
8970 { AddrExp *ae1 = (AddrExp *)e1;
8971 AddrExp *ae2 = (AddrExp *)e2;
8973 if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar)
8974 { VarExp *ve1 = (VarExp *)ae1->e1;
8975 VarExp *ve2 = (VarExp *)ae2->e1;
8977 if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/)
8979 // They are the same, result is 'true' for ==, 'false' for !=
8980 e = new IntegerExp(loc, (op == TOKequal), Type::tboolean);
8981 return e;
8986 if (e1->type->toBasetype()->ty == Tclass && e2->op == TOKnull ||
8987 e2->type->toBasetype()->ty == Tclass && e1->op == TOKnull)
8989 error("use '%s' instead of '%s' when comparing with null",
8990 Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity),
8991 Token::toChars(op));
8994 //if (e2->op != TOKnull)
8996 e = op_overload(sc);
8997 if (e)
8999 if (op == TOKnotequal)
9001 e = new NotExp(e->loc, e);
9002 e = e->semantic(sc);
9004 return e;
9008 e = typeCombine(sc);
9009 type = Type::tboolean;
9011 // Special handling for array comparisons
9012 t1 = e1->type->toBasetype();
9013 t2 = e2->type->toBasetype();
9015 if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
9016 (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
9018 if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
9019 t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
9020 (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
9021 error("array equality comparison type mismatch, %s vs %s", t1->toChars(), t2->toChars());
9023 else
9025 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
9027 // Cast both to complex
9028 e1 = e1->castTo(sc, Type::tcomplex80);
9029 e2 = e2->castTo(sc, Type::tcomplex80);
9032 return e;
9035 int EqualExp::isBit()
9037 return TRUE;
9042 /************************************************************/
9044 IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
9045 : BinExp(loc, op, sizeof(IdentityExp), e1, e2)
9049 Expression *IdentityExp::semantic(Scope *sc)
9051 if (type)
9052 return this;
9054 BinExp::semanticp(sc);
9055 type = Type::tboolean;
9056 typeCombine(sc);
9057 if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
9059 // Cast both to complex
9060 e1 = e1->castTo(sc, Type::tcomplex80);
9061 e2 = e2->castTo(sc, Type::tcomplex80);
9063 return this;
9066 int IdentityExp::isBit()
9068 return TRUE;
9072 /****************************************************************/
9074 CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2)
9075 : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2)
9077 this->econd = econd;
9080 Expression *CondExp::syntaxCopy()
9082 return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy());
9086 Expression *CondExp::semantic(Scope *sc)
9087 { Type *t1;
9088 Type *t2;
9089 unsigned cs0;
9090 unsigned cs1;
9092 #if LOGSEMANTIC
9093 printf("CondExp::semantic('%s')\n", toChars());
9094 #endif
9095 if (type)
9096 return this;
9098 econd = econd->semantic(sc);
9099 econd = resolveProperties(sc, econd);
9100 econd = econd->checkToPointer();
9101 econd = econd->checkToBoolean();
9103 #if 0 /* this cannot work right because the types of e1 and e2
9104 * both contribute to the type of the result.
9106 if (sc->flags & SCOPEstaticif)
9108 /* If in static if, don't evaluate what we don't have to.
9110 econd = econd->optimize(WANTflags);
9111 if (econd->isBool(TRUE))
9113 e1 = e1->semantic(sc);
9114 e1 = resolveProperties(sc, e1);
9115 return e1;
9117 else if (econd->isBool(FALSE))
9119 e2 = e2->semantic(sc);
9120 e2 = resolveProperties(sc, e2);
9121 return e2;
9124 #endif
9127 cs0 = sc->callSuper;
9128 e1 = e1->semantic(sc);
9129 e1 = resolveProperties(sc, e1);
9130 cs1 = sc->callSuper;
9131 sc->callSuper = cs0;
9132 e2 = e2->semantic(sc);
9133 e2 = resolveProperties(sc, e2);
9134 sc->mergeCallSuper(loc, cs1);
9137 // If either operand is void, the result is void
9138 t1 = e1->type;
9139 t2 = e2->type;
9140 if (t1->ty == Tvoid || t2->ty == Tvoid)
9141 type = Type::tvoid;
9142 else if (t1 == t2)
9143 type = t1;
9144 else
9146 typeCombine(sc);
9147 switch (e1->type->toBasetype()->ty)
9149 case Tcomplex32:
9150 case Tcomplex64:
9151 case Tcomplex80:
9152 e2 = e2->castTo(sc, e1->type);
9153 break;
9155 switch (e2->type->toBasetype()->ty)
9157 case Tcomplex32:
9158 case Tcomplex64:
9159 case Tcomplex80:
9160 e1 = e1->castTo(sc, e2->type);
9161 break;
9163 if (type->toBasetype()->ty == Tarray)
9165 e1 = e1->castTo(sc, type);
9166 e2 = e2->castTo(sc, type);
9169 #if 0
9170 printf("res: %s\n", type->toChars());
9171 printf("e1 : %s\n", e1->type->toChars());
9172 printf("e2 : %s\n", e2->type->toChars());
9173 #endif
9174 return this;
9177 Expression *CondExp::toLvalue(Scope *sc, Expression *ex)
9179 PtrExp *e;
9181 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
9182 e = new PtrExp(loc, this, type);
9184 e1 = e1->addressOf(sc);
9185 //e1 = e1->toLvalue(sc, NULL);
9187 e2 = e2->addressOf(sc);
9188 //e2 = e2->toLvalue(sc, NULL);
9190 typeCombine(sc);
9192 type = e2->type;
9193 return e;
9196 Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e)
9198 error("conditional expression %s is not a modifiable lvalue", toChars());
9199 return this;
9202 void CondExp::checkEscape()
9204 e1->checkEscape();
9205 e2->checkEscape();
9209 Expression *CondExp::checkToBoolean()
9211 e1 = e1->checkToBoolean();
9212 e2 = e2->checkToBoolean();
9213 return this;
9216 int CondExp::checkSideEffect(int flag)
9218 if (flag == 2)
9220 return econd->checkSideEffect(2) ||
9221 e1->checkSideEffect(2) ||
9222 e2->checkSideEffect(2);
9224 else
9226 econd->checkSideEffect(1);
9227 e1->checkSideEffect(flag);
9228 return e2->checkSideEffect(flag);
9232 int CondExp::canThrow()
9234 return econd->canThrow() || e1->canThrow() || e2->canThrow();
9238 void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
9240 expToCBuffer(buf, hgs, econd, PREC_oror);
9241 buf->writestring(" ? ");
9242 expToCBuffer(buf, hgs, e1, PREC_expr);
9243 buf->writestring(" : ");
9244 expToCBuffer(buf, hgs, e2, PREC_cond);
9248 /****************************************************************/
9250 DefaultInitExp::DefaultInitExp(Loc loc, enum TOK subop, int size)
9251 : Expression(loc, TOKdefault, size)
9253 this->subop = subop;
9256 void DefaultInitExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
9258 buf->writestring(Token::toChars(subop));
9261 /****************************************************************/
9263 FileInitExp::FileInitExp(Loc loc)
9264 : DefaultInitExp(loc, TOKfile, sizeof(FileInitExp))
9268 Expression *FileInitExp::semantic(Scope *sc)
9270 //printf("FileInitExp::semantic()\n");
9271 type = Type::tchar->invariantOf()->arrayOf();
9272 return this;
9275 Expression *FileInitExp::resolve(Loc loc, Scope *sc)
9277 //printf("FileInitExp::resolve() %s\n", toChars());
9278 char *s = loc.filename ? loc.filename : sc->module->ident->toChars();
9279 Expression *e = new StringExp(loc, s);
9280 e = e->semantic(sc);
9281 e = e->castTo(sc, type);
9282 return e;
9285 /****************************************************************/
9287 LineInitExp::LineInitExp(Loc loc)
9288 : DefaultInitExp(loc, TOKline, sizeof(LineInitExp))
9292 Expression *LineInitExp::semantic(Scope *sc)
9294 type = Type::tint32;
9295 return this;
9298 Expression *LineInitExp::resolve(Loc loc, Scope *sc)
9300 Expression *e = new IntegerExp(loc, loc.linnum, Type::tint32);
9301 e = e->castTo(sc, type);
9302 return e;