1:
2: // Compiler implementation of the D programming language
3: // Copyright (c) 1999-2011 by Digital Mars
4: // All Rights Reserved
5: // written by Walter Bright
6: // http://www.digitalmars.com
7: // License for redistribution is by either the Artistic License
8: // in artistic.txt, or the GNU General Public License in gnu.txt.
9: // See the included readme.txt for details.
10:
11: #include <stdio.h>
12: #include <stdlib.h>
13: #include <ctype.h>
14: #include <math.h>
15: static char __file__[] = __FILE__; /* for tassert.h */
16: #include "tassert.h"
17: #if _MSC_VER
18: #include <complex>
19: #else
20: #include <complex.h>
21: #endif
22:
23: #if _WIN32 && __DMC__
24: extern "C" char * __cdecl __locale_decpoint;
25: #endif
26:
27: #include "cdef.h"
28: #include "rmem.h"
29: #include "port.h"
30: #include "root.h"
31:
32: #include "mtype.h"
33: #include "init.h"
34: #include "expression.h"
35: #include "template.h"
36: #include "utf.h"
37: #include "enum.h"
38: #include "scope.h"
39: #include "statement.h"
40: #include "declaration.h"
41: #include "aggregate.h"
42: #include "import.h"
43: #include "id.h"
44: #include "dsymbol.h"
45: #include "module.h"
46: #include "attrib.h"
47: #include "hdrgen.h"
48: #include "parse.h"
49: #include "doc.h"
50:
51:
52: Expression *createTypeInfoArray(Scope *sc, Expression *args[], int dim);
53: Expression *expandVar(int result, VarDeclaration *v);
54:
55: #define LOGSEMANTIC 0
56:
57: /*************************************************************
58: * Given var, we need to get the
59: * right 'this' pointer if var is in an outer class, but our
60: * existing 'this' pointer is in an inner class.
61: * Input:
62: * e1 existing 'this'
63: * ad struct or class we need the correct 'this' for
64: * var the specific member of ad we're accessing
65: */
66:
67: Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
68: Expression *e1, Declaration *var)
69: {
70: //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
71: L1:
72: Type *t = e1->type->toBasetype();
73: //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
74:
75: /* If e1 is not the 'this' pointer for ad
76: */
77: if (ad &&
78: !(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
79: ((TypeStruct *)t->nextOf())->sym == ad)
80: &&
81: !(t->ty == Tstruct &&
82: ((TypeStruct *)t)->sym == ad)
83: )
84: {
85: ClassDeclaration *cd = ad->isClassDeclaration();
86: ClassDeclaration *tcd = t->isClassHandle();
87:
88: /* e1 is the right this if ad is a base class of e1
89: */
90: if (!cd || !tcd ||
91: !(tcd == cd || cd->isBaseOf(tcd, NULL))
92: )
93: {
94: /* Only classes can be inner classes with an 'outer'
95: * member pointing to the enclosing class instance
96: */
97: if (tcd && tcd->isNested())
98: { /* e1 is the 'this' pointer for an inner class: tcd.
99: * Rewrite it as the 'this' pointer for the outer class.
100: */
101:
102: e1 = new DotVarExp(loc, e1, tcd->vthis);
warning C6211: Leaking memory 'e1' due to an exception. Consider using a local catch block to clean up memory: Lines: 71, 72, 80, 85, 86, 90, 97, 102, 103, 109, 110, 111, 112, 130, 136, 137, 71, 72, 80, 85, 86, 90, 97, 102, 103, 109, 110, 111, 112, 130, 136, 137, 71, 72, 80, 85, 86, 90, 97, 102, 103, 109, 110, 111, 112, 114, 115, 118, 119
103: e1->type = tcd->vthis->type;
104: // Do not call checkNestedRef()
105: //e1 = e1->semantic(sc);
106:
107: // Skip up over nested functions, and get the enclosing
108: // class type.
109: int n = 0;
110: Dsymbol *s;
111: for (s = tcd->toParent();
112: s && s->isFuncDeclaration();
113: s = s->toParent())
114: { FuncDeclaration *f = s->isFuncDeclaration();
115: if (f->vthis)
116: {
117: //printf("rewriting e1 to %s's this\n", f->toChars());
118: n++;
119: e1 = new VarExp(loc, f->vthis);
120: }
121: else
122: {
123: e1->error("need 'this' of type %s to access member %s"
124: " from static function %s",
125: ad->toChars(), var->toChars(), f->toChars());
126: e1 = new ErrorExp();
127: return e1;
128: }
129: }
130: if (s && s->isClassDeclaration())
131: { e1->type = s->isClassDeclaration()->type;
132: if (n > 1)
133: e1 = e1->semantic(sc);
134: }
135: else
136: e1 = e1->semantic(sc);
137: goto L1;
138: }
139: /* Can't find a path from e1 to ad
140: */
141: e1->error("this for %s needs to be type %s not type %s",
142: var->toChars(), ad->toChars(), t->toChars());
143: e1 = new ErrorExp();
144: }
145: }
146: return e1;
147: }
148:
149: /*****************************************
150: * Determine if 'this' is available.
151: * If it is, return the FuncDeclaration that has it.
152: */
153:
154: FuncDeclaration *hasThis(Scope *sc)
155: { FuncDeclaration *fd;
156: FuncDeclaration *fdthis;
157:
158: //printf("hasThis()\n");
159: fdthis = sc->parent->isFuncDeclaration();
160: //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : "");
161:
162: // Go upwards until we find the enclosing member function
163: fd = fdthis;
164: while (1)
165: {
166: if (!fd)
167: {
168: goto Lno;
169: }
170: if (!fd->isNested())
171: break;
172:
173: Dsymbol *parent = fd->parent;
174: while (parent)
175: {
176: TemplateInstance *ti = parent->isTemplateInstance();
177: if (ti)
178: parent = ti->parent;
179: else
180: break;
181: }
182:
183: fd = parent->isFuncDeclaration();
warning C6011: Dereferencing NULL pointer 'parent': Lines: 155, 156, 159, 163, 164, 166, 170, 173, 174, 183
184: }
185:
186: if (!fd->isThis())
187: { //printf("test '%s'\n", fd->toChars());
188: goto Lno;
189: }
190:
191: assert(fd->vthis);
192: return fd;
193:
194: Lno:
195: return NULL; // don't have 'this' available
196: }
197:
198:
199: /***************************************
200: * Pull out any properties.
201: */
202:
203: Expression *resolveProperties(Scope *sc, Expression *e)
204: {
205: //printf("resolveProperties(%s)\n", e->toChars());
206: if (e->type)
207: {
208: Type *t = e->type->toBasetype();
209:
210: if (t->ty == Tfunction || e->op == TOKoverloadset)
211: {
212: #if 1
213: if (t->ty == Tfunction && !((TypeFunction *)t)->isproperty &&
214: global.params.enforcePropertySyntax)
215: {
216: error(e->loc, "not a property %s\n", e->toChars());
217: }
218: #endif
219: e = new CallExp(e->loc, e);
220: e = e->semantic(sc);
221: }
222:
223: /* Look for e being a lazy parameter; rewrite as delegate call
224: */
225: else if (e->op == TOKvar)
226: { VarExp *ve = (VarExp *)e;
227:
228: if (ve->var->storage_class & STClazy)
229: {
230: e = new CallExp(e->loc, e);
231: e = e->semantic(sc);
232: }
233: }
234:
235: else if (e->op == TOKdotexp)
236: {
237: e->error("expression has no value");
238: return new ErrorExp();
239: }
240:
241: }
242: else if (e->op == TOKdottd)
243: {
244: e = new CallExp(e->loc, e);
245: e = e->semantic(sc);
246: }
247: return e;
248: }
249:
250: /******************************
251: * Perform semantic() on an array of Expressions.
252: */
253:
254: Expressions *arrayExpressionSemantic(Expressions *exps, Scope *sc)
255: {
256: if (exps)
257: {
258: for (size_t i = 0; i < exps->dim; i++)
259: { Expression *e = (*exps)[i];
260: if (e)
261: { e = e->semantic(sc);
262: (*exps)[i] = e;
263: }
264: }
265: }
266: return exps;
267: }
268:
269:
270: /******************************
271: * Perform canThrow() on an array of Expressions.
272: */
273:
274: #if DMDV2
275: int arrayExpressionCanThrow(Expressions *exps, bool mustNotThrow)
276: {
277: if (exps)
278: {
279: for (size_t i = 0; i < exps->dim; i++)
280: { Expression *e = (*exps)[i];
281: if (e && e->canThrow(mustNotThrow))
282: return 1;
283: }
284: }
285: return 0;
286: }
287: #endif
288:
289: /****************************************
290: * Expand tuples.
291: */
292:
293: void expandTuples(Expressions *exps)
294: {
295: //printf("expandTuples()\n");
296: if (exps)
297: {
298: for (size_t i = 0; i < exps->dim; i++)
299: { Expression *arg = (*exps)[i];
300: if (!arg)
301: continue;
302:
303: // Look for tuple with 0 members
304: if (arg->op == TOKtype)
305: { TypeExp *e = (TypeExp *)arg;
306: if (e->type->toBasetype()->ty == Ttuple)
307: { TypeTuple *tt = (TypeTuple *)e->type->toBasetype();
308:
309: if (!tt->arguments || tt->arguments->dim == 0)
310: {
311: exps->remove(i);
312: if (i == exps->dim)
313: return;
314: i--;
315: continue;
316: }
317: }
318: }
319:
320: // Inline expand all the tuples
321: while (arg->op == TOKtuple)
322: { TupleExp *te = (TupleExp *)arg;
323:
324: exps->remove(i); // remove arg
325: exps->insert(i, te->exps); // replace with tuple contents
326: if (i == exps->dim)
327: return; // empty tuple, no more arguments
328: arg = (*exps)[i];
329: }
330: }
331: }
332: }
333:
334: Expressions *arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
335: {
336: #if DMDV1
337: /* The first element sets the type
338: */
339: Type *t0 = NULL;
340: for (size_t i = 0; i < exps->dim; i++)
341: { Expression *e = (*exps)[i];
342:
343: if (!e->type)
344: { error("%s has no value", e->toChars());
345: e = new ErrorExp();
346: }
347: e = resolveProperties(sc, e);
348:
349: if (!t0)
350: t0 = e->type;
351: else
352: e = e->implicitCastTo(sc, t0);
353: (*exps)[i] = e;
354: }
355:
356: if (!t0)
357: t0 = Type::tvoid;
358: if (pt)
359: *pt = t0;
360:
361: // Eventually, we want to make this copy-on-write
362: return exps;
363: #endif
364: #if DMDV2
365: /* The type is determined by applying ?: to each pair.
366: */
367: /* Still have a problem with:
368: * ubyte[][] = [ cast(ubyte[])"hello", [1]];
369: * which works if the array literal is initialized top down with the ubyte[][]
370: * type, but fails with this function doing bottom up typing.
371: */
372: //printf("arrayExpressionToCommonType()\n");
373: IntegerExp integerexp(0);
374: CondExp condexp(0, &integerexp, NULL, NULL);
375:
376: Type *t0 = NULL;
377: Expression *e0;
378: int j0;
379: for (size_t i = 0; i < exps->dim; i++)
380: { Expression *e = (*exps)[i];
381:
382: e = resolveProperties(sc, e);
383: if (!e->type)
384: { error("%s has no value", e->toChars());
385: e = new ErrorExp();
386: }
387:
388: if (t0)
389: { if (t0 != e->type)
390: {
391: /* This applies ?: to merge the types. It's backwards;
392: * ?: should call this function to merge types.
393: */
394: condexp.type = NULL;
395: condexp.e1 = e0;
396: condexp.e2 = e;
397: condexp.loc = e->loc;
398: condexp.semantic(sc);
399: (*exps)[j0] = condexp.e1;
400: e = condexp.e2;
401: j0 = i;
402: e0 = e;
403: t0 = e0->type;
404: }
405: }
406: else
407: { j0 = i;
408: e0 = e;
409: t0 = e->type;
410: }
411: (*exps)[i] = e;
412: }
413:
414: if (t0)
415: {
416: for (size_t i = 0; i < exps->dim; i++)
417: { Expression *e = (*exps)[i];
418: e = e->implicitCastTo(sc, t0);
419: (*exps)[i] = e;
420: }
421: }
422: else
423: t0 = Type::tvoid; // [] is typed as void[]
424: if (pt)
425: *pt = t0;
426:
427: // Eventually, we want to make this copy-on-write
428: return exps;
429: #endif
430: }
431:
432: /****************************************
433: * Get TemplateDeclaration enclosing FuncDeclaration.
434: */
435:
436: TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s)
437: {
438: FuncDeclaration *f = s->isFuncDeclaration();
439: if (f && f->parent)
440: { TemplateInstance *ti = f->parent->isTemplateInstance();
441:
442: if (ti &&
443: !ti->isTemplateMixin() &&
444: (ti->name == f->ident ||
445: ti->toAlias()->ident == f->ident)
446: &&
447: ti->tempdecl && ti->tempdecl->onemember)
448: {
449: return ti->tempdecl;
450: }
451: }
452: return NULL;
453: }
454:
455: /****************************************
456: * Preprocess arguments to function.
457: */
458:
459: void preFunctionParameters(Loc loc, Scope *sc, Expressions *exps)
460: {
461: if (exps)
462: {
463: expandTuples(exps);
464:
465: for (size_t i = 0; i < exps->dim; i++)
466: { Expression *arg = (*exps)[i];
467:
468: if (!arg->type)
469: {
470: #ifdef DEBUG
471: if (!global.gag)
472: printf("1: \n");
473: #endif
474: arg->error("%s is not an expression", arg->toChars());
475: arg = new ErrorExp();
476: }
477:
478: arg = resolveProperties(sc, arg);
479: (*exps)[i] = arg;
480:
481: //arg->rvalue();
482: #if 0
483: if (arg->type->ty == Tfunction)
484: {
485: arg = new AddrExp(arg->loc, arg);
486: arg = arg->semantic(sc);
487: (*exps)[i] = arg;
488: }
489: #endif
490: }
491: }
492: }
493:
494: /************************************************
495: * If we want the value of this expression, but do not want to call
496: * the destructor on it.
497: */
498:
499: void valueNoDtor(Expression *e)
500: {
501: if (e->op == TOKcall)
502: {
503: /* The struct value returned from the function is transferred
504: * so do not call the destructor on it.
505: * Recognize:
506: * ((S _ctmp = S.init), _ctmp).this(...)
507: * and make sure the destructor is not called on _ctmp
508: * BUG: if e is a CommaExp, we should go down the right side.
509: */
510: CallExp *ce = (CallExp *)e;
511: if (ce->e1->op == TOKdotvar)
512: { DotVarExp *dve = (DotVarExp *)ce->e1;
513: if (dve->var->isCtorDeclaration())
514: { // It's a constructor call
515: if (dve->e1->op == TOKcomma)
516: { CommaExp *comma = (CommaExp *)dve->e1;
517: if (comma->e2->op == TOKvar)
518: { VarExp *ve = (VarExp *)comma->e2;
519: VarDeclaration *ctmp = ve->var->isVarDeclaration();
520: if (ctmp)
521: ctmp->noscope = 1;
522: }
523: }
524: }
525: }
526: }
527: }
528:
529: /*********************************************
530: * Call copy constructor for struct value argument.
531: */
532: #if DMDV2
533: Expression *callCpCtor(Loc loc, Scope *sc, Expression *e, int noscope)
534: {
535: Type *tb = e->type->toBasetype();
536: assert(tb->ty == Tstruct);
537: StructDeclaration *sd = ((TypeStruct *)tb)->sym;
538: if (sd->cpctor)
539: {
540: /* Create a variable tmp, and replace the argument e with:
541: * (tmp = e),tmp
542: * and let AssignExp() handle the construction.
543: * This is not the most efficent, ideally tmp would be constructed
544: * directly onto the stack.
545: */
546: Identifier *idtmp = Lexer::uniqueId("__cpcttmp");
547: VarDeclaration *tmp = new VarDeclaration(loc, tb, idtmp, new ExpInitializer(0, e));
548: tmp->storage_class |= STCctfe;
549: tmp->noscope = noscope;
550: Expression *ae = new DeclarationExp(loc, tmp);
551: e = new CommaExp(loc, ae, new VarExp(loc, tmp));
552: e = e->semantic(sc);
553: }
554: return e;
555: }
556: #endif
557:
558: /****************************************
559: * Now that we know the exact type of the function we're calling,
560: * the arguments[] need to be adjusted:
561: * 1. implicitly convert argument to the corresponding parameter type
562: * 2. add default arguments for any missing arguments
563: * 3. do default promotions on arguments corresponding to ...
564: * 4. add hidden _arguments[] argument
565: * 5. call copy constructor for struct value arguments
566: * Returns:
567: * return type from function
568: */
569:
570: Type *functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
571: Expressions *arguments, FuncDeclaration *fd)
572: {
573: //printf("functionParameters()\n");
574: assert(arguments);
575: size_t nargs = arguments ? arguments->dim : 0;
576: size_t nparams = Parameter::dim(tf->parameters);
577:
578: if (nargs > nparams && tf->varargs == 0)
579: error(loc, "expected %"SIZE_T_FORMAT"u arguments, not %"SIZE_T_FORMAT"u for non-variadic function type %s", nparams, nargs, tf->toChars());
580:
581: unsigned n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
582:
583: unsigned wildmatch = 0;
584: int done = 0;
585: for (size_t i = 0; i < n; i++)
586: {
587: Expression *arg;
588:
589: if (i < nargs)
590: arg = arguments->tdata()[i];
591: else
592: arg = NULL;
593: Type *tb;
594:
595: if (i < nparams)
596: {
597: Parameter *p = Parameter::getNth(tf->parameters, i);
598:
599: if (!arg)
600: {
601: if (!p->defaultArg)
602: {
603: if (tf->varargs == 2 && i + 1 == nparams)
604: goto L2;
605: error(loc, "expected %"SIZE_T_FORMAT"u function arguments, not %"SIZE_T_FORMAT"u", nparams, nargs);
606: return tf->next;
607: }
608: arg = p->defaultArg;
609: arg = arg->inlineCopy(sc);
610: #if DMDV2
611: arg = arg->resolveLoc(loc, sc); // __FILE__ and __LINE__
612: #endif
613: arguments->push(arg);
614: nargs++;
615: }
616:
617: if (tf->varargs == 2 && i + 1 == nparams)
618: {
619: //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
620: if (arg->implicitConvTo(p->type))
621: {
622: if (nargs != nparams)
623: { error(loc, "expected %"SIZE_T_FORMAT"u function arguments, not %"SIZE_T_FORMAT"u", nparams, nargs);
624: return tf->next;
625: }
626: goto L1;
627: }
628: L2:
629: Type *tb = p->type->toBasetype();
warning C6246: Local declaration of 'tb' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '593' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 593
630: Type *tret = p->isLazyArray();
631: switch (tb->ty)
632: {
633: case Tsarray:
634: case Tarray:
635: { // Create a static array variable v of type arg->type
636: #ifdef IN_GCC
637: /* GCC 4.0 does not like zero length arrays used like
638: this; pass a null array value instead. Could also
639: just make a one-element array. */
640: if (nargs - i == 0)
641: {
642: arg = new NullExp(loc);
643: break;
644: }
645: #endif
646: Identifier *id = Lexer::uniqueId("__arrayArg");
647: Type *t = new TypeSArray(((TypeArray *)tb)->next, new IntegerExp(nargs - i));
648: t = t->semantic(loc, sc);
649: VarDeclaration *v = new VarDeclaration(loc, t, id, fd->isSafe() ? NULL : new VoidInitializer(loc));
650: v->storage_class |= STCctfe;
651: v->semantic(sc);
652: v->parent = sc->parent;
653: //sc->insert(v);
654:
655: Expression *c = new DeclarationExp(0, v);
656: c->type = v->type;
657:
658: for (size_t u = i; u < nargs; u++)
659: { Expression *a = arguments->tdata()[u];
660: if (tret && !((TypeArray *)tb)->next->equals(a->type))
661: a = a->toDelegate(sc, tret);
662:
663: Expression *e = new VarExp(loc, v);
664: e = new IndexExp(loc, e, new IntegerExp(u + 1 - nparams));
665: ConstructExp *ae = new ConstructExp(loc, e, a);
666: if (c)
667: c = new CommaExp(loc, c, ae);
668: else
669: c = ae;
670: }
671: arg = new VarExp(loc, v);
672: if (c)
673: arg = new CommaExp(loc, c, arg);
674: break;
675: }
676: case Tclass:
677: { /* Set arg to be:
678: * new Tclass(arg0, arg1, ..., argn)
679: */
680: Expressions *args = new Expressions();
681: args->setDim(nargs - i);
682: for (size_t u = i; u < nargs; u++)
683: args->tdata()[u - i] = arguments->tdata()[u];
684: arg = new NewExp(loc, NULL, NULL, p->type, args);
685: break;
686: }
687: default:
688: if (!arg)
689: { error(loc, "not enough arguments");
690: return tf->next;
691: }
692: break;
693: }
694: arg = arg->semantic(sc);
695: //printf("\targ = '%s'\n", arg->toChars());
696: arguments->setDim(i + 1);
697: done = 1;
698: }
699:
700: L1:
701: if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
702: {
703: if (p->type != arg->type)
704: {
705: //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
706: if (arg->op == TOKtype)
707: { arg->error("cannot pass type %s as function argument", arg->toChars());
708: arg = new ErrorExp();
709: goto L3;
710: }
711: if (p->type->isWild() && tf->next->isWild())
712: { Type *t = p->type;
713: MATCH m = arg->implicitConvTo(t);
714: if (m == MATCHnomatch)
715: { t = t->constOf();
716: m = arg->implicitConvTo(t);
717: if (m == MATCHnomatch)
718: { t = t->sharedConstOf();
719: m = arg->implicitConvTo(t);
720: }
721: wildmatch |= p->type->wildMatch(arg->type);
722: }
723: arg = arg->implicitCastTo(sc, t);
724: }
725: else
726: arg = arg->implicitCastTo(sc, p->type);
727: arg = arg->optimize(WANTvalue);
728: }
729: }
730: if (p->storageClass & STCref)
731: {
732: arg = arg->toLvalue(sc, arg);
733: }
734: else if (p->storageClass & STCout)
735: {
736: arg = arg->modifiableLvalue(sc, arg);
737: }
738:
739: tb = arg->type->toBasetype();
740: #if !SARRAYVALUE
741: // Convert static arrays to pointers
742: if (tb->ty == Tsarray)
743: {
744: arg = arg->checkToPointer();
745: }
746: #endif
747: #if DMDV2
748: if (tb->ty == Tstruct && !(p->storageClass & (STCref | STCout)))
749: {
750: if (arg->op == TOKcall)
751: {
752: /* The struct value returned from the function is transferred
753: * to the function, so the callee should not call the destructor
754: * on it.
755: */
756: valueNoDtor(arg);
757: }
758: else
759: { /* Not transferring it, so call the copy constructor
760: */
761: arg = callCpCtor(loc, sc, arg, 1);
762: }
763: }
764: #endif
765:
766: //printf("arg: %s\n", arg->toChars());
767: //printf("type: %s\n", arg->type->toChars());
768:
769: // Convert lazy argument to a delegate
770: if (p->storageClass & STClazy)
771: {
772: arg = arg->toDelegate(sc, p->type);
773: }
774: #if DMDV2
775: /* Look for arguments that cannot 'escape' from the called
776: * function.
777: */
778: if (!tf->parameterEscapes(p))
779: {
780: /* Function literals can only appear once, so if this
781: * appearance was scoped, there cannot be any others.
782: */
783: if (arg->op == TOKfunction)
784: { FuncExp *fe = (FuncExp *)arg;
785: fe->fd->tookAddressOf = 0;
786: }
787:
788: /* For passing a delegate to a scoped parameter,
789: * this doesn't count as taking the address of it.
790: * We only worry about 'escaping' references to the function.
791: */
792: else if (arg->op == TOKdelegate)
793: { DelegateExp *de = (DelegateExp *)arg;
794: if (de->e1->op == TOKvar)
795: { VarExp *ve = (VarExp *)de->e1;
796: FuncDeclaration *f = ve->var->isFuncDeclaration();
797: if (f)
798: { f->tookAddressOf--;
799: //printf("tookAddressOf = %d\n", f->tookAddressOf);
800: }
801: }
802: }
803: }
804: #endif
805: }
806: else
807: {
808:
809: // If not D linkage, do promotions
810: if (tf->linkage != LINKd)
811: {
812: // Promote bytes, words, etc., to ints
813: arg = arg->integralPromotions(sc);
814:
815: // Promote floats to doubles
816: switch (arg->type->ty)
817: {
818: case Tfloat32:
819: arg = arg->castTo(sc, Type::tfloat64);
820: break;
821:
822: case Timaginary32:
823: arg = arg->castTo(sc, Type::timaginary64);
824: break;
825: }
826: }
827:
828: // Do not allow types that need destructors
829: if (arg->type->needsDestruction())
830: arg->error("cannot pass types that need destruction as variadic arguments");
831:
832: // Convert static arrays to dynamic arrays
833: // BUG: I don't think this is right for D2
834: tb = arg->type->toBasetype();
835: if (tb->ty == Tsarray)
836: { TypeSArray *ts = (TypeSArray *)tb;
837: Type *ta = ts->next->arrayOf();
838: if (ts->size(arg->loc) == 0)
839: arg = new NullExp(arg->loc, ta);
840: else
841: arg = arg->castTo(sc, ta);
842: }
843: #if DMDV2
844: if (tb->ty == Tstruct)
845: {
846: arg = callCpCtor(loc, sc, arg, 1);
847: }
848: #endif
849:
850: // Give error for overloaded function addresses
851: if (arg->op == TOKsymoff)
852: { SymOffExp *se = (SymOffExp *)arg;
853: if (
854: #if DMDV2
855: se->hasOverloads &&
856: #endif
857: !se->var->isFuncDeclaration()->isUnique())
858: arg->error("function %s is overloaded", arg->toChars());
859: }
860: arg->rvalue();
861: }
862: arg = arg->optimize(WANTvalue);
863: L3:
864: arguments->tdata()[i] = arg;
865: if (done)
866: break;
867: }
868:
869: // If D linkage and variadic, add _arguments[] as first argument
870: if (tf->linkage == LINKd && tf->varargs == 1)
871: {
872: assert(arguments->dim >= nparams);
873: Expression *e = createTypeInfoArray(sc, (Expression **)&arguments->tdata()[nparams],
874: arguments->dim - nparams);
875: arguments->insert(0, e);
876: }
877:
878: // If inferring return type, and semantic3() needs to be run if not already run
879: if (!tf->next && fd->inferRetType)
880: fd->semantic3(fd->scope);
881:
882: Type *tret = tf->next;
883: if (wildmatch)
884: { /* Adjust function return type based on wildmatch
885: */
886: //printf("wildmatch = x%x\n", wildmatch);
887: assert(tret->isWild());
888: if (wildmatch & MODconst || wildmatch & (wildmatch - 1))
889: tret = tret->constOf();
890: else if (wildmatch & MODimmutable)
891: tret = tret->invariantOf();
892: else
893: { assert(wildmatch & MODmutable);
894: tret = tret->mutableOf();
895: }
896: }
897: return tret;
898: }
899:
900: /**************************************************
901: * Write expression out to buf, but wrap it
902: * in ( ) if its precedence is less than pr.
903: */
904:
905: void expToCBuffer(OutBuffer *buf, HdrGenState *hgs, Expression *e, enum PREC pr)
906: {
907: #ifdef DEBUG
908: if (precedence[e->op] == PREC_zero)
909: printf("precedence not defined for token '%s'\n",Token::tochars[e->op]);
910: #endif
911: assert(precedence[e->op] != PREC_zero);
912: assert(pr != PREC_zero);
913:
914: //if (precedence[e->op] == 0) e->dump(0);
915: if (precedence[e->op] < pr ||
916: /* Despite precedence, we don't allow a<b<c expressions.
917: * They must be parenthesized.
918: */
919: (pr == PREC_rel && precedence[e->op] == pr))
920: {
921: buf->writeByte('(');
922: e->toCBuffer(buf, hgs);
923: buf->writeByte(')');
924: }
925: else
926: e->toCBuffer(buf, hgs);
927: }
928:
929: /**************************************************
930: * Write out argument list to buf.
931: */
932:
933: void argsToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
934: {
935: if (arguments)
936: {
937: for (size_t i = 0; i < arguments->dim; i++)
938: { Expression *arg = arguments->tdata()[i];
939:
940: if (arg)
941: { if (i)
942: buf->writeByte(',');
943: expToCBuffer(buf, hgs, arg, PREC_assign);
944: }
945: }
946: }
947: }
948:
949: /**************************************************
950: * Write out argument types to buf.
951: */
952:
953: void argExpTypesToCBuffer(OutBuffer *buf, Expressions *arguments, HdrGenState *hgs)
954: {
955: if (arguments)
956: { OutBuffer argbuf;
957:
958: for (size_t i = 0; i < arguments->dim; i++)
959: { Expression *arg = arguments->tdata()[i];
960:
961: if (i)
962: buf->writeByte(',');
963: argbuf.reset();
964: arg->type->toCBuffer2(&argbuf, hgs, 0);
965: buf->write(&argbuf);
966: }
967: }
968: }
969:
970: /******************************** Expression **************************/
971:
972: Expression::Expression(Loc loc, enum TOK op, int size)
973: : loc(loc)
974: {
975: //printf("Expression::Expression(op = %d) this = %p\n", op, this);
976: this->loc = loc;
977: this->op = op;
978: this->size = size;
979: this->parens = 0;
980: type = NULL;
981: }
982:
983: Expression *Expression::syntaxCopy()
984: {
985: //printf("Expression::syntaxCopy()\n");
986: //dump(0);
987: return copy();
988: }
989:
990: /*********************************
991: * Does *not* do a deep copy.
992: */
993:
994: Expression *Expression::copy()
995: {
996: Expression *e;
997: if (!size)
998: {
999: #ifdef DEBUG
1000: fprintf(stdmsg, "No expression copy for: %s\n", toChars());
1001: printf("op = %d\n", op);
1002: dump(0);
1003: #endif
1004: assert(0);
1005: }
1006: e = (Expression *)mem.malloc(size);
1007: //printf("Expression::copy(op = %d) e = %p\n", op, e);
1008: return (Expression *)memcpy(e, this, size);
1009: }
1010:
1011: /**************************
1012: * Semantically analyze Expression.
1013: * Determine types, fold constants, etc.
1014: */
1015:
1016: Expression *Expression::semantic(Scope *sc)
1017: {
1018: #if LOGSEMANTIC
1019: printf("Expression::semantic() %s\n", toChars());
1020: #endif
1021: if (type)
1022: type = type->semantic(loc, sc);
1023: else
1024: type = Type::tvoid;
1025: return this;
1026: }
1027:
1028: /**********************************
1029: * Try to run semantic routines.
1030: * If they fail, return NULL.
1031: */
1032:
1033: Expression *Expression::trySemantic(Scope *sc)
1034: {
1035: //printf("+trySemantic(%s)\n", toChars());
1036: unsigned errors = global.errors;
1037: global.gag++;
1038: Expression *e = semantic(sc);
1039: global.gag--;
1040: if (errors != global.errors)
1041: {
1042: global.errors = errors;
1043: e = NULL;
1044: }
1045: //printf("-trySemantic(%s)\n", toChars());
1046: return e;
1047: }
1048:
1049: void Expression::print()
1050: {
1051: fprintf(stdmsg, "%s\n", toChars());
1052: fflush(stdmsg);
1053: }
1054:
1055: char *Expression::toChars()
1056: { OutBuffer *buf;
1057: HdrGenState hgs;
1058:
1059: memset(&hgs, 0, sizeof(hgs));
1060: buf = new OutBuffer();
1061: toCBuffer(buf, &hgs);
1062: return buf->toChars();
1063: }
1064:
1065: void Expression::error(const char *format, ...)
1066: {
1067: if (type != Type::terror)
1068: {
1069: va_list ap;
1070: va_start(ap, format);
1071: ::verror(loc, format, ap);
1072: va_end( ap );
1073: }
1074: }
1075:
1076: void Expression::warning(const char *format, ...)
1077: {
1078: if (type != Type::terror)
1079: {
1080: va_list ap;
1081: va_start(ap, format);
1082: ::vwarning(loc, format, ap);
1083: va_end( ap );
1084: }
1085: }
1086:
1087: void Expression::rvalue()
1088: {
1089: if (type && type->toBasetype()->ty == Tvoid)
1090: { error("expression %s is void and has no value", toChars());
1091: #if 0
1092: dump(0);
1093: halt();
1094: #endif
1095: type = Type::terror;
1096: }
1097: }
1098:
1099: Expression *Expression::combine(Expression *e1, Expression *e2)
1100: {
1101: if (e1)
1102: {
1103: if (e2)
1104: {
1105: e1 = new CommaExp(e1->loc, e1, e2);
1106: e1->type = e2->type;
1107: }
1108: }
1109: else
1110: e1 = e2;
1111: return e1;
1112: }
1113:
1114: dinteger_t Expression::toInteger()
1115: {
1116: //printf("Expression %s\n", Token::toChars(op));
1117: error("Integer constant expression expected instead of %s", toChars());
1118: return 0;
1119: }
1120:
1121: uinteger_t Expression::toUInteger()
1122: {
1123: //printf("Expression %s\n", Token::toChars(op));
1124: return (uinteger_t)toInteger();
1125: }
1126:
1127: real_t Expression::toReal()
1128: {
1129: error("Floating point constant expression expected instead of %s", toChars());
1130: return 0;
1131: }
1132:
1133: real_t Expression::toImaginary()
1134: {
1135: error("Floating point constant expression expected instead of %s", toChars());
1136: return 0;
1137: }
1138:
1139: complex_t Expression::toComplex()
1140: {
1141: error("Floating point constant expression expected instead of %s", toChars());
1142: #ifdef IN_GCC
1143: return complex_t(real_t(0)); // %% nicer
1144: #else
1145: return 0;
1146: #endif
1147: }
1148:
1149: void Expression::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1150: {
1151: buf->writestring(Token::toChars(op));
1152: }
1153:
1154: void Expression::toMangleBuffer(OutBuffer *buf)
1155: {
1156: error("expression %s is not a valid template value argument", toChars());
1157: #ifdef DEBUG
1158: dump(0);
1159: #endif
1160: }
1161:
1162: /***************************************
1163: * Return !=0 if expression is an lvalue.
1164: */
1165: #if DMDV2
1166: int Expression::isLvalue()
1167: {
1168: return 0;
1169: }
1170: #endif
1171:
1172: /*******************************
1173: * Give error if we're not an lvalue.
1174: * If we can, convert expression to be an lvalue.
1175: */
1176:
1177: Expression *Expression::toLvalue(Scope *sc, Expression *e)
1178: {
1179: if (!e)
1180: e = this;
1181: else if (!loc.filename)
1182: loc = e->loc;
1183: error("%s is not an lvalue", e->toChars());
1184: return this;
1185: }
1186:
1187: Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
1188: {
1189: //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
1190:
1191: // See if this expression is a modifiable lvalue (i.e. not const)
1192: #if DMDV2
1193: if (type && (!type->isMutable() || !type->isAssignable()))
1194: error("%s is not mutable", e->toChars());
1195: #endif
1196: return toLvalue(sc, e);
1197: }
1198:
1199: /************************************
1200: * Detect cases where pointers to the stack can 'escape' the
1201: * lifetime of the stack frame.
1202: */
1203:
1204: void Expression::checkEscape()
1205: {
1206: }
1207:
1208: void Expression::checkEscapeRef()
1209: {
1210: }
1211:
1212: void Expression::checkScalar()
1213: {
1214: if (!type->isscalar() && type->toBasetype() != Type::terror)
1215: error("'%s' is not a scalar, it is a %s", toChars(), type->toChars());
1216: rvalue();
1217: }
1218:
1219: void Expression::checkNoBool()
1220: {
1221: if (type->toBasetype()->ty == Tbool)
1222: error("operation not allowed on bool '%s'", toChars());
1223: }
1224:
1225: Expression *Expression::checkIntegral()
1226: {
1227: if (!type->isintegral())
1228: { if (type->toBasetype() != Type::terror)
1229: error("'%s' is not of integral type, it is a %s", toChars(), type->toChars());
1230: return new ErrorExp();
1231: }
1232: rvalue();
1233: return this;
1234: }
1235:
1236: Expression *Expression::checkArithmetic()
1237: {
1238: if (!type->isintegral() && !type->isfloating())
1239: { if (type->toBasetype() != Type::terror)
1240: error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
1241: return new ErrorExp();
1242: }
1243: rvalue();
1244: return this;
1245: }
1246:
1247: void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
1248: {
1249: s->checkDeprecated(loc, sc);
1250: }
1251:
1252: #if DMDV2
1253: /*********************************************
1254: * Calling function f.
1255: * Check the purity, i.e. if we're in a pure function
1256: * we can only call other pure functions.
1257: */
1258: void Expression::checkPurity(Scope *sc, FuncDeclaration *f)
1259: {
1260: #if 1
1261: if (sc->func)
1262: {
1263: /* Given:
1264: * void f()
1265: * { pure void g()
1266: * {
1267: * void h()
1268: * {
1269: * void i() { }
1270: * }
1271: * }
1272: * }
1273: * g() can call h() but not f()
1274: * i() can call h() and g() but not f()
1275: */
1276: FuncDeclaration *outerfunc = sc->func;
1277: // Find the closest pure parent of the calling function
1278: while (outerfunc->toParent2() &&
1279: !outerfunc->isPure() &&
1280: outerfunc->toParent2()->isFuncDeclaration())
1281: {
1282: outerfunc = outerfunc->toParent2()->isFuncDeclaration();
1283: }
1284: // Find the closest pure parent of the called function
1285: FuncDeclaration *calledparent = f;
1286: while (calledparent->toParent2() && !calledparent->isPure()
1287: && calledparent->toParent2()->isFuncDeclaration() )
1288: {
1289: calledparent = calledparent->toParent2()->isFuncDeclaration();
1290: }
1291: // If the caller has a pure parent, then either the called func must be pure,
1292: // OR, they must have the same pure parent.
1293: if (/*outerfunc->isPure() &&*/ // comment out because we deduce purity now
1294: !sc->intypeof &&
1295: !(sc->flags & SCOPEdebug) &&
1296: !(f->isPure() || (calledparent == outerfunc)))
1297: {
1298: if (outerfunc->setImpure())
1299: error("pure function '%s' cannot call impure function '%s'",
1300: outerfunc->toChars(), f->toChars());
1301: }
1302: }
1303: #else
1304: if (sc->func && sc->func->isPure() && !sc->intypeof && !f->isPure())
1305: error("pure function '%s' cannot call impure function '%s'",
1306: sc->func->toChars(), f->toChars());
1307: #endif
1308: }
1309:
1310: /*******************************************
1311: * Accessing variable v.
1312: * Check for purity and safety violations.
1313: * If ethis is not NULL, then ethis is the 'this' pointer as in ethis.v
1314: */
1315:
1316: void Expression::checkPurity(Scope *sc, VarDeclaration *v, Expression *ethis)
1317: {
1318: /* Look for purity and safety violations when accessing variable v
1319: * from current function.
1320: */
1321: if (sc->func &&
1322: !sc->intypeof && // allow violations inside typeof(expression)
1323: !(sc->flags & SCOPEdebug) && // allow violations inside debug conditionals
1324: v->ident != Id::ctfe && // magic variable never violates pure and safe
1325: !v->isImmutable() && // always safe and pure to access immutables...
1326: !(v->isConst() && v->isDataseg() && !v->type->hasPointers()) && // const global value types are immutable
1327: !(v->storage_class & STCmanifest) // ...or manifest constants
1328: )
1329: {
1330: if (v->isDataseg())
1331: {
1332: /* Accessing global mutable state.
1333: * Therefore, this function and all its immediately enclosing
1334: * functions must be pure.
1335: */
1336: bool msg = FALSE;
1337: for (Dsymbol *s = sc->func; s; s = s->toParent2())
1338: {
1339: FuncDeclaration *ff = s->isFuncDeclaration();
1340: if (!ff)
1341: break;
1342: if (ff->setImpure() && !msg)
1343: { error("pure function '%s' cannot access mutable static data '%s'",
1344: sc->func->toChars(), v->toChars());
1345: msg = TRUE; // only need the innermost message
1346: }
1347: }
1348: }
1349: else
1350: {
1351: /* Given:
1352: * void f()
1353: * { int fx;
1354: * pure void g()
1355: * { int gx;
1356: * void h()
1357: * { int hx;
1358: * void i() { }
1359: * }
1360: * }
1361: * }
1362: * i() can modify hx and gx but not fx
1363: */
1364:
1365: Dsymbol *vparent = v->toParent2();
1366: for (Dsymbol *s = sc->func; s; s = s->toParent2())
1367: {
1368: if (s == vparent)
1369: break;
1370: FuncDeclaration *ff = s->isFuncDeclaration();
1371: if (!ff)
1372: break;
1373: if (ff->setImpure())
1374: { error("pure nested function '%s' cannot access mutable data '%s'",
1375: ff->toChars(), v->toChars());
1376: break;
1377: }
1378: }
1379: }
1380:
1381: /* Do not allow safe functions to access __gshared data
1382: */
1383: if (v->storage_class & STCgshared)
1384: {
1385: if (sc->func->setUnsafe())
1386: error("safe function '%s' cannot access __gshared data '%s'",
1387: sc->func->toChars(), v->toChars());
1388: }
1389:
1390: L1: ;
warning C4102: 'L1' : unreferenced label
1391: }
1392: }
1393:
1394: void Expression::checkSafety(Scope *sc, FuncDeclaration *f)
1395: {
1396: if (sc->func && !sc->intypeof &&
1397: !f->isSafe() && !f->isTrusted())
1398: {
1399: if (sc->func->setUnsafe())
1400: error("safe function '%s' cannot call system function '%s'",
1401: sc->func->toChars(), f->toChars());
1402: }
1403: }
1404: #endif
1405:
1406: /********************************
1407: * Check for expressions that have no use.
1408: * Input:
1409: * flag 0 not going to use the result, so issue error message if no
1410: * side effects
1411: * 1 the result of the expression is used, but still check
1412: * for useless subexpressions
1413: * 2 do not issue error messages, just return !=0 if expression
1414: * has side effects
1415: */
1416:
1417: int Expression::checkSideEffect(int flag)
1418: {
1419: if (flag == 0)
1420: {
1421: if (op == TOKerror)
1422: { // Error should have already been printed
1423: }
1424: else if (op == TOKimport)
1425: {
1426: error("%s has no effect", toChars());
1427: }
1428: else
1429: error("%s has no effect in expression (%s)",
1430: Token::toChars(op), toChars());
1431: }
1432: return 0;
1433: }
1434:
1435: /*****************************
1436: * Check that expression can be tested for true or false.
1437: */
1438:
1439: Expression *Expression::checkToBoolean(Scope *sc)
1440: {
1441: // Default is 'yes' - do nothing
1442:
1443: #ifdef DEBUG
1444: if (!type)
1445: dump(0);
1446: #endif
1447:
1448: // Structs can be converted to bool using opCast(bool)()
1449: Type *tb = type->toBasetype();
1450: if (tb->ty == Tstruct)
1451: { AggregateDeclaration *ad = ((TypeStruct *)tb)->sym;
1452: /* Don't really need to check for opCast first, but by doing so we
1453: * get better error messages if it isn't there.
1454: */
1455: Dsymbol *fd = search_function(ad, Id::cast);
1456: if (fd)
1457: {
1458: Expression *e = new CastExp(loc, this, Type::tbool);
1459: e = e->semantic(sc);
1460: return e;
1461: }
1462:
1463: // Forward to aliasthis.
1464: if (ad->aliasthis)
1465: {
1466: Expression *e = new DotIdExp(loc, this, ad->aliasthis->ident);
1467: e = e->semantic(sc);
1468: e = resolveProperties(sc, e);
1469: e = e->checkToBoolean(sc);
1470: return e;
1471: }
1472: }
1473:
1474: if (!type->checkBoolean())
1475: { if (type->toBasetype() != Type::terror)
1476: error("expression %s of type %s does not have a boolean value", toChars(), type->toChars());
1477: return new ErrorExp();
1478: }
1479: return this;
1480: }
1481:
1482: /****************************
1483: */
1484:
1485: Expression *Expression::checkToPointer()
1486: {
1487: //printf("Expression::checkToPointer()\n");
1488: Expression *e = this;
1489:
1490: #if !SARRAYVALUE
1491: // If C static array, convert to pointer
1492: Type *tb = type->toBasetype();
1493: if (tb->ty == Tsarray)
1494: { TypeSArray *ts = (TypeSArray *)tb;
1495: if (ts->size(loc) == 0)
1496: e = new NullExp(loc);
1497: else
1498: e = new AddrExp(loc, this);
1499: e->type = ts->next->pointerTo();
1500: }
1501: #endif
1502: return e;
1503: }
1504:
1505: /******************************
1506: * Take address of expression.
1507: */
1508:
1509: Expression *Expression::addressOf(Scope *sc)
1510: {
1511: Expression *e;
1512:
1513: //printf("Expression::addressOf()\n");
1514: e = toLvalue(sc, NULL);
1515: e = new AddrExp(loc, e);
1516: e->type = type->pointerTo();
1517: return e;
1518: }
1519:
1520: /******************************
1521: * If this is a reference, dereference it.
1522: */
1523:
1524: Expression *Expression::deref()
1525: {
1526: //printf("Expression::deref()\n");
1527: // type could be null if forward referencing an 'auto' variable
1528: if (type && type->ty == Treference)
1529: {
1530: Expression *e = new PtrExp(loc, this);
1531: e->type = ((TypeReference *)type)->next;
1532: return e;
1533: }
1534: return this;
1535: }
1536:
1537: /********************************
1538: * Does this expression statically evaluate to a boolean TRUE or FALSE?
1539: */
1540:
1541: int Expression::isBool(int result)
1542: {
1543: return FALSE;
1544: }
1545:
1546: /********************************
1547: * Does this expression result in either a 1 or a 0?
1548: */
1549:
1550: int Expression::isBit()
1551: {
1552: return FALSE;
1553: }
1554:
1555: /********************************
1556: * Can this expression throw an exception?
1557: * Valid only after semantic() pass.
1558: *
1559: * If 'mustNotThrow' is true, generate an error if it throws
1560: */
1561:
1562: int Expression::canThrow(bool mustNotThrow)
1563: {
1564: #if DMDV2
1565: return FALSE;
1566: #else
1567: return TRUE;
1568: #endif
1569: }
1570:
1571: /****************************************
1572: * Resolve __LINE__ and __FILE__ to loc.
1573: */
1574:
1575: Expression *Expression::resolveLoc(Loc loc, Scope *sc)
1576: {
1577: return this;
1578: }
1579:
1580: Expressions *Expression::arraySyntaxCopy(Expressions *exps)
1581: { Expressions *a = NULL;
1582:
1583: if (exps)
1584: {
1585: a = new Expressions();
1586: a->setDim(exps->dim);
1587: for (int i = 0; i < a->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
1588: { Expression *e = (*exps)[i];
1589:
1590: if (e)
1591: e = e->syntaxCopy();
1592: a->tdata()[i] = e;
1593: }
1594: }
1595: return a;
1596: }
1597:
1598: /***************************************************
1599: * Recognize expressions of the form:
1600: * ((T v = init), v)
1601: * where v is a temp.
1602: * This is used in optimizing out unnecessary temporary generation.
1603: * Returns initializer expression of v if so, NULL if not.
1604: */
1605:
1606: Expression *Expression::isTemp()
1607: {
1608: //printf("isTemp() %s\n", toChars());
1609: if (op == TOKcomma)
1610: { CommaExp *ec = (CommaExp *)this;
1611: if (ec->e1->op == TOKdeclaration &&
1612: ec->e2->op == TOKvar)
1613: { DeclarationExp *de = (DeclarationExp *)ec->e1;
1614: VarExp *ve = (VarExp *)ec->e2;
1615: if (ve->var == de->declaration && ve->var->storage_class & STCctfe)
1616: { VarDeclaration *v = ve->var->isVarDeclaration();
1617: if (v && v->init)
1618: {
1619: ExpInitializer *ei = v->init->isExpInitializer();
1620: if (ei)
1621: { Expression *e = ei->exp;
1622: if (e->op == TOKconstruct)
1623: { ConstructExp *ce = (ConstructExp *)e;
1624: if (ce->e1->op == TOKvar && ((VarExp *)ce->e1)->var == ve->var)
1625: e = ce->e2;
1626: }
1627: return e;
1628: }
1629: }
1630: }
1631: }
1632: }
1633: return NULL;
1634: }
1635:
1636: /************************************************
1637: * Destructors are attached to VarDeclarations.
1638: * Hence, if expression returns a temp that needs a destructor,
1639: * make sure and create a VarDeclaration for that temp.
1640: */
1641:
1642: Expression *Expression::addDtorHook(Scope *sc)
1643: {
1644: return this;
1645: }
1646:
1647: /******************************** IntegerExp **************************/
1648:
1649: IntegerExp::IntegerExp(Loc loc, dinteger_t value, Type *type)
1650: : Expression(loc, TOKint64, sizeof(IntegerExp))
1651: {
1652: //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
1653: if (type && !type->isscalar())
1654: {
1655: //printf("%s, loc = %d\n", toChars(), loc.linnum);
1656: if (type->ty != Terror)
1657: error("integral constant must be scalar type, not %s", type->toChars());
1658: type = Type::terror;
1659: }
1660: this->type = type;
1661: this->value = value;
1662: }
1663:
1664: IntegerExp::IntegerExp(dinteger_t value)
1665: : Expression(0, TOKint64, sizeof(IntegerExp))
1666: {
1667: this->type = Type::tint32;
1668: this->value = value;
1669: }
1670:
1671: int IntegerExp::equals(Object *o)
1672: { IntegerExp *ne;
1673:
1674: if (this == o ||
1675: (((Expression *)o)->op == TOKint64 &&
1676: ((ne = (IntegerExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
1677: value == ne->value))
1678: return 1;
1679: return 0;
1680: }
1681:
1682: char *IntegerExp::toChars()
1683: {
1684: #if 1
1685: return Expression::toChars();
1686: #else
1687: static char buffer[sizeof(value) * 3 + 1];
1688:
1689: sprintf(buffer, "%jd", value);
1690: return buffer;
1691: #endif
1692: }
1693:
1694: dinteger_t IntegerExp::toInteger()
1695: { Type *t;
1696:
1697: t = type;
1698: while (t)
1699: {
1700: switch (t->ty)
1701: {
1702: case Tbool: value = (value != 0); break;
1703: case Tint8: value = (d_int8) value; break;
1704: case Tchar:
1705: case Tuns8: value = (d_uns8) value; break;
1706: case Tint16: value = (d_int16) value; break;
1707: case Twchar:
1708: case Tuns16: value = (d_uns16) value; break;
1709: case Tint32: value = (d_int32) value; break;
1710: case Tdchar:
1711: case Tuns32: value = (d_uns32) value; break;
1712: case Tint64: value = (d_int64) value; break;
1713: case Tuns64: value = (d_uns64) value; break;
1714: case Tpointer:
1715: if (PTRSIZE == 4)
1716: value = (d_uns32) value;
1717: else if (PTRSIZE == 8)
1718: value = (d_uns64) value;
1719: else
1720: assert(0);
1721: break;
1722:
1723: case Tenum:
1724: {
1725: TypeEnum *te = (TypeEnum *)t;
1726: t = te->sym->memtype;
1727: continue;
1728: }
1729:
1730: case Ttypedef:
1731: {
1732: TypeTypedef *tt = (TypeTypedef *)t;
1733: t = tt->sym->basetype;
1734: continue;
1735: }
1736:
1737: default:
1738: /* This can happen if errors, such as
1739: * the type is painted on like in fromConstInitializer().
1740: */
1741: if (!global.errors)
1742: {
1743: printf("e = %p, ty = %d\n", this, type->ty);
1744: type->print();
1745: assert(0);
1746: }
1747: break;
1748: }
1749: break;
1750: }
1751: return value;
1752: }
1753:
1754: real_t IntegerExp::toReal()
1755: {
1756: Type *t;
1757:
1758: toInteger();
1759: t = type->toBasetype();
1760: if (t->ty == Tuns64)
1761: return (real_t)(d_uns64)value;
1762: else
1763: return (real_t)(d_int64)value;
1764: }
1765:
1766: real_t IntegerExp::toImaginary()
1767: {
1768: return (real_t) 0;
1769: }
1770:
1771: complex_t IntegerExp::toComplex()
1772: {
1773: return toReal();
1774: }
1775:
1776: int IntegerExp::isBool(int result)
1777: {
1778: int r = toInteger() != 0;
1779: return result ? r : !r;
1780: }
1781:
1782: Expression *IntegerExp::semantic(Scope *sc)
1783: {
1784: if (!type)
1785: {
1786: // Determine what the type of this number is
1787: dinteger_t number = value;
1788:
1789: if (number & 0x8000000000000000LL)
1790: type = Type::tuns64;
1791: else if (number & 0xFFFFFFFF80000000LL)
1792: type = Type::tint64;
1793: else
1794: type = Type::tint32;
1795: }
1796: else
1797: { if (!type->deco)
1798: type = type->semantic(loc, sc);
1799: }
1800: return this;
1801: }
1802:
1803: Expression *IntegerExp::toLvalue(Scope *sc, Expression *e)
1804: {
1805: if (!e)
1806: e = this;
1807: else if (!loc.filename)
1808: loc = e->loc;
1809: e->error("constant %s is not an lvalue", e->toChars());
1810: return this;
1811: }
1812:
1813: void IntegerExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1814: {
1815: dinteger_t v = toInteger();
1816:
1817: if (type)
1818: { Type *t = type;
1819:
1820: L1:
1821: switch (t->ty)
1822: {
1823: case Tenum:
1824: { TypeEnum *te = (TypeEnum *)t;
1825: buf->printf("cast(%s)", te->sym->toChars());
1826: t = te->sym->memtype;
1827: goto L1;
1828: }
1829:
1830: case Ttypedef:
1831: { TypeTypedef *tt = (TypeTypedef *)t;
1832: buf->printf("cast(%s)", tt->sym->toChars());
1833: t = tt->sym->basetype;
1834: goto L1;
1835: }
1836:
1837: case Twchar: // BUG: need to cast(wchar)
1838: case Tdchar: // BUG: need to cast(dchar)
1839: if ((uinteger_t)v > 0xFF)
1840: {
1841: buf->printf("'\\U%08x'", v);
1842: break;
1843: }
1844: case Tchar:
1845: {
1846: unsigned o = buf->offset;
1847: if (v == '\'')
1848: buf->writestring("'\\''");
1849: else if (isprint(v) && v != '\\')
warning C4244: 'argument' : conversion from 'dinteger_t' to 'int', possible loss of data
1850: buf->printf("'%c'", (int)v);
1851: else
1852: buf->printf("'\\x%02x'", (int)v);
1853: if (hgs->ddoc)
1854: escapeDdocString(buf, o);
1855: break;
1856: }
1857:
1858: case Tint8:
1859: buf->writestring("cast(byte)");
1860: goto L2;
1861:
1862: case Tint16:
1863: buf->writestring("cast(short)");
1864: goto L2;
1865:
1866: case Tint32:
1867: L2:
1868: buf->printf("%d", (int)v);
1869: break;
1870:
1871: case Tuns8:
1872: buf->writestring("cast(ubyte)");
1873: goto L3;
1874:
1875: case Tuns16:
1876: buf->writestring("cast(ushort)");
1877: goto L3;
1878:
1879: case Tuns32:
1880: L3:
1881: buf->printf("%du", (unsigned)v);
1882: break;
1883:
1884: case Tint64:
1885: buf->printf("%jdL", v);
1886: break;
1887:
1888: case Tuns64:
1889: L4:
1890: buf->printf("%juLU", v);
1891: break;
1892:
1893: case Tbool:
1894: buf->writestring((char *)(v ? "true" : "false"));
1895: break;
1896:
1897: case Tpointer:
1898: buf->writestring("cast(");
1899: buf->writestring(t->toChars());
1900: buf->writeByte(')');
1901: if (PTRSIZE == 4)
1902: goto L3;
1903: else if (PTRSIZE == 8)
1904: goto L4;
1905: else
1906: assert(0);
1907:
1908: default:
1909: /* This can happen if errors, such as
1910: * the type is painted on like in fromConstInitializer().
1911: */
1912: if (!global.errors)
1913: {
1914: #ifdef DEBUG
1915: t->print();
1916: #endif
1917: assert(0);
1918: }
1919: break;
1920: }
1921: }
1922: else if (v & 0x8000000000000000LL)
1923: buf->printf("0x%jx", v);
1924: else
1925: buf->printf("%jd", v);
1926: }
1927:
1928: void IntegerExp::toMangleBuffer(OutBuffer *buf)
1929: {
1930: if ((sinteger_t)value < 0)
1931: buf->printf("N%jd", -value);
warning C4146: unary minus operator applied to unsigned type, result still unsigned
1932: else
1933: {
1934: /* This is an awful hack to maintain backwards compatibility.
1935: * There really always should be an 'i' before a number, but
1936: * there wasn't in earlier implementations, so to maintain
1937: * backwards compatibility it is only done if necessary to disambiguate.
1938: * See bugzilla 3029
1939: */
1940: if (buf->offset > 0 && isdigit(buf->data[buf->offset - 1]))
1941: buf->writeByte('i');
1942:
1943: buf->printf("%jd", value);
1944: }
1945: }
1946:
1947: /******************************** ErrorExp **************************/
1948:
1949: /* Use this expression for error recovery.
1950: * It should behave as a 'sink' to prevent further cascaded error messages.
1951: */
1952:
1953: ErrorExp::ErrorExp()
1954: : IntegerExp(0, 0, Type::terror)
1955: {
1956: op = TOKerror;
1957: }
1958:
1959: Expression *ErrorExp::toLvalue(Scope *sc, Expression *e)
1960: {
1961: return this;
1962: }
1963:
1964: void ErrorExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
1965: {
1966: buf->writestring("__error");
1967: }
1968:
1969: /******************************** RealExp **************************/
1970:
1971: RealExp::RealExp(Loc loc, real_t value, Type *type)
1972: : Expression(loc, TOKfloat64, sizeof(RealExp))
1973: {
1974: //printf("RealExp::RealExp(%Lg)\n", value);
1975: this->value = value;
1976: this->type = type;
1977: }
1978:
1979: char *RealExp::toChars()
1980: {
1981: char buffer[sizeof(value) * 3 + 8 + 1 + 1];
1982:
1983: #ifdef IN_GCC
1984: value.format(buffer, sizeof(buffer));
1985: if (type->isimaginary())
1986: strcat(buffer, "i");
1987: #else
1988: sprintf(buffer, type->isimaginary() ? "%Lgi" : "%Lg", value);
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
1989: #endif
1990: assert(strlen(buffer) < sizeof(buffer));
1991: return mem.strdup(buffer);
1992: }
1993:
1994: dinteger_t RealExp::toInteger()
1995: {
1996: #ifdef IN_GCC
1997: return toReal().toInt();
1998: #else
1999: return (sinteger_t) toReal();
2000: #endif
2001: }
2002:
2003: uinteger_t RealExp::toUInteger()
2004: {
2005: #ifdef IN_GCC
2006: return (uinteger_t) toReal().toInt();
2007: #else
2008: return (uinteger_t) toReal();
2009: #endif
2010: }
2011:
2012: real_t RealExp::toReal()
2013: {
2014: return type->isreal() ? value : 0;
2015: }
2016:
2017: real_t RealExp::toImaginary()
2018: {
2019: return type->isreal() ? 0 : value;
2020: }
2021:
2022: complex_t RealExp::toComplex()
2023: {
2024: #ifdef __DMC__
2025: return toReal() + toImaginary() * I;
2026: #else
2027: return complex_t(toReal(), toImaginary());
2028: #endif
2029: }
2030:
2031: /********************************
2032: * Test to see if two reals are the same.
2033: * Regard NaN's as equivalent.
2034: * Regard +0 and -0 as different.
2035: */
2036:
2037: int RealEquals(real_t x1, real_t x2)
2038: {
2039: return (Port::isNan(x1) && Port::isNan(x2)) ||
2040: /* In some cases, the REALPAD bytes get garbage in them,
2041: * so be sure and ignore them.
2042: */
2043: memcmp(&x1, &x2, REALSIZE - REALPAD) == 0;
2044: }
2045:
2046: int RealExp::equals(Object *o)
2047: { RealExp *ne;
2048:
2049: if (this == o ||
2050: (((Expression *)o)->op == TOKfloat64 &&
2051: ((ne = (RealExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
2052: RealEquals(value, ne->value)
2053: )
2054: )
2055: return 1;
2056: return 0;
2057: }
2058:
2059: Expression *RealExp::semantic(Scope *sc)
2060: {
2061: if (!type)
2062: type = Type::tfloat64;
2063: else
2064: type = type->semantic(loc, sc);
2065: return this;
2066: }
2067:
2068: int RealExp::isBool(int result)
2069: {
2070: #ifdef IN_GCC
2071: return result ? (! value.isZero()) : (value.isZero());
2072: #else
2073: return result ? (value != 0)
2074: : (value == 0);
2075: #endif
2076: }
2077:
2078: void floatToBuffer(OutBuffer *buf, Type *type, real_t value)
2079: {
2080: /* In order to get an exact representation, try converting it
2081: * to decimal then back again. If it matches, use it.
2082: * If it doesn't, fall back to hex, which is
2083: * always exact.
2084: */
2085: char buffer[25];
2086: sprintf(buffer, "%Lg", value);
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
2087: assert(strlen(buffer) < sizeof(buffer));
2088: #if _WIN32 && __DMC__
2089: char *save = __locale_decpoint;
2090: __locale_decpoint = ".";
2091: real_t r = strtold(buffer, NULL);
2092: __locale_decpoint = save;
2093: #else
2094: real_t r = strtold(buffer, NULL);
2095: #endif
2096: if (r == value) // if exact duplication
2097: buf->writestring(buffer);
2098: else
2099: buf->printf("%La", value); // ensure exact duplication
2100:
2101: if (type)
2102: {
2103: Type *t = type->toBasetype();
2104: switch (t->ty)
2105: {
2106: case Tfloat32:
2107: case Timaginary32:
2108: case Tcomplex32:
2109: buf->writeByte('F');
2110: break;
2111:
2112: case Tfloat80:
2113: case Timaginary80:
2114: case Tcomplex80:
2115: buf->writeByte('L');
2116: break;
2117:
2118: default:
2119: break;
2120: }
2121: if (t->isimaginary())
2122: buf->writeByte('i');
2123: }
2124: }
2125:
2126: void RealExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2127: {
2128: floatToBuffer(buf, type, value);
2129: }
2130:
2131: void realToMangleBuffer(OutBuffer *buf, real_t value)
2132: {
2133: /* Rely on %A to get portable mangling.
2134: * Must munge result to get only identifier characters.
2135: *
2136: * Possible values from %A => mangled result
2137: * NAN => NAN
2138: * -INF => NINF
2139: * INF => INF
2140: * -0X1.1BC18BA997B95P+79 => N11BC18BA997B95P79
2141: * 0X1.9P+2 => 19P2
2142: */
2143:
2144: if (Port::isNan(value))
2145: buf->writestring("NAN"); // no -NAN bugs
2146: else
2147: {
2148: char buffer[32];
2149: int n = sprintf(buffer, "%LA", value);
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
2150: assert(n > 0 && n < sizeof(buffer));
2151: for (int i = 0; i < n; i++)
2152: { char c = buffer[i];
2153:
2154: switch (c)
2155: {
2156: case '-':
2157: buf->writeByte('N');
2158: break;
2159:
2160: case '+':
2161: case 'X':
2162: case '.':
2163: break;
2164:
2165: case '0':
2166: if (i < 2)
2167: break; // skip leading 0X
2168: default:
2169: buf->writeByte(c);
2170: break;
2171: }
2172: }
2173: }
2174: }
2175:
2176: void RealExp::toMangleBuffer(OutBuffer *buf)
2177: {
2178: buf->writeByte('e');
2179: realToMangleBuffer(buf, value);
2180: }
2181:
2182:
2183: /******************************** ComplexExp **************************/
2184:
2185: ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type)
2186: : Expression(loc, TOKcomplex80, sizeof(ComplexExp))
2187: {
2188: this->value = value;
2189: this->type = type;
2190: //printf("ComplexExp::ComplexExp(%s)\n", toChars());
2191: }
2192:
2193: char *ComplexExp::toChars()
2194: {
2195: char buffer[sizeof(value) * 3 + 8 + 1];
2196:
2197: #ifdef IN_GCC
2198: char buf1[sizeof(value) * 3 + 8 + 1];
2199: char buf2[sizeof(value) * 3 + 8 + 1];
2200: creall(value).format(buf1, sizeof(buf1));
2201: cimagl(value).format(buf2, sizeof(buf2));
2202: sprintf(buffer, "(%s+%si)", buf1, buf2);
2203: #else
2204: sprintf(buffer, "(%Lg+%Lgi)", creall(value), cimagl(value));
warning C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead. To disable deprecation, use _CRT_SECURE_NO_WARNINGS. See online help for details.
c:\Program Files (x86)\Microsoft Visual Studio 10.0\VC\include\stdio.h(371) : see declaration of 'sprintf'
2205: assert(strlen(buffer) < sizeof(buffer));
2206: #endif
2207: return mem.strdup(buffer);
2208: }
2209:
2210: dinteger_t ComplexExp::toInteger()
2211: {
2212: #ifdef IN_GCC
2213: return (sinteger_t) toReal().toInt();
2214: #else
2215: return (sinteger_t) toReal();
2216: #endif
2217: }
2218:
2219: uinteger_t ComplexExp::toUInteger()
2220: {
2221: #ifdef IN_GCC
2222: return (uinteger_t) toReal().toInt();
2223: #else
2224: return (uinteger_t) toReal();
2225: #endif
2226: }
2227:
2228: real_t ComplexExp::toReal()
2229: {
2230: return creall(value);
2231: }
2232:
2233: real_t ComplexExp::toImaginary()
2234: {
2235: return cimagl(value);
2236: }
2237:
2238: complex_t ComplexExp::toComplex()
2239: {
2240: return value;
2241: }
2242:
2243: int ComplexExp::equals(Object *o)
2244: { ComplexExp *ne;
2245:
2246: if (this == o ||
2247: (((Expression *)o)->op == TOKcomplex80 &&
2248: ((ne = (ComplexExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
2249: RealEquals(creall(value), creall(ne->value)) &&
2250: RealEquals(cimagl(value), cimagl(ne->value))
2251: )
2252: )
2253: return 1;
2254: return 0;
2255: }
2256:
2257: Expression *ComplexExp::semantic(Scope *sc)
2258: {
2259: if (!type)
2260: type = Type::tcomplex80;
2261: else
2262: type = type->semantic(loc, sc);
2263: return this;
2264: }
2265:
2266: int ComplexExp::isBool(int result)
2267: {
2268: if (result)
2269: return (bool)(value);
2270: else
2271: return !value;
2272: }
2273:
2274: void ComplexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2275: {
2276: /* Print as:
2277: * (re+imi)
2278: */
2279: #ifdef IN_GCC
2280: char buf1[sizeof(value) * 3 + 8 + 1];
2281: char buf2[sizeof(value) * 3 + 8 + 1];
2282: creall(value).format(buf1, sizeof(buf1));
2283: cimagl(value).format(buf2, sizeof(buf2));
2284: buf->printf("(%s+%si)", buf1, buf2);
2285: #else
2286: buf->writeByte('(');
2287: floatToBuffer(buf, type, creall(value));
2288: buf->writeByte('+');
2289: floatToBuffer(buf, type, cimagl(value));
2290: buf->writestring("i)");
2291: #endif
2292: }
2293:
2294: void ComplexExp::toMangleBuffer(OutBuffer *buf)
2295: {
2296: buf->writeByte('c');
2297: real_t r = toReal();
2298: realToMangleBuffer(buf, r);
2299: buf->writeByte('c'); // separate the two
2300: r = toImaginary();
2301: realToMangleBuffer(buf, r);
2302: }
2303:
2304: /******************************** IdentifierExp **************************/
2305:
2306: IdentifierExp::IdentifierExp(Loc loc, Identifier *ident)
2307: : Expression(loc, TOKidentifier, sizeof(IdentifierExp))
2308: {
2309: this->ident = ident;
2310: }
2311:
2312: Expression *IdentifierExp::semantic(Scope *sc)
2313: {
2314: Dsymbol *s;
2315: Dsymbol *scopesym;
2316:
2317: #if LOGSEMANTIC
2318: printf("IdentifierExp::semantic('%s')\n", ident->toChars());
2319: #endif
2320: s = sc->search(loc, ident, &scopesym);
2321: if (s)
2322: { Expression *e;
2323: WithScopeSymbol *withsym;
2324:
2325: /* See if the symbol was a member of an enclosing 'with'
2326: */
2327: withsym = scopesym->isWithScopeSymbol();
2328: if (withsym)
2329: {
2330: #if DMDV2
2331: /* Disallow shadowing
2332: */
2333: // First find the scope of the with
2334: Scope *scwith = sc;
2335: while (scwith->scopesym != scopesym)
2336: { scwith = scwith->enclosing;
2337: assert(scwith);
2338: }
2339: // Look at enclosing scopes for symbols with the same name,
2340: // in the same function
2341: for (Scope *scx = scwith; scx && scx->func == scwith->func; scx = scx->enclosing)
2342: { Dsymbol *s2;
2343:
2344: if (scx->scopesym && scx->scopesym->symtab &&
2345: (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL &&
2346: s != s2)
2347: {
2348: error("with symbol %s is shadowing local symbol %s", s->toPrettyChars(), s2->toPrettyChars());
2349: }
2350: }
2351: #endif
2352: s = s->toAlias();
2353:
2354: // Same as wthis.ident
2355: if (s->needThis() || s->isTemplateDeclaration())
2356: {
2357: e = new VarExp(loc, withsym->withstate->wthis);
2358: e = new DotIdExp(loc, e, ident);
2359: }
2360: else
2361: { Type *t = withsym->withstate->wthis->type;
2362: if (t->ty == Tpointer)
2363: t = ((TypePointer *)t)->next;
2364: e = typeDotIdExp(loc, t, ident);
2365: }
2366: }
2367: else
2368: {
2369: /* If f is really a function template,
2370: * then replace f with the function template declaration.
2371: */
2372: FuncDeclaration *f = s->isFuncDeclaration();
2373: if (f)
2374: { TemplateDeclaration *tempdecl = getFuncTemplateDecl(f);
2375: if (tempdecl)
2376: {
2377: if (tempdecl->overroot) // if not start of overloaded list of TemplateDeclaration's
2378: tempdecl = tempdecl->overroot; // then get the start
2379: e = new TemplateExp(loc, tempdecl);
2380: e = e->semantic(sc);
2381: return e;
2382: }
2383: }
2384: // Haven't done overload resolution yet, so pass 1
2385: e = new DsymbolExp(loc, s, 1);
2386: }
2387: return e->semantic(sc);
2388: }
2389: #if DMDV2
2390: if (ident == Id::ctfe)
2391: { // Create the magic __ctfe bool variable
2392: VarDeclaration *vd = new VarDeclaration(loc, Type::tbool, Id::ctfe, NULL);
2393: Expression *e = new VarExp(loc, vd);
2394: e = e->semantic(sc);
2395: return e;
2396: }
2397: #endif
2398: const char *n = importHint(ident->toChars());
2399: if (n)
2400: error("'%s' is not defined, perhaps you need to import %s; ?", ident->toChars(), n);
2401: else
2402: {
2403: s = sc->search_correct(ident);
2404: if (s)
2405: error("undefined identifier %s, did you mean %s %s?", ident->toChars(), s->kind(), s->toChars());
2406: else
2407: error("undefined identifier %s", ident->toChars());
2408: }
2409: return new ErrorExp();
2410: }
2411:
2412: char *IdentifierExp::toChars()
2413: {
2414: return ident->toChars();
2415: }
2416:
2417: void IdentifierExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2418: {
2419: if (hgs->hdrgen)
2420: buf->writestring(ident->toHChars2());
2421: else
2422: buf->writestring(ident->toChars());
2423: }
2424:
2425: #if DMDV2
2426: int IdentifierExp::isLvalue()
2427: {
2428: return 1;
2429: }
2430: #endif
2431:
2432: Expression *IdentifierExp::toLvalue(Scope *sc, Expression *e)
2433: {
2434: #if 0
2435: tym = tybasic(e1->ET->Tty);
2436: if (!(tyscalar(tym) ||
2437: tym == TYstruct ||
2438: tym == TYarray && e->Eoper == TOKaddr))
2439: synerr(EM_lvalue); // lvalue expected
2440: #endif
2441: return this;
2442: }
2443:
2444: /******************************** DollarExp **************************/
2445:
2446: DollarExp::DollarExp(Loc loc)
2447: : IdentifierExp(loc, Id::dollar)
2448: {
2449: }
2450:
2451: /******************************** DsymbolExp **************************/
2452:
2453: DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, int hasOverloads)
2454: : Expression(loc, TOKdsymbol, sizeof(DsymbolExp))
2455: {
2456: this->s = s;
2457: this->hasOverloads = hasOverloads;
2458: }
2459:
2460: Expression *DsymbolExp::semantic(Scope *sc)
2461: {
2462: #if LOGSEMANTIC
2463: printf("DsymbolExp::semantic('%s')\n", s->toChars());
2464: #endif
2465:
2466: Lagain:
2467: EnumMember *em;
2468: Expression *e;
2469: VarDeclaration *v;
2470: FuncDeclaration *f;
2471: FuncLiteralDeclaration *fld;
2472: OverloadSet *o;
2473: Declaration *d;
warning C4101: 'd' : unreferenced local variable
2474: ClassDeclaration *cd;
2475: ClassDeclaration *thiscd = NULL;
2476: Import *imp;
2477: Package *pkg;
2478: Type *t;
2479:
2480: //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
2481: //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
2482: if (type)
2483: return this;
2484: if (!s->isFuncDeclaration()) // functions are checked after overloading
2485: checkDeprecated(sc, s);
2486: s = s->toAlias();
2487: //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
2488: if (!s->isFuncDeclaration())
2489: checkDeprecated(sc, s);
2490:
2491: if (sc->func)
2492: thiscd = sc->func->parent->isClassDeclaration();
2493:
2494: // BUG: This should happen after overload resolution for functions, not before
2495: if (s->needThis())
2496: {
2497: if (hasThis(sc)
2498: #if DMDV2
2499: && !s->isFuncDeclaration()
2500: #endif
2501: )
2502: {
2503: // Supply an implicit 'this', as in
2504: // this.ident
2505:
2506: DotVarExp *de;
2507:
2508: de = new DotVarExp(loc, new ThisExp(loc), s->isDeclaration());
2509: return de->semantic(sc);
2510: }
2511: }
2512:
2513: em = s->isEnumMember();
2514: if (em)
2515: {
2516: e = em->value;
2517: e = e->semantic(sc);
2518: return e;
2519: }
2520: v = s->isVarDeclaration();
2521: if (v)
2522: {
2523: //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
2524: if (!type)
2525: { if ((!v->type || !v->type->deco) && v->scope)
2526: v->semantic(v->scope);
2527: type = v->type;
2528: if (!v->type)
2529: { error("forward reference of %s %s", v->kind(), v->toChars());
2530: return new ErrorExp();
2531: }
2532: }
2533:
2534: if ((v->storage_class & STCmanifest) && v->init)
2535: {
2536: e = v->init->toExpression();
2537: if (!e)
2538: { error("cannot make expression out of initializer for %s", v->toChars());
2539: return new ErrorExp();
2540: }
2541: e = e->semantic(sc);
2542: return e;
2543: }
2544:
2545: e = new VarExp(loc, v);
2546: e->type = type;
2547: e = e->semantic(sc);
2548: return e->deref();
2549: }
2550: fld = s->isFuncLiteralDeclaration();
2551: if (fld)
2552: { //printf("'%s' is a function literal\n", fld->toChars());
2553: e = new FuncExp(loc, fld);
2554: return e->semantic(sc);
2555: }
2556: f = s->isFuncDeclaration();
2557: if (f)
2558: { //printf("'%s' is a function\n", f->toChars());
2559:
2560: if (!f->originalType && f->scope) // semantic not yet run
2561: f->semantic(f->scope);
2562:
2563: // if inferring return type, sematic3 needs to be run
2564: if (f->inferRetType && f->scope && f->type && !f->type->nextOf())
2565: f->semantic3(f->scope);
2566:
2567: if (f->isUnitTestDeclaration())
2568: {
2569: error("cannot call unittest function %s", toChars());
2570: return new ErrorExp();
2571: }
2572: if (!f->type->deco)
warning C6011: Dereferencing NULL pointer 'f->type': Lines: 2466, 2467, 2468, 2469, 2470, 2471, 2472, 2473, 2474, 2475, 2476, 2477, 2478, 2482, 2484, 2485, 2486, 2488, 2489, 2491, 2492, 2495, 2499, 2513, 2514, 2520, 2521, 2550, 2551, 2556, 2557, 2560, 2561, 2564, 2567, 2572
2573: {
2574: error("forward reference to %s", toChars());
2575: return new ErrorExp();
2576: }
2577: return new VarExp(loc, f, hasOverloads);
2578: }
2579: o = s->isOverloadSet();
2580: if (o)
2581: { //printf("'%s' is an overload set\n", o->toChars());
2582: return new OverExp(o);
2583: }
2584: cd = s->isClassDeclaration();
2585: if (cd && thiscd && cd->isBaseOf(thiscd, NULL) && sc->func->needThis())
2586: {
2587: // We need to add an implicit 'this' if cd is this class or a base class.
2588: DotTypeExp *dte;
2589:
2590: dte = new DotTypeExp(loc, new ThisExp(loc), s);
2591: return dte->semantic(sc);
2592: }
2593: imp = s->isImport();
2594: if (imp)
2595: {
2596: if (!imp->pkg)
2597: { error("forward reference of import %s", imp->toChars());
2598: return new ErrorExp();
2599: }
2600: ScopeExp *ie = new ScopeExp(loc, imp->pkg);
2601: return ie->semantic(sc);
2602: }
2603: pkg = s->isPackage();
2604: if (pkg)
2605: {
2606: ScopeExp *ie;
2607:
2608: ie = new ScopeExp(loc, pkg);
2609: return ie->semantic(sc);
2610: }
2611: Module *mod = s->isModule();
2612: if (mod)
2613: {
2614: ScopeExp *ie;
2615:
2616: ie = new ScopeExp(loc, mod);
2617: return ie->semantic(sc);
2618: }
2619:
2620: t = s->getType();
2621: if (t)
2622: {
2623: return new TypeExp(loc, t);
2624: }
2625:
2626: TupleDeclaration *tup = s->isTupleDeclaration();
2627: if (tup)
2628: {
2629: e = new TupleExp(loc, tup);
2630: e = e->semantic(sc);
2631: return e;
2632: }
2633:
2634: TemplateInstance *ti = s->isTemplateInstance();
2635: if (ti && !global.errors)
2636: { if (!ti->semanticRun)
2637: ti->semantic(sc);
2638: s = ti->inst->toAlias();
2639: if (!s->isTemplateInstance())
2640: goto Lagain;
2641: e = new ScopeExp(loc, ti);
2642: e = e->semantic(sc);
2643: return e;
2644: }
2645:
2646: TemplateDeclaration *td = s->isTemplateDeclaration();
2647: if (td)
2648: {
2649: e = new TemplateExp(loc, td);
2650: e = e->semantic(sc);
2651: return e;
2652: }
2653:
2654: Lerr:
warning C4102: 'Lerr' : unreferenced label
2655: error("%s '%s' is not a variable", s->kind(), s->toChars());
2656: return new ErrorExp();
2657: }
2658:
2659: char *DsymbolExp::toChars()
2660: {
2661: return s->toChars();
2662: }
2663:
2664: void DsymbolExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2665: {
2666: buf->writestring(s->toChars());
2667: }
2668:
2669: #if DMDV2
2670: int DsymbolExp::isLvalue()
2671: {
2672: return 1;
2673: }
2674: #endif
2675:
2676: Expression *DsymbolExp::toLvalue(Scope *sc, Expression *e)
2677: {
2678: #if 0
2679: tym = tybasic(e1->ET->Tty);
2680: if (!(tyscalar(tym) ||
2681: tym == TYstruct ||
2682: tym == TYarray && e->Eoper == TOKaddr))
2683: synerr(EM_lvalue); // lvalue expected
2684: #endif
2685: return this;
2686: }
2687:
2688: /******************************** ThisExp **************************/
2689:
2690: ThisExp::ThisExp(Loc loc)
2691: : Expression(loc, TOKthis, sizeof(ThisExp))
2692: {
2693: //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
2694: var = NULL;
2695: }
2696:
2697: Expression *ThisExp::semantic(Scope *sc)
2698: { FuncDeclaration *fd;
2699: FuncDeclaration *fdthis;
2700: int nested = 0;
2701:
2702: #if LOGSEMANTIC
2703: printf("ThisExp::semantic()\n");
2704: #endif
2705: if (type)
2706: { //assert(global.errors || var);
2707: return this;
2708: }
2709:
2710: /* Special case for typeof(this) and typeof(super) since both
2711: * should work even if they are not inside a non-static member function
2712: */
2713: if (sc->intypeof)
2714: {
2715: // Find enclosing struct or class
2716: for (Dsymbol *s = sc->parent; 1; s = s->parent)
2717: {
2718: if (!s)
2719: {
2720: error("%s is not in a class or struct scope", toChars());
2721: goto Lerr;
2722: }
2723: ClassDeclaration *cd = s->isClassDeclaration();
2724: if (cd)
2725: {
2726: type = cd->type;
2727: return this;
2728: }
2729: StructDeclaration *sd = s->isStructDeclaration();
2730: if (sd)
2731: {
2732: #if STRUCTTHISREF
2733: type = sd->type;
2734: #else
2735: type = sd->type->pointerTo();
2736: #endif
2737: return this;
2738: }
2739: }
2740: }
2741:
2742: fdthis = sc->parent->isFuncDeclaration();
2743: fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
2744: if (!fd)
2745: goto Lerr;
2746:
2747: assert(fd->vthis);
2748: var = fd->vthis;
2749: assert(var->parent);
2750: type = var->type;
2751: var->isVarDeclaration()->checkNestedReference(sc, loc);
2752: if (!sc->intypeof)
2753: sc->callSuper |= CSXthis;
2754: return this;
2755:
2756: Lerr:
2757: error("'this' is only defined in non-static member functions, not %s", sc->parent->toChars());
warning C6011: Dereferencing NULL pointer 'sc->parent': Lines: 2698, 2699, 2700, 2705, 2713, 2716, 2718, 2720, 2721, 2756, 2757
2758: return new ErrorExp();
2759: }
2760:
2761: int ThisExp::isBool(int result)
2762: {
2763: return result ? TRUE : FALSE;
2764: }
2765:
2766: void ThisExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2767: {
2768: buf->writestring("this");
2769: }
2770:
2771: #if DMDV2
2772: int ThisExp::isLvalue()
2773: {
2774: return 1;
2775: }
2776: #endif
2777:
2778: Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
2779: {
2780: return this;
2781: }
2782:
2783: /******************************** SuperExp **************************/
2784:
2785: SuperExp::SuperExp(Loc loc)
2786: : ThisExp(loc)
2787: {
2788: op = TOKsuper;
2789: }
2790:
2791: Expression *SuperExp::semantic(Scope *sc)
2792: { FuncDeclaration *fd;
2793: FuncDeclaration *fdthis;
2794: ClassDeclaration *cd;
2795: Dsymbol *s;
2796:
2797: #if LOGSEMANTIC
2798: printf("SuperExp::semantic('%s')\n", toChars());
2799: #endif
2800: if (type)
2801: return this;
2802:
2803: /* Special case for typeof(this) and typeof(super) since both
2804: * should work even if they are not inside a non-static member function
2805: */
2806: if (sc->intypeof)
2807: {
2808: // Find enclosing class
2809: for (Dsymbol *s = sc->parent; 1; s = s->parent)
warning C6246: Local declaration of 's' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '2795' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 2795
2810: {
2811: ClassDeclaration *cd;
warning C6246: Local declaration of 'cd' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '2794' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 2794
2812:
2813: if (!s)
2814: {
2815: error("%s is not in a class scope", toChars());
2816: goto Lerr;
2817: }
2818: cd = s->isClassDeclaration();
2819: if (cd)
2820: {
2821: cd = cd->baseClass;
2822: if (!cd)
2823: { error("class %s has no 'super'", s->toChars());
2824: goto Lerr;
2825: }
2826: type = cd->type;
2827: return this;
2828: }
2829: }
2830: }
2831:
2832: fdthis = sc->parent->isFuncDeclaration();
2833: fd = hasThis(sc);
2834: if (!fd)
2835: goto Lerr;
2836: assert(fd->vthis);
2837: var = fd->vthis;
2838: assert(var->parent);
2839:
2840: s = fd->toParent();
2841: while (s && s->isTemplateInstance())
2842: s = s->toParent();
2843: assert(s);
2844: cd = s->isClassDeclaration();
2845: //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
2846: if (!cd)
2847: goto Lerr;
2848: if (!cd->baseClass)
2849: {
2850: error("no base class for %s", cd->toChars());
2851: type = fd->vthis->type;
2852: }
2853: else
2854: {
2855: type = cd->baseClass->type;
2856: }
2857:
2858: var->isVarDeclaration()->checkNestedReference(sc, loc);
2859:
2860: if (!sc->intypeof)
2861: sc->callSuper |= CSXsuper;
2862: return this;
2863:
2864:
2865: Lerr:
2866: error("'super' is only allowed in non-static class member functions");
2867: return new ErrorExp();
2868: }
2869:
2870: void SuperExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2871: {
2872: buf->writestring("super");
2873: }
2874:
2875:
2876: /******************************** NullExp **************************/
2877:
2878: NullExp::NullExp(Loc loc, Type *type)
2879: : Expression(loc, TOKnull, sizeof(NullExp))
2880: {
2881: committed = 0;
2882: this->type = type;
2883: }
2884:
2885: Expression *NullExp::semantic(Scope *sc)
2886: {
2887: #if LOGSEMANTIC
2888: printf("NullExp::semantic('%s')\n", toChars());
2889: #endif
2890: // NULL is the same as (void *)0
2891: if (!type)
2892: type = Type::tvoid->pointerTo();
2893: return this;
2894: }
2895:
2896: int NullExp::isBool(int result)
2897: {
2898: return result ? FALSE : TRUE;
2899: }
2900:
2901: void NullExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
2902: {
2903: buf->writestring("null");
2904: }
2905:
2906: void NullExp::toMangleBuffer(OutBuffer *buf)
2907: {
2908: buf->writeByte('n');
2909: }
2910:
2911: /******************************** StringExp **************************/
2912:
2913: StringExp::StringExp(Loc loc, char *string)
2914: : Expression(loc, TOKstring, sizeof(StringExp))
2915: {
2916: this->string = string;
2917: this->len = strlen(string);
2918: this->sz = 1;
2919: this->committed = 0;
2920: this->postfix = 0;
2921: }
2922:
2923: StringExp::StringExp(Loc loc, void *string, size_t len)
2924: : Expression(loc, TOKstring, sizeof(StringExp))
2925: {
2926: this->string = string;
2927: this->len = len;
2928: this->sz = 1;
2929: this->committed = 0;
2930: this->postfix = 0;
2931: }
2932:
2933: StringExp::StringExp(Loc loc, void *string, size_t len, unsigned char postfix)
2934: : Expression(loc, TOKstring, sizeof(StringExp))
2935: {
2936: this->string = string;
2937: this->len = len;
2938: this->sz = 1;
2939: this->committed = 0;
2940: this->postfix = postfix;
2941: }
2942:
2943: #if 0
2944: Expression *StringExp::syntaxCopy()
2945: {
2946: printf("StringExp::syntaxCopy() %s\n", toChars());
2947: return copy();
2948: }
2949: #endif
2950:
2951: int StringExp::equals(Object *o)
2952: {
2953: //printf("StringExp::equals('%s') %s\n", o->toChars(), toChars());
2954: if (o && o->dyncast() == DYNCAST_EXPRESSION)
2955: { Expression *e = (Expression *)o;
2956:
2957: if (e->op == TOKstring)
2958: {
2959: return compare(o) == 0;
2960: }
2961: }
2962: return FALSE;
2963: }
2964:
2965: char *StringExp::toChars()
2966: {
2967: OutBuffer buf;
2968: HdrGenState hgs;
2969: char *p;
2970:
2971: memset(&hgs, 0, sizeof(hgs));
2972: toCBuffer(&buf, &hgs);
2973: buf.writeByte(0);
2974: p = (char *)buf.data;
2975: buf.data = NULL;
2976: return p;
2977: }
2978:
2979: Expression *StringExp::semantic(Scope *sc)
2980: {
2981: #if LOGSEMANTIC
2982: printf("StringExp::semantic() %s\n", toChars());
2983: #endif
2984: if (!type)
2985: { OutBuffer buffer;
2986: size_t newlen = 0;
2987: const char *p;
2988: size_t u;
2989: unsigned c;
2990:
2991: switch (postfix)
2992: {
2993: case 'd':
2994: for (u = 0; u < len;)
2995: {
2996: p = utf_decodeChar((unsigned char *)string, len, &u, &c);
2997: if (p)
2998: { error("%s", p);
2999: return new ErrorExp();
3000: }
3001: else
3002: { buffer.write4(c);
3003: newlen++;
3004: }
3005: }
3006: buffer.write4(0);
3007: string = buffer.extractData();
3008: len = newlen;
3009: sz = 4;
3010: //type = new TypeSArray(Type::tdchar, new IntegerExp(loc, len, Type::tindex));
3011: type = new TypeDArray(Type::tdchar->invariantOf());
3012: committed = 1;
3013: break;
3014:
3015: case 'w':
3016: for (u = 0; u < len;)
3017: {
3018: p = utf_decodeChar((unsigned char *)string, len, &u, &c);
3019: if (p)
3020: { error("%s", p);
3021: return new ErrorExp();
3022: }
3023: else
3024: { buffer.writeUTF16(c);
3025: newlen++;
3026: if (c >= 0x10000)
3027: newlen++;
3028: }
3029: }
3030: buffer.writeUTF16(0);
3031: string = buffer.extractData();
3032: len = newlen;
3033: sz = 2;
3034: //type = new TypeSArray(Type::twchar, new IntegerExp(loc, len, Type::tindex));
3035: type = new TypeDArray(Type::twchar->invariantOf());
3036: committed = 1;
3037: break;
3038:
3039: case 'c':
3040: committed = 1;
3041: default:
3042: //type = new TypeSArray(Type::tchar, new IntegerExp(loc, len, Type::tindex));
3043: type = new TypeDArray(Type::tchar->invariantOf());
3044: break;
3045: }
3046: type = type->semantic(loc, sc);
3047: //type = type->invariantOf();
3048: //printf("type = %s\n", type->toChars());
3049: }
3050: return this;
3051: }
3052:
3053: /**********************************
3054: * Return length of string.
3055: */
3056:
3057: size_t StringExp::length()
3058: {
3059: size_t result = 0;
3060: dchar_t c;
3061: const char *p;
3062:
3063: switch (sz)
3064: {
3065: case 1:
3066: for (size_t u = 0; u < len;)
3067: {
3068: p = utf_decodeChar((unsigned char *)string, len, &u, &c);
3069: if (p)
3070: { error("%s", p);
3071: return 0;
3072: }
3073: else
3074: result++;
3075: }
3076: break;
3077:
3078: case 2:
3079: for (size_t u = 0; u < len;)
3080: {
3081: p = utf_decodeWchar((unsigned short *)string, len, &u, &c);
3082: if (p)
3083: { error("%s", p);
3084: return 0;
3085: }
3086: else
3087: result++;
3088: }
3089: break;
3090:
3091: case 4:
3092: result = len;
3093: break;
3094:
3095: default:
3096: assert(0);
3097: }
3098: return result;
3099: }
3100:
3101: /****************************************
3102: * Convert string to char[].
3103: */
3104:
3105: StringExp *StringExp::toUTF8(Scope *sc)
3106: {
3107: if (sz != 1)
3108: { // Convert to UTF-8 string
3109: committed = 0;
3110: Expression *e = castTo(sc, Type::tchar->arrayOf());
3111: e = e->optimize(WANTvalue);
3112: assert(e->op == TOKstring);
3113: StringExp *se = (StringExp *)e;
3114: assert(se->sz == 1);
3115: return se;
3116: }
3117: return this;
3118: }
3119:
3120: int StringExp::compare(Object *obj)
3121: {
3122: //printf("StringExp::compare()\n");
3123: // Used to sort case statement expressions so we can do an efficient lookup
3124: StringExp *se2 = (StringExp *)(obj);
3125:
3126: // This is a kludge so isExpression() in template.c will return 5
3127: // for StringExp's.
3128: if (!se2)
3129: return 5;
3130:
3131: assert(se2->op == TOKstring);
3132:
3133: int len1 = len;
3134: int len2 = se2->len;
3135:
3136: //printf("sz = %d, len1 = %d, len2 = %d\n", sz, len1, len2);
3137: if (len1 == len2)
3138: {
3139: switch (sz)
3140: {
3141: case 1:
3142: return memcmp((char *)string, (char *)se2->string, len1);
3143:
3144: case 2:
3145: { unsigned u;
3146: d_wchar *s1 = (d_wchar *)string;
3147: d_wchar *s2 = (d_wchar *)se2->string;
3148:
3149: for (u = 0; u < len; u++)
3150: {
3151: if (s1[u] != s2[u])
3152: return s1[u] - s2[u];
3153: }
3154: }
3155:
3156: case 4:
3157: { unsigned u;
3158: d_dchar *s1 = (d_dchar *)string;
3159: d_dchar *s2 = (d_dchar *)se2->string;
3160:
3161: for (u = 0; u < len; u++)
3162: {
3163: if (s1[u] != s2[u])
3164: return s1[u] - s2[u];
3165: }
3166: }
3167: break;
3168:
3169: default:
3170: assert(0);
3171: }
3172: }
3173: return len1 - len2;
3174: }
3175:
3176: int StringExp::isBool(int result)
3177: {
3178: return result ? TRUE : FALSE;
3179: }
3180:
3181: #if DMDV2
3182: int StringExp::isLvalue()
3183: {
3184: return 1;
3185: }
3186: #endif
3187:
3188: Expression *StringExp::toLvalue(Scope *sc, Expression *e)
3189: {
3190: //printf("StringExp::toLvalue(%s)\n", toChars());
3191: return this;
3192: }
3193:
3194: unsigned StringExp::charAt(size_t i)
3195: { unsigned value;
3196:
3197: switch (sz)
3198: {
3199: case 1:
3200: value = ((unsigned char *)string)[i];
3201: break;
3202:
3203: case 2:
3204: value = ((unsigned short *)string)[i];
3205: break;
3206:
3207: case 4:
3208: value = ((unsigned int *)string)[i];
3209: break;
3210:
3211: default:
3212: assert(0);
3213: break;
3214: }
3215: return value;
3216: }
3217:
3218: void StringExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3219: {
3220: buf->writeByte('"');
3221: unsigned o = buf->offset;
3222: for (size_t i = 0; i < len; i++)
3223: { unsigned c = charAt(i);
3224:
3225: switch (c)
3226: {
3227: case '"':
3228: case '\\':
3229: if (!hgs->console)
3230: buf->writeByte('\\');
3231: default:
3232: if (c <= 0xFF)
3233: { if (c <= 0x7F && (isprint(c) || hgs->console))
3234: buf->writeByte(c);
3235: else
3236: buf->printf("\\x%02x", c);
3237: }
3238: else if (c <= 0xFFFF)
3239: buf->printf("\\x%02x\\x%02x", c & 0xFF, c >> 8);
3240: else
3241: buf->printf("\\x%02x\\x%02x\\x%02x\\x%02x",
3242: c & 0xFF, (c >> 8) & 0xFF, (c >> 16) & 0xFF, c >> 24);
3243: break;
3244: }
3245: }
3246: if (hgs->ddoc)
3247: escapeDdocString(buf, o);
3248: buf->writeByte('"');
3249: if (postfix)
3250: buf->writeByte(postfix);
3251: }
3252:
3253: void StringExp::toMangleBuffer(OutBuffer *buf)
3254: { char m;
3255: OutBuffer tmp;
3256: const char *p;
3257: unsigned c;
3258: size_t u;
3259: unsigned char *q;
3260: unsigned qlen;
3261:
3262: /* Write string in UTF-8 format
3263: */
3264: switch (sz)
3265: { case 1:
3266: m = 'a';
3267: q = (unsigned char *)string;
3268: qlen = len;
3269: break;
3270: case 2:
3271: m = 'w';
3272: for (u = 0; u < len; )
3273: {
3274: p = utf_decodeWchar((unsigned short *)string, len, &u, &c);
3275: if (p)
3276: error("%s", p);
3277: else
3278: tmp.writeUTF8(c);
3279: }
3280: q = tmp.data;
3281: qlen = tmp.offset;
3282: break;
3283: case 4:
3284: m = 'd';
3285: for (u = 0; u < len; u++)
3286: {
3287: c = ((unsigned *)string)[u];
3288: if (!utf_isValidDchar(c))
3289: error("invalid UCS-32 char \\U%08x", c);
3290: else
3291: tmp.writeUTF8(c);
3292: }
3293: q = tmp.data;
3294: qlen = tmp.offset;
3295: break;
3296: default:
3297: assert(0);
3298: }
3299: buf->writeByte(m);
3300: buf->printf("%d_", qlen);
3301: for (size_t i = 0; i < qlen; i++)
3302: buf->printf("%02x", q[i]);
3303: }
3304:
3305: /************************ ArrayLiteralExp ************************************/
3306:
3307: // [ e1, e2, e3, ... ]
3308:
3309: ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements)
3310: : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
3311: {
3312: this->elements = elements;
3313: }
3314:
3315: ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e)
3316: : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
3317: {
3318: elements = new Expressions;
3319: elements->push(e);
3320: }
3321:
3322: Expression *ArrayLiteralExp::syntaxCopy()
3323: {
3324: return new ArrayLiteralExp(loc, arraySyntaxCopy(elements));
3325: }
3326:
3327: Expression *ArrayLiteralExp::semantic(Scope *sc)
3328: {
3329: #if LOGSEMANTIC
3330: printf("ArrayLiteralExp::semantic('%s')\n", toChars());
3331: #endif
3332: if (type)
3333: return this;
3334:
3335: /* Perhaps an empty array literal [ ] should be rewritten as null?
3336: */
3337:
3338: arrayExpressionSemantic(elements, sc); // run semantic() on each element
3339: expandTuples(elements);
3340:
3341: Type *t0;
3342: elements = arrayExpressionToCommonType(sc, elements, &t0);
3343:
3344: type = t0->arrayOf();
3345: //type = new TypeSArray(t0, new IntegerExp(elements->dim));
3346: type = type->semantic(loc, sc);
3347:
3348: /* Disallow array literals of type void being used.
3349: */
3350: if (elements->dim > 0 && t0->ty == Tvoid)
3351: error("%s of type %s has no value", toChars(), type->toChars());
3352:
3353: return this;
3354: }
3355:
3356: int ArrayLiteralExp::checkSideEffect(int flag)
3357: { int f = 0;
3358:
3359: for (size_t i = 0; i < elements->dim; i++)
3360: { Expression *e = elements->tdata()[i];
3361:
3362: f |= e->checkSideEffect(2);
3363: }
3364: if (flag == 0 && f == 0)
3365: Expression::checkSideEffect(0);
3366: return f;
3367: }
3368:
3369: int ArrayLiteralExp::isBool(int result)
3370: {
3371: size_t dim = elements ? elements->dim : 0;
3372: return result ? (dim != 0) : (dim == 0);
3373: }
3374:
3375: #if DMDV2
3376: int ArrayLiteralExp::canThrow(bool mustNotThrow)
3377: {
3378: /* Memory allocation failures throw non-recoverable exceptions, which
3379: * we don't need to count as 'throwing'.
3380: */
3381: return arrayExpressionCanThrow(elements, mustNotThrow);
3382: }
3383: #endif
3384:
3385: void ArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3386: {
3387: buf->writeByte('[');
3388: argsToCBuffer(buf, elements, hgs);
3389: buf->writeByte(']');
3390: }
3391:
3392: void ArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
3393: {
3394: size_t dim = elements ? elements->dim : 0;
3395: buf->printf("A%u", dim);
3396: for (size_t i = 0; i < dim; i++)
3397: { Expression *e = elements->tdata()[i];
3398: e->toMangleBuffer(buf);
3399: }
3400: }
3401:
3402: /************************ AssocArrayLiteralExp ************************************/
3403:
3404: // [ key0 : value0, key1 : value1, ... ]
3405:
3406: AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc,
3407: Expressions *keys, Expressions *values)
3408: : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp))
3409: {
3410: assert(keys->dim == values->dim);
3411: this->keys = keys;
3412: this->values = values;
3413: }
3414:
3415: Expression *AssocArrayLiteralExp::syntaxCopy()
3416: {
3417: return new AssocArrayLiteralExp(loc,
3418: arraySyntaxCopy(keys), arraySyntaxCopy(values));
3419: }
3420:
3421: Expression *AssocArrayLiteralExp::semantic(Scope *sc)
3422: { Expression *e;
warning C4101: 'e' : unreferenced local variable
3423:
3424: #if LOGSEMANTIC
3425: printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
3426: #endif
3427:
3428: if (type)
3429: return this;
3430:
3431: // Run semantic() on each element
3432: arrayExpressionSemantic(keys, sc);
3433: arrayExpressionSemantic(values, sc);
3434: expandTuples(keys);
3435: expandTuples(values);
3436: if (keys->dim != values->dim)
3437: {
3438: error("number of keys is %u, must match number of values %u", keys->dim, values->dim);
3439: return new ErrorExp();
3440: }
3441:
3442: Type *tkey = NULL;
3443: Type *tvalue = NULL;
3444: keys = arrayExpressionToCommonType(sc, keys, &tkey);
3445: values = arrayExpressionToCommonType(sc, values, &tvalue);
3446:
3447: type = new TypeAArray(tvalue, tkey);
3448: type = type->semantic(loc, sc);
3449: return this;
3450: }
3451:
3452: int AssocArrayLiteralExp::checkSideEffect(int flag)
3453: { int f = 0;
3454:
3455: for (size_t i = 0; i < keys->dim; i++)
3456: { Expression *key = keys->tdata()[i];
3457: Expression *value = values->tdata()[i];
3458:
3459: f |= key->checkSideEffect(2);
3460: f |= value->checkSideEffect(2);
3461: }
3462: if (flag == 0 && f == 0)
3463: Expression::checkSideEffect(0);
3464: return f;
3465: }
3466:
3467: int AssocArrayLiteralExp::isBool(int result)
3468: {
3469: size_t dim = keys->dim;
3470: return result ? (dim != 0) : (dim == 0);
3471: }
3472:
3473: #if DMDV2
3474: int AssocArrayLiteralExp::canThrow(bool mustNotThrow)
3475: {
3476: /* Memory allocation failures throw non-recoverable exceptions, which
3477: * we don't need to count as 'throwing'.
3478: */
3479: return (arrayExpressionCanThrow(keys, mustNotThrow) ||
3480: arrayExpressionCanThrow(values, mustNotThrow));
3481: }
3482: #endif
3483:
3484: void AssocArrayLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3485: {
3486: buf->writeByte('[');
3487: for (size_t i = 0; i < keys->dim; i++)
3488: { Expression *key = keys->tdata()[i];
3489: Expression *value = values->tdata()[i];
3490:
3491: if (i)
3492: buf->writeByte(',');
3493: expToCBuffer(buf, hgs, key, PREC_assign);
3494: buf->writeByte(':');
3495: expToCBuffer(buf, hgs, value, PREC_assign);
3496: }
3497: buf->writeByte(']');
3498: }
3499:
3500: void AssocArrayLiteralExp::toMangleBuffer(OutBuffer *buf)
3501: {
3502: size_t dim = keys->dim;
3503: buf->printf("A%u", dim);
3504: for (size_t i = 0; i < dim; i++)
3505: { Expression *key = keys->tdata()[i];
3506: Expression *value = values->tdata()[i];
3507:
3508: key->toMangleBuffer(buf);
3509: value->toMangleBuffer(buf);
3510: }
3511: }
3512:
3513: /************************ StructLiteralExp ************************************/
3514:
3515: // sd( e1, e2, e3, ... )
3516:
3517: StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype)
3518: : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp))
3519: {
3520: this->sd = sd;
3521: this->elements = elements;
3522: this->stype = stype;
3523: this->sym = NULL;
3524: this->soffset = 0;
3525: this->fillHoles = 1;
3526: }
3527:
3528: Expression *StructLiteralExp::syntaxCopy()
3529: {
3530: return new StructLiteralExp(loc, sd, arraySyntaxCopy(elements), stype);
3531: }
3532:
3533: Expression *StructLiteralExp::semantic(Scope *sc)
3534: { Expression *e;
3535: int nfields = sd->fields.dim - sd->isnested;
3536:
3537: #if LOGSEMANTIC
3538: printf("StructLiteralExp::semantic('%s')\n", toChars());
3539: #endif
3540: if (type)
3541: return this;
3542:
3543: elements = arrayExpressionSemantic(elements, sc); // run semantic() on each element
3544: expandTuples(elements);
3545: size_t offset = 0;
3546: for (size_t i = 0; i < elements->dim; i++)
3547: { e = elements->tdata()[i];
3548: if (!e)
3549: continue;
3550:
3551: if (!e->type)
3552: { error("%s has no value", e->toChars());
3553: return new ErrorExp();
3554: }
3555: e = resolveProperties(sc, e);
3556: if (i >= nfields)
warning C4018: '>=' : signed/unsigned mismatch
3557: { error("more initializers than fields of %s", sd->toChars());
3558: return new ErrorExp();
3559: }
3560: Dsymbol *s = sd->fields.tdata()[i];
3561: VarDeclaration *v = s->isVarDeclaration();
3562: assert(v);
3563: if (v->offset < offset)
3564: { error("overlapping initialization for %s", v->toChars());
3565: return new ErrorExp();
3566: }
3567: offset = v->offset + v->type->size();
warning C4244: '=' : conversion from 'd_uns64' to 'size_t', possible loss of data
3568:
3569: Type *telem = v->type;
3570: if (stype)
3571: telem = telem->addMod(stype->mod);
3572: while (!e->implicitConvTo(telem) && telem->toBasetype()->ty == Tsarray)
3573: { /* Static array initialization, as in:
3574: * T[3][5] = e;
3575: */
3576: telem = telem->toBasetype()->nextOf();
3577: }
3578:
3579: e = e->implicitCastTo(sc, telem);
3580:
3581: elements->tdata()[i] = e;
3582: }
3583:
3584: /* Fill out remainder of elements[] with default initializers for fields[]
3585: */
3586: for (size_t i = elements->dim; i < nfields; i++)
warning C4018: '<' : signed/unsigned mismatch
3587: { Dsymbol *s = sd->fields.tdata()[i];
3588: VarDeclaration *v = s->isVarDeclaration();
3589: assert(v);
3590: assert(!v->isThisDeclaration());
3591:
3592: if (v->offset < offset)
3593: { e = NULL;
3594: sd->hasUnions = 1;
3595: }
3596: else
3597: {
3598: if (v->init)
3599: { if (v->init->isVoidInitializer())
3600: e = NULL;
3601: else
3602: { e = v->init->toExpression();
3603: if (!e)
3604: { error("cannot make expression out of initializer for %s", v->toChars());
3605: return new ErrorExp();
3606: }
3607: else if (v->scope)
3608: { // Do deferred semantic analysis
3609: Initializer *i2 = v->init->syntaxCopy();
3610: i2 = i2->semantic(v->scope, v->type, WANTinterpret);
3611: e = i2->toExpression();
3612: v->scope = NULL;
3613: }
3614: }
3615: }
3616: else
3617: e = v->type->defaultInitLiteral(loc);
3618: offset = v->offset + v->type->size();
warning C4244: '=' : conversion from 'd_uns64' to 'size_t', possible loss of data
3619: }
3620: elements->push(e);
3621: }
3622:
3623: type = stype ? stype : sd->type;
3624:
3625: /* If struct requires a destructor, rewrite as:
3626: * (S tmp = S()),tmp
3627: * so that the destructor can be hung on tmp.
3628: */
3629: if (sd->dtor)
3630: {
3631: Identifier *idtmp = Lexer::uniqueId("__sl");
3632: VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(0, this));
3633: tmp->storage_class |= STCctfe;
3634: Expression *ae = new DeclarationExp(loc, tmp);
3635: Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp));
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3534' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 3534
3636: e = e->semantic(sc);
3637: return e;
3638: }
3639:
3640: return this;
3641: }
3642:
3643: /**************************************
3644: * Gets expression at offset of type.
3645: * Returns NULL if not found.
3646: */
3647:
3648: Expression *StructLiteralExp::getField(Type *type, unsigned offset)
3649: {
3650: //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
3651: // /*toChars()*/"", type->toChars(), offset);
3652: Expression *e = NULL;
3653: int i = getFieldIndex(type, offset);
3654:
3655: if (i != -1)
3656: {
3657: //printf("\ti = %d\n", i);
3658: assert(i < elements->dim);
warning C4018: '<' : signed/unsigned mismatch
3659: e = elements->tdata()[i];
3660: if (e)
3661: {
3662: //printf("e = %s, e->type = %s\n", e->toChars(), e->type->toChars());
3663:
3664: /* If type is a static array, and e is an initializer for that array,
3665: * then the field initializer should be an array literal of e.
3666: */
3667: if (e->type->castMod(0) != type->castMod(0) && type->ty == Tsarray)
3668: { TypeSArray *tsa = (TypeSArray *)type;
3669: uinteger_t length = tsa->dim->toInteger();
3670: Expressions *z = new Expressions;
3671: z->setDim(length);
warning C4244: 'argument' : conversion from 'uinteger_t' to 'unsigned int', possible loss of data
3672: for (int q = 0; q < length; ++q)
3673: z->tdata()[q] = e->copy();
3674: e = new ArrayLiteralExp(loc, z);
3675: e->type = type;
3676: }
3677: else
3678: {
3679: e = e->copy();
3680: e->type = type;
3681: }
3682: }
3683: }
3684: return e;
3685: }
3686:
3687: /************************************
3688: * Get index of field.
3689: * Returns -1 if not found.
3690: */
3691:
3692: int StructLiteralExp::getFieldIndex(Type *type, unsigned offset)
3693: {
3694: /* Find which field offset is by looking at the field offsets
3695: */
3696: if (elements->dim)
3697: {
3698: for (size_t i = 0; i < sd->fields.dim; i++)
3699: {
3700: Dsymbol *s = sd->fields.tdata()[i];
3701: VarDeclaration *v = s->isVarDeclaration();
3702: assert(v);
3703:
3704: if (offset == v->offset &&
3705: type->size() == v->type->size())
3706: { Expression *e = elements->tdata()[i];
3707: if (e)
3708: {
3709: return i;
3710: }
3711: break;
3712: }
3713: }
3714: }
3715: return -1;
3716: }
3717:
3718: #if DMDV2
3719: int StructLiteralExp::isLvalue()
3720: {
3721: return 1;
3722: }
3723: #endif
3724:
3725: Expression *StructLiteralExp::toLvalue(Scope *sc, Expression *e)
3726: {
3727: return this;
3728: }
3729:
3730:
3731: int StructLiteralExp::checkSideEffect(int flag)
3732: { int f = 0;
3733:
3734: for (size_t i = 0; i < elements->dim; i++)
3735: { Expression *e = elements->tdata()[i];
3736: if (!e)
3737: continue;
3738:
3739: f |= e->checkSideEffect(2);
3740: }
3741: if (flag == 0 && f == 0)
3742: Expression::checkSideEffect(0);
3743: return f;
3744: }
3745:
3746: #if DMDV2
3747: int StructLiteralExp::canThrow(bool mustNotThrow)
3748: {
3749: return arrayExpressionCanThrow(elements, mustNotThrow);
3750: }
3751: #endif
3752:
3753: void StructLiteralExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3754: {
3755: buf->writestring(sd->toChars());
3756: buf->writeByte('(');
3757: argsToCBuffer(buf, elements, hgs);
3758: buf->writeByte(')');
3759: }
3760:
3761: void StructLiteralExp::toMangleBuffer(OutBuffer *buf)
3762: {
3763: size_t dim = elements ? elements->dim : 0;
3764: buf->printf("S%u", dim);
3765: for (size_t i = 0; i < dim; i++)
3766: { Expression *e = elements->tdata()[i];
3767: if (e)
3768: e->toMangleBuffer(buf);
3769: else
3770: buf->writeByte('v'); // 'v' for void
3771: }
3772: }
3773:
3774: /************************ TypeDotIdExp ************************************/
3775:
3776: /* Things like:
3777: * int.size
3778: * foo.size
3779: * (foo).size
3780: * cast(foo).size
3781: */
3782:
3783: Expression *typeDotIdExp(Loc loc, Type *type, Identifier *ident)
3784: {
3785: return new DotIdExp(loc, new TypeExp(loc, type), ident);
3786: }
3787:
3788:
3789: /************************************************************/
3790:
3791: // Mainly just a placeholder
3792:
3793: TypeExp::TypeExp(Loc loc, Type *type)
3794: : Expression(loc, TOKtype, sizeof(TypeExp))
3795: {
3796: //printf("TypeExp::TypeExp(%s)\n", type->toChars());
3797: this->type = type;
3798: }
3799:
3800: Expression *TypeExp::syntaxCopy()
3801: {
3802: //printf("TypeExp::syntaxCopy()\n");
3803: return new TypeExp(loc, type->syntaxCopy());
3804: }
3805:
3806: Expression *TypeExp::semantic(Scope *sc)
3807: {
3808: //printf("TypeExp::semantic(%s)\n", type->toChars());
3809: type = type->semantic(loc, sc);
3810: return this;
3811: }
3812:
3813: void TypeExp::rvalue()
3814: {
3815: error("type %s has no value", toChars());
3816: }
3817:
3818: void TypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3819: {
3820: type->toCBuffer(buf, NULL, hgs);
3821: }
3822:
3823: /************************************************************/
3824:
3825: // Mainly just a placeholder
3826:
3827: ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *pkg)
3828: : Expression(loc, TOKimport, sizeof(ScopeExp))
3829: {
3830: //printf("ScopeExp::ScopeExp(pkg = '%s')\n", pkg->toChars());
3831: //static int count; if (++count == 38) *(char*)0=0;
3832: this->sds = pkg;
3833: }
3834:
3835: Expression *ScopeExp::syntaxCopy()
3836: {
3837: ScopeExp *se = new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL));
3838: return se;
3839: }
3840:
3841: Expression *ScopeExp::semantic(Scope *sc)
3842: {
3843: TemplateInstance *ti;
3844: ScopeDsymbol *sds2;
3845:
3846: #if LOGSEMANTIC
3847: printf("+ScopeExp::semantic('%s')\n", toChars());
3848: #endif
3849: Lagain:
3850: ti = sds->isTemplateInstance();
3851: if (ti && !global.errors)
3852: {
3853: if (!ti->semanticRun)
3854: ti->semantic(sc);
3855: if (ti->inst)
3856: {
3857: Dsymbol *s = ti->inst->toAlias();
3858: sds2 = s->isScopeDsymbol();
3859: if (!sds2)
3860: { Expression *e;
3861:
3862: //printf("s = %s, '%s'\n", s->kind(), s->toChars());
3863: if (ti->withsym)
3864: {
3865: // Same as wthis.s
3866: e = new VarExp(loc, ti->withsym->withstate->wthis);
3867: e = new DotVarExp(loc, e, s->isDeclaration());
3868: }
3869: else
3870: e = new DsymbolExp(loc, s);
3871: e = e->semantic(sc);
3872: //printf("-1ScopeExp::semantic()\n");
3873: return e;
3874: }
3875: if (sds2 != sds)
3876: {
3877: sds = sds2;
3878: goto Lagain;
3879: }
3880: //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3881: }
3882: if (global.errors)
3883: return new ErrorExp();
3884: }
3885: else
3886: {
3887: //printf("sds = %s, '%s'\n", sds->kind(), sds->toChars());
3888: //printf("\tparent = '%s'\n", sds->parent->toChars());
3889: sds->semantic(sc);
3890: }
3891: type = Type::tvoid;
3892: //printf("-2ScopeExp::semantic() %s\n", toChars());
3893: return this;
3894: }
3895:
3896: void ScopeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3897: {
3898: if (sds->isTemplateInstance())
3899: {
3900: sds->toCBuffer(buf, hgs);
3901: }
3902: else
3903: {
3904: buf->writestring(sds->kind());
3905: buf->writestring(" ");
3906: buf->writestring(sds->toChars());
3907: }
3908: }
3909:
3910: /********************** TemplateExp **************************************/
3911:
3912: // Mainly just a placeholder
3913:
3914: TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td)
3915: : Expression(loc, TOKtemplate, sizeof(TemplateExp))
3916: {
3917: //printf("TemplateExp(): %s\n", td->toChars());
3918: this->td = td;
3919: }
3920:
3921: void TemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
3922: {
3923: buf->writestring(td->toChars());
3924: }
3925:
3926: void TemplateExp::rvalue()
3927: {
3928: error("template %s has no value", toChars());
3929: }
3930:
3931: /********************** NewExp **************************************/
3932:
3933: /* thisexp.new(newargs) newtype(arguments) */
3934:
3935: NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
3936: Type *newtype, Expressions *arguments)
3937: : Expression(loc, TOKnew, sizeof(NewExp))
3938: {
3939: this->thisexp = thisexp;
3940: this->newargs = newargs;
3941: this->newtype = newtype;
3942: this->arguments = arguments;
3943: member = NULL;
3944: allocator = NULL;
3945: onstack = 0;
3946: }
3947:
3948: Expression *NewExp::syntaxCopy()
3949: {
3950: return new NewExp(loc,
3951: thisexp ? thisexp->syntaxCopy() : NULL,
3952: arraySyntaxCopy(newargs),
3953: newtype->syntaxCopy(), arraySyntaxCopy(arguments));
3954: }
3955:
3956:
3957: Expression *NewExp::semantic(Scope *sc)
3958: { int i;
warning C4101: 'i' : unreferenced local variable
3959: Type *tb;
3960: ClassDeclaration *cdthis = NULL;
3961:
3962: #if LOGSEMANTIC
3963: printf("NewExp::semantic() %s\n", toChars());
3964: if (thisexp)
3965: printf("\tthisexp = %s\n", thisexp->toChars());
3966: printf("\tnewtype: %s\n", newtype->toChars());
3967: #endif
3968: if (type) // if semantic() already run
3969: return this;
3970:
3971: Lagain:
3972: if (thisexp)
3973: { thisexp = thisexp->semantic(sc);
3974: cdthis = thisexp->type->isClassHandle();
3975: if (cdthis)
3976: {
3977: sc = sc->push(cdthis);
3978: type = newtype->semantic(loc, sc);
3979: sc = sc->pop();
3980: }
3981: else
3982: {
3983: error("'this' for nested class must be a class type, not %s", thisexp->type->toChars());
3984: goto Lerr;
3985: }
3986: }
3987: else
3988: type = newtype->semantic(loc, sc);
3989: newtype = type; // in case type gets cast to something else
3990: tb = type->toBasetype();
3991: //printf("tb: %s, deco = %s\n", tb->toChars(), tb->deco);
3992:
3993: arrayExpressionSemantic(newargs, sc);
3994: preFunctionParameters(loc, sc, newargs);
3995: arrayExpressionSemantic(arguments, sc);
3996: preFunctionParameters(loc, sc, arguments);
3997:
3998: if (thisexp && tb->ty != Tclass)
3999: { error("e.new is only for allocating nested classes, not %s", tb->toChars());
4000: goto Lerr;
4001: }
4002:
4003: if (tb->ty == Tclass)
4004: {
4005: TypeClass *tc = (TypeClass *)(tb);
4006: ClassDeclaration *cd = tc->sym->isClassDeclaration();
4007: if (cd->isInterfaceDeclaration())
4008: { error("cannot create instance of interface %s", cd->toChars());
4009: goto Lerr;
4010: }
4011: else if (cd->isAbstract())
4012: { error("cannot create instance of abstract class %s", cd->toChars());
4013: for (int i = 0; i < cd->vtbl.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3958' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 3958
4014: { FuncDeclaration *fd = cd->vtbl.tdata()[i]->isFuncDeclaration();
4015: if (fd && fd->isAbstract())
4016: error("function %s is abstract", fd->toChars());
4017: }
4018: goto Lerr;
4019: }
4020:
4021: if (cd->noDefaultCtor && (!arguments || !arguments->dim))
4022: error("default construction is disabled for type %s", cd->toChars());
4023:
4024: checkDeprecated(sc, cd);
4025: if (cd->isNested())
4026: { /* We need a 'this' pointer for the nested class.
4027: * Ensure we have the right one.
4028: */
4029: Dsymbol *s = cd->toParent2();
4030: ClassDeclaration *cdn = s->isClassDeclaration();
4031: FuncDeclaration *fdn = s->isFuncDeclaration();
4032:
4033: //printf("cd isNested, cdn = %s\n", cdn ? cdn->toChars() : "null");
4034: if (cdn)
4035: {
4036: if (!cdthis)
4037: {
4038: // Supply an implicit 'this' and try again
4039: thisexp = new ThisExp(loc);
4040: for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
4041: { if (!sp)
4042: {
4043: error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
4044: goto Lerr;
4045: }
4046: ClassDeclaration *cdp = sp->isClassDeclaration();
4047: if (!cdp)
4048: continue;
4049: if (cdp == cdn || cdn->isBaseOf(cdp, NULL))
4050: break;
4051: // Add a '.outer' and try again
4052: thisexp = new DotIdExp(loc, thisexp, Id::outer);
4053: }
4054: if (!global.errors)
4055: goto Lagain;
4056: }
4057: if (cdthis)
4058: {
4059: //printf("cdthis = %s\n", cdthis->toChars());
4060: if (cdthis != cdn && !cdn->isBaseOf(cdthis, NULL))
4061: { error("'this' for nested class must be of type %s, not %s", cdn->toChars(), thisexp->type->toChars());
4062: goto Lerr;
4063: }
4064: }
4065: #if 0
4066: else
4067: {
4068: for (Dsymbol *sf = sc->func; 1; sf= sf->toParent2()->isFuncDeclaration())
4069: {
4070: if (!sf)
4071: {
4072: error("outer class %s 'this' needed to 'new' nested class %s", cdn->toChars(), cd->toChars());
4073: goto Lerr;
4074: }
4075: printf("sf = %s\n", sf->toChars());
4076: AggregateDeclaration *ad = sf->isThis();
4077: if (ad && (ad == cdn || cdn->isBaseOf(ad->isClassDeclaration(), NULL)))
4078: break;
4079: }
4080: }
4081: #endif
4082: }
4083: #if 1
4084: else if (thisexp)
4085: { error("e.new is only for allocating nested classes");
4086: goto Lerr;
4087: }
4088: else if (fdn)
4089: {
4090: // make sure the parent context fdn of cd is reachable from sc
4091: for (Dsymbol *sp = sc->parent; 1; sp = sp->parent)
4092: {
4093: if (fdn == sp)
4094: break;
4095: FuncDeclaration *fsp = sp ? sp->isFuncDeclaration() : NULL;
4096: if (!sp || (fsp && fsp->isStatic()))
4097: {
4098: error("outer function context of %s is needed to 'new' nested class %s", fdn->toPrettyChars(), cd->toPrettyChars());
4099: goto Lerr;
4100: }
4101: }
4102: }
4103: #else
4104: else if (fdn)
4105: { /* The nested class cd is nested inside a function,
4106: * we'll let getEthis() look for errors.
4107: */
4108: //printf("nested class %s is nested inside function %s, we're in %s\n", cd->toChars(), fdn->toChars(), sc->func->toChars());
4109: if (thisexp)
4110: { // Because thisexp cannot be a function frame pointer
4111: error("e.new is only for allocating nested classes");
4112: goto Lerr;
4113: }
4114: }
4115: #endif
4116: else
4117: assert(0);
4118: }
4119: else if (thisexp)
4120: { error("e.new is only for allocating nested classes");
4121: goto Lerr;
4122: }
4123:
4124: FuncDeclaration *f = NULL;
4125: if (cd->ctor)
4126: f = resolveFuncCall(sc, loc, cd->ctor, NULL, NULL, arguments, 0);
4127: if (f)
4128: {
4129: checkDeprecated(sc, f);
4130: member = f->isCtorDeclaration();
4131: assert(member);
4132:
4133: cd->accessCheck(loc, sc, member);
4134:
4135: TypeFunction *tf = (TypeFunction *)f->type;
4136:
4137: if (!arguments)
4138: arguments = new Expressions();
4139: functionParameters(loc, sc, tf, arguments, f);
4140:
4141: type = type->addMod(tf->nextOf()->mod);
4142: }
4143: else
4144: {
4145: if (arguments && arguments->dim)
4146: { error("no constructor for %s", cd->toChars());
4147: goto Lerr;
4148: }
4149: }
4150:
4151: if (cd->aggNew)
4152: {
4153: // Prepend the size argument to newargs[]
4154: Expression *e = new IntegerExp(loc, cd->size(loc), Type::tsize_t);
4155: if (!newargs)
4156: newargs = new Expressions();
4157: newargs->shift(e);
4158:
4159: f = cd->aggNew->overloadResolve(loc, NULL, newargs);
4160: allocator = f->isNewDeclaration();
4161: assert(allocator);
4162:
4163: TypeFunction *tf = (TypeFunction *)f->type;
4164: functionParameters(loc, sc, tf, newargs, f);
4165: }
4166: else
4167: {
4168: if (newargs && newargs->dim)
4169: { error("no allocator for %s", cd->toChars());
4170: goto Lerr;
4171: }
4172: }
4173: }
4174: else if (tb->ty == Tstruct)
4175: {
4176: TypeStruct *ts = (TypeStruct *)tb;
4177: StructDeclaration *sd = ts->sym;
4178: TypeFunction *tf;
4179:
4180: if (sd->noDefaultCtor && (!arguments || !arguments->dim))
4181: error("default construction is disabled for type %s", sd->toChars());
4182:
4183: FuncDeclaration *f = NULL;
4184: if (sd->ctor)
4185: f = resolveFuncCall(sc, loc, sd->ctor, NULL, NULL, arguments, 0);
4186: if (f)
4187: {
4188: checkDeprecated(sc, f);
4189: member = f->isCtorDeclaration();
4190: assert(member);
4191:
4192: sd->accessCheck(loc, sc, member);
4193:
4194: tf = (TypeFunction *)f->type;
4195: type = tf->next;
4196:
4197: if (!arguments)
4198: arguments = new Expressions();
4199: functionParameters(loc, sc, tf, arguments, f);
4200: }
4201: else
4202: {
4203: if (arguments && arguments->dim)
4204: { error("no constructor for %s", sd->toChars());
4205: goto Lerr;
4206: }
4207: }
4208:
4209:
4210: if (sd->aggNew)
4211: {
4212: // Prepend the uint size argument to newargs[]
4213: Expression *e = new IntegerExp(loc, sd->size(loc), Type::tuns32);
4214: if (!newargs)
4215: newargs = new Expressions();
4216: newargs->shift(e);
4217:
4218: f = sd->aggNew->overloadResolve(loc, NULL, newargs);
4219: allocator = f->isNewDeclaration();
4220: assert(allocator);
4221:
4222: tf = (TypeFunction *)f->type;
4223: functionParameters(loc, sc, tf, newargs, f);
4224: #if 0
4225: e = new VarExp(loc, f);
4226: e = new CallExp(loc, e, newargs);
4227: e = e->semantic(sc);
4228: e->type = type->pointerTo();
4229: return e;
4230: #endif
4231: }
4232: else
4233: {
4234: if (newargs && newargs->dim)
4235: { error("no allocator for %s", sd->toChars());
4236: goto Lerr;
4237: }
4238: }
4239:
4240: type = type->pointerTo();
4241: }
4242: else if (tb->ty == Tarray && (arguments && arguments->dim))
4243: {
4244: for (size_t i = 0; i < arguments->dim; i++)
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '3958' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 3958
4245: {
4246: if (tb->ty != Tarray)
4247: { error("too many arguments for array");
4248: goto Lerr;
4249: }
4250:
4251: Expression *arg = arguments->tdata()[i];
4252: arg = resolveProperties(sc, arg);
4253: arg = arg->implicitCastTo(sc, Type::tsize_t);
4254: arg = arg->optimize(WANTvalue);
4255: if (arg->op == TOKint64 && (sinteger_t)arg->toInteger() < 0)
4256: { error("negative array index %s", arg->toChars());
4257: goto Lerr;
4258: }
4259: arguments->tdata()[i] = arg;
4260: tb = ((TypeDArray *)tb)->next->toBasetype();
4261: }
4262: }
4263: else if (tb->isscalar())
4264: {
4265: if (arguments && arguments->dim)
4266: { error("no constructor for %s", type->toChars());
4267: goto Lerr;
4268: }
4269:
4270: type = type->pointerTo();
4271: }
4272: else
4273: {
4274: error("new can only create structs, dynamic arrays or class objects, not %s's", type->toChars());
4275: goto Lerr;
4276: }
4277:
4278: //printf("NewExp: '%s'\n", toChars());
4279: //printf("NewExp:type '%s'\n", type->toChars());
4280:
4281: return this;
4282:
4283: Lerr:
4284: return new ErrorExp();
4285: }
4286:
4287: int NewExp::checkSideEffect(int flag)
4288: {
4289: return 1;
4290: }
4291:
4292: #if DMDV2
4293: int NewExp::canThrow(bool mustNotThrow)
4294: {
4295: if (arrayExpressionCanThrow(newargs, mustNotThrow) ||
4296: arrayExpressionCanThrow(arguments, mustNotThrow))
4297: return 1;
4298: if (member)
4299: {
4300: // See if constructor call can throw
4301: Type *t = member->type->toBasetype();
4302: if (t->ty == Tfunction && !((TypeFunction *)t)->isnothrow)
4303: {
4304: if (mustNotThrow)
4305: error("constructor %s is not nothrow", member->toChars());
4306: return 1;
4307: }
4308: }
4309: // regard storage allocation failures as not recoverable
4310: return 0;
4311: }
4312: #endif
4313:
4314: void NewExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4315: { int i;
warning C4101: 'i' : unreferenced local variable
4316:
4317: if (thisexp)
4318: { expToCBuffer(buf, hgs, thisexp, PREC_primary);
4319: buf->writeByte('.');
4320: }
4321: buf->writestring("new ");
4322: if (newargs && newargs->dim)
4323: {
4324: buf->writeByte('(');
4325: argsToCBuffer(buf, newargs, hgs);
4326: buf->writeByte(')');
4327: }
4328: newtype->toCBuffer(buf, NULL, hgs);
4329: if (arguments && arguments->dim)
4330: {
4331: buf->writeByte('(');
4332: argsToCBuffer(buf, arguments, hgs);
4333: buf->writeByte(')');
4334: }
4335: }
4336:
4337: /********************** NewAnonClassExp **************************************/
4338:
4339: NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp,
4340: Expressions *newargs, ClassDeclaration *cd, Expressions *arguments)
4341: : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp))
4342: {
4343: this->thisexp = thisexp;
4344: this->newargs = newargs;
4345: this->cd = cd;
4346: this->arguments = arguments;
4347: }
4348:
4349: Expression *NewAnonClassExp::syntaxCopy()
4350: {
4351: return new NewAnonClassExp(loc,
4352: thisexp ? thisexp->syntaxCopy() : NULL,
4353: arraySyntaxCopy(newargs),
4354: (ClassDeclaration *)cd->syntaxCopy(NULL),
4355: arraySyntaxCopy(arguments));
4356: }
4357:
4358:
4359: Expression *NewAnonClassExp::semantic(Scope *sc)
4360: {
4361: #if LOGSEMANTIC
4362: printf("NewAnonClassExp::semantic() %s\n", toChars());
4363: //printf("thisexp = %p\n", thisexp);
4364: //printf("type: %s\n", type->toChars());
4365: #endif
4366:
4367: Expression *d = new DeclarationExp(loc, cd);
warning C6211: Leaking memory 'd' due to an exception. Consider using a local catch block to clean up memory: Lines: 4367, 4368, 4370
4368: d = d->semantic(sc);
4369:
4370: Expression *n = new NewExp(loc, thisexp, newargs, cd->type, arguments);
4371:
4372: Expression *c = new CommaExp(loc, d, n);
4373: return c->semantic(sc);
4374: }
4375:
4376: int NewAnonClassExp::checkSideEffect(int flag)
4377: {
4378: return 1;
4379: }
4380:
4381: #if DMDV2
4382: int NewAnonClassExp::canThrow(bool mustNotThrow)
4383: {
4384: assert(0); // should have been lowered by semantic()
4385: return 1;
4386: }
4387: #endif
4388:
4389: void NewAnonClassExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4390: { int i;
warning C4101: 'i' : unreferenced local variable
4391:
4392: if (thisexp)
4393: { expToCBuffer(buf, hgs, thisexp, PREC_primary);
4394: buf->writeByte('.');
4395: }
4396: buf->writestring("new");
4397: if (newargs && newargs->dim)
4398: {
4399: buf->writeByte('(');
4400: argsToCBuffer(buf, newargs, hgs);
4401: buf->writeByte(')');
4402: }
4403: buf->writestring(" class ");
4404: if (arguments && arguments->dim)
4405: {
4406: buf->writeByte('(');
4407: argsToCBuffer(buf, arguments, hgs);
4408: buf->writeByte(')');
4409: }
4410: //buf->writestring(" { }");
4411: if (cd)
4412: {
4413: cd->toCBuffer(buf, hgs);
4414: }
4415: }
4416:
4417: /********************** SymbolExp **************************************/
4418:
4419: #if DMDV2
4420: SymbolExp::SymbolExp(Loc loc, enum TOK op, int size, Declaration *var, int hasOverloads)
4421: : Expression(loc, op, size)
4422: {
4423: assert(var);
4424: this->var = var;
4425: this->hasOverloads = hasOverloads;
4426: }
4427: #endif
4428:
4429: /********************** SymOffExp **************************************/
4430:
4431: SymOffExp::SymOffExp(Loc loc, Declaration *var, unsigned offset, int hasOverloads)
4432: : SymbolExp(loc, TOKsymoff, sizeof(SymOffExp), var, hasOverloads)
4433: {
4434: this->offset = offset;
4435: VarDeclaration *v = var->isVarDeclaration();
4436: if (v && v->needThis())
4437: error("need 'this' for address of %s", v->toChars());
4438: }
4439:
4440: Expression *SymOffExp::semantic(Scope *sc)
4441: {
4442: #if LOGSEMANTIC
4443: printf("SymOffExp::semantic('%s')\n", toChars());
4444: #endif
4445: //var->semantic(sc);
4446: if (!type)
4447: type = var->type->pointerTo();
4448: VarDeclaration *v = var->isVarDeclaration();
4449: if (v)
4450: v->checkNestedReference(sc, loc);
4451: return this;
4452: }
4453:
4454: int SymOffExp::isBool(int result)
4455: {
4456: return result ? TRUE : FALSE;
4457: }
4458:
4459: void SymOffExp::checkEscape()
4460: {
4461: VarDeclaration *v = var->isVarDeclaration();
4462: if (v)
4463: {
4464: if (!v->isDataseg() && !(v->storage_class & (STCref | STCout)))
4465: { /* BUG: This should be allowed:
4466: * void foo()
4467: * { int a;
4468: * int* bar() { return &a; }
4469: * }
4470: */
4471: error("escaping reference to local %s", v->toChars());
4472: }
4473: }
4474: }
4475:
4476: void SymOffExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4477: {
4478: if (offset)
4479: buf->printf("(& %s+%u)", var->toChars(), offset);
4480: else
4481: buf->printf("& %s", var->toChars());
4482: }
4483:
4484: /******************************** VarExp **************************/
4485:
4486: VarExp::VarExp(Loc loc, Declaration *var, int hasOverloads)
4487: : SymbolExp(loc, TOKvar, sizeof(VarExp), var, hasOverloads)
4488: {
4489: //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
4490: //if (strcmp(var->ident->toChars(), "func") == 0) halt();
4491: this->type = var->type;
4492: }
4493:
4494: int VarExp::equals(Object *o)
4495: { VarExp *ne;
4496:
4497: if (this == o ||
4498: (((Expression *)o)->op == TOKvar &&
4499: ((ne = (VarExp *)o), type->toHeadMutable()->equals(ne->type->toHeadMutable())) &&
4500: var == ne->var))
4501: return 1;
4502: return 0;
4503: }
4504:
4505: Expression *VarExp::semantic(Scope *sc)
4506: { FuncLiteralDeclaration *fd;
warning C4101: 'fd' : unreferenced local variable
4507:
4508: #if LOGSEMANTIC
4509: printf("VarExp::semantic(%s)\n", toChars());
4510: #endif
4511: // if (var->sem == SemanticStart && var->scope) // if forward referenced
4512: // var->semantic(sc);
4513: if (!type)
4514: { type = var->type;
4515: #if 0
4516: if (var->storage_class & STClazy)
4517: {
4518: TypeFunction *tf = new TypeFunction(NULL, type, 0, LINKd);
4519: type = new TypeDelegate(tf);
4520: type = type->semantic(loc, sc);
4521: }
4522: #endif
4523: }
4524:
4525: if (type && !type->deco)
4526: type = type->semantic(loc, sc);
4527:
4528: /* Fix for 1161 doesn't work because it causes protection
4529: * problems when instantiating imported templates passing private
4530: * variables as alias template parameters.
4531: */
4532: //accessCheck(loc, sc, NULL, var);
4533:
4534: VarDeclaration *v = var->isVarDeclaration();
4535: if (v)
4536: {
4537: v->checkNestedReference(sc, loc);
4538: #if DMDV2
4539: checkPurity(sc, v, NULL);
4540: #endif
4541: }
4542: #if 0
4543: else if ((fd = var->isFuncLiteralDeclaration()) != NULL)
4544: { Expression *e;
4545: e = new FuncExp(loc, fd);
4546: e->type = type;
4547: return e;
4548: }
4549: #endif
4550:
4551: return this;
4552: }
4553:
4554: char *VarExp::toChars()
4555: {
4556: return var->toChars();
4557: }
4558:
4559: void VarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4560: {
4561: buf->writestring(var->toChars());
4562: }
4563:
4564: void VarExp::checkEscape()
4565: {
4566: VarDeclaration *v = var->isVarDeclaration();
4567: if (v)
4568: { Type *tb = v->type->toBasetype();
4569: // if reference type
4570: if (tb->ty == Tarray || tb->ty == Tsarray || tb->ty == Tclass)
4571: {
4572: if (v->isScope() && !v->noscope)
4573: error("escaping reference to scope local %s", v->toChars());
4574: else if (v->storage_class & STCvariadic)
4575: error("escaping reference to variadic parameter %s", v->toChars());
4576: }
4577: }
4578: }
4579:
4580: void VarExp::checkEscapeRef()
4581: {
4582: VarDeclaration *v = var->isVarDeclaration();
4583: if (v)
4584: {
4585: if (!v->isDataseg() && !(v->storage_class & (STCref | STCout)))
4586: error("escaping reference to local variable %s", v->toChars());
4587: }
4588: }
4589:
4590: #if DMDV2
4591: int VarExp::isLvalue()
4592: {
4593: if (var->storage_class & STClazy)
4594: return 0;
4595: return 1;
4596: }
4597: #endif
4598:
4599: Expression *VarExp::toLvalue(Scope *sc, Expression *e)
4600: {
4601: #if 0
4602: tym = tybasic(e1->ET->Tty);
4603: if (!(tyscalar(tym) ||
4604: tym == TYstruct ||
4605: tym == TYarray && e->Eoper == TOKaddr))
4606: synerr(EM_lvalue); // lvalue expected
4607: #endif
4608: if (var->storage_class & STClazy)
4609: { error("lazy variables cannot be lvalues");
4610: return new ErrorExp();
4611: }
4612: return this;
4613: }
4614:
4615: Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
4616: {
4617: //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
4618: //if (type && type->toBasetype()->ty == Tsarray)
4619: //error("cannot change reference to static array '%s'", var->toChars());
4620:
4621: var->checkModify(loc, sc, type);
4622:
4623: // See if this expression is a modifiable lvalue (i.e. not const)
4624: return toLvalue(sc, e);
4625: }
4626:
4627:
4628: /******************************** OverExp **************************/
4629:
4630: #if DMDV2
4631: OverExp::OverExp(OverloadSet *s)
4632: : Expression(loc, TOKoverloadset, sizeof(OverExp))
4633: {
4634: //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
4635: vars = s;
4636: type = Type::tvoid;
4637: }
4638:
4639: int OverExp::isLvalue()
4640: {
4641: return 1;
4642: }
4643:
4644: Expression *OverExp::toLvalue(Scope *sc, Expression *e)
4645: {
4646: return this;
4647: }
4648: #endif
4649:
4650:
4651: /******************************** TupleExp **************************/
4652:
4653: TupleExp::TupleExp(Loc loc, Expressions *exps)
4654: : Expression(loc, TOKtuple, sizeof(TupleExp))
4655: {
4656: //printf("TupleExp(this = %p)\n", this);
4657: this->exps = exps;
4658: this->type = NULL;
4659: }
4660:
4661:
4662: TupleExp::TupleExp(Loc loc, TupleDeclaration *tup)
4663: : Expression(loc, TOKtuple, sizeof(TupleExp))
4664: {
4665: exps = new Expressions();
4666: type = NULL;
4667:
4668: exps->reserve(tup->objects->dim);
4669: for (size_t i = 0; i < tup->objects->dim; i++)
4670: { Object *o = tup->objects->tdata()[i];
4671: if (o->dyncast() == DYNCAST_EXPRESSION)
4672: {
4673: Expression *e = (Expression *)o;
4674: if (e->op == TOKdsymbol)
4675: e = e->syntaxCopy();
4676: exps->push(e);
4677: }
4678: else if (o->dyncast() == DYNCAST_DSYMBOL)
4679: {
4680: Dsymbol *s = (Dsymbol *)o;
4681: Expression *e = new DsymbolExp(loc, s);
4682: exps->push(e);
4683: }
4684: else if (o->dyncast() == DYNCAST_TYPE)
4685: {
4686: Type *t = (Type *)o;
4687: Expression *e = new TypeExp(loc, t);
4688: exps->push(e);
4689: }
4690: else
4691: {
4692: error("%s is not an expression", o->toChars());
4693: }
4694: }
4695: }
4696:
4697: int TupleExp::equals(Object *o)
4698: { TupleExp *ne;
warning C4101: 'ne' : unreferenced local variable
4699:
4700: if (this == o)
4701: return 1;
4702: if (((Expression *)o)->op == TOKtuple)
4703: {
4704: TupleExp *te = (TupleExp *)o;
4705: if (exps->dim != te->exps->dim)
4706: return 0;
4707: for (size_t i = 0; i < exps->dim; i++)
4708: { Expression *e1 = (*exps)[i];
4709: Expression *e2 = (*te->exps)[i];
4710:
4711: if (!e1->equals(e2))
4712: return 0;
4713: }
4714: return 1;
4715: }
4716: return 0;
4717: }
4718:
4719: Expression *TupleExp::syntaxCopy()
4720: {
4721: return new TupleExp(loc, arraySyntaxCopy(exps));
4722: }
4723:
4724: Expression *TupleExp::semantic(Scope *sc)
4725: {
4726: #if LOGSEMANTIC
4727: printf("+TupleExp::semantic(%s)\n", toChars());
4728: #endif
4729: if (type)
4730: return this;
4731:
4732: // Run semantic() on each argument
4733: for (size_t i = 0; i < exps->dim; i++)
4734: { Expression *e = (*exps)[i];
4735:
4736: e = e->semantic(sc);
4737: if (!e->type)
4738: { error("%s has no value", e->toChars());
4739: e = new ErrorExp();
4740: }
4741: (*exps)[i] = e;
4742: }
4743:
4744: expandTuples(exps);
4745: if (0 && exps->dim == 1)
4746: {
4747: return (*exps)[0];
4748: }
4749: type = new TypeTuple(exps);
4750: type = type->semantic(loc, sc);
4751: //printf("-TupleExp::semantic(%s)\n", toChars());
4752: return this;
4753: }
4754:
4755: void TupleExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4756: {
4757: buf->writestring("tuple(");
4758: argsToCBuffer(buf, exps, hgs);
4759: buf->writeByte(')');
4760: }
4761:
4762: int TupleExp::checkSideEffect(int flag)
4763: { int f = 0;
4764:
4765: for (int i = 0; i < exps->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
4766: { Expression *e = (*exps)[i];
4767:
4768: f |= e->checkSideEffect(2);
4769: }
4770: if (flag == 0 && f == 0)
4771: Expression::checkSideEffect(0);
4772: return f;
4773: }
4774:
4775: #if DMDV2
4776: int TupleExp::canThrow(bool mustNotThrow)
4777: {
4778: return arrayExpressionCanThrow(exps, mustNotThrow);
4779: }
4780: #endif
4781:
4782: void TupleExp::checkEscape()
4783: {
4784: for (size_t i = 0; i < exps->dim; i++)
4785: { Expression *e = (*exps)[i];
4786: e->checkEscape();
4787: }
4788: }
4789:
4790: /******************************** FuncExp *********************************/
4791:
4792: FuncExp::FuncExp(Loc loc, FuncLiteralDeclaration *fd)
4793: : Expression(loc, TOKfunction, sizeof(FuncExp))
4794: {
4795: this->fd = fd;
4796: }
4797:
4798: Expression *FuncExp::syntaxCopy()
4799: {
4800: return new FuncExp(loc, (FuncLiteralDeclaration *)fd->syntaxCopy(NULL));
4801: }
4802:
4803: Expression *FuncExp::semantic(Scope *sc)
4804: {
4805: #if LOGSEMANTIC
4806: printf("FuncExp::semantic(%s)\n", toChars());
4807: #endif
4808: if (!type)
4809: {
4810: fd->semantic(sc);
4811: //fd->parent = sc->parent;
4812: if (global.errors)
4813: {
4814: }
4815: else
4816: {
4817: fd->semantic2(sc);
4818: if (!global.errors ||
4819: // need to infer return type
4820: (fd->type && fd->type->ty == Tfunction && !fd->type->nextOf()))
4821: {
4822: fd->semantic3(sc);
4823:
4824: if (!global.errors && global.params.useInline)
4825: fd->inlineScan();
4826: }
4827: }
4828:
4829: // need to infer return type
4830: if (global.errors && fd->type && fd->type->ty == Tfunction && !fd->type->nextOf())
4831: ((TypeFunction *)fd->type)->next = Type::terror;
4832:
4833: // Type is a "delegate to" or "pointer to" the function literal
4834: if (fd->isNested())
4835: {
4836: type = new TypeDelegate(fd->type);
4837: type = type->semantic(loc, sc);
4838: }
4839: else
4840: {
4841: type = fd->type->pointerTo();
warning C6011: Dereferencing NULL pointer 'fd->type': Lines: 4808, 4810, 4812, 4830, 4834, 4841
4842: }
4843: fd->tookAddressOf++;
4844: }
4845: return this;
4846: }
4847:
4848: char *FuncExp::toChars()
4849: {
4850: return fd->toChars();
4851: }
4852:
4853: void FuncExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
4854: {
4855: fd->toCBuffer(buf, hgs);
4856: //buf->writestring(fd->toChars());
4857: }
4858:
4859:
4860: /******************************** DeclarationExp **************************/
4861:
4862: DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration)
4863: : Expression(loc, TOKdeclaration, sizeof(DeclarationExp))
4864: {
4865: this->declaration = declaration;
4866: }
4867:
4868: Expression *DeclarationExp::syntaxCopy()
4869: {
4870: return new DeclarationExp(loc, declaration->syntaxCopy(NULL));
4871: }
4872:
4873: Expression *DeclarationExp::semantic(Scope *sc)
4874: {
4875: if (type)
4876: return this;
4877:
4878: #if LOGSEMANTIC
4879: printf("DeclarationExp::semantic() %s\n", toChars());
4880: #endif
4881:
4882: /* This is here to support extern(linkage) declaration,
4883: * where the extern(linkage) winds up being an AttribDeclaration
4884: * wrapper.
4885: */
4886: Dsymbol *s = declaration;
4887:
4888: AttribDeclaration *ad = declaration->isAttribDeclaration();
4889: if (ad)
4890: {
4891: if (ad->decl && ad->decl->dim == 1)
4892: s = ad->decl->tdata()[0];
4893: }
4894:
4895: if (s->isVarDeclaration())
4896: { // Do semantic() on initializer first, so:
4897: // int a = a;
4898: // will be illegal.
4899: declaration->semantic(sc);
4900: s->parent = sc->parent;
4901: }
4902:
4903: //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc);
4904: // Insert into both local scope and function scope.
4905: // Must be unique in both.
4906: if (s->ident)
4907: {
4908: if (!sc->insert(s))
4909: error("declaration %s is already defined", s->toPrettyChars());
4910: else if (sc->func)
4911: { VarDeclaration *v = s->isVarDeclaration();
4912: if ( (s->isFuncDeclaration() || s->isTypedefDeclaration() ||
4913: s->isAggregateDeclaration() || s->isEnumDeclaration() ||
4914: s->isInterfaceDeclaration()) &&
4915: !sc->func->localsymtab->insert(s))
4916: {
4917: error("declaration %s is already defined in another scope in %s",
4918: s->toPrettyChars(), sc->func->toChars());
4919: }
4920: else if (!global.params.useDeprecated)
4921: { // Disallow shadowing
4922:
4923: for (Scope *scx = sc->enclosing; scx && scx->func == sc->func; scx = scx->enclosing)
4924: { Dsymbol *s2;
4925:
4926: if (scx->scopesym && scx->scopesym->symtab &&
4927: (s2 = scx->scopesym->symtab->lookup(s->ident)) != NULL &&
4928: s != s2)
4929: {
4930: error("shadowing declaration %s is deprecated", s->toPrettyChars());
4931: }
4932: }
4933: }
4934: }
4935: }
4936: if (!s->isVarDeclaration())
4937: {
4938: Scope *sc2 = sc;
4939: if (sc2->stc & (STCpure | STCnothrow))
4940: sc2 = sc->push();
4941: sc2->stc &= ~(STCpure | STCnothrow);
4942: declaration->semantic(sc2);
4943: if (sc2 != sc)
4944: sc2->pop();
4945: s->parent = sc->parent;
4946: }
4947: if (!global.errors)
4948: {
4949: declaration->semantic2(sc);
4950: if (!global.errors)
4951: {
4952: declaration->semantic3(sc);
4953:
4954: if (!global.errors && global.params.useInline)
4955: declaration->inlineScan();
4956: }
4957: }
4958:
4959: type = Type::tvoid;
4960: return this;
4961: }
4962:
4963: int DeclarationExp::checkSideEffect(int flag)
4964: {
4965: return 1;
4966: }
4967:
4968: #if DMDV2
4969: /**************************************
4970: * Does symbol, when initialized, throw?
4971: * Mirrors logic in Dsymbol_toElem().
4972: */
4973:
4974: int Dsymbol_canThrow(Dsymbol *s, bool mustNotThrow)
4975: {
4976: AttribDeclaration *ad;
4977: VarDeclaration *vd;
4978: TemplateMixin *tm;
4979: TupleDeclaration *td;
4980:
4981: //printf("Dsymbol_toElem() %s\n", s->toChars());
4982: ad = s->isAttribDeclaration();
4983: if (ad)
4984: {
4985: Dsymbols *decl = ad->include(NULL, NULL);
4986: if (decl && decl->dim)
4987: {
4988: for (size_t i = 0; i < decl->dim; i++)
4989: {
4990: s = decl->tdata()[i];
4991: if (Dsymbol_canThrow(s, mustNotThrow))
4992: return 1;
4993: }
4994: }
4995: }
4996: else if ((vd = s->isVarDeclaration()) != NULL)
4997: {
4998: s = s->toAlias();
4999: if (s != vd)
5000: return Dsymbol_canThrow(s, mustNotThrow);
5001: if (vd->storage_class & STCmanifest)
5002: ;
5003: else if (vd->isStatic() || vd->storage_class & (STCextern | STCtls | STCgshared))
5004: ;
5005: else
5006: {
5007: if (vd->init)
5008: { ExpInitializer *ie = vd->init->isExpInitializer();
5009: if (ie && ie->exp->canThrow(mustNotThrow))
5010: return 1;
5011: }
5012: if (vd->edtor && !vd->noscope)
5013: return vd->edtor->canThrow(mustNotThrow);
5014: }
5015: }
5016: else if ((tm = s->isTemplateMixin()) != NULL)
5017: {
5018: //printf("%s\n", tm->toChars());
5019: if (tm->members)
5020: {
5021: for (size_t i = 0; i < tm->members->dim; i++)
5022: {
5023: Dsymbol *sm = tm->members->tdata()[i];
5024: if (Dsymbol_canThrow(sm, mustNotThrow))
5025: return 1;
5026: }
5027: }
5028: }
5029: else if ((td = s->isTupleDeclaration()) != NULL)
5030: {
5031: for (size_t i = 0; i < td->objects->dim; i++)
5032: { Object *o = td->objects->tdata()[i];
5033: if (o->dyncast() == DYNCAST_EXPRESSION)
5034: { Expression *eo = (Expression *)o;
5035: if (eo->op == TOKdsymbol)
5036: { DsymbolExp *se = (DsymbolExp *)eo;
5037: if (Dsymbol_canThrow(se->s, mustNotThrow))
5038: return 1;
5039: }
5040: }
5041: }
5042: }
5043: return 0;
5044: }
5045:
5046:
5047: int DeclarationExp::canThrow(bool mustNotThrow)
5048: {
5049: return Dsymbol_canThrow(declaration, mustNotThrow);
5050: }
5051: #endif
5052:
5053: void DeclarationExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5054: {
5055: declaration->toCBuffer(buf, hgs);
5056: }
5057:
5058:
5059: /************************ TypeidExp ************************************/
5060:
5061: /*
5062: * typeid(int)
5063: */
5064:
5065: TypeidExp::TypeidExp(Loc loc, Object *o)
5066: : Expression(loc, TOKtypeid, sizeof(TypeidExp))
5067: {
5068: this->obj = o;
5069: }
5070:
5071:
5072: Expression *TypeidExp::syntaxCopy()
5073: {
5074: return new TypeidExp(loc, objectSyntaxCopy(obj));
5075: }
5076:
5077:
5078: Expression *TypeidExp::semantic(Scope *sc)
5079: { Expression *e;
5080:
5081: #if LOGSEMANTIC
5082: printf("TypeidExp::semantic() %s\n", toChars());
5083: #endif
5084: Type *ta = isType(obj);
5085: Expression *ea = isExpression(obj);
5086: Dsymbol *sa = isDsymbol(obj);
5087:
5088: //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5089:
5090: if (ta)
5091: {
5092: ta->resolve(loc, sc, &ea, &ta, &sa);
5093: }
5094:
5095: if (ea)
5096: {
5097: ea = ea->semantic(sc);
5098: ea = resolveProperties(sc, ea);
5099: ta = ea->type;
5100: if (ea->op == TOKtype)
5101: ea = NULL;
5102: }
5103:
5104: if (!ta)
5105: {
5106: //printf("ta %p ea %p sa %p\n", ta, ea, sa);
5107: error("no type for typeid(%s)", ea ? ea->toChars() : (sa ? sa->toChars() : ""));
5108: return new ErrorExp();
5109: }
5110:
5111: if (ea && ta->toBasetype()->ty == Tclass)
5112: { /* Get the dynamic type, which is .classinfo
5113: */
5114: e = new DotIdExp(ea->loc, ea, Id::classinfo);
5115: e = e->semantic(sc);
5116: }
5117: else
5118: { /* Get the static type
5119: */
5120: e = ta->getTypeInfo(sc);
5121: if (e->loc.linnum == 0)
5122: e->loc = loc; // so there's at least some line number info
5123: if (ea)
5124: {
5125: e = new CommaExp(loc, ea, e); // execute ea
5126: e = e->semantic(sc);
5127: }
5128: }
5129: return e;
5130: }
5131:
5132: void TypeidExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5133: {
5134: buf->writestring("typeid(");
5135: ObjectToCBuffer(buf, hgs, obj);
5136: buf->writeByte(')');
5137: }
5138:
5139: /************************ TraitsExp ************************************/
5140: #if DMDV2
5141: /*
5142: * __traits(identifier, args...)
5143: */
5144:
5145: TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args)
5146: : Expression(loc, TOKtraits, sizeof(TraitsExp))
5147: {
5148: this->ident = ident;
5149: this->args = args;
5150: }
5151:
5152:
5153: Expression *TraitsExp::syntaxCopy()
5154: {
5155: return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args));
5156: }
5157:
5158:
5159: void TraitsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5160: {
5161: buf->writestring("__traits(");
5162: buf->writestring(ident->toChars());
5163: if (args)
5164: {
5165: for (int i = 0; i < args->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5166: {
5167: buf->writeByte(',');
5168: Object *oarg = args->tdata()[i];
5169: ObjectToCBuffer(buf, hgs, oarg);
5170: }
5171: }
5172: buf->writeByte(')');
5173: }
5174: #endif
5175:
5176: /************************************************************/
5177:
5178: HaltExp::HaltExp(Loc loc)
5179: : Expression(loc, TOKhalt, sizeof(HaltExp))
5180: {
5181: }
5182:
5183: Expression *HaltExp::semantic(Scope *sc)
5184: {
5185: #if LOGSEMANTIC
5186: printf("HaltExp::semantic()\n");
5187: #endif
5188: type = Type::tvoid;
5189: return this;
5190: }
5191:
5192: int HaltExp::checkSideEffect(int flag)
5193: {
5194: return 1;
5195: }
5196:
5197: void HaltExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5198: {
5199: buf->writestring("halt");
5200: }
5201:
5202: /************************************************************/
5203:
5204: IsExp::IsExp(Loc loc, Type *targ, Identifier *id, enum TOK tok,
5205: Type *tspec, enum TOK tok2, TemplateParameters *parameters)
5206: : Expression(loc, TOKis, sizeof(IsExp))
5207: {
5208: this->targ = targ;
5209: this->id = id;
5210: this->tok = tok;
5211: this->tspec = tspec;
5212: this->tok2 = tok2;
5213: this->parameters = parameters;
5214: }
5215:
5216: Expression *IsExp::syntaxCopy()
5217: {
5218: // This section is identical to that in TemplateDeclaration::syntaxCopy()
5219: TemplateParameters *p = NULL;
5220: if (parameters)
5221: {
5222: p = new TemplateParameters();
5223: p->setDim(parameters->dim);
5224: for (int i = 0; i < p->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5225: { TemplateParameter *tp = parameters->tdata()[i];
5226: p->tdata()[i] = tp->syntaxCopy();
5227: }
5228: }
5229:
5230: return new IsExp(loc,
5231: targ->syntaxCopy(),
5232: id,
5233: tok,
5234: tspec ? tspec->syntaxCopy() : NULL,
5235: tok2,
5236: p);
5237: }
5238:
5239: Expression *IsExp::semantic(Scope *sc)
5240: { Type *tded;
5241:
5242: /* is(targ id tok tspec)
5243: * is(targ id : tok2)
5244: * is(targ id == tok2)
5245: */
5246:
5247: //printf("IsExp::semantic(%s)\n", toChars());
5248: if (id && !(sc->flags & (SCOPEstaticif | SCOPEstaticassert)))
5249: { error("can only declare type aliases within static if conditionals or static asserts");
5250: return new ErrorExp();
5251: }
5252:
5253: Type *t = targ->trySemantic(loc, sc);
5254: if (!t)
5255: goto Lno; // errors, so condition is false
5256: targ = t;
5257: if (tok2 != TOKreserved)
5258: {
5259: switch (tok2)
5260: {
5261: case TOKtypedef:
5262: if (targ->ty != Ttypedef)
5263: goto Lno;
5264: tded = ((TypeTypedef *)targ)->sym->basetype;
5265: break;
5266:
5267: case TOKstruct:
5268: if (targ->ty != Tstruct)
5269: goto Lno;
5270: if (((TypeStruct *)targ)->sym->isUnionDeclaration())
5271: goto Lno;
5272: tded = targ;
5273: break;
5274:
5275: case TOKunion:
5276: if (targ->ty != Tstruct)
5277: goto Lno;
5278: if (!((TypeStruct *)targ)->sym->isUnionDeclaration())
5279: goto Lno;
5280: tded = targ;
5281: break;
5282:
5283: case TOKclass:
5284: if (targ->ty != Tclass)
5285: goto Lno;
5286: if (((TypeClass *)targ)->sym->isInterfaceDeclaration())
5287: goto Lno;
5288: tded = targ;
5289: break;
5290:
5291: case TOKinterface:
5292: if (targ->ty != Tclass)
5293: goto Lno;
5294: if (!((TypeClass *)targ)->sym->isInterfaceDeclaration())
5295: goto Lno;
5296: tded = targ;
5297: break;
5298: #if DMDV2
5299: case TOKconst:
5300: if (!targ->isConst())
5301: goto Lno;
5302: tded = targ;
5303: break;
5304:
5305: case TOKinvariant:
5306: if (!global.params.useDeprecated)
5307: error("use of 'invariant' rather than 'immutable' is deprecated");
5308: case TOKimmutable:
5309: if (!targ->isImmutable())
5310: goto Lno;
5311: tded = targ;
5312: break;
5313:
5314: case TOKshared:
5315: if (!targ->isShared())
5316: goto Lno;
5317: tded = targ;
5318: break;
5319:
5320: case TOKwild:
5321: if (!targ->isWild())
5322: goto Lno;
5323: tded = targ;
5324: break;
5325: #endif
5326:
5327: case TOKsuper:
5328: // If class or interface, get the base class and interfaces
5329: if (targ->ty != Tclass)
5330: goto Lno;
5331: else
5332: { ClassDeclaration *cd = ((TypeClass *)targ)->sym;
5333: Parameters *args = new Parameters;
5334: args->reserve(cd->baseclasses->dim);
5335: for (size_t i = 0; i < cd->baseclasses->dim; i++)
5336: { BaseClass *b = cd->baseclasses->tdata()[i];
5337: args->push(new Parameter(STCin, b->type, NULL, NULL));
5338: }
5339: tded = new TypeTuple(args);
5340: }
5341: break;
5342:
5343: case TOKenum:
5344: if (targ->ty != Tenum)
5345: goto Lno;
5346: tded = ((TypeEnum *)targ)->sym->memtype;
5347: break;
5348:
5349: case TOKdelegate:
5350: if (targ->ty != Tdelegate)
5351: goto Lno;
5352: tded = ((TypeDelegate *)targ)->next; // the underlying function type
5353: break;
5354:
5355: case TOKfunction:
5356: {
5357: if (targ->ty != Tfunction)
5358: goto Lno;
5359: tded = targ;
5360:
5361: /* Generate tuple from function parameter types.
5362: */
5363: assert(tded->ty == Tfunction);
5364: Parameters *params = ((TypeFunction *)tded)->parameters;
5365: size_t dim = Parameter::dim(params);
5366: Parameters *args = new Parameters;
5367: args->reserve(dim);
5368: for (size_t i = 0; i < dim; i++)
5369: { Parameter *arg = Parameter::getNth(params, i);
5370: assert(arg && arg->type);
5371: args->push(new Parameter(arg->storageClass, arg->type, NULL, NULL));
5372: }
5373: tded = new TypeTuple(args);
5374: break;
5375: }
5376: case TOKreturn:
5377: /* Get the 'return type' for the function,
5378: * delegate, or pointer to function.
5379: */
5380: if (targ->ty == Tfunction)
5381: tded = ((TypeFunction *)targ)->next;
5382: else if (targ->ty == Tdelegate)
5383: { tded = ((TypeDelegate *)targ)->next;
5384: tded = ((TypeFunction *)tded)->next;
5385: }
5386: else if (targ->ty == Tpointer &&
5387: ((TypePointer *)targ)->next->ty == Tfunction)
5388: { tded = ((TypePointer *)targ)->next;
5389: tded = ((TypeFunction *)tded)->next;
5390: }
5391: else
5392: goto Lno;
5393: break;
5394:
5395: case TOKargTypes:
5396: /* Generate a type tuple of the equivalent types used to determine if a
5397: * function argument of this type can be passed in registers.
5398: * The results of this are highly platform dependent, and intended
5399: * primarly for use in implementing va_arg().
5400: */
5401: tded = targ->toArgTypes();
5402: if (!tded)
5403: goto Lno; // not valid for a parameter
5404: break;
5405:
5406: default:
5407: assert(0);
5408: }
5409: goto Lyes;
5410: }
5411: else if (id && tspec)
5412: {
5413: /* Evaluate to TRUE if targ matches tspec.
5414: * If TRUE, declare id as an alias for the specialized type.
5415: */
5416:
5417: assert(parameters && parameters->dim);
5418:
5419: Objects dedtypes;
5420: dedtypes.setDim(parameters->dim);
5421: dedtypes.zero();
5422:
5423: MATCH m = targ->deduceType(sc, tspec, parameters, &dedtypes);
5424: //printf("targ: %s\n", targ->toChars());
5425: //printf("tspec: %s\n", tspec->toChars());
5426: if (m == MATCHnomatch ||
5427: (m != MATCHexact && tok == TOKequal))
5428: {
5429: goto Lno;
5430: }
5431: else
5432: {
5433: tded = (Type *)dedtypes.tdata()[0];
5434: if (!tded)
5435: tded = targ;
5436: #if DMDV2
5437: Objects tiargs;
5438: tiargs.setDim(1);
5439: tiargs.tdata()[0] = targ;
5440:
5441: /* Declare trailing parameters
5442: */
5443: for (int i = 1; i < parameters->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5444: { TemplateParameter *tp = parameters->tdata()[i];
5445: Declaration *s = NULL;
5446:
5447: m = tp->matchArg(sc, &tiargs, i, parameters, &dedtypes, &s);
5448: if (m == MATCHnomatch)
5449: goto Lno;
5450: s->semantic(sc);
5451: #if 0
5452: Type *o = dedtypes.tdata()[i];
5453: Dsymbol *s = TemplateDeclaration::declareParameter(loc, sc, tp, o);
5454: #endif
5455: if (sc->sd)
5456: s->addMember(sc, sc->sd, 1);
5457: else if (!sc->insert(s))
5458: error("declaration %s is already defined", s->toChars());
5459: }
5460: #endif
5461: goto Lyes;
5462: }
5463: }
5464: else if (id)
5465: {
5466: /* Declare id as an alias for type targ. Evaluate to TRUE
5467: */
5468: tded = targ;
5469: goto Lyes;
5470: }
5471: else if (tspec)
5472: {
5473: /* Evaluate to TRUE if targ matches tspec
5474: * is(targ == tspec)
5475: * is(targ : tspec)
5476: */
5477: tspec = tspec->semantic(loc, sc);
5478: //printf("targ = %s, %s\n", targ->toChars(), targ->deco);
5479: //printf("tspec = %s, %s\n", tspec->toChars(), tspec->deco);
5480: if (tok == TOKcolon)
5481: { if (targ->implicitConvTo(tspec))
5482: goto Lyes;
5483: else
5484: goto Lno;
5485: }
5486: else /* == */
5487: { if (targ->equals(tspec))
5488: goto Lyes;
5489: else
5490: goto Lno;
5491: }
5492: }
5493:
5494: Lyes:
5495: if (id)
5496: {
5497: Dsymbol *s = new AliasDeclaration(loc, id, tded);
5498: s->semantic(sc);
5499: if (!sc->insert(s))
5500: error("declaration %s is already defined", s->toChars());
5501: if (sc->sd)
5502: s->addMember(sc, sc->sd, 1);
5503: }
5504: //printf("Lyes\n");
5505: return new IntegerExp(loc, 1, Type::tbool);
5506:
5507: Lno:
5508: //printf("Lno\n");
5509: return new IntegerExp(loc, 0, Type::tbool);
5510:
5511: Lerr:
warning C4102: 'Lerr' : unreferenced label
5512: return new ErrorExp();
5513: }
5514:
5515: void IsExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5516: {
5517: buf->writestring("is(");
5518: targ->toCBuffer(buf, id, hgs);
5519: if (tok2 != TOKreserved)
5520: {
5521: buf->printf(" %s %s", Token::toChars(tok), Token::toChars(tok2));
5522: }
5523: else if (tspec)
5524: {
5525: if (tok == TOKcolon)
5526: buf->writestring(" : ");
5527: else
5528: buf->writestring(" == ");
5529: tspec->toCBuffer(buf, NULL, hgs);
5530: }
5531: #if DMDV2
5532: if (parameters)
5533: { // First parameter is already output, so start with second
5534: for (int i = 1; i < parameters->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
5535: {
5536: buf->writeByte(',');
5537: TemplateParameter *tp = parameters->tdata()[i];
5538: tp->toCBuffer(buf, hgs);
5539: }
5540: }
5541: #endif
5542: buf->writeByte(')');
5543: }
5544:
5545:
5546: /************************************************************/
5547:
5548: UnaExp::UnaExp(Loc loc, enum TOK op, int size, Expression *e1)
5549: : Expression(loc, op, size)
5550: {
5551: this->e1 = e1;
5552: }
5553:
5554: Expression *UnaExp::syntaxCopy()
5555: {
5556: UnaExp *e = (UnaExp *)copy();
5557: e->type = NULL;
5558: e->e1 = e->e1->syntaxCopy();
5559: return e;
5560: }
5561:
5562: Expression *UnaExp::semantic(Scope *sc)
5563: {
5564: #if LOGSEMANTIC
5565: printf("UnaExp::semantic('%s')\n", toChars());
5566: #endif
5567: e1 = e1->semantic(sc);
5568: // if (!e1->type)
5569: // error("%s has no value", e1->toChars());
5570: return this;
5571: }
5572:
5573: #if DMDV2
5574: int UnaExp::canThrow(bool mustNotThrow)
5575: {
5576: return e1->canThrow(mustNotThrow);
5577: }
5578: #endif
5579:
5580: Expression *UnaExp::resolveLoc(Loc loc, Scope *sc)
5581: {
5582: e1 = e1->resolveLoc(loc, sc);
5583: return this;
5584: }
5585:
5586: void UnaExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5587: {
5588: buf->writestring(Token::toChars(op));
5589: expToCBuffer(buf, hgs, e1, precedence[op]);
5590: }
5591:
5592: /************************************************************/
5593:
5594: BinExp::BinExp(Loc loc, enum TOK op, int size, Expression *e1, Expression *e2)
5595: : Expression(loc, op, size)
5596: {
5597: this->e1 = e1;
5598: this->e2 = e2;
5599: }
5600:
5601: Expression *BinExp::syntaxCopy()
5602: {
5603: BinExp *e = (BinExp *)copy();
5604: e->type = NULL;
5605: e->e1 = e->e1->syntaxCopy();
5606: e->e2 = e->e2->syntaxCopy();
5607: return e;
5608: }
5609:
5610: Expression *BinExp::semantic(Scope *sc)
5611: {
5612: #if LOGSEMANTIC
5613: printf("BinExp::semantic('%s')\n", toChars());
5614: #endif
5615: e1 = e1->semantic(sc);
5616: if (!e1->type &&
5617: !(op == TOKassign && e1->op == TOKdottd)) // a.template = e2
5618: {
5619: error("%s has no value", e1->toChars());
5620: return new ErrorExp();
5621: }
5622: e2 = e2->semantic(sc);
5623: if (!e2->type)
5624: {
5625: error("%s has no value", e2->toChars());
5626: return new ErrorExp();
5627: }
5628: if (e1->op == TOKerror || e2->op == TOKerror)
5629: return new ErrorExp();
5630: return this;
5631: }
5632:
5633: Expression *BinExp::semanticp(Scope *sc)
5634: {
5635: BinExp::semantic(sc);
5636: e1 = resolveProperties(sc, e1);
5637: e2 = resolveProperties(sc, e2);
5638: return this;
5639: }
5640:
5641: int BinExp::checkSideEffect(int flag)
5642: {
5643: if (op == TOKplusplus ||
5644: op == TOKminusminus ||
5645: op == TOKassign ||
5646: op == TOKconstruct ||
5647: op == TOKblit ||
5648: op == TOKaddass ||
5649: op == TOKminass ||
5650: op == TOKcatass ||
5651: op == TOKmulass ||
5652: op == TOKdivass ||
5653: op == TOKmodass ||
5654: op == TOKshlass ||
5655: op == TOKshrass ||
5656: op == TOKushrass ||
5657: op == TOKandass ||
5658: op == TOKorass ||
5659: op == TOKxorass ||
5660: op == TOKpowass ||
5661: op == TOKin ||
5662: op == TOKremove)
5663: return 1;
5664: return Expression::checkSideEffect(flag);
5665: }
5666:
5667: // generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary
5668: void BinExp::checkComplexMulAssign()
5669: {
5670: // Any multiplication by an imaginary or complex number yields a complex result.
5671: // r *= c, i*=c, r*=i, i*=i are all forbidden operations.
5672: const char *opstr = Token::toChars(op);
5673: if ( e1->type->isreal() && e2->type->iscomplex())
5674: {
5675: error("%s %s %s is undefined. Did you mean %s %s %s.re ?",
5676: e1->type->toChars(), opstr, e2->type->toChars(),
5677: e1->type->toChars(), opstr, e2->type->toChars());
5678: }
5679: else if (e1->type->isimaginary() && e2->type->iscomplex())
5680: {
5681: error("%s %s %s is undefined. Did you mean %s %s %s.im ?",
5682: e1->type->toChars(), opstr, e2->type->toChars(),
5683: e1->type->toChars(), opstr, e2->type->toChars());
5684: }
5685: else if ((e1->type->isreal() || e1->type->isimaginary()) &&
5686: e2->type->isimaginary())
5687: {
5688: error("%s %s %s is an undefined operation", e1->type->toChars(),
5689: opstr, e2->type->toChars());
5690: }
5691: }
5692:
5693: // generate an error if this is a nonsensical += or -=, eg real += imaginary
5694: void BinExp::checkComplexAddAssign()
5695: {
5696: // Addition or subtraction of a real and an imaginary is a complex result.
5697: // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
5698: if ( (e1->type->isreal() && (e2->type->isimaginary() || e2->type->iscomplex())) ||
5699: (e1->type->isimaginary() && (e2->type->isreal() || e2->type->iscomplex()))
5700: )
5701: {
5702: error("%s %s %s is undefined (result is complex)",
5703: e1->type->toChars(), Token::toChars(op), e2->type->toChars());
5704: }
5705: }
5706:
5707: void BinExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5708: {
5709: expToCBuffer(buf, hgs, e1, precedence[op]);
5710: buf->writeByte(' ');
5711: buf->writestring(Token::toChars(op));
5712: buf->writeByte(' ');
5713: expToCBuffer(buf, hgs, e2, (enum PREC)(precedence[op] + 1));
5714: }
5715:
5716: int BinExp::isunsigned()
5717: {
5718: return e1->type->isunsigned() || e2->type->isunsigned();
5719: }
5720:
5721: #if DMDV2
5722: int BinExp::canThrow(bool mustNotThrow)
5723: {
5724: return e1->canThrow(mustNotThrow) || e2->canThrow(mustNotThrow);
5725: }
5726: #endif
5727:
5728: void BinExp::incompatibleTypes()
5729: {
5730: if (e1->type->toBasetype() != Type::terror &&
5731: e2->type->toBasetype() != Type::terror
5732: )
5733: error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
5734: e1->toChars(), Token::toChars(op), e2->toChars(),
5735: e1->type->toChars(), e2->type->toChars());
5736: }
5737:
5738: /********************** BinAssignExp **************************************/
5739:
5740: /***************************
5741: * Common semantic routine for some xxxAssignExp's.
5742: */
5743:
5744: Expression *BinAssignExp::commonSemanticAssign(Scope *sc)
5745: { Expression *e;
5746:
5747: if (!type)
5748: {
5749: if (e1->op == TOKarraylength)
5750: {
5751: e = ArrayLengthExp::rewriteOpAssign(this);
5752: e = e->semantic(sc);
5753: return e;
5754: }
5755:
5756: if (e1->op == TOKslice)
5757: { // T[] op= ...
5758: e = typeCombine(sc);
5759: if (e->op == TOKerror)
5760: return e;
5761: type = e1->type;
5762: return arrayOp(sc);
5763: }
5764:
5765: e1 = e1->modifiableLvalue(sc, e1);
5766: e1->checkScalar();
5767: type = e1->type;
5768: if (type->toBasetype()->ty == Tbool)
5769: {
5770: error("operator not allowed on bool expression %s", toChars());
5771: return new ErrorExp();
5772: }
5773: typeCombine(sc);
5774: e1->checkArithmetic();
5775: e2->checkArithmetic();
5776:
5777: if (op == TOKmodass && e2->type->iscomplex())
5778: { error("cannot perform modulo complex arithmetic");
5779: return new ErrorExp();
5780: }
5781: }
5782: return this;
5783: }
5784:
5785: Expression *BinAssignExp::commonSemanticAssignIntegral(Scope *sc)
5786: { Expression *e;
5787:
5788: if (!type)
5789: {
5790: e = op_overload(sc);
5791: if (e)
5792: return e;
5793:
5794: if (e1->op == TOKarraylength)
5795: {
5796: e = ArrayLengthExp::rewriteOpAssign(this);
5797: e = e->semantic(sc);
5798: return e;
5799: }
5800:
5801: if (e1->op == TOKslice)
5802: { // T[] op= ...
5803: e = typeCombine(sc);
5804: if (e->op == TOKerror)
5805: return e;
5806: type = e1->type;
5807: return arrayOp(sc);
5808: }
5809:
5810: e1 = e1->modifiableLvalue(sc, e1);
5811: e1->checkScalar();
5812: type = e1->type;
5813: if (type->toBasetype()->ty == Tbool)
5814: {
5815: e2 = e2->implicitCastTo(sc, type);
5816: }
5817:
5818: typeCombine(sc);
5819: e1->checkIntegral();
5820: e2->checkIntegral();
5821: }
5822: return this;
5823: }
5824:
5825: #if DMDV2
5826: int BinAssignExp::isLvalue()
5827: {
5828: return 1;
5829: }
5830:
5831: Expression *BinAssignExp::toLvalue(Scope *sc, Expression *ex)
5832: { Expression *e;
5833:
5834: if (e1->op == TOKvar)
5835: {
5836: /* Convert (e1 op= e2) to
5837: * e1 op= e2;
5838: * e1
5839: */
5840: e = e1->copy();
5841: e = new CommaExp(loc, this, e);
5842: e = e->semantic(sc);
5843: }
5844: else
5845: {
5846: /* Convert (e1 op= e2) to
5847: * ref v = e1;
5848: * v op= e2;
5849: * v
5850: */
5851:
5852: // ref v = e1;
5853: Identifier *id = Lexer::uniqueId("__assignop");
5854: ExpInitializer *ei = new ExpInitializer(loc, e1);
5855: VarDeclaration *v = new VarDeclaration(loc, e1->type, id, ei);
5856: v->storage_class |= STCref | STCforeach;
5857: Expression *de = new DeclarationExp(loc, v);
warning C6211: Leaking memory 'de' due to an exception. Consider using a local catch block to clean up memory: Lines: 5832, 5834, 5853, 5854, 5855, 5856, 5857, 5860
5858:
5859: // v op= e2
5860: e1 = new VarExp(e1->loc, v);
5861:
5862: e = new CommaExp(loc, de, this);
5863: e = new CommaExp(loc, e, new VarExp(loc, v));
5864: e = e->semantic(sc);
5865: }
5866: return e;
5867: }
5868:
5869: Expression *BinAssignExp::modifiableLvalue(Scope *sc, Expression *e)
5870: {
5871: return toLvalue(sc, this);
5872: }
5873:
5874: #endif
5875:
5876: /************************************************************/
5877:
5878: CompileExp::CompileExp(Loc loc, Expression *e)
5879: : UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
5880: {
5881: }
5882:
5883: Expression *CompileExp::semantic(Scope *sc)
5884: {
5885: #if LOGSEMANTIC
5886: printf("CompileExp::semantic('%s')\n", toChars());
5887: #endif
5888: UnaExp::semantic(sc);
5889: e1 = resolveProperties(sc, e1);
5890: if (e1->op == TOKerror)
5891: return e1;
5892: if (!e1->type->isString())
5893: {
5894: error("argument to mixin must be a string type, not %s\n", e1->type->toChars());
5895: return new ErrorExp();
5896: }
5897: e1 = e1->optimize(WANTvalue | WANTinterpret);
5898: if (e1->op != TOKstring)
5899: { error("argument to mixin must be a string, not (%s)", e1->toChars());
5900: return new ErrorExp();
5901: }
5902: StringExp *se = (StringExp *)e1;
5903: se = se->toUTF8(sc);
5904: Parser p(sc->module, (unsigned char *)se->string, se->len, 0);
5905: p.loc = loc;
5906: p.nextToken();
5907: //printf("p.loc.linnum = %d\n", p.loc.linnum);
5908: Expression *e = p.parseExpression();
5909: if (p.token.value != TOKeof)
5910: { error("incomplete mixin expression (%s)", se->toChars());
5911: return new ErrorExp();
5912: }
5913: return e->semantic(sc);
5914: }
5915:
5916: void CompileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5917: {
5918: buf->writestring("mixin(");
5919: expToCBuffer(buf, hgs, e1, PREC_assign);
5920: buf->writeByte(')');
5921: }
5922:
5923: /************************************************************/
5924:
5925: FileExp::FileExp(Loc loc, Expression *e)
5926: : UnaExp(loc, TOKmixin, sizeof(FileExp), e)
5927: {
5928: }
5929:
5930: Expression *FileExp::semantic(Scope *sc)
5931: { char *name;
5932: StringExp *se;
5933:
5934: #if LOGSEMANTIC
5935: printf("FileExp::semantic('%s')\n", toChars());
5936: #endif
5937: UnaExp::semantic(sc);
5938: e1 = resolveProperties(sc, e1);
5939: e1 = e1->optimize(WANTvalue | WANTinterpret);
5940: if (e1->op != TOKstring)
5941: { error("file name argument must be a string, not (%s)", e1->toChars());
5942: goto Lerror;
5943: }
5944: se = (StringExp *)e1;
5945: se = se->toUTF8(sc);
5946: name = (char *)se->string;
5947:
5948: if (!global.params.fileImppath)
5949: { error("need -Jpath switch to import text file %s", name);
5950: goto Lerror;
5951: }
5952:
5953: /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory
5954: * ('Path Traversal') attacks.
5955: * http://cwe.mitre.org/data/definitions/22.html
5956: */
5957:
5958: name = FileName::safeSearchPath(global.filePath, name);
5959: if (!name)
5960: { error("file %s cannot be found or not in a path specified with -J", se->toChars());
5961: goto Lerror;
5962: }
5963:
5964: if (global.params.verbose)
5965: printf("file %s\t(%s)\n", (char *)se->string, name);
5966:
5967: { File f(name);
5968: if (f.read())
5969: { error("cannot read file %s", f.toChars());
5970: goto Lerror;
5971: }
5972: else
5973: {
5974: f.ref = 1;
5975: se = new StringExp(loc, f.buffer, f.len);
5976: }
5977: }
5978: Lret:
warning C4102: 'Lret' : unreferenced label
5979: return se->semantic(sc);
5980:
5981: Lerror:
5982: return new ErrorExp();
5983: }
5984:
5985: void FileExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
5986: {
5987: buf->writestring("import(");
5988: expToCBuffer(buf, hgs, e1, PREC_assign);
5989: buf->writeByte(')');
5990: }
5991:
5992: /************************************************************/
5993:
5994: AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg)
5995: : UnaExp(loc, TOKassert, sizeof(AssertExp), e)
5996: {
5997: this->msg = msg;
5998: }
5999:
6000: Expression *AssertExp::syntaxCopy()
6001: {
6002: AssertExp *ae = new AssertExp(loc, e1->syntaxCopy(),
6003: msg ? msg->syntaxCopy() : NULL);
6004: return ae;
6005: }
6006:
6007: Expression *AssertExp::semantic(Scope *sc)
6008: {
6009: #if LOGSEMANTIC
6010: printf("AssertExp::semantic('%s')\n", toChars());
6011: #endif
6012: UnaExp::semantic(sc);
6013: e1 = resolveProperties(sc, e1);
6014: // BUG: see if we can do compile time elimination of the Assert
6015: e1 = e1->optimize(WANTvalue);
6016: e1 = e1->checkToBoolean(sc);
6017: if (msg)
6018: {
6019: msg = msg->semantic(sc);
6020: msg = resolveProperties(sc, msg);
6021: msg = msg->implicitCastTo(sc, Type::tchar->constOf()->arrayOf());
6022: msg = msg->optimize(WANTvalue);
6023: }
6024: if (e1->isBool(FALSE))
6025: {
6026: FuncDeclaration *fd = sc->parent->isFuncDeclaration();
6027: if (fd)
6028: fd->hasReturnExp |= 4;
6029:
6030: if (!global.params.useAssert)
6031: { Expression *e = new HaltExp(loc);
6032: e = e->semantic(sc);
6033: return e;
6034: }
6035: }
6036: type = Type::tvoid;
6037: return this;
6038: }
6039:
6040: int AssertExp::checkSideEffect(int flag)
6041: {
6042: return 1;
6043: }
6044:
6045: #if DMDV2
6046: int AssertExp::canThrow(bool mustNotThrow)
6047: {
6048: /* assert()s are non-recoverable errors, so functions that
6049: * use them can be considered "nothrow"
6050: */
6051: return 0; //(global.params.useAssert != 0);
6052: }
6053: #endif
6054:
6055: void AssertExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6056: {
6057: buf->writestring("assert(");
6058: expToCBuffer(buf, hgs, e1, PREC_assign);
6059: if (msg)
6060: {
6061: buf->writeByte(',');
6062: expToCBuffer(buf, hgs, msg, PREC_assign);
6063: }
6064: buf->writeByte(')');
6065: }
6066:
6067: /************************************************************/
6068:
6069: DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident)
6070: : UnaExp(loc, TOKdot, sizeof(DotIdExp), e)
6071: {
6072: this->ident = ident;
6073: }
6074:
6075: Expression *DotIdExp::semantic(Scope *sc)
6076: {
6077: // Indicate we didn't come from CallExp::semantic()
6078: return semantic(sc, 0);
6079: }
6080:
6081: Expression *DotIdExp::semantic(Scope *sc, int flag)
6082: { Expression *e;
6083: Expression *eleft;
6084: Expression *eright;
6085:
6086: #if LOGSEMANTIC
6087: printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars());
6088: //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
6089: #endif
6090:
6091: //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
6092:
6093: #if 0
6094: /* Don't do semantic analysis if we'll be converting
6095: * it to a string.
6096: */
6097: if (ident == Id::stringof)
6098: { char *s = e1->toChars();
6099: e = new StringExp(loc, s, strlen(s), 'c');
6100: e = e->semantic(sc);
6101: return e;
6102: }
6103: #endif
6104:
6105: /* Special case: rewrite this.id and super.id
6106: * to be classtype.id and baseclasstype.id
6107: * if we have no this pointer.
6108: */
6109: if ((e1->op == TOKthis || e1->op == TOKsuper) && !hasThis(sc))
6110: { ClassDeclaration *cd;
6111: StructDeclaration *sd;
6112: AggregateDeclaration *ad;
6113:
6114: ad = sc->getStructClassScope();
6115: if (ad)
6116: {
6117: cd = ad->isClassDeclaration();
6118: if (cd)
6119: {
6120: if (e1->op == TOKthis)
6121: {
6122: e = typeDotIdExp(loc, cd->type, ident);
6123: return e->semantic(sc);
6124: }
6125: else if (cd->baseClass && e1->op == TOKsuper)
6126: {
6127: e = typeDotIdExp(loc, cd->baseClass->type, ident);
6128: return e->semantic(sc);
6129: }
6130: }
6131: else
6132: {
6133: sd = ad->isStructDeclaration();
6134: if (sd)
6135: {
6136: if (e1->op == TOKthis)
6137: {
6138: e = typeDotIdExp(loc, sd->type, ident);
6139: return e->semantic(sc);
6140: }
6141: }
6142: }
6143: }
6144: }
6145:
6146: UnaExp::semantic(sc);
6147:
6148: if (e1->op == TOKdotexp)
6149: {
6150: DotExp *de = (DotExp *)e1;
6151: eleft = de->e1;
6152: eright = de->e2;
6153: }
6154: else
6155: {
6156: if (e1->op != TOKtype)
6157: e1 = resolveProperties(sc, e1);
6158: eleft = NULL;
6159: eright = e1;
6160: }
6161: #if DMDV2
6162: if (e1->op == TOKtuple && ident == Id::offsetof)
6163: { /* 'distribute' the .offsetof to each of the tuple elements.
6164: */
6165: TupleExp *te = (TupleExp *)e1;
6166: Expressions *exps = new Expressions();
6167: exps->setDim(te->exps->dim);
6168: for (int i = 0; i < exps->dim; i++)
warning C4018: '<' : signed/unsigned mismatch
6169: { Expression *e = (*te->exps)[i];
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6082' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6082
6170: e = e->semantic(sc);
6171: e = new DotIdExp(e->loc, e, Id::offsetof);
6172: (*exps)[i] = e;
6173: }
6174: e = new TupleExp(loc, exps);
6175: e = e->semantic(sc);
6176: return e;
6177: }
6178: #endif
6179:
6180: if (e1->op == TOKtuple && ident == Id::length)
6181: {
6182: TupleExp *te = (TupleExp *)e1;
6183: e = new IntegerExp(loc, te->exps->dim, Type::tsize_t);
6184: return e;
6185: }
6186:
6187: if (e1->op == TOKdottd)
6188: {
6189: error("template %s does not have property %s", e1->toChars(), ident->toChars());
6190: return new ErrorExp();
6191: }
6192:
6193: if (!e1->type)
6194: {
6195: error("expression %s does not have property %s", e1->toChars(), ident->toChars());
6196: return new ErrorExp();
6197: }
6198:
6199: Type *t1b = e1->type->toBasetype();
6200:
6201: if (eright->op == TOKimport) // also used for template alias's
6202: {
6203: ScopeExp *ie = (ScopeExp *)eright;
6204:
6205: /* Disable access to another module's private imports.
6206: * The check for 'is sds our current module' is because
6207: * the current module should have access to its own imports.
6208: */
6209: Dsymbol *s = ie->sds->search(loc, ident,
6210: (ie->sds->isModule() && ie->sds != sc->module) ? 1 : 0);
6211: if (s)
6212: {
6213: s = s->toAlias();
6214: checkDeprecated(sc, s);
6215:
6216: EnumMember *em = s->isEnumMember();
6217: if (em)
6218: {
6219: e = em->value;
6220: e = e->semantic(sc);
6221: return e;
6222: }
6223:
6224: VarDeclaration *v = s->isVarDeclaration();
6225: if (v)
6226: {
6227: //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
6228: if (v->inuse)
6229: {
6230: error("circular reference to '%s'", v->toChars());
6231: return new ErrorExp();
6232: }
6233: type = v->type;
6234: if (v->needThis())
6235: {
6236: if (!eleft)
6237: eleft = new ThisExp(loc);
6238: e = new DotVarExp(loc, eleft, v);
6239: e = e->semantic(sc);
6240: }
6241: else
6242: {
6243: e = new VarExp(loc, v);
6244: if (eleft)
6245: { e = new CommaExp(loc, eleft, e);
6246: e->type = v->type;
6247: }
6248: }
6249: e = e->deref();
6250: return e->semantic(sc);
6251: }
6252:
6253: FuncDeclaration *f = s->isFuncDeclaration();
6254: if (f)
6255: {
6256: //printf("it's a function\n");
6257: if (f->needThis())
6258: {
6259: if (!eleft)
6260: eleft = new ThisExp(loc);
6261: e = new DotVarExp(loc, eleft, f);
6262: e = e->semantic(sc);
6263: }
6264: else
6265: {
6266: e = new VarExp(loc, f, 1);
6267: if (eleft)
6268: { e = new CommaExp(loc, eleft, e);
6269: e->type = f->type;
6270: }
6271: }
6272: return e;
6273: }
6274: #if DMDV2
6275: OverloadSet *o = s->isOverloadSet();
6276: if (o)
6277: { //printf("'%s' is an overload set\n", o->toChars());
6278: return new OverExp(o);
6279: }
6280: #endif
6281:
6282: Type *t = s->getType();
6283: if (t)
6284: {
6285: return new TypeExp(loc, t);
6286: }
6287:
6288: TupleDeclaration *tup = s->isTupleDeclaration();
6289: if (tup)
6290: {
6291: if (eleft)
6292: { error("cannot have e.tuple");
6293: return new ErrorExp();
6294: }
6295: e = new TupleExp(loc, tup);
6296: e = e->semantic(sc);
6297: return e;
6298: }
6299:
6300: ScopeDsymbol *sds = s->isScopeDsymbol();
6301: if (sds)
6302: {
6303: //printf("it's a ScopeDsymbol\n");
6304: e = new ScopeExp(loc, sds);
6305: e = e->semantic(sc);
6306: if (eleft)
6307: e = new DotExp(loc, eleft, e);
6308: return e;
6309: }
6310:
6311: Import *imp = s->isImport();
6312: if (imp)
6313: {
6314: ScopeExp *ie;
warning C6246: Local declaration of 'ie' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6203' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6203
6315:
6316: ie = new ScopeExp(loc, imp->pkg);
6317: return ie->semantic(sc);
6318: }
6319:
6320: // BUG: handle other cases like in IdentifierExp::semantic()
6321: #ifdef DEBUG
6322: printf("s = '%s', kind = '%s'\n", s->toChars(), s->kind());
6323: #endif
6324: assert(0);
6325: }
6326: else if (ident == Id::stringof)
6327: { char *s = ie->toChars();
warning C6246: Local declaration of 's' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6209' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6209
6328: e = new StringExp(loc, s, strlen(s), 'c');
6329: e = e->semantic(sc);
6330: return e;
6331: }
6332: error("undefined identifier %s", toChars());
6333: return new ErrorExp();
6334: }
6335: else if (t1b->ty == Tpointer &&
6336: ident != Id::init && ident != Id::__sizeof &&
6337: ident != Id::__xalignof && ident != Id::offsetof &&
6338: ident != Id::mangleof && ident != Id::stringof)
6339: { /* Rewrite:
6340: * p.ident
6341: * as:
6342: * (*p).ident
6343: */
6344: e = new PtrExp(loc, e1);
6345: e->type = ((TypePointer *)t1b)->next;
6346: return e->type->dotExp(sc, e, ident);
6347: }
6348: #if DMDV2
6349: else if (t1b->ty == Tarray ||
6350: t1b->ty == Tsarray ||
6351: t1b->ty == Taarray)
6352: { /* If ident is not a valid property, rewrite:
6353: * e1.ident
6354: * as:
6355: * .ident(e1)
6356: */
6357: unsigned errors = global.errors;
6358: global.gag++;
6359: Type *t1 = e1->type;
6360: e = e1->type->dotExp(sc, e1, ident);
6361: global.gag--;
6362: if (errors != global.errors) // if failed to find the property
6363: {
6364: global.errors = errors;
6365: e1->type = t1; // kludge to restore type
6366: e = new DotIdExp(loc, new IdentifierExp(loc, Id::empty), ident);
6367: e = new CallExp(loc, e, e1);
6368: }
6369: e = e->semantic(sc);
6370: return e;
6371: }
6372: #endif
6373: else
6374: {
6375: e = e1->type->dotExp(sc, e1, ident);
6376: if (!(flag && e->op == TOKdotti)) // let CallExp::semantic() handle this
6377: e = e->semantic(sc);
6378: return e;
6379: }
6380: }
6381:
6382: void DotIdExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6383: {
6384: //printf("DotIdExp::toCBuffer()\n");
6385: expToCBuffer(buf, hgs, e1, PREC_primary);
6386: buf->writeByte('.');
6387: buf->writestring(ident->toChars());
6388: }
6389:
6390: /********************** DotTemplateExp ***********************************/
6391:
6392: // Mainly just a placeholder
6393:
6394: DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td)
6395: : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e)
6396:
6397: {
6398: this->td = td;
6399: }
6400:
6401: void DotTemplateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6402: {
6403: expToCBuffer(buf, hgs, e1, PREC_primary);
6404: buf->writeByte('.');
6405: buf->writestring(td->toChars());
6406: }
6407:
6408:
6409: /************************************************************/
6410:
6411: DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *v, int hasOverloads)
6412: : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e)
6413: {
6414: //printf("DotVarExp()\n");
6415: this->var = v;
6416: this->hasOverloads = hasOverloads;
6417: }
6418:
6419: Expression *DotVarExp::semantic(Scope *sc)
6420: {
6421: #if LOGSEMANTIC
6422: printf("DotVarExp::semantic('%s')\n", toChars());
6423: #endif
6424: if (!type)
6425: {
6426: var = var->toAlias()->isDeclaration();
6427:
6428: TupleDeclaration *tup = var->isTupleDeclaration();
6429: if (tup)
6430: { /* Replace:
6431: * e1.tuple(a, b, c)
6432: * with:
6433: * tuple(e1.a, e1.b, e1.c)
6434: */
6435: Expressions *exps = new Expressions;
warning C6211: Leaking memory 'exps' due to an exception. Consider using a local catch block to clean up memory: Lines: 6424, 6426, 6428, 6429, 6435, 6437, 6438, 6439, 6440, 6447, 6448, 6453, 6455
6436:
6437: exps->reserve(tup->objects->dim);
6438: for (size_t i = 0; i < tup->objects->dim; i++)
6439: { Object *o = tup->objects->tdata()[i];
6440: if (o->dyncast() != DYNCAST_EXPRESSION)
6441: {
6442: error("%s is not an expression", o->toChars());
6443: goto Lerr;
6444: }
6445: else
6446: {
6447: Expression *e = (Expression *)o;
6448: if (e->op != TOKdsymbol)
6449: { error("%s is not a member", e->toChars());
6450: goto Lerr;
6451: }
6452: else
6453: { DsymbolExp *ve = (DsymbolExp *)e;
6454:
6455: e = new DotVarExp(loc, e1, ve->s->isDeclaration());
6456: exps->push(e);
6457: }
6458: }
6459: }
6460: Expression *e = new TupleExp(loc, exps);
6461: e = e->semantic(sc);
6462: return e;
6463: }
6464:
6465: e1 = e1->semantic(sc);
6466: e1 = e1->addDtorHook(sc);
6467: type = var->type;
6468: if (!type && global.errors)
6469: { // var is goofed up, just return 0
6470: return new ErrorExp();
6471: }
6472: assert(type);
6473:
6474: Type *t1 = e1->type;
6475: if (!var->isFuncDeclaration()) // for functions, do checks after overload resolution
6476: {
6477: if (t1->ty == Tpointer)
6478: t1 = t1->nextOf();
6479:
6480: type = type->addMod(t1->mod);
6481:
6482: Dsymbol *vparent = var->toParent();
6483: AggregateDeclaration *ad = vparent ? vparent->isAggregateDeclaration() : NULL;
6484: e1 = getRightThis(loc, sc, ad, e1, var);
6485: if (!sc->noaccesscheck)
6486: accessCheck(loc, sc, e1, var);
6487:
6488: VarDeclaration *v = var->isVarDeclaration();
6489: Expression *e = expandVar(WANTvalue, v);
6490: if (e)
6491: return e;
6492: }
6493: Dsymbol *s;
6494: if (sc->func && !sc->intypeof && t1->hasPointers() &&
6495: (s = t1->toDsymbol(sc)) != NULL)
6496: {
6497: AggregateDeclaration *ad = s->isAggregateDeclaration();
6498: if (ad && ad->hasUnions)
6499: {
6500: if (sc->func->setUnsafe())
6501: { error("union %s containing pointers are not allowed in @safe functions", t1->toChars());
6502: goto Lerr;
6503: }
6504: }
6505: }
6506: }
6507:
6508: //printf("-DotVarExp::semantic('%s')\n", toChars());
6509: return this;
6510:
6511: Lerr:
6512: return new ErrorExp();
6513: }
6514:
6515: #if DMDV2
6516: int DotVarExp::isLvalue()
6517: {
6518: return 1;
6519: }
6520: #endif
6521:
6522: Expression *DotVarExp::toLvalue(Scope *sc, Expression *e)
6523: {
6524: //printf("DotVarExp::toLvalue(%s)\n", toChars());
6525: return this;
6526: }
6527:
6528: Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
6529: {
6530: #if 0
6531: printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
6532: printf("e1->type = %s\n", e1->type->toChars());
6533: printf("var->type = %s\n", var->type->toChars());
6534: #endif
6535:
6536: Type *t1 = e1->type->toBasetype();
6537:
6538: if (!t1->isMutable() ||
6539: (t1->ty == Tpointer && !t1->nextOf()->isMutable()) ||
6540: !var->type->isMutable() ||
6541: !var->type->isAssignable() ||
6542: var->storage_class & STCmanifest
6543: )
6544: {
6545: if (var->isCtorinit())
6546: { // It's only modifiable if inside the right constructor
6547: Dsymbol *s = sc->func;
6548: while (1)
6549: {
6550: FuncDeclaration *fd = NULL;
6551: if (s)
6552: fd = s->isFuncDeclaration();
6553: if (fd &&
6554: ((fd->isCtorDeclaration() && var->storage_class & STCfield) ||
6555: (fd->isStaticCtorDeclaration() && !(var->storage_class & STCfield))) &&
6556: fd->toParent2() == var->toParent() &&
6557: e1->op == TOKthis
6558: )
6559: {
6560: VarDeclaration *v = var->isVarDeclaration();
6561: assert(v);
6562: v->ctorinit = 1;
6563: //printf("setting ctorinit\n");
6564: }
6565: else
6566: {
6567: if (s)
6568: { s = s->toParent2();
6569: continue;
6570: }
6571: else
6572: {
6573: const char *p = var->isStatic() ? "static " : "";
6574: error("can only initialize %sconst member %s inside %sconstructor",
6575: p, var->toChars(), p);
6576: }
6577: }
6578: break;
6579: }
6580: }
6581: else
6582: {
6583: error("cannot modify const/immutable/inout expression %s", toChars());
6584: }
6585: }
6586: return this;
6587: }
6588:
6589: void DotVarExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6590: {
6591: expToCBuffer(buf, hgs, e1, PREC_primary);
6592: buf->writeByte('.');
6593: buf->writestring(var->toChars());
6594: }
6595:
6596: /************************************************************/
6597:
6598: /* Things like:
6599: * foo.bar!(args)
6600: */
6601:
6602: DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, Identifier *name, Objects *tiargs)
6603: : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e)
6604: {
6605: //printf("DotTemplateInstanceExp()\n");
6606: this->ti = new TemplateInstance(loc, name);
6607: this->ti->tiargs = tiargs;
6608: }
6609:
6610: Expression *DotTemplateInstanceExp::syntaxCopy()
6611: {
6612: DotTemplateInstanceExp *de = new DotTemplateInstanceExp(loc,
6613: e1->syntaxCopy(),
6614: ti->name,
6615: TemplateInstance::arraySyntaxCopy(ti->tiargs));
6616: return de;
6617: }
6618:
6619: TemplateDeclaration *DotTemplateInstanceExp::getTempdecl(Scope *sc)
6620: {
6621: #if LOGSEMANTIC
6622: printf("DotTemplateInstanceExp::getTempdecl('%s')\n", toChars());
6623: #endif
6624: if (!ti->tempdecl)
6625: {
6626: Expression *e = new DotIdExp(loc, e1, ti->name);
6627: e = e->semantic(sc);
6628: if (e->op == TOKdottd)
6629: {
6630: DotTemplateExp *dte = (DotTemplateExp *)e;
6631: ti->tempdecl = dte->td;
6632: }
6633: else if (e->op == TOKimport)
6634: { ScopeExp *se = (ScopeExp *)e;
6635: ti->tempdecl = se->sds->isTemplateDeclaration();
6636: }
6637: }
6638: return ti->tempdecl;
6639: }
6640:
6641: Expression *DotTemplateInstanceExp::semantic(Scope *sc)
6642: {
6643: #if LOGSEMANTIC
6644: printf("DotTemplateInstanceExp::semantic('%s')\n", toChars());
6645: #endif
6646: Expression *eleft;
6647: Expression *e = new DotIdExp(loc, e1, ti->name);
6648: L1:
6649: e = e->semantic(sc);
6650: if (e->op == TOKerror)
6651: return e;
6652: if (e->op == TOKdottd)
6653: {
6654: if (global.errors)
6655: return new ErrorExp(); // TemplateInstance::semantic() will fail anyway
6656: DotTemplateExp *dte = (DotTemplateExp *)e;
6657: TemplateDeclaration *td = dte->td;
6658: eleft = dte->e1;
6659: ti->tempdecl = td;
6660: ti->semantic(sc);
6661: if (!ti->inst) // if template failed to expand
6662: return new ErrorExp();
6663: Dsymbol *s = ti->inst->toAlias();
6664: Declaration *v = s->isDeclaration();
6665: if (v)
6666: {
6667: /* Fix for Bugzilla 4003
6668: * The problem is a class template member function v returning a reference to the same
6669: * type as the enclosing template instantiation. This results in a nested instantiation,
6670: * which of course gets short circuited. The return type then gets set to
6671: * the template instance type before instantiation, rather than after.
6672: * We can detect this by the deco not being set. If so, go ahead and retry
6673: * the return type semantic.
6674: * The offending code is the return type from std.typecons.Tuple.slice:
6675: * ref Tuple!(Types[from .. to]) slice(uint from, uint to)()
6676: * {
6677: * return *cast(typeof(return) *) &(field[from]);
6678: * }
6679: * and this line from the following unittest:
6680: * auto s = a.slice!(1, 3);
6681: * where s's type wound up not having semantic() run on it.
6682: */
6683: if (v->type && !v->type->deco)
6684: v->type = v->type->semantic(v->loc, sc);
6685:
6686: e = new DotVarExp(loc, eleft, v);
6687: e = e->semantic(sc);
6688: return e;
6689: }
6690: e = new ScopeExp(loc, ti);
6691: e = new DotExp(loc, eleft, e);
6692: e = e->semantic(sc);
6693: return e;
6694: }
6695: else if (e->op == TOKimport)
6696: { ScopeExp *se = (ScopeExp *)e;
6697: TemplateDeclaration *td = se->sds->isTemplateDeclaration();
6698: if (!td)
6699: { error("%s is not a template", e->toChars());
6700: return new ErrorExp();
6701: }
6702: ti->tempdecl = td;
6703: e = new ScopeExp(loc, ti);
6704: e = e->semantic(sc);
6705: return e;
6706: }
6707: else if (e->op == TOKdotexp)
6708: { DotExp *de = (DotExp *)e;
6709:
6710: if (de->e2->op == TOKoverloadset)
6711: {
6712: return e;
6713: }
6714:
6715: if (de->e2->op == TOKimport)
6716: { // This should *really* be moved to ScopeExp::semantic()
6717: ScopeExp *se = (ScopeExp *)de->e2;
6718: de->e2 = new DsymbolExp(loc, se->sds);
6719: de->e2 = de->e2->semantic(sc);
6720: }
6721:
6722: if (de->e2->op == TOKtemplate)
6723: { TemplateExp *te = (TemplateExp *) de->e2;
6724: e = new DotTemplateExp(loc,de->e1,te->td);
6725: }
6726: goto L1;
6727: }
6728: error("%s isn't a template", e->toChars());
6729: return new ErrorExp();
6730: }
6731:
6732: void DotTemplateInstanceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6733: {
6734: expToCBuffer(buf, hgs, e1, PREC_primary);
6735: buf->writeByte('.');
6736: ti->toCBuffer(buf, hgs);
6737: }
6738:
6739: /************************************************************/
6740:
6741: DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f, int hasOverloads)
6742: : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
6743: {
6744: this->func = f;
6745: this->hasOverloads = hasOverloads;
6746: }
6747:
6748: Expression *DelegateExp::semantic(Scope *sc)
6749: {
6750: #if LOGSEMANTIC
6751: printf("DelegateExp::semantic('%s')\n", toChars());
6752: #endif
6753: if (!type)
6754: {
6755: e1 = e1->semantic(sc);
6756: type = new TypeDelegate(func->type);
6757: type = type->semantic(loc, sc);
6758: AggregateDeclaration *ad = func->toParent()->isAggregateDeclaration();
6759: if (func->needThis())
6760: e1 = getRightThis(loc, sc, ad, e1, func);
6761: if (ad && ad->isClassDeclaration() && ad->type != e1->type)
6762: { // A downcast is required for interfaces, see Bugzilla 3706
6763: e1 = new CastExp(loc, e1, ad->type);
6764: e1 = e1->semantic(sc);
6765: }
6766: }
6767: return this;
6768: }
6769:
6770: void DelegateExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6771: {
6772: buf->writeByte('&');
6773: if (!func->isNested())
6774: {
6775: expToCBuffer(buf, hgs, e1, PREC_primary);
6776: buf->writeByte('.');
6777: }
6778: buf->writestring(func->toChars());
6779: }
6780:
6781: /************************************************************/
6782:
6783: DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s)
6784: : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e)
6785: {
6786: this->sym = s;
6787: this->type = s->getType();
6788: }
6789:
6790: Expression *DotTypeExp::semantic(Scope *sc)
6791: {
6792: #if LOGSEMANTIC
6793: printf("DotTypeExp::semantic('%s')\n", toChars());
6794: #endif
6795: UnaExp::semantic(sc);
6796: return this;
6797: }
6798:
6799: void DotTypeExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
6800: {
6801: expToCBuffer(buf, hgs, e1, PREC_primary);
6802: buf->writeByte('.');
6803: buf->writestring(sym->toChars());
6804: }
6805:
6806: /************************************************************/
6807:
6808: CallExp::CallExp(Loc loc, Expression *e, Expressions *exps)
6809: : UnaExp(loc, TOKcall, sizeof(CallExp), e)
6810: {
6811: this->arguments = exps;
6812: }
6813:
6814: CallExp::CallExp(Loc loc, Expression *e)
6815: : UnaExp(loc, TOKcall, sizeof(CallExp), e)
6816: {
6817: this->arguments = NULL;
6818: }
6819:
6820: CallExp::CallExp(Loc loc, Expression *e, Expression *earg1)
6821: : UnaExp(loc, TOKcall, sizeof(CallExp), e)
6822: {
6823: Expressions *arguments = new Expressions();
6824: if (earg1)
6825: { arguments->setDim(1);
6826: arguments->tdata()[0] = earg1;
6827: }
6828: this->arguments = arguments;
6829: }
6830:
6831: CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2)
6832: : UnaExp(loc, TOKcall, sizeof(CallExp), e)
6833: {
6834: Expressions *arguments = new Expressions();
6835: arguments->setDim(2);
6836: arguments->tdata()[0] = earg1;
6837: arguments->tdata()[1] = earg2;
6838:
6839: this->arguments = arguments;
6840: }
6841:
6842: Expression *CallExp::syntaxCopy()
6843: {
6844: return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
6845: }
6846:
6847:
6848: Expression *CallExp::semantic(Scope *sc)
6849: {
6850: TypeFunction *tf;
6851: FuncDeclaration *f;
6852: int i;
warning C4101: 'i' : unreferenced local variable
6853: Type *t1;
6854: int istemp;
6855: Objects *targsi = NULL; // initial list of template arguments
6856: TemplateInstance *tierror = NULL;
6857: Expression *ethis = NULL;
6858:
6859: #if LOGSEMANTIC
6860: printf("CallExp::semantic() %s\n", toChars());
6861: #endif
6862: if (type)
6863: return this; // semantic() already run
6864: #if 0
6865: if (arguments && arguments->dim)
6866: {
6867: Expression *earg = arguments->tdata()[0];
6868: earg->print();
6869: if (earg->type) earg->type->print();
6870: }
6871: #endif
6872:
6873: if (e1->op == TOKdelegate)
6874: { DelegateExp *de = (DelegateExp *)e1;
6875:
6876: e1 = new DotVarExp(de->loc, de->e1, de->func);
6877: return semantic(sc);
6878: }
6879:
6880: /* Transform:
6881: * array.id(args) into .id(array,args)
6882: * aa.remove(arg) into delete aa[arg]
6883: */
6884: if (e1->op == TOKdot)
6885: {
6886: // BUG: we should handle array.a.b.c.e(args) too
6887:
6888: DotIdExp *dotid = (DotIdExp *)(e1);
6889: dotid->e1 = dotid->e1->semantic(sc);
6890: assert(dotid->e1);
6891: if (dotid->e1->type)
6892: {
6893: TY e1ty = dotid->e1->type->toBasetype()->ty;
6894: if (e1ty == Taarray && dotid->ident == Id::remove)
6895: {
6896: if (!arguments || arguments->dim != 1)
6897: { error("expected key as argument to aa.remove()");
6898: return new ErrorExp();
6899: }
6900: Expression *key = arguments->tdata()[0];
6901: key = key->semantic(sc);
6902: key = resolveProperties(sc, key);
6903: key->rvalue();
6904:
6905: TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype();
6906: key = key->implicitCastTo(sc, taa->index);
6907:
6908: return new RemoveExp(loc, dotid->e1, key);
6909: }
6910: else if (e1ty == Tarray || e1ty == Tsarray ||
6911: (e1ty == Taarray && dotid->ident != Id::apply && dotid->ident != Id::applyReverse))
6912: {
6913: if (e1ty == Taarray)
6914: { TypeAArray *taa = (TypeAArray *)dotid->e1->type->toBasetype();
6915: assert(taa->ty == Taarray);
6916: StructDeclaration *sd = taa->getImpl();
6917: Dsymbol *s = sd->search(0, dotid->ident, 2);
6918: if (s)
6919: goto L2;
6920: }
6921: if (!arguments)
6922: arguments = new Expressions();
6923: arguments->shift(dotid->e1);
6924: #if DMDV2
6925: e1 = new DotIdExp(dotid->loc, new IdentifierExp(dotid->loc, Id::empty), dotid->ident);
6926: #else
6927: e1 = new IdentifierExp(dotid->loc, dotid->ident);
6928: #endif
6929: }
6930:
6931: L2:
6932: ;
6933: }
6934: }
6935:
6936: #if 1
6937: /* This recognizes:
6938: * foo!(tiargs)(funcargs)
6939: */
6940: if (e1->op == TOKimport && !e1->type)
6941: { ScopeExp *se = (ScopeExp *)e1;
6942: TemplateInstance *ti = se->sds->isTemplateInstance();
6943: if (ti && !ti->semanticRun)
6944: {
6945: /* Attempt to instantiate ti. If that works, go with it.
6946: * If not, go with partial explicit specialization.
6947: */
6948: ti->semanticTiargs(sc);
6949: if (ti->needsTypeInference(sc))
6950: {
6951: /* Go with partial explicit specialization
6952: */
6953: targsi = ti->tiargs;
6954: tierror = ti; // for error reporting
6955: e1 = new IdentifierExp(loc, ti->name);
6956: }
6957: else
6958: {
6959: ti->semantic(sc);
6960: }
6961: }
6962: }
6963:
6964: /* This recognizes:
6965: * expr.foo!(tiargs)(funcargs)
6966: */
6967: Ldotti:
6968: if (e1->op == TOKdotti && !e1->type)
6969: { DotTemplateInstanceExp *se = (DotTemplateInstanceExp *)e1;
6970: TemplateInstance *ti = se->ti;
6971: if (!ti->semanticRun)
6972: {
6973: /* Attempt to instantiate ti. If that works, go with it.
6974: * If not, go with partial explicit specialization.
6975: */
6976: ti->semanticTiargs(sc);
6977: #if 0
6978: Expression *etmp = e1->trySemantic(sc);
6979: if (etmp)
6980: e1 = etmp; // it worked
6981: else // didn't work
6982: {
6983: targsi = ti->tiargs;
6984: tierror = ti; // for error reporting
6985: e1 = new DotIdExp(loc, se->e1, ti->name);
6986: }
6987: #else
6988: if (!ti->tempdecl)
6989: {
6990: se->getTempdecl(sc);
6991: }
6992: if (ti->tempdecl && ti->needsTypeInference(sc))
6993: {
6994: /* Go with partial explicit specialization
6995: */
6996: targsi = ti->tiargs;
6997: tierror = ti; // for error reporting
6998: e1 = new DotIdExp(loc, se->e1, ti->name);
6999: }
7000: else
7001: {
7002: e1 = e1->semantic(sc);
7003: }
7004: #endif
7005: }
7006: }
7007: #endif
7008:
7009: istemp = 0;
7010: Lagain:
7011: //printf("Lagain: %s\n", toChars());
7012: f = NULL;
7013: if (e1->op == TOKthis || e1->op == TOKsuper)
7014: {
7015: // semantic() run later for these
7016: }
7017: else
7018: {
7019: if (e1->op == TOKdot)
7020: { DotIdExp *die = (DotIdExp *)e1;
7021: e1 = die->semantic(sc, 1);
7022: /* Look for e1 having been rewritten to expr.opDispatch!(string)
7023: * We handle such earlier, so go back.
7024: * Note that in the rewrite, we carefully did not run semantic() on e1
7025: */
7026: if (e1->op == TOKdotti && !e1->type)
7027: {
7028: goto Ldotti;
7029: }
7030: }
7031: else
7032: UnaExp::semantic(sc);
7033:
7034:
7035: /* Look for e1 being a lazy parameter
7036: */
7037: if (e1->op == TOKvar)
7038: { VarExp *ve = (VarExp *)e1;
7039:
7040: if (ve->var->storage_class & STClazy)
7041: {
7042: TypeFunction *tf = new TypeFunction(NULL, ve->var->type, 0, LINKd);
warning C6246: Local declaration of 'tf' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6850' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6850
7043: TypeDelegate *t = new TypeDelegate(tf);
7044: ve->type = t->semantic(loc, sc);
7045: }
7046: }
7047:
7048: if (e1->op == TOKimport)
7049: { // Perhaps this should be moved to ScopeExp::semantic()
7050: ScopeExp *se = (ScopeExp *)e1;
7051: e1 = new DsymbolExp(loc, se->sds);
7052: e1 = e1->semantic(sc);
7053: }
7054: #if 1 // patch for #540 by Oskar Linde
7055: else if (e1->op == TOKdotexp)
7056: {
7057: DotExp *de = (DotExp *) e1;
7058:
7059: if (de->e2->op == TOKoverloadset)
7060: {
7061: ethis = de->e1;
7062: e1 = de->e2;
7063: }
7064:
7065: if (de->e2->op == TOKimport)
7066: { // This should *really* be moved to ScopeExp::semantic()
7067: ScopeExp *se = (ScopeExp *)de->e2;
7068: de->e2 = new DsymbolExp(loc, se->sds);
7069: de->e2 = de->e2->semantic(sc);
7070: }
7071:
7072: if (de->e2->op == TOKtemplate)
7073: { TemplateExp *te = (TemplateExp *) de->e2;
7074: e1 = new DotTemplateExp(loc,de->e1,te->td);
7075: }
7076: }
7077: #endif
7078: }
7079:
7080: if (e1->op == TOKcomma)
7081: { /* Rewrite (a,b)(args) as (a,(b(args)))
7082: */
7083: CommaExp *ce = (CommaExp *)e1;
7084:
7085: e1 = ce->e2;
7086: e1->type = ce->type;
7087: ce->e2 = this;
7088: ce->type = NULL;
7089: return ce->semantic(sc);
7090: }
7091:
7092: t1 = NULL;
7093: if (e1->type)
7094: t1 = e1->type->toBasetype();
7095:
7096: // Check for call operator overload
7097: if (t1)
7098: { AggregateDeclaration *ad;
7099:
7100: if (t1->ty == Tstruct)
7101: {
7102: ad = ((TypeStruct *)t1)->sym;
7103: #if DMDV2
7104: // First look for constructor
7105: if (ad->ctor && arguments && arguments->dim)
7106: {
7107: // Create variable that will get constructed
7108: Identifier *idtmp = Lexer::uniqueId("__ctmp");
7109: VarDeclaration *tmp = new VarDeclaration(loc, t1, idtmp, NULL);
7110: tmp->storage_class |= STCctfe;
7111: Expression *av = new DeclarationExp(loc, tmp);
7112: av = new CommaExp(loc, av, new VarExp(loc, tmp));
7113:
7114: Expression *e;
7115: CtorDeclaration *cf = ad->ctor->isCtorDeclaration();
7116: if (cf)
7117: e = new DotVarExp(loc, av, cf, 1);
7118: else
7119: { TemplateDeclaration *td = ad->ctor->isTemplateDeclaration();
7120: assert(td);
7121: e = new DotTemplateExp(loc, av, td);
7122: }
7123: e = new CallExp(loc, e, arguments);
7124: #if !STRUCTTHISREF
7125: /* Constructors return a pointer to the instance
7126: */
7127: e = new PtrExp(loc, e);
7128: #endif
7129: e = e->semantic(sc);
7130: return e;
7131: }
7132: #endif
7133: // No constructor, look for overload of opCall
7134: if (search_function(ad, Id::call))
7135: goto L1; // overload of opCall, therefore it's a call
7136:
7137: if (e1->op != TOKtype)
7138: { error("%s %s does not overload ()", ad->kind(), ad->toChars());
7139: return new ErrorExp();
7140: }
7141:
7142: /* It's a struct literal
7143: */
7144: Expression *e = new StructLiteralExp(loc, (StructDeclaration *)ad, arguments, e1->type);
7145: e = e->semantic(sc);
7146: return e;
7147: }
7148: else if (t1->ty == Tclass)
7149: {
7150: ad = ((TypeClass *)t1)->sym;
7151: goto L1;
7152: L1:
7153: // Rewrite as e1.call(arguments)
7154: Expression *e = new DotIdExp(loc, e1, Id::call);
7155: e = new CallExp(loc, e, arguments);
7156: e = e->semantic(sc);
7157: return e;
7158: }
7159: }
7160:
7161: arguments = arrayExpressionSemantic(arguments, sc);
7162:
7163: preFunctionParameters(loc, sc, arguments);
7164:
7165: // If there was an error processing any argument, or the call,
7166: // return an error without trying to resolve the function call.
7167: if (arguments && arguments->dim)
7168: {
7169: for (int k = 0; k < arguments->dim; k++)
warning C4018: '<' : signed/unsigned mismatch
7170: { Expression *checkarg = arguments->tdata()[k];
7171: if (checkarg->op == TOKerror)
7172: return checkarg;
7173: }
7174: }
7175: if (e1->op == TOKerror)
7176: return e1;
7177:
7178: if (e1->op == TOKdotvar && t1->ty == Tfunction ||
7179: e1->op == TOKdottd)
7180: {
7181: DotVarExp *dve;
7182: DotTemplateExp *dte;
7183: AggregateDeclaration *ad;
7184: UnaExp *ue = (UnaExp *)(e1);
7185:
7186: if (e1->op == TOKdotvar)
7187: { // Do overload resolution
7188: dve = (DotVarExp *)(e1);
7189:
7190: f = dve->var->isFuncDeclaration();
7191: assert(f);
7192: f = f->overloadResolve(loc, ue->e1, arguments);
7193:
7194: ad = f->toParent()->isAggregateDeclaration();
7195: }
7196: else
7197: { dte = (DotTemplateExp *)(e1);
7198: TemplateDeclaration *td = dte->td;
7199: assert(td);
7200: if (!arguments)
7201: // Should fix deduceFunctionTemplate() so it works on NULL argument
7202: arguments = new Expressions();
7203: f = td->deduceFunctionTemplate(sc, loc, targsi, ue->e1, arguments);
7204: if (!f)
7205: { type = Type::terror;
7206: return this;
7207: }
7208: ad = td->toParent()->isAggregateDeclaration();
7209: }
7210: if (f->needThis())
7211: {
7212: ue->e1 = getRightThis(loc, sc, ad, ue->e1, f);
7213: }
7214:
7215: /* Cannot call public functions from inside invariant
7216: * (because then the invariant would have infinite recursion)
7217: */
7218: if (sc->func && sc->func->isInvariantDeclaration() &&
7219: ue->e1->op == TOKthis &&
7220: f->addPostInvariant()
7221: )
7222: {
7223: error("cannot call public/export function %s from invariant", f->toChars());
7224: return new ErrorExp();
7225: }
7226:
7227: checkDeprecated(sc, f);
7228: #if DMDV2
7229: checkPurity(sc, f);
7230: checkSafety(sc, f);
7231: #endif
7232: accessCheck(loc, sc, ue->e1, f);
7233: if (!f->needThis())
7234: {
7235: VarExp *ve = new VarExp(loc, f);
7236: e1 = new CommaExp(loc, ue->e1, ve);
7237: e1->type = f->type;
7238: }
7239: else
7240: {
7241: if (e1->op == TOKdotvar)
7242: dve->var = f;
7243: else
7244: e1 = new DotVarExp(loc, dte->e1, f);
7245: e1->type = f->type;
7246: #if 0
7247: printf("ue->e1 = %s\n", ue->e1->toChars());
7248: printf("f = %s\n", f->toChars());
7249: printf("t = %s\n", t->toChars());
7250: printf("e1 = %s\n", e1->toChars());
7251: printf("e1->type = %s\n", e1->type->toChars());
7252: #endif
7253: // Const member function can take const/immutable/mutable/inout this
7254: if (!(f->type->isConst()))
7255: {
7256: // Check for const/immutable compatibility
7257: Type *tthis = ue->e1->type->toBasetype();
7258: if (tthis->ty == Tpointer)
7259: tthis = tthis->nextOf()->toBasetype();
7260: #if 0 // this checking should have been already done
7261: if (f->type->isImmutable())
7262: {
7263: if (tthis->mod != MODimmutable)
7264: error("%s can only be called with an immutable object", e1->toChars());
7265: }
7266: else if (f->type->isShared())
7267: {
7268: if (tthis->mod != MODimmutable &&
7269: tthis->mod != MODshared &&
7270: tthis->mod != (MODshared | MODconst))
7271: error("shared %s can only be called with a shared or immutable object", e1->toChars());
7272: }
7273: else
7274: {
7275: if (tthis->mod != 0)
7276: { //printf("mod = %x\n", tthis->mod);
7277: error("%s can only be called with a mutable object, not %s", e1->toChars(), tthis->toChars());
7278: }
7279: }
7280: #endif
7281: /* Cannot call mutable method on a final struct
7282: */
7283: if (tthis->ty == Tstruct &&
7284: ue->e1->op == TOKvar)
7285: { VarExp *v = (VarExp *)ue->e1;
7286: if (v->var->storage_class & STCfinal)
7287: error("cannot call mutable method on final struct");
7288: }
7289: }
7290:
7291: // See if we need to adjust the 'this' pointer
7292: AggregateDeclaration *ad = f->isThis();
warning C6246: Local declaration of 'ad' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '7183' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 7183
7293: ClassDeclaration *cd = ue->e1->type->isClassHandle();
7294: if (ad && cd && ad->isClassDeclaration() && ad != cd &&
7295: ue->e1->op != TOKsuper)
7296: {
7297: ue->e1 = ue->e1->castTo(sc, ad->type); //new CastExp(loc, ue->e1, ad->type);
7298: ue->e1 = ue->e1->semantic(sc);
7299: }
7300: }
7301: t1 = e1->type;
7302: }
7303: else if (e1->op == TOKsuper)
7304: {
7305: // Base class constructor call
7306: ClassDeclaration *cd = NULL;
7307:
7308: if (sc->func)
7309: cd = sc->func->toParent()->isClassDeclaration();
7310: if (!cd || !cd->baseClass || !sc->func->isCtorDeclaration())
7311: {
7312: error("super class constructor call must be in a constructor");
7313: return new ErrorExp();
7314: }
7315: else
7316: {
7317: if (!cd->baseClass->ctor)
7318: { error("no super class constructor for %s", cd->baseClass->toChars());
7319: return new ErrorExp();
7320: }
7321: else
7322: {
7323: if (!sc->intypeof)
7324: {
7325: #if 0
7326: if (sc->callSuper & (CSXthis | CSXsuper))
7327: error("reference to this before super()");
7328: #endif
7329: if (sc->noctor || sc->callSuper & CSXlabel)
7330: error("constructor calls not allowed in loops or after labels");
7331: if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
7332: error("multiple constructor calls");
7333: sc->callSuper |= CSXany_ctor | CSXsuper_ctor;
7334: }
7335:
7336: f = resolveFuncCall(sc, loc, cd->baseClass->ctor, NULL, NULL, arguments, 0);
7337: checkDeprecated(sc, f);
7338: #if DMDV2
7339: checkPurity(sc, f);
7340: checkSafety(sc, f);
7341: #endif
7342: e1 = new DotVarExp(e1->loc, e1, f);
7343: e1 = e1->semantic(sc);
7344: t1 = e1->type;
7345: }
7346: }
7347: }
7348: else if (e1->op == TOKthis)
7349: {
7350: // same class constructor call
7351: AggregateDeclaration *cd = NULL;
7352:
7353: if (sc->func)
7354: cd = sc->func->toParent()->isAggregateDeclaration();
7355: if (!cd || !sc->func->isCtorDeclaration())
7356: {
7357: error("constructor call must be in a constructor");
7358: return new ErrorExp();
7359: }
7360: else
7361: {
7362: if (!sc->intypeof)
7363: {
7364: #if 0
7365: if (sc->callSuper & (CSXthis | CSXsuper))
7366: error("reference to this before super()");
7367: #endif
7368: if (sc->noctor || sc->callSuper & CSXlabel)
7369: error("constructor calls not allowed in loops or after labels");
7370: if (sc->callSuper & (CSXsuper_ctor | CSXthis_ctor))
7371: error("multiple constructor calls");
7372: sc->callSuper |= CSXany_ctor | CSXthis_ctor;
7373: }
7374:
7375: f = resolveFuncCall(sc, loc, cd->ctor, NULL, NULL, arguments, 0);
7376: checkDeprecated(sc, f);
7377: #if DMDV2
7378: checkPurity(sc, f);
7379: checkSafety(sc, f);
7380: #endif
7381: e1 = new DotVarExp(e1->loc, e1, f);
7382: e1 = e1->semantic(sc);
7383: t1 = e1->type;
7384:
7385: // BUG: this should really be done by checking the static
7386: // call graph
7387: if (f == sc->func)
7388: { error("cyclic constructor call");
7389: return new ErrorExp();
7390: }
7391: }
7392: }
7393: else if (e1->op == TOKoverloadset)
7394: {
7395: OverExp *eo = (OverExp *)e1;
7396: FuncDeclaration *f = NULL;
warning C6246: Local declaration of 'f' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6851' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6851
7397: Dsymbol *s = NULL;
7398: for (int i = 0; i < eo->vars->a.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
warning C6246: Local declaration of 'i' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6852' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6852
7399: { s = eo->vars->a.tdata()[i];
7400: FuncDeclaration *f2 = s->isFuncDeclaration();
7401: if (f2)
7402: {
7403: f2 = f2->overloadResolve(loc, ethis, arguments, 1);
7404: }
7405: else
7406: { TemplateDeclaration *td = s->isTemplateDeclaration();
7407: assert(td);
7408: f2 = td->deduceFunctionTemplate(sc, loc, targsi, ethis, arguments, 1);
7409: }
7410: if (f2)
7411: { if (f)
7412: /* Error if match in more than one overload set,
7413: * even if one is a 'better' match than the other.
7414: */
7415: ScopeDsymbol::multiplyDefined(loc, f, f2);
7416: else
7417: f = f2;
7418: }
7419: }
7420: if (!f)
7421: { /* No overload matches
7422: */
7423: error("no overload matches for %s", s->toChars());
7424: return new ErrorExp();
7425: }
7426: if (ethis)
7427: e1 = new DotVarExp(loc, ethis, f);
7428: else
7429: e1 = new VarExp(loc, f);
7430: goto Lagain;
7431: }
7432: else if (!t1)
7433: {
7434: error("function expected before (), not '%s'", e1->toChars());
7435: return new ErrorExp();
7436: }
7437: else if (t1->ty != Tfunction)
7438: {
7439: if (t1->ty == Tdelegate)
7440: { TypeDelegate *td = (TypeDelegate *)t1;
7441: assert(td->next->ty == Tfunction);
7442: tf = (TypeFunction *)(td->next);
7443: if (sc->func && !tf->purity && !(sc->flags & SCOPEdebug))
7444: {
7445: if (sc->func->setImpure())
7446: error("pure function '%s' cannot call impure delegate '%s'", sc->func->toChars(), e1->toChars());
7447: }
7448: if (sc->func && tf->trust <= TRUSTsystem)
7449: {
7450: if (sc->func->setUnsafe())
7451: error("safe function '%s' cannot call system delegate '%s'", sc->func->toChars(), e1->toChars());
7452: }
7453: goto Lcheckargs;
7454: }
7455: else if (t1->ty == Tpointer && ((TypePointer *)t1)->next->ty == Tfunction)
7456: {
7457: Expression *e = new PtrExp(loc, e1);
7458: t1 = ((TypePointer *)t1)->next;
7459: if (sc->func && !((TypeFunction *)t1)->purity && !(sc->flags & SCOPEdebug))
7460: {
7461: if (sc->func->setImpure())
7462: error("pure function '%s' cannot call impure function pointer '%s'", sc->func->toChars(), e1->toChars());
7463: }
7464: if (sc->func && !((TypeFunction *)t1)->trust <= TRUSTsystem)
warning C4804: '<=' : unsafe use of type 'bool' in operation
7465: {
7466: if (sc->func->setUnsafe())
7467: error("safe function '%s' cannot call system function pointer '%s'", sc->func->toChars(), e1->toChars());
7468: }
7469: e->type = t1;
7470: e1 = e;
7471: }
7472: else if (e1->op == TOKtemplate)
7473: {
7474: TemplateExp *te = (TemplateExp *)e1;
7475: f = te->td->deduceFunctionTemplate(sc, loc, targsi, NULL, arguments);
7476: if (!f)
7477: { if (tierror)
7478: tierror->error("errors instantiating template"); // give better error message
7479: return new ErrorExp();
7480: }
7481: if (f->needThis() && hasThis(sc))
7482: {
7483: // Supply an implicit 'this', as in
7484: // this.ident
7485:
7486: e1 = new DotTemplateExp(loc, (new ThisExp(loc))->semantic(sc), te->td);
7487: goto Lagain;
7488: }
7489:
7490: e1 = new VarExp(loc, f);
7491: goto Lagain;
7492: }
7493: else
7494: { error("function expected before (), not %s of type %s", e1->toChars(), e1->type->toChars());
7495: return new ErrorExp();
7496: }
7497: }
7498: else if (e1->op == TOKvar)
7499: {
7500: // Do overload resolution
7501: VarExp *ve = (VarExp *)e1;
7502:
7503: f = ve->var->isFuncDeclaration();
7504: assert(f);
7505:
7506: if (ve->hasOverloads)
7507: f = f->overloadResolve(loc, NULL, arguments);
7508: checkDeprecated(sc, f);
7509: #if DMDV2
7510: checkPurity(sc, f);
7511: checkSafety(sc, f);
7512: #endif
7513:
7514: if (f->needThis() && hasThis(sc))
7515: {
7516: // Supply an implicit 'this', as in
7517: // this.ident
7518:
7519: e1 = new DotVarExp(loc, new ThisExp(loc), f);
7520: goto Lagain;
7521: }
7522:
7523: accessCheck(loc, sc, NULL, f);
7524:
7525: ve->var = f;
7526: // ve->hasOverloads = 0;
7527: ve->type = f->type;
7528: t1 = f->type;
7529: }
7530: assert(t1->ty == Tfunction);
7531: tf = (TypeFunction *)(t1);
7532:
7533: Lcheckargs:
7534: assert(tf->ty == Tfunction);
7535:
7536: if (!arguments)
7537: arguments = new Expressions();
7538: type = functionParameters(loc, sc, tf, arguments, f);
7539:
7540: if (!type)
7541: {
7542: error("forward reference to inferred return type of function call %s", toChars());
7543: return new ErrorExp();
7544: }
7545:
7546: if (f && f->tintro)
7547: {
7548: Type *t = type;
7549: int offset = 0;
7550: TypeFunction *tf = (TypeFunction *)f->tintro;
warning C6246: Local declaration of 'tf' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '6850' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 6850
7551:
7552: if (tf->next->isBaseOf(t, &offset) && offset)
7553: {
7554: type = tf->next;
7555: return castTo(sc, t);
7556: }
7557: }
7558:
7559: return this;
7560: }
7561:
7562: int CallExp::checkSideEffect(int flag)
7563: {
7564: #if DMDV2
7565: int result = 1;
7566:
7567: /* Calling a function or delegate that is pure nothrow
7568: * has no side effects.
7569: */
7570: if (e1->type)
7571: {
7572: Type *t = e1->type->toBasetype();
7573: if ((t->ty == Tfunction && ((TypeFunction *)t)->purity > PUREweak &&
7574: ((TypeFunction *)t)->isnothrow)
7575: ||
7576: (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->purity > PUREweak &&
7577: ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow)
7578: )
7579: {
7580: result = 0;
7581: //if (flag == 0)
7582: //warning("pure nothrow function %s has no effect", e1->toChars());
7583: }
7584: else
7585: result = 1;
7586: }
7587:
7588: result |= e1->checkSideEffect(1);
7589:
7590: /* If any of the arguments have side effects, this expression does
7591: */
7592: for (size_t i = 0; i < arguments->dim; i++)
7593: { Expression *e = arguments->tdata()[i];
7594:
7595: result |= e->checkSideEffect(1);
7596: }
7597:
7598: return result;
7599: #else
7600: return 1;
7601: #endif
7602: }
7603:
7604: #if DMDV2
7605: int CallExp::canThrow(bool mustNotThrow)
7606: {
7607: //printf("CallExp::canThrow() %s\n", toChars());
7608: if (e1->canThrow(mustNotThrow))
7609: return 1;
7610:
7611: /* If any of the arguments can throw, then this expression can throw
7612: */
7613: if (arrayExpressionCanThrow(arguments, mustNotThrow))
7614: return 1;
7615:
7616: if (global.errors && !e1->type)
7617: return 0; // error recovery
7618:
7619: /* If calling a function or delegate that is typed as nothrow,
7620: * then this expression cannot throw.
7621: * Note that pure functions can throw.
7622: */
7623: Type *t = e1->type->toBasetype();
7624: if (t->ty == Tfunction && ((TypeFunction *)t)->isnothrow)
7625: return 0;
7626: if (t->ty == Tdelegate && ((TypeFunction *)((TypeDelegate *)t)->next)->isnothrow)
7627: return 0;
7628: if (mustNotThrow)
7629: error("%s is not nothrow", e1->toChars());
7630: return 1;
7631: }
7632: #endif
7633:
7634: #if DMDV2
7635: int CallExp::isLvalue()
7636: {
7637: // if (type->toBasetype()->ty == Tstruct)
7638: // return 1;
7639: Type *tb = e1->type->toBasetype();
7640: if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref)
7641: return 1; // function returns a reference
7642: return 0;
7643: }
7644: #endif
7645:
7646: Expression *CallExp::toLvalue(Scope *sc, Expression *e)
7647: {
7648: if (isLvalue())
7649: return this;
7650: return Expression::toLvalue(sc, e);
7651: }
7652:
7653: Expression *CallExp::addDtorHook(Scope *sc)
7654: {
7655: /* Only need to add dtor hook if it's a type that needs destruction.
7656: * Use same logic as VarDeclaration::callScopeDtor()
7657: */
7658:
7659: if (e1->type && e1->type->ty == Tfunction)
7660: {
7661: TypeFunction *tf = (TypeFunction *)e1->type;
7662: if (tf->isref)
7663: return this;
7664: }
7665:
7666: Type *tv = type->toBasetype();
7667: while (tv->ty == Tsarray)
7668: { TypeSArray *ta = (TypeSArray *)tv;
7669: tv = tv->nextOf()->toBasetype();
7670: }
7671: if (tv->ty == Tstruct)
7672: { TypeStruct *ts = (TypeStruct *)tv;
7673: StructDeclaration *sd = ts->sym;
7674: if (sd->dtor)
7675: { /* Type needs destruction, so declare a tmp
7676: * which the back end will recognize and call dtor on
7677: */
7678: if (e1->op == TOKdotvar)
7679: {
7680: DotVarExp* dve = (DotVarExp*)e1;
7681: if (dve->e1->isTemp() != NULL)
7682: goto Lnone; // already got a tmp
7683: }
7684:
7685: Identifier *idtmp = Lexer::uniqueId("__tmpfordtor");
7686: VarDeclaration *tmp = new VarDeclaration(loc, type, idtmp, new ExpInitializer(loc, this));
7687: tmp->storage_class |= STCctfe;
7688: Expression *ae = new DeclarationExp(loc, tmp);
7689: Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp));
7690: e = e->semantic(sc);
7691: return e;
7692: }
7693: }
7694: Lnone:
7695: return this;
7696: }
7697:
7698: void CallExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7699: {
7700: if (e1->op == TOKtype)
7701: /* Avoid parens around type to prevent forbidden cast syntax:
7702: * (sometype)(arg1)
7703: * This is ok since types in constructor calls
7704: * can never depend on parens anyway
7705: */
7706: e1->toCBuffer(buf, hgs);
7707: else
7708: expToCBuffer(buf, hgs, e1, precedence[op]);
7709: buf->writeByte('(');
7710: argsToCBuffer(buf, arguments, hgs);
7711: buf->writeByte(')');
7712: }
7713:
7714:
7715: /************************************************************/
7716:
7717: AddrExp::AddrExp(Loc loc, Expression *e)
7718: : UnaExp(loc, TOKaddress, sizeof(AddrExp), e)
7719: {
7720: }
7721:
7722: Expression *AddrExp::semantic(Scope *sc)
7723: {
7724: #if LOGSEMANTIC
7725: printf("AddrExp::semantic('%s')\n", toChars());
7726: #endif
7727: if (!type)
7728: {
7729: UnaExp::semantic(sc);
7730: if (e1->type == Type::terror)
7731: return new ErrorExp();
7732: e1 = e1->toLvalue(sc, NULL);
7733: if (e1->op == TOKerror)
7734: return e1;
7735: if (!e1->type)
7736: {
7737: error("cannot take address of %s", e1->toChars());
7738: return new ErrorExp();
7739: }
7740: if (!e1->type->deco)
7741: {
7742: /* No deco means semantic() was not run on the type.
7743: * We have to run semantic() on the symbol to get the right type:
7744: * auto x = &bar;
7745: * pure: int bar() { return 1;}
7746: * otherwise the 'pure' is missing from the type assigned to x.
7747: */
7748:
7749: error("forward reference to %s", e1->toChars());
7750: return new ErrorExp();
7751: }
7752:
7753: type = e1->type->pointerTo();
7754:
7755: // See if this should really be a delegate
7756: if (e1->op == TOKdotvar)
7757: {
7758: DotVarExp *dve = (DotVarExp *)e1;
7759: FuncDeclaration *f = dve->var->isFuncDeclaration();
7760:
7761: if (f)
7762: {
7763: if (!dve->hasOverloads)
7764: f->tookAddressOf++;
7765: Expression *e = new DelegateExp(loc, dve->e1, f, dve->hasOverloads);
7766: e = e->semantic(sc);
7767: return e;
7768: }
7769: }
7770: else if (e1->op == TOKvar)
7771: {
7772: VarExp *ve = (VarExp *)e1;
7773:
7774: VarDeclaration *v = ve->var->isVarDeclaration();
7775: if (v)
7776: {
7777: if (!v->canTakeAddressOf())
7778: { error("cannot take address of %s", e1->toChars());
7779: return new ErrorExp();
7780: }
7781:
7782: if (sc->func && !sc->intypeof && !v->isDataseg())
7783: {
7784: if (sc->func->setUnsafe())
7785: {
7786: error("cannot take address of %s %s in @safe function %s",
7787: v->isParameter() ? "parameter" : "local",
7788: v->toChars(),
7789: sc->func->toChars());
7790: }
7791: }
7792: }
7793:
7794: FuncDeclaration *f = ve->var->isFuncDeclaration();
7795:
7796: if (f)
7797: {
7798: if (!ve->hasOverloads ||
7799: /* Because nested functions cannot be overloaded,
7800: * mark here that we took its address because castTo()
7801: * may not be called with an exact match.
7802: */
7803: f->toParent2()->isFuncDeclaration())
7804: f->tookAddressOf++;
7805: if (f->isNested())
7806: {
7807: Expression *e = new DelegateExp(loc, e1, f, ve->hasOverloads);
7808: e = e->semantic(sc);
7809: return e;
7810: }
7811: if (f->needThis() && hasThis(sc))
7812: {
7813: /* Should probably supply 'this' after overload resolution,
7814: * not before.
7815: */
7816: Expression *ethis = new ThisExp(loc);
7817: Expression *e = new DelegateExp(loc, ethis, f, ve->hasOverloads);
7818: e = e->semantic(sc);
7819: return e;
7820: }
7821: }
7822: }
7823: return optimize(WANTvalue);
7824: }
7825: return this;
7826: }
7827:
7828: void AddrExp::checkEscape()
7829: {
7830: e1->checkEscapeRef();
7831: }
7832:
7833: /************************************************************/
7834:
7835: PtrExp::PtrExp(Loc loc, Expression *e)
7836: : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
7837: {
7838: // if (e->type)
7839: // type = ((TypePointer *)e->type)->next;
7840: }
7841:
7842: PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
7843: : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
7844: {
7845: type = t;
7846: }
7847:
7848: Expression *PtrExp::semantic(Scope *sc)
7849: {
7850: #if LOGSEMANTIC
7851: printf("PtrExp::semantic('%s')\n", toChars());
7852: #endif
7853: if (!type)
7854: {
7855: Expression *e = op_overload(sc);
7856: if (e)
7857: return e;
7858: Type *tb = e1->type->toBasetype();
7859: switch (tb->ty)
7860: {
7861: case Tpointer:
7862: type = ((TypePointer *)tb)->next;
7863: break;
7864:
7865: case Tsarray:
7866: case Tarray:
7867: type = ((TypeArray *)tb)->next;
7868: e1 = e1->castTo(sc, type->pointerTo());
7869: break;
7870:
7871: default:
7872: error("can only * a pointer, not a '%s'", e1->type->toChars());
7873: case Terror:
7874: return new ErrorExp();
7875: }
7876: rvalue();
7877: }
7878: return this;
7879: }
7880:
7881: #if DMDV2
7882: int PtrExp::isLvalue()
7883: {
7884: return 1;
7885: }
7886: #endif
7887:
7888: void PtrExp::checkEscapeRef()
7889: {
7890: e1->checkEscape();
7891: }
7892:
7893: Expression *PtrExp::toLvalue(Scope *sc, Expression *e)
7894: {
7895: #if 0
7896: tym = tybasic(e1->ET->Tty);
7897: if (!(tyscalar(tym) ||
7898: tym == TYstruct ||
7899: tym == TYarray && e->Eoper == TOKaddr))
7900: synerr(EM_lvalue); // lvalue expected
7901: #endif
7902: return this;
7903: }
7904:
7905: #if DMDV2
7906: Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e)
7907: {
7908: //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
7909:
7910: if (e1->op == TOKsymoff)
7911: { SymOffExp *se = (SymOffExp *)e1;
7912: se->var->checkModify(loc, sc, type);
7913: //return toLvalue(sc, e);
7914: }
7915:
7916: return Expression::modifiableLvalue(sc, e);
7917: }
7918: #endif
7919:
7920: void PtrExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
7921: {
7922: buf->writeByte('*');
7923: expToCBuffer(buf, hgs, e1, precedence[op]);
7924: }
7925:
7926: /************************************************************/
7927:
7928: NegExp::NegExp(Loc loc, Expression *e)
7929: : UnaExp(loc, TOKneg, sizeof(NegExp), e)
7930: {
7931: }
7932:
7933: Expression *NegExp::semantic(Scope *sc)
7934: { Expression *e;
7935:
7936: #if LOGSEMANTIC
7937: printf("NegExp::semantic('%s')\n", toChars());
7938: #endif
7939: if (!type)
7940: {
7941: e = op_overload(sc);
7942: if (e)
7943: return e;
7944:
7945: e1->checkNoBool();
7946: if (!e1->isArrayOperand())
7947: e1->checkArithmetic();
7948: type = e1->type;
7949: }
7950: return this;
7951: }
7952:
7953: /************************************************************/
7954:
7955: UAddExp::UAddExp(Loc loc, Expression *e)
7956: : UnaExp(loc, TOKuadd, sizeof(UAddExp), e)
7957: {
7958: }
7959:
7960: Expression *UAddExp::semantic(Scope *sc)
7961: { Expression *e;
7962:
7963: #if LOGSEMANTIC
7964: printf("UAddExp::semantic('%s')\n", toChars());
7965: #endif
7966: assert(!type);
7967: e = op_overload(sc);
7968: if (e)
7969: return e;
7970: e1->checkNoBool();
7971: e1->checkArithmetic();
7972: return e1;
7973: }
7974:
7975: /************************************************************/
7976:
7977: ComExp::ComExp(Loc loc, Expression *e)
7978: : UnaExp(loc, TOKtilde, sizeof(ComExp), e)
7979: {
7980: }
7981:
7982: Expression *ComExp::semantic(Scope *sc)
7983: { Expression *e;
7984:
7985: if (!type)
7986: {
7987: e = op_overload(sc);
7988: if (e)
7989: return e;
7990:
7991: e1->checkNoBool();
7992: if (!e1->isArrayOperand())
7993: e1 = e1->checkIntegral();
7994: type = e1->type;
7995: }
7996: return this;
7997: }
7998:
7999: /************************************************************/
8000:
8001: NotExp::NotExp(Loc loc, Expression *e)
8002: : UnaExp(loc, TOKnot, sizeof(NotExp), e)
8003: {
8004: }
8005:
8006: Expression *NotExp::semantic(Scope *sc)
8007: {
8008: if (!type)
8009: { // Note there is no operator overload
8010: UnaExp::semantic(sc);
8011: e1 = resolveProperties(sc, e1);
8012: e1 = e1->checkToBoolean(sc);
8013: type = Type::tboolean;
8014: }
8015: return this;
8016: }
8017:
8018: int NotExp::isBit()
8019: {
8020: return TRUE;
8021: }
8022:
8023:
8024:
8025: /************************************************************/
8026:
8027: BoolExp::BoolExp(Loc loc, Expression *e, Type *t)
8028: : UnaExp(loc, TOKtobool, sizeof(BoolExp), e)
8029: {
8030: type = t;
8031: }
8032:
8033: Expression *BoolExp::semantic(Scope *sc)
8034: {
8035: if (!type)
8036: { // Note there is no operator overload
8037: UnaExp::semantic(sc);
8038: e1 = resolveProperties(sc, e1);
8039: e1 = e1->checkToBoolean(sc);
8040: type = Type::tboolean;
8041: }
8042: return this;
8043: }
8044:
8045: int BoolExp::isBit()
8046: {
8047: return TRUE;
8048: }
8049:
8050: /************************************************************/
8051:
8052: DeleteExp::DeleteExp(Loc loc, Expression *e)
8053: : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e)
8054: {
8055: }
8056:
8057: Expression *DeleteExp::semantic(Scope *sc)
8058: {
8059: Type *tb;
8060:
8061: UnaExp::semantic(sc);
8062: e1 = resolveProperties(sc, e1);
8063: e1 = e1->toLvalue(sc, NULL);
8064: if (e1->op == TOKerror)
8065: return e1;
8066: type = Type::tvoid;
8067:
8068: tb = e1->type->toBasetype();
8069: switch (tb->ty)
8070: { case Tclass:
8071: { TypeClass *tc = (TypeClass *)tb;
8072: ClassDeclaration *cd = tc->sym;
8073:
8074: if (cd->isCOMinterface())
8075: { /* Because COM classes are deleted by IUnknown.Release()
8076: */
8077: error("cannot delete instance of COM interface %s", cd->toChars());
8078: }
8079: break;
8080: }
8081: case Tpointer:
8082: tb = ((TypePointer *)tb)->next->toBasetype();
8083: if (tb->ty == Tstruct)
8084: {
8085: TypeStruct *ts = (TypeStruct *)tb;
8086: StructDeclaration *sd = ts->sym;
8087: FuncDeclaration *f = sd->aggDelete;
8088: FuncDeclaration *fd = sd->dtor;
8089:
8090: if (!f && !fd)
8091: break;
8092:
8093: /* Construct:
8094: * ea = copy e1 to a tmp to do side effects only once
8095: * eb = call destructor
8096: * ec = call deallocator
8097: */
8098: Expression *ea = NULL;
8099: Expression *eb = NULL;
8100: Expression *ec = NULL;
8101: VarDeclaration *v;
8102:
8103: if (fd && f)
8104: { Identifier *id = Lexer::idPool("__tmp");
8105: v = new VarDeclaration(loc, e1->type, id, new ExpInitializer(loc, e1));
8106: v->semantic(sc);
8107: v->parent = sc->parent;
8108: ea = new DeclarationExp(loc, v);
8109: ea->type = v->type;
8110: }
8111:
8112: if (fd)
8113: { Expression *e = ea ? new VarExp(loc, v) : e1;
8114: e = new DotVarExp(0, e, fd, 0);
8115: eb = new CallExp(loc, e);
8116: eb = eb->semantic(sc);
8117: }
8118:
8119: if (f)
8120: {
8121: Type *tpv = Type::tvoid->pointerTo();
8122: Expression *e = ea ? new VarExp(loc, v) : e1->castTo(sc, tpv);
8123: e = new CallExp(loc, new VarExp(loc, f), e);
8124: ec = e->semantic(sc);
8125: }
8126: ea = combine(ea, eb);
8127: ea = combine(ea, ec);
8128: assert(ea);
8129: return ea;
8130: }
8131: break;
8132:
8133: case Tarray:
8134: /* BUG: look for deleting arrays of structs with dtors.
8135: */
8136: break;
8137:
8138: default:
8139: if (e1->op == TOKindex)
8140: {
8141: IndexExp *ae = (IndexExp *)(e1);
8142: Type *tb1 = ae->e1->type->toBasetype();
8143: if (tb1->ty == Taarray)
8144: break;
8145: }
8146: error("cannot delete type %s", e1->type->toChars());
8147: return new ErrorExp();
8148: }
8149:
8150: if (e1->op == TOKindex)
8151: {
8152: IndexExp *ae = (IndexExp *)(e1);
8153: Type *tb1 = ae->e1->type->toBasetype();
8154: if (tb1->ty == Taarray)
8155: { if (!global.params.useDeprecated)
8156: error("delete aa[key] deprecated, use aa.remove(key)");
8157: }
8158: }
8159:
8160: return this;
8161: }
8162:
8163: int DeleteExp::checkSideEffect(int flag)
8164: {
8165: return 1;
8166: }
8167:
8168: Expression *DeleteExp::checkToBoolean(Scope *sc)
8169: {
8170: error("delete does not give a boolean result");
8171: return new ErrorExp();
8172: }
8173:
8174: void DeleteExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
8175: {
8176: buf->writestring("delete ");
8177: expToCBuffer(buf, hgs, e1, precedence[op]);
8178: }
8179:
8180: /************************************************************/
8181:
8182: CastExp::CastExp(Loc loc, Expression *e, Type *t)
8183: : UnaExp(loc, TOKcast, sizeof(CastExp), e)
8184: {
8185: to = t;
8186: this->mod = ~0;
8187: }
8188:
8189: #if DMDV2
8190: /* For cast(const) and cast(immutable)
8191: */
8192: CastExp::CastExp(Loc loc, Expression *e, unsigned mod)
8193: : UnaExp(loc, TOKcast, sizeof(CastExp), e)
8194: {
8195: to = NULL;
8196: this->mod = mod;
8197: }
8198: #endif
8199:
8200: Expression *CastExp::syntaxCopy()
8201: {
8202: return to ? new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy())
8203: : new CastExp(loc, e1->syntaxCopy(), mod);
8204: }
8205:
8206:
8207: Expression *CastExp::semantic(Scope *sc)
8208: { Expression *e;
8209: BinExp *b;
warning C4101: 'b' : unreferenced local variable
8210: UnaExp *u;
warning C4101: 'u' : unreferenced local variable
8211:
8212: #if LOGSEMANTIC
8213: printf("CastExp::semantic('%s')\n", toChars());
8214: #endif
8215:
8216: //static int x; assert(++x < 10);
8217:
8218: if (type)
8219: return this;
8220: UnaExp::semantic(sc);
8221: if (e1->type) // if not a tuple
8222: {
8223: e1 = resolveProperties(sc, e1);
8224:
8225: if (!to)
8226: {
8227: /* Handle cast(const) and cast(immutable), etc.
8228: */
8229: to = e1->type->castMod(mod);
8230: }
8231: else
8232: to = to->semantic(loc, sc);
8233:
8234: if (!to->equals(e1->type))
8235: {
8236: e = op_overload(sc);
8237: if (e)
8238: {
8239: return e->implicitCastTo(sc, to);
8240: }
8241: }
8242:
8243: if (e1->op == TOKtemplate)
8244: {
8245: error("cannot cast template %s to type %s", e1->toChars(), to->toChars());
8246: return new ErrorExp();
8247: }
8248:
8249: Type *t1b = e1->type->toBasetype();
8250: Type *tob = to->toBasetype();
8251: if (tob->ty == Tstruct &&
8252: !tob->equals(t1b)
8253: )
8254: {
8255: /* Look to replace:
8256: * cast(S)t
8257: * with:
8258: * S(t)
8259: */
8260:
8261: // Rewrite as to.call(e1)
8262: e = new TypeExp(loc, to);
8263: e = new CallExp(loc, e, e1);
8264: e = e->trySemantic(sc);
8265: if (e)
8266: return e;
8267: }
8268:
8269: // Struct casts are possible only when the sizes match
8270: if (tob->ty == Tstruct || t1b->ty == Tstruct)
8271: {
8272: size_t fromsize = t1b->size(loc);
warning C4244: 'initializing' : conversion from 'd_uns64' to 'size_t', possible loss of data
8273: size_t tosize = tob->size(loc);
warning C4244: 'initializing' : conversion from 'd_uns64' to 'size_t', possible loss of data
8274: if (fromsize != tosize)
8275: {
8276: error("cannot cast from %s to %s", e1->type->toChars(), to->toChars());
8277: return new ErrorExp();
8278: }
8279: }
8280: }
8281: else if (!to)
8282: { error("cannot cast tuple");
8283: return new ErrorExp();
8284: }
8285:
8286: if (!e1->type)
8287: { error("cannot cast %s", e1->toChars());
8288: return new ErrorExp();
8289: }
8290:
8291: // Check for unsafe casts
8292: if (sc->func && !sc->intypeof)
8293: { // Disallow unsafe casts
8294: Type *tob = to->toBasetype();
8295: Type *t1b = e1->type->toBasetype();
8296:
8297: // Implicit conversions are always safe
8298: if (t1b->implicitConvTo(tob))
8299: goto Lsafe;
8300:
8301: if (!t1b->isMutable() && tob->isMutable())
8302: goto Lunsafe;
8303:
8304: if (t1b->isShared() && !tob->isShared())
8305: // Cast away shared
8306: goto Lunsafe;
8307:
8308: if (!tob->hasPointers())
8309: goto Lsafe;
8310:
8311: if (tob->ty == Tclass && t1b->ty == Tclass)
8312: {
8313: ClassDeclaration *cdfrom = t1b->isClassHandle();
8314: ClassDeclaration *cdto = tob->isClassHandle();
8315:
8316: int offset;
8317: if (!cdfrom->isBaseOf(cdto, &offset))
8318: goto Lunsafe;
8319:
8320: if (cdfrom->isCPPinterface() ||
8321: cdto->isCPPinterface())
8322: goto Lunsafe;
8323:
8324: goto Lsafe;
8325: }
8326:
8327: if (tob->ty == Tarray && t1b->ty == Tarray)
8328: {
8329: Type* tobn = tob->nextOf()->toBasetype();
8330: Type* t1bn = t1b->nextOf()->toBasetype();
8331: if (!tobn->hasPointers() && MODimplicitConv(t1bn->mod, tobn->mod))
8332: goto Lsafe;
8333: }
8334: if (tob->ty == Tpointer && t1b->ty == Tpointer)
8335: {
8336: Type* tobn = tob->nextOf()->toBasetype();
8337: Type* t1bn = t1b->nextOf()->toBasetype();
8338: if (!tobn->hasPointers() &&
8339: tobn->ty != Tfunction && t1bn->ty != Tfunction &&
8340: tobn->size() <= t1bn->size() &&
8341: MODimplicitConv(t1bn->mod, tobn->mod))
8342: goto Lsafe;
8343: }
8344:
8345: Lunsafe:
8346: if (sc->func->setUnsafe())
8347: { error("cast from %s to %s not allowed in safe code", e1->type->toChars(), to->toChars());
8348: return new ErrorExp();
8349: }
8350: }
8351:
8352: Lsafe:
8353: e = e1->castTo(sc, to);
8354: return e;
8355: }
8356:
8357: int CastExp::checkSideEffect(int flag)
8358: {
8359: /* if not:
8360: * cast(void)
8361: * cast(classtype)func()
8362: */
8363: if (!to->equals(Type::tvoid) &&
8364: !(to->ty == Tclass && e1->op == TOKcall && e1->type->ty == Tclass))
8365: return Expression::checkSideEffect(flag);
8366: return 1;
8367: }
8368:
8369: void CastExp::checkEscape()
8370: { Type *tb = type->toBasetype();
8371: if (tb->ty == Tarray && e1->op == TOKvar &&
8372: e1->type->toBasetype()->ty == Tsarray)
8373: { VarExp *ve = (VarExp *)e1;
8374: VarDeclaration *v = ve->var->isVarDeclaration();
8375: if (v)
8376: {
8377: if (!v->isDataseg() && !v->isParameter())
8378: error("escaping reference to local %s", v->toChars());
8379: }
8380: }
8381: }
8382:
8383: void CastExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
8384: {
8385: buf->writestring("cast(");
8386: #if DMDV1
8387: to->toCBuffer(buf, NULL, hgs);
8388: #else
8389: if (to)
8390: to->toCBuffer(buf, NULL, hgs);
8391: else
8392: {
8393: MODtoBuffer(buf, mod);
8394: }
8395: #endif
8396: buf->writeByte(')');
8397: expToCBuffer(buf, hgs, e1, precedence[op]);
8398: }
8399:
8400:
8401: /************************************************************/
8402:
8403: SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr)
8404: : UnaExp(loc, TOKslice, sizeof(SliceExp), e1)
8405: {
8406: this->upr = upr;
8407: this->lwr = lwr;
8408: lengthVar = NULL;
8409: }
8410:
8411: Expression *SliceExp::syntaxCopy()
8412: {
8413: Expression *lwr = NULL;
8414: if (this->lwr)
8415: lwr = this->lwr->syntaxCopy();
8416:
8417: Expression *upr = NULL;
8418: if (this->upr)
8419: upr = this->upr->syntaxCopy();
8420:
8421: return new SliceExp(loc, e1->syntaxCopy(), lwr, upr);
8422: }
8423:
8424: Expression *SliceExp::semantic(Scope *sc)
8425: { Expression *e;
8426: AggregateDeclaration *ad;
8427: //FuncDeclaration *fd;
8428: ScopeDsymbol *sym;
8429:
8430: #if LOGSEMANTIC
8431: printf("SliceExp::semantic('%s')\n", toChars());
8432: #endif
8433: if (type)
8434: return this;
8435:
8436: UnaExp::semantic(sc);
8437: e1 = resolveProperties(sc, e1);
8438:
8439: e = this;
8440:
8441: Type *t = e1->type->toBasetype();
8442: if (t->ty == Tpointer)
8443: {
8444: if (!lwr || !upr)
8445: { error("need upper and lower bound to slice pointer");
8446: return new ErrorExp();
8447: }
8448: }
8449: else if (t->ty == Tarray)
8450: {
8451: }
8452: else if (t->ty == Tsarray)
8453: {
8454: }
8455: else if (t->ty == Tclass)
8456: {
8457: ad = ((TypeClass *)t)->sym;
8458: goto L1;
8459: }
8460: else if (t->ty == Tstruct)
8461: {
8462: ad = ((TypeStruct *)t)->sym;
8463:
8464: L1:
8465: if (search_function(ad, Id::slice))
8466: {
8467: // Rewrite as e1.slice(lwr, upr)
8468: e = new DotIdExp(loc, e1, Id::slice);
8469:
8470: if (lwr)
8471: {
8472: assert(upr);
8473: e = new CallExp(loc, e, lwr, upr);
8474: }
8475: else
8476: { assert(!upr);
8477: e = new CallExp(loc, e);
8478: }
8479: e = e->semantic(sc);
8480: return e;
8481: }
8482: goto Lerror;
8483: }
8484: else if (t->ty == Ttuple)
8485: {
8486: if (!lwr && !upr)
8487: return e1;
8488: if (!lwr || !upr)
8489: { error("need upper and lower bound to slice tuple");
8490: goto Lerror;
8491: }
8492: }
8493: else if (t == Type::terror)
8494: goto Lerr;
8495: else
8496: goto Lerror;
8497:
8498: {
8499: Scope *sc2 = sc;
8500: if (t->ty == Tsarray || t->ty == Tarray || t->ty == Ttuple)
8501: {
8502: sym = new ArrayScopeSymbol(sc, this);
8503: sym->loc = loc;
8504: sym->parent = sc->scopesym;
8505: sc2 = sc->push(sym);
8506: }
8507:
8508: if (lwr)
8509: { lwr = lwr->semantic(sc2);
8510: lwr = resolveProperties(sc2, lwr);
8511: lwr = lwr->implicitCastTo(sc2, Type::tsize_t);
8512: if (lwr->type == Type::terror)
8513: goto Lerr;
8514: }
8515: if (upr)
8516: { upr = upr->semantic(sc2);
8517: upr = resolveProperties(sc2, upr);
8518: upr = upr->implicitCastTo(sc2, Type::tsize_t);
8519: if (upr->type == Type::terror)
8520: goto Lerr;
8521: }
8522:
8523: if (sc2 != sc)
8524: sc2->pop();
8525: }
8526:
8527: if (t->ty == Ttuple)
8528: {
8529: lwr = lwr->optimize(WANTvalue | WANTinterpret);
8530: upr = upr->optimize(WANTvalue | WANTinterpret);
8531: uinteger_t i1 = lwr->toUInteger();
8532: uinteger_t i2 = upr->toUInteger();
8533:
8534: size_t length;
8535: TupleExp *te;
8536: TypeTuple *tup;
8537:
8538: if (e1->op == TOKtuple) // slicing an expression tuple
8539: { te = (TupleExp *)e1;
8540: length = te->exps->dim;
8541: }
8542: else if (e1->op == TOKtype) // slicing a type tuple
8543: { tup = (TypeTuple *)t;
8544: length = Parameter::dim(tup->arguments);
8545: }
8546: else
8547: assert(0);
8548:
8549: if (i1 <= i2 && i2 <= length)
8550: { size_t j1 = (size_t) i1;
8551: size_t j2 = (size_t) i2;
8552:
8553: if (e1->op == TOKtuple)
8554: { Expressions *exps = new Expressions;
8555: exps->setDim(j2 - j1);
8556: for (size_t i = 0; i < j2 - j1; i++)
8557: { Expression *e = (*te->exps)[j1 + i];
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '8425' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 8425
8558: (*exps)[i] = e;
8559: }
8560: e = new TupleExp(loc, exps);
8561: }
8562: else
8563: { Parameters *args = new Parameters;
8564: args->reserve(j2 - j1);
8565: for (size_t i = j1; i < j2; i++)
8566: { Parameter *arg = Parameter::getNth(tup->arguments, i);
8567: args->push(arg);
8568: }
8569: e = new TypeExp(e1->loc, new TypeTuple(args));
8570: }
8571: e = e->semantic(sc);
8572: }
8573: else
8574: {
8575: error("string slice [%ju .. %ju] is out of bounds", i1, i2);
8576: goto Lerr;
8577: }
8578: return e;
8579: }
8580:
8581: if (t->ty == Tarray)
8582: {
8583: type = e1->type;
8584: }
8585: else
8586: type = t->nextOf()->arrayOf();
8587: return e;
8588:
8589: Lerror:
8590: if (e1->op == TOKerror)
8591: return e1;
8592: char *s;
8593: if (t->ty == Tvoid)
8594: s = e1->toChars();
8595: else
8596: s = t->toChars();
8597: error("%s cannot be sliced with []", s);
8598: Lerr:
8599: e = new ErrorExp();
8600: return e;
8601: }
8602:
8603: void SliceExp::checkEscape()
8604: {
8605: e1->checkEscape();
8606: }
8607:
8608: void SliceExp::checkEscapeRef()
8609: {
8610: e1->checkEscapeRef();
8611: }
8612:
8613: #if DMDV2
8614: int SliceExp::isLvalue()
8615: {
8616: return 1;
8617: }
8618: #endif
8619:
8620: Expression *SliceExp::toLvalue(Scope *sc, Expression *e)
8621: {
8622: return this;
8623: }
8624:
8625: Expression *SliceExp::modifiableLvalue(Scope *sc, Expression *e)
8626: {
8627: error("slice expression %s is not a modifiable lvalue", toChars());
8628: return this;
8629: }
8630:
8631: int SliceExp::isBool(int result)
8632: {
8633: return e1->isBool(result);
8634: }
8635:
8636: void SliceExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
8637: {
8638: expToCBuffer(buf, hgs, e1, precedence[op]);
8639: buf->writeByte('[');
8640: if (upr || lwr)
8641: {
8642: if (lwr)
8643: expToCBuffer(buf, hgs, lwr, PREC_assign);
8644: else
8645: buf->writeByte('0');
8646: buf->writestring("..");
8647: if (upr)
8648: expToCBuffer(buf, hgs, upr, PREC_assign);
8649: else
8650: buf->writestring("length"); // BUG: should be array.length
8651: }
8652: buf->writeByte(']');
8653: }
8654:
8655: int SliceExp::canThrow(bool mustNotThrow)
8656: {
8657: return UnaExp::canThrow(mustNotThrow)
8658: || (lwr != NULL && lwr->canThrow(mustNotThrow))
8659: || (upr != NULL && upr->canThrow(mustNotThrow));
8660: }
8661:
8662: /********************** ArrayLength **************************************/
8663:
8664: ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1)
8665: : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1)
8666: {
8667: }
8668:
8669: Expression *ArrayLengthExp::semantic(Scope *sc)
8670: {
8671: #if LOGSEMANTIC
8672: printf("ArrayLengthExp::semantic('%s')\n", toChars());
8673: #endif
8674: if (!type)
8675: {
8676: UnaExp::semantic(sc);
8677: e1 = resolveProperties(sc, e1);
8678:
8679: type = Type::tsize_t;
8680: }
8681: return this;
8682: }
8683:
8684: Expression *opAssignToOp(Loc loc, enum TOK op, Expression *e1, Expression *e2)
8685: { Expression *e;
8686:
8687: switch (op)
8688: {
8689: case TOKaddass: e = new AddExp(loc, e1, e2); break;
8690: case TOKminass: e = new MinExp(loc, e1, e2); break;
8691: case TOKmulass: e = new MulExp(loc, e1, e2); break;
8692: case TOKdivass: e = new DivExp(loc, e1, e2); break;
8693: case TOKmodass: e = new ModExp(loc, e1, e2); break;
8694: case TOKandass: e = new AndExp(loc, e1, e2); break;
8695: case TOKorass: e = new OrExp (loc, e1, e2); break;
8696: case TOKxorass: e = new XorExp(loc, e1, e2); break;
8697: case TOKshlass: e = new ShlExp(loc, e1, e2); break;
8698: case TOKshrass: e = new ShrExp(loc, e1, e2); break;
8699: case TOKushrass: e = new UshrExp(loc, e1, e2); break;
8700: default: assert(0);
8701: }
8702: return e;
8703: }
8704:
8705: /*********************
8706: * Rewrite:
8707: * array.length op= e2
8708: * as:
8709: * array.length = array.length op e2
8710: * or:
8711: * auto tmp = &array;
8712: * (*tmp).length = (*tmp).length op e2
8713: */
8714:
8715: Expression *ArrayLengthExp::rewriteOpAssign(BinExp *exp)
8716: { Expression *e;
8717:
8718: assert(exp->e1->op == TOKarraylength);
8719: ArrayLengthExp *ale = (ArrayLengthExp *)exp->e1;
8720: if (ale->e1->op == TOKvar)
8721: { e = opAssignToOp(exp->loc, exp->op, ale, exp->e2);
8722: e = new AssignExp(exp->loc, ale->syntaxCopy(), e);
8723: }
8724: else
8725: {
8726: /* auto tmp = &array;
8727: * (*tmp).length = (*tmp).length op e2
8728: */
8729: Identifier *id = Lexer::uniqueId("__arraylength");
8730: ExpInitializer *ei = new ExpInitializer(ale->loc, new AddrExp(ale->loc, ale->e1));
8731: VarDeclaration *tmp = new VarDeclaration(ale->loc, ale->e1->type->pointerTo(), id, ei);
8732:
8733: Expression *e1 = new ArrayLengthExp(ale->loc, new PtrExp(ale->loc, new VarExp(ale->loc, tmp)));
8734: Expression *elvalue = e1->syntaxCopy();
8735: e = opAssignToOp(exp->loc, exp->op, e1, exp->e2);
8736: e = new AssignExp(exp->loc, elvalue, e);
8737: e = new CommaExp(exp->loc, new DeclarationExp(ale->loc, tmp), e);
8738: }
8739: return e;
8740: }
8741:
8742: void ArrayLengthExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
8743: {
8744: expToCBuffer(buf, hgs, e1, PREC_primary);
8745: buf->writestring(".length");
8746: }
8747:
8748: /*********************** ArrayExp *************************************/
8749:
8750: // e1 [ i1, i2, i3, ... ]
8751:
8752: ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args)
8753: : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1)
8754: {
8755: arguments = args;
8756: }
8757:
8758: Expression *ArrayExp::syntaxCopy()
8759: {
8760: return new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
8761: }
8762:
8763: Expression *ArrayExp::semantic(Scope *sc)
8764: { Expression *e;
8765: Type *t1;
8766:
8767: #if LOGSEMANTIC
8768: printf("ArrayExp::semantic('%s')\n", toChars());
8769: #endif
8770: UnaExp::semantic(sc);
8771: e1 = resolveProperties(sc, e1);
8772:
8773: t1 = e1->type->toBasetype();
8774: if (t1->ty != Tclass && t1->ty != Tstruct)
8775: { // Convert to IndexExp
8776: if (arguments->dim != 1)
8777: { error("only one index allowed to index %s", t1->toChars());
8778: goto Lerr;
8779: }
8780: e = new IndexExp(loc, e1, arguments->tdata()[0]);
8781: return e->semantic(sc);
8782: }
8783:
8784: // Run semantic() on each argument
8785: for (size_t i = 0; i < arguments->dim; i++)
8786: { e = arguments->tdata()[i];
8787:
8788: e = e->semantic(sc);
8789: if (!e->type)
8790: { error("%s has no value", e->toChars());
8791: goto Lerr;
8792: }
8793: else if (e->type == Type::terror)
8794: goto Lerr;
8795: arguments->tdata()[i] = e;
8796: }
8797:
8798: expandTuples(arguments);
8799: assert(arguments && arguments->dim);
8800:
8801: e = op_overload(sc);
8802: if (!e)
8803: { error("no [] operator overload for type %s", e1->type->toChars());
8804: goto Lerr;
8805: }
8806: return e;
8807:
8808: Lerr:
8809: return new ErrorExp();
8810: }
8811:
8812: #if DMDV2
8813: int ArrayExp::isLvalue()
8814: {
8815: if (type && type->toBasetype()->ty == Tvoid)
8816: return 0;
8817: return 1;
8818: }
8819: #endif
8820:
8821: Expression *ArrayExp::toLvalue(Scope *sc, Expression *e)
8822: {
8823: if (type && type->toBasetype()->ty == Tvoid)
8824: error("voids have no value");
8825: return this;
8826: }
8827:
8828:
8829: void ArrayExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
8830: {
8831: expToCBuffer(buf, hgs, e1, PREC_primary);
8832: buf->writeByte('[');
8833: argsToCBuffer(buf, arguments, hgs);
8834: buf->writeByte(']');
8835: }
8836:
8837: /************************* DotExp ***********************************/
8838:
8839: DotExp::DotExp(Loc loc, Expression *e1, Expression *e2)
8840: : BinExp(loc, TOKdotexp, sizeof(DotExp), e1, e2)
8841: {
8842: }
8843:
8844: Expression *DotExp::semantic(Scope *sc)
8845: {
8846: #if LOGSEMANTIC
8847: printf("DotExp::semantic('%s')\n", toChars());
8848: if (type) printf("\ttype = %s\n", type->toChars());
8849: #endif
8850: e1 = e1->semantic(sc);
8851: e2 = e2->semantic(sc);
8852: if (e2->op == TOKimport)
8853: {
8854: ScopeExp *se = (ScopeExp *)e2;
8855: TemplateDeclaration *td = se->sds->isTemplateDeclaration();
8856: if (td)
8857: { Expression *e = new DotTemplateExp(loc, e1, td);
8858: e = e->semantic(sc);
8859: return e;
8860: }
8861: }
8862: if (!type)
8863: type = e2->type;
8864: return this;
8865: }
8866:
8867: void DotExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
8868: {
8869: expToCBuffer(buf, hgs, e1, PREC_primary);
8870: buf->writeByte('.');
8871: expToCBuffer(buf, hgs, e2, PREC_primary);
8872: }
8873:
8874: /************************* CommaExp ***********************************/
8875:
8876: CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2)
8877: : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2)
8878: {
8879: }
8880:
8881: Expression *CommaExp::semantic(Scope *sc)
8882: {
8883: if (!type)
8884: { BinExp::semanticp(sc);
8885: e1 = e1->addDtorHook(sc);
8886: type = e2->type;
8887: }
8888: return this;
8889: }
8890:
8891: void CommaExp::checkEscape()
8892: {
8893: e2->checkEscape();
8894: }
8895:
8896: void CommaExp::checkEscapeRef()
8897: {
8898: e2->checkEscapeRef();
8899: }
8900:
8901: #if DMDV2
8902: int CommaExp::isLvalue()
8903: {
8904: return e2->isLvalue();
8905: }
8906: #endif
8907:
8908: Expression *CommaExp::toLvalue(Scope *sc, Expression *e)
8909: {
8910: e2 = e2->toLvalue(sc, NULL);
8911: return this;
8912: }
8913:
8914: Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e)
8915: {
8916: e2 = e2->modifiableLvalue(sc, e);
8917: return this;
8918: }
8919:
8920: int CommaExp::isBool(int result)
8921: {
8922: return e2->isBool(result);
8923: }
8924:
8925: int CommaExp::checkSideEffect(int flag)
8926: {
8927: /* Check for compiler-generated code of the form auto __tmp, e, __tmp;
8928: * In such cases, only check e for side effect (it's OK for __tmp to have
8929: * no side effect).
8930: * See Bugzilla 4231 for discussion
8931: */
8932: CommaExp* firstComma = this;
8933: while (firstComma->e1->op == TOKcomma)
8934: firstComma = (CommaExp *)firstComma->e1;
8935: if (firstComma->e1->op == TOKdeclaration &&
8936: e2->op == TOKvar &&
8937: ((DeclarationExp *)firstComma->e1)->declaration == ((VarExp*)e2)->var)
8938: {
8939: return e1->checkSideEffect(flag);
8940: }
8941:
8942: if (flag == 2)
8943: return e1->checkSideEffect(2) || e2->checkSideEffect(2);
8944: else
8945: {
8946: // Don't check e1 until we cast(void) the a,b code generation
8947: return e2->checkSideEffect(flag);
8948: }
8949: }
8950:
8951: Expression *CommaExp::addDtorHook(Scope *sc)
8952: {
8953: e2 = e2->addDtorHook(sc);
8954: return this;
8955: }
8956:
8957: /************************** IndexExp **********************************/
8958:
8959: // e1 [ e2 ]
8960:
8961: IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2)
8962: : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2)
8963: {
8964: //printf("IndexExp::IndexExp('%s')\n", toChars());
8965: lengthVar = NULL;
8966: modifiable = 0; // assume it is an rvalue
8967: }
8968:
8969: Expression *IndexExp::semantic(Scope *sc)
8970: { Expression *e;
8971: BinExp *b;
warning C4101: 'b' : unreferenced local variable
8972: UnaExp *u;
warning C4101: 'u' : unreferenced local variable
8973: Type *t1;
8974: ScopeDsymbol *sym;
8975:
8976: #if LOGSEMANTIC
8977: printf("IndexExp::semantic('%s')\n", toChars());
8978: #endif
8979: if (type)
8980: return this;
8981: if (!e1->type)
8982: e1 = e1->semantic(sc);
8983: assert(e1->type); // semantic() should already be run on it
8984: if (e1->op == TOKerror)
8985: goto Lerr;
8986: e = this;
8987:
8988: // Note that unlike C we do not implement the int[ptr]
8989:
8990: t1 = e1->type->toBasetype();
8991:
8992: if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
8993: { // Create scope for 'length' variable
8994: sym = new ArrayScopeSymbol(sc, this);
8995: sym->loc = loc;
8996: sym->parent = sc->scopesym;
8997: sc = sc->push(sym);
8998: }
8999:
9000: e2 = e2->semantic(sc);
9001: if (!e2->type)
9002: {
9003: error("%s has no value", e2->toChars());
9004: goto Lerr;
9005: }
9006: if (e2->type->ty == Ttuple && ((TupleExp *)e2)->exps->dim == 1) // bug 4444 fix
9007: e2 = (Expression *)((TupleExp *)e2)->exps->data[0];
9008: e2 = resolveProperties(sc, e2);
9009: if (e2->type == Type::terror)
9010: goto Lerr;
9011:
9012: if (t1->ty == Tsarray || t1->ty == Tarray || t1->ty == Ttuple)
9013: sc = sc->pop();
9014:
9015: switch (t1->ty)
9016: {
9017: case Tpointer:
9018: case Tarray:
9019: e2 = e2->implicitCastTo(sc, Type::tsize_t);
9020: e->type = ((TypeNext *)t1)->next;
9021: break;
9022:
9023: case Tsarray:
9024: {
9025: e2 = e2->implicitCastTo(sc, Type::tsize_t);
9026:
9027: TypeSArray *tsa = (TypeSArray *)t1;
9028:
9029: #if 0 // Don't do now, because it might be short-circuit evaluated
9030: // Do compile time array bounds checking if possible
9031: e2 = e2->optimize(WANTvalue);
9032: if (e2->op == TOKint64)
9033: {
9034: dinteger_t index = e2->toInteger();
9035: dinteger_t length = tsa->dim->toInteger();
9036: if (index < 0 || index >= length)
9037: error("array index [%lld] is outside array bounds [0 .. %lld]",
9038: index, length);
9039: }
9040: #endif
9041: e->type = t1->nextOf();
9042: break;
9043: }
9044:
9045: case Taarray:
9046: { TypeAArray *taa = (TypeAArray *)t1;
9047: /* We can skip the implicit conversion if they differ only by
9048: * constness (Bugzilla 2684, see also bug 2954b)
9049: */
9050: if (!arrayTypeCompatibleWithoutCasting(e2->loc, e2->type, taa->index))
9051: {
9052: e2 = e2->implicitCastTo(sc, taa->index); // type checking
9053: }
9054: type = taa->next;
9055: break;
9056: }
9057:
9058: case Ttuple:
9059: {
9060: e2 = e2->implicitCastTo(sc, Type::tsize_t);
9061: e2 = e2->optimize(WANTvalue | WANTinterpret);
9062: uinteger_t index = e2->toUInteger();
9063: size_t length;
9064: TupleExp *te;
9065: TypeTuple *tup;
9066:
9067: if (e1->op == TOKtuple)
9068: { te = (TupleExp *)e1;
9069: length = te->exps->dim;
9070: }
9071: else if (e1->op == TOKtype)
9072: {
9073: tup = (TypeTuple *)t1;
9074: length = Parameter::dim(tup->arguments);
9075: }
9076: else
9077: assert(0);
9078:
9079: if (index < length)
9080: {
9081:
9082: if (e1->op == TOKtuple)
9083: e = (*te->exps)[(size_t)index];
9084: else
9085: e = new TypeExp(e1->loc, Parameter::getNth(tup->arguments, (size_t)index)->type);
9086: }
9087: else
9088: {
9089: error("array index [%ju] is outside array bounds [0 .. %"SIZE_T_FORMAT"u]",
9090: index, length);
9091: e = e1;
9092: }
9093: break;
9094: }
9095:
9096: default:
9097: if (e1->op == TOKerror)
9098: goto Lerr;
9099: error("%s must be an array or pointer type, not %s",
9100: e1->toChars(), e1->type->toChars());
9101: case Terror:
9102: goto Lerr;
9103: }
9104: return e;
9105:
9106: Lerr:
9107: return new ErrorExp();
9108: }
9109:
9110: #if DMDV2
9111: int IndexExp::isLvalue()
9112: {
9113: return 1;
9114: }
9115: #endif
9116:
9117: Expression *IndexExp::toLvalue(Scope *sc, Expression *e)
9118: {
9119: // if (type && type->toBasetype()->ty == Tvoid)
9120: // error("voids have no value");
9121: return this;
9122: }
9123:
9124: Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
9125: {
9126: //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
9127: modifiable = 1;
9128: if (e1->op == TOKstring)
9129: error("string literals are immutable");
9130: if (type && (!type->isMutable() || !type->isAssignable()))
9131: error("%s isn't mutable", e->toChars());
9132: Type *t1 = e1->type->toBasetype();
9133: if (t1->ty == Taarray)
9134: { TypeAArray *taa = (TypeAArray *)t1;
9135: Type *t2b = e2->type->toBasetype();
9136: if (t2b->ty == Tarray && t2b->nextOf()->isMutable())
9137: error("associative arrays can only be assigned values with immutable keys, not %s", e2->type->toChars());
9138: e1 = e1->modifiableLvalue(sc, e1);
9139: }
9140: return toLvalue(sc, e);
9141: }
9142:
9143: void IndexExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
9144: {
9145: expToCBuffer(buf, hgs, e1, PREC_primary);
9146: buf->writeByte('[');
9147: expToCBuffer(buf, hgs, e2, PREC_assign);
9148: buf->writeByte(']');
9149: }
9150:
9151:
9152: /************************* PostExp ***********************************/
9153:
9154: PostExp::PostExp(enum TOK op, Loc loc, Expression *e)
9155: : BinExp(loc, op, sizeof(PostExp), e,
9156: new IntegerExp(loc, 1, Type::tint32))
9157: {
9158: }
9159:
9160: Expression *PostExp::semantic(Scope *sc)
9161: { Expression *e = this;
9162:
9163: if (!type)
9164: {
9165: BinExp::semantic(sc);
9166: e1 = resolveProperties(sc, e1);
9167:
9168: e = op_overload(sc);
9169: if (e)
9170: return e;
9171:
9172: e1 = e1->modifiableLvalue(sc, e1);
9173:
9174: Type *t1 = e1->type->toBasetype();
9175: if (t1->ty == Tclass || t1->ty == Tstruct)
9176: { /* Check for operator overloading,
9177: * but rewrite in terms of ++e instead of e++
9178: */
9179:
9180: /* If e1 is not trivial, take a reference to it
9181: */
9182: Expression *de = NULL;
9183: if (e1->op != TOKvar)
9184: {
9185: // ref v = e1;
9186: Identifier *id = Lexer::uniqueId("__postref");
9187: ExpInitializer *ei = new ExpInitializer(loc, e1);
9188: VarDeclaration *v = new VarDeclaration(loc, e1->type, id, ei);
9189: v->storage_class |= STCref | STCforeach;
9190: de = new DeclarationExp(loc, v);
warning C6211: Leaking memory 'de' due to an exception. Consider using a local catch block to clean up memory: Lines: 9161, 9163, 9165, 9166, 9168, 9169, 9172, 9174, 9175, 9182, 9183, 9186, 9187, 9188, 9189, 9190, 9191
9191: e1 = new VarExp(e1->loc, v);
9192: }
9193:
9194: /* Rewrite as:
9195: * auto tmp = e1; ++e1; tmp
9196: */
9197: Identifier *id = Lexer::uniqueId("__pitmp");
9198: ExpInitializer *ei = new ExpInitializer(loc, e1);
9199: VarDeclaration *tmp = new VarDeclaration(loc, e1->type, id, ei);
9200: Expression *ea = new DeclarationExp(loc, tmp);
warning C6211: Leaking memory 'ea' due to an exception. Consider using a local catch block to clean up memory: Lines: 9161, 9163, 9165, 9166, 9168, 9169, 9172, 9174, 9175, 9182, 9183, 9197, 9198, 9199, 9200, 9202, 9203
9201:
9202: Expression *eb = e1->syntaxCopy();
9203: eb = new PreExp(op == TOKplusplus ? TOKpreplusplus : TOKpreminusminus, loc, eb);
warning C6211: Leaking memory 'eb' due to an exception. Consider using a local catch block to clean up memory: Lines: 9161, 9163, 9165, 9166, 9168, 9169, 9172, 9174, 9175, 9182, 9183, 9197, 9198, 9199, 9200, 9202, 9203, 9205
9204:
9205: Expression *ec = new VarExp(loc, tmp);
warning C6211: Leaking memory 'ec' due to an exception. Consider using a local catch block to clean up memory: Lines: 9161, 9163, 9165, 9166, 9168, 9169, 9172, 9174, 9175, 9182, 9183, 9197, 9198, 9199, 9200, 9202, 9203, 9205, 9208, 9210
9206:
9207: // Combine de,ea,eb,ec
9208: if (de)
9209: ea = new CommaExp(loc, de, ea);
9210: e = new CommaExp(loc, ea, eb);
9211: e = new CommaExp(loc, e, ec);
9212: e = e->semantic(sc);
9213: return e;
9214: }
9215:
9216: e = this;
9217: e1->checkScalar();
9218: e1->checkNoBool();
9219: if (e1->type->ty == Tpointer)
9220: e = scaleFactor(sc);
9221: else
9222: e2 = e2->castTo(sc, e1->type);
9223: e->type = e1->type;
9224: }
9225: return e;
9226: }
9227:
9228: void PostExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
9229: {
9230: expToCBuffer(buf, hgs, e1, precedence[op]);
9231: buf->writestring(Token::toChars(op));
9232: }
9233:
9234: /************************* PreExp ***********************************/
9235:
9236: PreExp::PreExp(enum TOK op, Loc loc, Expression *e)
9237: : UnaExp(loc, op, sizeof(PreExp), e)
9238: {
9239: }
9240:
9241: Expression *PreExp::semantic(Scope *sc)
9242: {
9243: Expression *e;
9244:
9245: e = op_overload(sc);
9246: if (e)
9247: return e;
9248:
9249: // Rewrite as e1+=1 or e1-=1
9250: if (op == TOKpreplusplus)
9251: e = new AddAssignExp(loc, e1, new IntegerExp(loc, 1, Type::tint32));
9252: else
9253: e = new MinAssignExp(loc, e1, new IntegerExp(loc, 1, Type::tint32));
9254: return e->semantic(sc);
9255: }
9256:
9257: void PreExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
9258: {
9259: buf->writestring(Token::toChars(op));
9260: expToCBuffer(buf, hgs, e1, precedence[op]);
9261: }
9262:
9263: /************************************************************/
9264:
9265: /* op can be TOKassign, TOKconstruct, or TOKblit */
9266:
9267: AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2)
9268: : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2)
9269: {
9270: ismemset = 0;
9271: }
9272:
9273: Expression *AssignExp::semantic(Scope *sc)
9274: {
9275: Expression *e1old = e1;
9276:
9277: #if LOGSEMANTIC
9278: printf("AssignExp::semantic('%s')\n", toChars());
9279: #endif
9280: //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
9281: //printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op));
9282:
9283: if (type)
9284: return this;
9285:
9286: if (e2->op == TOKcomma)
9287: { /* Rewrite to get rid of the comma from rvalue
9288: */
9289: AssignExp *ea = new AssignExp(loc, e1, ((CommaExp *)e2)->e2);
9290: ea->op = op;
9291: Expression *e = new CommaExp(loc, ((CommaExp *)e2)->e1, ea);
9292: return e->semantic(sc);
9293: }
9294:
9295: /* Look for operator overloading of a[i]=value.
9296: * Do it before semantic() otherwise the a[i] will have been
9297: * converted to a.opIndex() already.
9298: */
9299: if (e1->op == TOKarray)
9300: {
9301: ArrayExp *ae = (ArrayExp *)e1;
9302: AggregateDeclaration *ad;
9303: Identifier *id = Id::index;
9304:
9305: ae->e1 = ae->e1->semantic(sc);
9306: Type *t1 = ae->e1->type->toBasetype();
9307: if (t1->ty == Tstruct)
9308: {
9309: ad = ((TypeStruct *)t1)->sym;
9310: goto L1;
9311: }
9312: else if (t1->ty == Tclass)
9313: {
9314: ad = ((TypeClass *)t1)->sym;
9315: L1:
9316: // Rewrite (a[i] = value) to (a.opIndexAssign(value, i))
9317: if (search_function(ad, Id::indexass))
9318: { Expression *e = new DotIdExp(loc, ae->e1, Id::indexass);
9319: Expressions *a = (Expressions *)ae->arguments->copy();
9320:
9321: a->insert(0, e2);
9322: e = new CallExp(loc, e, a);
9323: e = e->semantic(sc);
9324: return e;
9325: }
9326: #if 0 // Turned off to allow rewriting (a[i]=value) to (a.opIndex(i)=value)
9327: else
9328: {
9329: // Rewrite (a[i] = value) to (a.opIndex(i, value))
9330: if (search_function(ad, id))
9331: { Expression *e = new DotIdExp(loc, ae->e1, id);
9332:
9333: if (1 || !global.params.useDeprecated)
9334: { error("operator [] assignment overload with opIndex(i, value) illegal, use opIndexAssign(value, i)");
9335: return new ErrorExp();
9336: }
9337:
9338: e = new CallExp(loc, e, ae->arguments->tdata()[0], e2);
9339: e = e->semantic(sc);
9340: return e;
9341: }
9342: }
9343: #endif
9344: }
9345: }
9346: /* Look for operator overloading of a[i..j]=value.
9347: * Do it before semantic() otherwise the a[i..j] will have been
9348: * converted to a.opSlice() already.
9349: */
9350: if (e1->op == TOKslice)
9351: { Type *t1;
9352: SliceExp *ae = (SliceExp *)e1;
9353: AggregateDeclaration *ad;
9354: Identifier *id = Id::index;
9355:
9356: ae->e1 = ae->e1->semantic(sc);
9357: ae->e1 = resolveProperties(sc, ae->e1);
9358: t1 = ae->e1->type->toBasetype();
9359: if (t1->ty == Tstruct)
9360: {
9361: ad = ((TypeStruct *)t1)->sym;
9362: goto L2;
9363: }
9364: else if (t1->ty == Tclass)
9365: {
9366: ad = ((TypeClass *)t1)->sym;
9367: L2:
9368: // Rewrite (a[i..j] = value) to (a.opSliceAssign(value, i, j))
9369: if (search_function(ad, Id::sliceass))
9370: { Expression *e = new DotIdExp(loc, ae->e1, Id::sliceass);
9371: Expressions *a = new Expressions();
9372:
9373: a->push(e2);
9374: if (ae->lwr)
9375: { a->push(ae->lwr);
9376: assert(ae->upr);
9377: a->push(ae->upr);
9378: }
9379: else
9380: assert(!ae->upr);
9381: e = new CallExp(loc, e, a);
9382: e = e->semantic(sc);
9383: return e;
9384: }
9385: }
9386: }
9387:
9388: Expression *e = BinExp::semantic(sc);
9389: if (e->op == TOKerror)
9390: return e;
9391:
9392: if (e1->op == TOKdottd)
9393: { // Rewrite a.b=e2, when b is a template, as a.b(e2)
9394: Expression *e = new CallExp(loc, e1, e2);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9395: e = e->semantic(sc);
9396: return e;
9397: }
9398:
9399: e2 = resolveProperties(sc, e2);
9400: assert(e1->type);
9401:
9402: /* Rewrite tuple assignment as a tuple of assignments.
9403: */
9404: if (e1->op == TOKtuple && e2->op == TOKtuple)
9405: { TupleExp *tup1 = (TupleExp *)e1;
9406: TupleExp *tup2 = (TupleExp *)e2;
9407: size_t dim = tup1->exps->dim;
9408: if (dim != tup2->exps->dim)
9409: {
9410: error("mismatched tuple lengths, %d and %d", (int)dim, (int)tup2->exps->dim);
9411: return new ErrorExp();
9412: }
9413: else
9414: { Expressions *exps = new Expressions;
9415: exps->setDim(dim);
9416:
9417: for (int i = 0; i < dim; i++)
warning C4018: '<' : signed/unsigned mismatch
9418: { Expression *ex1 = (*tup1->exps)[i];
9419: Expression *ex2 = (*tup2->exps)[i];
9420: (*exps)[i] = new AssignExp(loc, ex1, ex2);
9421: }
9422: Expression *e = new TupleExp(loc, exps);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9423: e = e->semantic(sc);
9424: return e;
9425: }
9426: }
9427:
9428: // Determine if this is an initialization of a reference
9429: int refinit = 0;
9430: if (op == TOKconstruct && e1->op == TOKvar)
9431: { VarExp *ve = (VarExp *)e1;
9432: VarDeclaration *v = ve->var->isVarDeclaration();
9433: if (v->storage_class & (STCout | STCref))
9434: refinit = 1;
9435: }
9436:
9437: Type *t1 = e1->type->toBasetype();
9438:
9439: if (t1->ty == Tfunction)
9440: { /* We have f=value.
9441: * Could mean:
9442: * f() = value
9443: * or:
9444: * f(value)
9445: */
9446: TypeFunction *tf = (TypeFunction *)t1;
9447: if (tf->isref)
9448: {
9449: // Rewrite e1 = e2 to e1() = e2
9450: e1 = resolveProperties(sc, e1);
9451: }
9452: else
9453: {
9454: // Rewrite f=value to f(value)
9455: Expression *e = new CallExp(loc, e1, e2);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9456: e = e->semantic(sc);
9457: return e;
9458: }
9459: }
9460:
9461: /* If it is an assignment from a 'foreign' type,
9462: * check for operator overloading.
9463: */
9464: if (t1->ty == Tstruct)
9465: {
9466: StructDeclaration *sd = ((TypeStruct *)t1)->sym;
9467: if (op == TOKassign)
9468: {
9469: Expression *e = op_overload(sc);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9470: if (e && e1->op == TOKindex &&
9471: ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray)
9472: {
9473: // Deal with AAs (Bugzilla 2451)
9474: // Rewrite as:
9475: // e1 = (typeof(aa.value) tmp = void, tmp = e2, tmp);
9476: Type * aaValueType = ((TypeAArray *)((IndexExp*)e1)->e1->type->toBasetype())->next;
9477: Identifier *id = Lexer::uniqueId("__aatmp");
9478: VarDeclaration *v = new VarDeclaration(loc, aaValueType,
9479: id, new VoidInitializer(0));
9480: v->storage_class |= STCctfe;
9481: v->semantic(sc);
9482: v->parent = sc->parent;
9483:
9484: Expression *de = new DeclarationExp(loc, v);
9485: VarExp *ve = new VarExp(loc, v);
9486:
9487: AssignExp *ae = new AssignExp(loc, ve, e2);
9488: e = ae->op_overload(sc);
9489: e2 = new CommaExp(loc, new CommaExp(loc, de, e), ve);
9490: e2 = e2->semantic(sc);
9491: }
9492: else if (e)
9493: return e;
9494: }
9495: else if (op == TOKconstruct && !refinit)
9496: { Type *t2 = e2->type->toBasetype();
9497: if (t2->ty == Tstruct &&
9498: sd == ((TypeStruct *)t2)->sym &&
9499: sd->cpctor)
9500: { /* We have a copy constructor for this
9501: */
9502: // Scan past commma's
9503: Expression *ec = NULL;
9504: while (e2->op == TOKcomma)
9505: { CommaExp *ecomma = (CommaExp *)e2;
9506: e2 = ecomma->e2;
9507: if (ec)
9508: ec = new CommaExp(ecomma->loc, ec, ecomma->e1);
9509: else
9510: ec = ecomma->e1;
9511: }
9512: if (e2->op == TOKquestion)
9513: { /* Write as:
9514: * a ? e1 = b : e1 = c;
9515: */
9516: CondExp *econd = (CondExp *)e2;
9517: AssignExp *ea1 = new AssignExp(econd->e1->loc, e1, econd->e1);
9518: ea1->op = op;
9519: AssignExp *ea2 = new AssignExp(econd->e1->loc, e1, econd->e2);
9520: ea2->op = op;
9521: Expression *e = new CondExp(loc, econd->econd, ea1, ea2);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9522: if (ec)
9523: e = new CommaExp(loc, ec, e);
9524: return e->semantic(sc);
9525: }
9526: else if (e2->op == TOKvar ||
9527: e2->op == TOKdotvar ||
9528: e2->op == TOKstar ||
9529: e2->op == TOKthis ||
9530: e2->op == TOKindex)
9531: { /* Write as:
9532: * e1.cpctor(e2);
9533: */
9534: Expression *e = new DotVarExp(loc, e1, sd->cpctor, 0);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9535: e = new CallExp(loc, e, e2);
9536: if (ec)
9537: e = new CommaExp(loc, ec, e);
9538: return e->semantic(sc);
9539: }
9540: else if (e2->op == TOKcall)
9541: {
9542: /* The struct value returned from the function is transferred
9543: * so should not call the destructor on it.
9544: */
9545: valueNoDtor(e2);
9546: }
9547: }
9548: }
9549: }
9550: else if (t1->ty == Tclass)
9551: { // Disallow assignment operator overloads for same type
9552: if (!e2->type->implicitConvTo(e1->type))
9553: {
9554: Expression *e = op_overload(sc);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9555: if (e)
9556: return e;
9557: }
9558: }
9559:
9560: if (t1->ty == Tsarray && !refinit)
9561: {
9562: if (e1->op == TOKindex &&
9563: ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray)
9564: {
9565: // Assignment to an AA of fixed-length arrays.
9566: // Convert T[n][U] = T[] into T[n][U] = T[n]
9567: e2 = e2->implicitCastTo(sc, e1->type);
9568: if (e2->type == Type::terror)
9569: return e2;
9570: }
9571: else
9572: {
9573: Type *t2 = e2->type->toBasetype();
9574: // Convert e2 to e2[], unless e2-> e1[0]
9575: if (t2->ty == Tsarray && !t2->implicitConvTo(t1->nextOf()))
9576: {
9577: e2 = new SliceExp(e2->loc, e2, NULL, NULL);
9578: e2 = e2->semantic(sc);
9579: }
9580:
9581: // Convert e1 to e1[]
9582: Expression *e = new SliceExp(e1->loc, e1, NULL, NULL);
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '9388' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 9388
9583: e1 = e->semantic(sc);
9584: t1 = e1->type->toBasetype();
9585: }
9586: }
9587:
9588: e2->rvalue();
9589:
9590: if (e1->op == TOKarraylength)
9591: {
9592: // e1 is not an lvalue, but we let code generator handle it
9593: ArrayLengthExp *ale = (ArrayLengthExp *)e1;
9594:
9595: ale->e1 = ale->e1->modifiableLvalue(sc, e1);
9596: }
9597: else if (e1->op == TOKslice)
9598: {
9599: Type *tn = e1->type->nextOf();
9600: if (op == TOKassign && tn && (!tn->isMutable() || !tn->isAssignable()))
9601: { error("slice %s is not mutable", e1->toChars());
9602: return new ErrorExp();
9603: }
9604: }
9605: else
9606: { // Try to do a decent error message with the expression
9607: // before it got constant folded
9608: if (e1->op != TOKvar)
9609: e1 = e1->optimize(WANTvalue);
9610:
9611: if (op != TOKconstruct)
9612: e1 = e1->modifiableLvalue(sc, e1old);
9613: }
9614:
9615: Type *t2 = e2->type;
9616: if (e1->op == TOKslice &&
9617: t1->nextOf() &&
9618: e2->implicitConvTo(t1->nextOf())
9619: )
9620: { // memset
9621: ismemset = 1; // make it easy for back end to tell what this is
9622: e2 = e2->implicitCastTo(sc, t1->nextOf());
9623: }
9624: else if (t1->ty == Tsarray)
9625: {
9626: /* Should have already converted e1 => e1[]
9627: * unless it is an AA
9628: */
9629: if (!(e1->op == TOKindex && t2->ty == Tsarray &&
9630: ((IndexExp *)e1)->e1->type->toBasetype()->ty == Taarray))
9631: {
9632: assert(op == TOKconstruct);
9633: }
9634: //error("cannot assign to static array %s", e1->toChars());
9635: }
9636: else if (e1->op == TOKslice && t2->toBasetype()->ty == Tarray &&
9637: t2->toBasetype()->nextOf()->implicitConvTo(t1->nextOf()))
9638: {
9639: e2 = e2->implicitCastTo(sc, e1->type->constOf());
9640: }
9641: else
9642: {
9643: e2 = e2->implicitCastTo(sc, e1->type);
9644: }
9645:
9646: /* Look for array operations
9647: */
9648: if (e1->op == TOKslice && !ismemset &&
9649: (e2->op == TOKadd || e2->op == TOKmin ||
9650: e2->op == TOKmul || e2->op == TOKdiv ||
9651: e2->op == TOKmod || e2->op == TOKxor ||
9652: e2->op == TOKand || e2->op == TOKor ||
9653: e2->op == TOKtilde || e2->op == TOKneg))
9654: {
9655: type = e1->type;
9656: return arrayOp(sc);
9657: }
9658:
9659: type = e1->type;
9660: assert(type);
9661: return this;
9662: }
9663:
9664: Expression *AssignExp::checkToBoolean(Scope *sc)
9665: {
9666: // Things like:
9667: // if (a = b) ...
9668: // are usually mistakes.
9669:
9670: error("'=' does not give a boolean result");
9671: return new ErrorExp();
9672: }
9673:
9674: /************************************************************/
9675:
9676: ConstructExp::ConstructExp(Loc loc, Expression *e1, Expression *e2)
9677: : AssignExp(loc, e1, e2)
9678: {
9679: op = TOKconstruct;
9680: }
9681:
9682: /************************************************************/
9683:
9684: AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
9685: : BinAssignExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
9686: {
9687: }
9688:
9689: Expression *AddAssignExp::semantic(Scope *sc)
9690: { Expression *e;
9691:
9692: if (type)
9693: return this;
9694:
9695: e = op_overload(sc);
9696: if (e)
9697: return e;
9698:
9699: Type *tb1 = e1->type->toBasetype();
9700: Type *tb2 = e2->type->toBasetype();
9701:
9702: if (e1->op == TOKarraylength)
9703: {
9704: e = ArrayLengthExp::rewriteOpAssign(this);
9705: e = e->semantic(sc);
9706: return e;
9707: }
9708:
9709: if (e1->op == TOKslice)
9710: {
9711: e = typeCombine(sc);
9712: if (e->op == TOKerror)
9713: return e;
9714: type = e1->type;
9715: return arrayOp(sc);
9716: }
9717: else
9718: {
9719: e1 = e1->modifiableLvalue(sc, e1);
9720: }
9721:
9722: if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
9723: (tb2->ty == Tarray || tb2->ty == Tsarray) &&
9724: tb1->nextOf()->equals(tb2->nextOf())
9725: )
9726: {
9727: type = e1->type;
9728: typeCombine(sc);
9729: e = this;
9730: }
9731: else
9732: {
9733: e1->checkScalar();
9734: e1->checkNoBool();
9735: if (tb1->ty == Tpointer && tb2->isintegral())
9736: e = scaleFactor(sc);
9737: else if (tb1->ty == Tbool)
9738: {
9739: #if 0
9740: // Need to rethink this
9741: if (e1->op != TOKvar)
9742: { // Rewrite e1+=e2 to (v=&e1),*v=*v+e2
9743: VarDeclaration *v;
9744: Expression *ea;
9745: Expression *ex;
9746:
9747: Identifier *id = Lexer::uniqueId("__name");
9748:
9749: v = new VarDeclaration(loc, tb1->pointerTo(), id, NULL);
9750: v->semantic(sc);
9751: if (!sc->insert(v))
9752: assert(0);
9753: v->parent = sc->func;
9754:
9755: ea = new AddrExp(loc, e1);
9756: ea = new AssignExp(loc, new VarExp(loc, v), ea);
9757:
9758: ex = new VarExp(loc, v);
9759: ex = new PtrExp(loc, ex);
9760: e = new AddExp(loc, ex, e2);
9761: e = new CastExp(loc, e, e1->type);
9762: e = new AssignExp(loc, ex->syntaxCopy(), e);
9763:
9764: e = new CommaExp(loc, ea, e);
9765: }
9766: else
9767: #endif
9768: { // Rewrite e1+=e2 to e1=e1+e2
9769: // BUG: doesn't account for side effects in e1
9770: // BUG: other assignment operators for bits aren't handled at all
9771: e = new AddExp(loc, e1, e2);
9772: e = new CastExp(loc, e, e1->type);
9773: e = new AssignExp(loc, e1->syntaxCopy(), e);
9774: }
9775: e = e->semantic(sc);
9776: }
9777: else
9778: {
9779: type = e1->type;
9780: typeCombine(sc);
9781: e1->checkArithmetic();
9782: e2->checkArithmetic();
9783: checkComplexAddAssign();
9784: if (type->isreal() || type->isimaginary())
9785: {
9786: assert(global.errors || e2->type->isfloating());
9787: e2 = e2->castTo(sc, e1->type);
9788: }
9789: e = this;
9790: }
9791: }
9792: return e;
9793: }
9794:
9795: /************************************************************/
9796:
9797: MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
9798: : BinAssignExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
9799: {
9800: }
9801:
9802: Expression *MinAssignExp::semantic(Scope *sc)
9803: { Expression *e;
9804:
9805: if (type)
9806: return this;
9807:
9808: e = op_overload(sc);
9809: if (e)
9810: return e;
9811:
9812: if (e1->op == TOKarraylength)
9813: {
9814: e = ArrayLengthExp::rewriteOpAssign(this);
9815: e = e->semantic(sc);
9816: return e;
9817: }
9818:
9819: if (e1->op == TOKslice)
9820: { // T[] -= ...
9821: e = typeCombine(sc);
9822: if (e->op == TOKerror)
9823: return e;
9824: type = e1->type;
9825: return arrayOp(sc);
9826: }
9827:
9828: e1 = e1->modifiableLvalue(sc, e1);
9829: e1->checkScalar();
9830: e1->checkNoBool();
9831: if (e1->type->ty == Tpointer && e2->type->isintegral())
9832: e = scaleFactor(sc);
9833: else
9834: {
9835: e1 = e1->checkArithmetic();
9836: e2 = e2->checkArithmetic();
9837: checkComplexAddAssign();
9838: type = e1->type;
9839: typeCombine(sc);
9840: if (type->isreal() || type->isimaginary())
9841: {
9842: assert(e2->type->isfloating());
9843: e2 = e2->castTo(sc, e1->type);
9844: }
9845: e = this;
9846: }
9847: return e;
9848: }
9849:
9850: /************************************************************/
9851:
9852: CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
9853: : BinAssignExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
9854: {
9855: }
9856:
9857: Expression *CatAssignExp::semantic(Scope *sc)
9858: { Expression *e;
9859:
9860: //printf("CatAssignExp::semantic() %s\n", toChars());
9861: e = op_overload(sc);
9862: if (e)
9863: return e;
9864:
9865: if (e1->op == TOKslice)
9866: { SliceExp *se = (SliceExp *)e1;
9867:
9868: if (se->e1->type->toBasetype()->ty == Tsarray)
9869: { error("cannot append to static array %s", se->e1->type->toChars());
9870: return new ErrorExp();
9871: }
9872: }
9873:
9874: e1 = e1->modifiableLvalue(sc, e1);
9875:
9876: Type *tb1 = e1->type->toBasetype();
9877: Type *tb2 = e2->type->toBasetype();
9878:
9879: e2->rvalue();
9880:
9881: Type *tb1next = tb1->nextOf();
9882:
9883: if ((tb1->ty == Tarray) &&
9884: (tb2->ty == Tarray || tb2->ty == Tsarray) &&
9885: (e2->implicitConvTo(e1->type)
9886: #if DMDV2
9887: || tb2->nextOf()->implicitConvTo(tb1next)
9888: #endif
9889: )
9890: )
9891: { // Append array
9892: e2 = e2->castTo(sc, e1->type);
9893: type = e1->type;
9894: e = this;
9895: }
9896: else if ((tb1->ty == Tarray) &&
9897: e2->implicitConvTo(tb1next)
9898: )
9899: { // Append element
9900: e2 = e2->castTo(sc, tb1next);
9901: type = e1->type;
9902: e = this;
9903: }
9904: else if (tb1->ty == Tarray &&
9905: (tb1next->ty == Tchar || tb1next->ty == Twchar) &&
9906: e2->type->ty != tb1next->ty &&
9907: e2->implicitConvTo(Type::tdchar)
9908: )
9909: { // Append dchar to char[] or wchar[]
9910: e2 = e2->castTo(sc, Type::tdchar);
9911: type = e1->type;
9912: e = this;
9913:
9914: /* Do not allow appending wchar to char[] because if wchar happens
9915: * to be a surrogate pair, nothing good can result.
9916: */
9917: }
9918: else
9919: {
9920: if (tb1 != Type::terror && tb2 != Type::terror)
9921: error("cannot append type %s to type %s", tb2->toChars(), tb1->toChars());
9922: e = new ErrorExp();
9923: }
9924: return e;
9925: }
9926:
9927: /************************************************************/
9928:
9929: MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
9930: : BinAssignExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
9931: {
9932: }
9933:
9934: Expression *MulAssignExp::semantic(Scope *sc)
9935: { Expression *e;
9936:
9937: e = op_overload(sc);
9938: if (e)
9939: return e;
9940:
9941: #if DMDV2
9942: if (e1->op == TOKarraylength)
9943: {
9944: e = ArrayLengthExp::rewriteOpAssign(this);
9945: e = e->semantic(sc);
9946: return e;
9947: }
9948: #endif
9949:
9950: if (e1->op == TOKslice)
9951: { // T[] *= ...
9952: e = typeCombine(sc);
9953: if (e->op == TOKerror)
9954: return e;
9955: return arrayOp(sc);
9956: }
9957:
9958: e1 = e1->modifiableLvalue(sc, e1);
9959: e1->checkScalar();
9960: e1->checkNoBool();
9961: type = e1->type;
9962: typeCombine(sc);
9963: e1->checkArithmetic();
9964: e2->checkArithmetic();
9965: checkComplexMulAssign();
9966: if (e2->type->isfloating())
9967: { Type *t1;
9968: Type *t2;
9969:
9970: t1 = e1->type;
9971: t2 = e2->type;
9972: if (t1->isreal())
9973: {
9974: if (t2->isimaginary() || t2->iscomplex())
9975: {
9976: e2 = e2->castTo(sc, t1);
9977: }
9978: }
9979: else if (t1->isimaginary())
9980: {
9981: if (t2->isimaginary() || t2->iscomplex())
9982: {
9983: switch (t1->ty)
9984: {
9985: case Timaginary32: t2 = Type::tfloat32; break;
9986: case Timaginary64: t2 = Type::tfloat64; break;
9987: case Timaginary80: t2 = Type::tfloat80; break;
9988: default:
9989: assert(0);
9990: }
9991: e2 = e2->castTo(sc, t2);
9992: }
9993: }
9994: }
9995: return this;
9996: }
9997:
9998: /************************************************************/
9999:
10000: DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
10001: : BinAssignExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
10002: {
10003: }
10004:
10005: Expression *DivAssignExp::semantic(Scope *sc)
10006: { Expression *e;
10007:
10008: e = op_overload(sc);
10009: if (e)
10010: return e;
10011:
10012: #if DMDV2
10013: if (e1->op == TOKarraylength)
10014: {
10015: e = ArrayLengthExp::rewriteOpAssign(this);
10016: e = e->semantic(sc);
10017: return e;
10018: }
10019: #endif
10020:
10021: if (e1->op == TOKslice)
10022: { // T[] /= ...
10023: e = typeCombine(sc);
10024: if (e->op == TOKerror)
10025: return e;
10026: type = e1->type;
10027: return arrayOp(sc);
10028: }
10029:
10030: e1 = e1->modifiableLvalue(sc, e1);
10031: e1->checkScalar();
10032: e1->checkNoBool();
10033: type = e1->type;
10034: typeCombine(sc);
10035: e1->checkArithmetic();
10036: e2->checkArithmetic();
10037: checkComplexMulAssign();
10038: if (e2->type->isimaginary())
10039: { Type *t1;
10040: Type *t2;
10041:
10042: t1 = e1->type;
10043: if (t1->isreal())
10044: { // x/iv = i(-x/v)
10045: // Therefore, the result is 0
10046: e2 = new CommaExp(loc, e2, new RealExp(loc, 0, t1));
10047: e2->type = t1;
10048: e = new AssignExp(loc, e1, e2);
10049: e->type = t1;
10050: return e;
10051: }
10052: else if (t1->isimaginary())
10053: { Expression *e;
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '10006' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 10006
10054:
10055: switch (t1->ty)
10056: {
10057: case Timaginary32: t2 = Type::tfloat32; break;
10058: case Timaginary64: t2 = Type::tfloat64; break;
10059: case Timaginary80: t2 = Type::tfloat80; break;
10060: default:
10061: assert(0);
10062: }
10063: e2 = e2->castTo(sc, t2);
10064: e = new AssignExp(loc, e1, e2);
10065: e->type = t1;
10066: return e;
10067: }
10068: }
10069: return this;
10070: }
10071:
10072: /************************************************************/
10073:
10074: ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
10075: : BinAssignExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
10076: {
10077: }
10078:
10079: Expression *ModAssignExp::semantic(Scope *sc)
10080: {
10081: if (!type)
10082: {
10083: Expression *e = op_overload(sc);
10084: if (e)
10085: return e;
10086:
10087: checkComplexMulAssign();
10088: return commonSemanticAssign(sc);
10089: }
10090: return this;
10091: }
10092:
10093: /************************************************************/
10094:
10095: ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
10096: : BinAssignExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
10097: {
10098: }
10099:
10100: Expression *ShlAssignExp::semantic(Scope *sc)
10101: { Expression *e;
10102:
10103: //printf("ShlAssignExp::semantic()\n");
10104:
10105: e = op_overload(sc);
10106: if (e)
10107: return e;
10108:
10109: if (e1->op == TOKarraylength)
10110: {
10111: e = ArrayLengthExp::rewriteOpAssign(this);
10112: e = e->semantic(sc);
10113: return e;
10114: }
10115:
10116: e1 = e1->modifiableLvalue(sc, e1);
10117: e1->checkScalar();
10118: e1->checkNoBool();
10119: type = e1->type;
10120: typeCombine(sc);
10121: e1->checkIntegral();
10122: e2 = e2->checkIntegral();
10123: e2 = e2->castTo(sc, Type::tshiftcnt);
10124: return this;
10125: }
10126:
10127: /************************************************************/
10128:
10129: ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
10130: : BinAssignExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
10131: {
10132: }
10133:
10134: Expression *ShrAssignExp::semantic(Scope *sc)
10135: { Expression *e;
10136:
10137: e = op_overload(sc);
10138: if (e)
10139: return e;
10140:
10141: if (e1->op == TOKarraylength)
10142: {
10143: e = ArrayLengthExp::rewriteOpAssign(this);
10144: e = e->semantic(sc);
10145: return e;
10146: }
10147:
10148: e1 = e1->modifiableLvalue(sc, e1);
10149: e1->checkScalar();
10150: e1->checkNoBool();
10151: type = e1->type;
10152: typeCombine(sc);
10153: e1->checkIntegral();
10154: e2 = e2->checkIntegral();
10155: e2 = e2->castTo(sc, Type::tshiftcnt);
10156: return this;
10157: }
10158:
10159: /************************************************************/
10160:
10161: UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
10162: : BinAssignExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
10163: {
10164: }
10165:
10166: Expression *UshrAssignExp::semantic(Scope *sc)
10167: { Expression *e;
10168:
10169: e = op_overload(sc);
10170: if (e)
10171: return e;
10172:
10173: if (e1->op == TOKarraylength)
10174: {
10175: e = ArrayLengthExp::rewriteOpAssign(this);
10176: e = e->semantic(sc);
10177: return e;
10178: }
10179:
10180: e1 = e1->modifiableLvalue(sc, e1);
10181: e1->checkScalar();
10182: e1->checkNoBool();
10183: type = e1->type;
10184: typeCombine(sc);
10185: e1->checkIntegral();
10186: e2 = e2->checkIntegral();
10187: e2 = e2->castTo(sc, Type::tshiftcnt);
10188: return this;
10189: }
10190:
10191: /************************************************************/
10192:
10193: AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
10194: : BinAssignExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
10195: {
10196: }
10197:
10198: Expression *AndAssignExp::semantic(Scope *sc)
10199: {
10200: return commonSemanticAssignIntegral(sc);
10201: }
10202:
10203: /************************************************************/
10204:
10205: OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
10206: : BinAssignExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
10207: {
10208: }
10209:
10210: Expression *OrAssignExp::semantic(Scope *sc)
10211: {
10212: return commonSemanticAssignIntegral(sc);
10213: }
10214:
10215: /************************************************************/
10216:
10217: XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
10218: : BinAssignExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
10219: {
10220: }
10221:
10222: Expression *XorAssignExp::semantic(Scope *sc)
10223: {
10224: return commonSemanticAssignIntegral(sc);
10225: }
10226:
10227: /***************** PowAssignExp *******************************************/
10228:
10229: PowAssignExp::PowAssignExp(Loc loc, Expression *e1, Expression *e2)
10230: : BinAssignExp(loc, TOKpowass, sizeof(PowAssignExp), e1, e2)
10231: {
10232: }
10233:
10234: Expression *PowAssignExp::semantic(Scope *sc)
10235: {
10236: Expression *e;
10237:
10238: if (type)
10239: return this;
10240:
10241: e = op_overload(sc);
10242: if (e)
10243: return e;
10244:
10245: e1 = e1->modifiableLvalue(sc, e1);
10246: assert(e1->type && e2->type);
10247:
10248: if ( (e1->type->isintegral() || e1->type->isfloating()) &&
10249: (e2->type->isintegral() || e2->type->isfloating()))
10250: {
10251: if (e1->op == TOKvar)
10252: { // Rewrite: e1 = e1 ^^ e2
10253: e = new PowExp(loc, e1->syntaxCopy(), e2);
10254: e = new AssignExp(loc, e1, e);
10255: }
10256: else
10257: { // Rewrite: ref tmp = e1; tmp = tmp ^^ e2
10258: Identifier *id = Lexer::uniqueId("__powtmp");
10259: VarDeclaration *v = new VarDeclaration(e1->loc, e1->type, id, new ExpInitializer(loc, e1));
10260: v->storage_class |= STCref | STCforeach;
10261: Expression *de = new DeclarationExp(e1->loc, v);
10262: VarExp *ve = new VarExp(e1->loc, v);
10263: e = new PowExp(loc, ve, e2);
10264: e = new AssignExp(loc, new VarExp(e1->loc, v), e);
10265: e = new CommaExp(loc, de, e);
10266: }
10267: e = e->semantic(sc);
10268: return e;
10269: }
10270: incompatibleTypes();
10271: return new ErrorExp();
10272: }
10273:
10274:
10275: /************************* AddExp *****************************/
10276:
10277: AddExp::AddExp(Loc loc, Expression *e1, Expression *e2)
10278: : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2)
10279: {
10280: }
10281:
10282: Expression *AddExp::semantic(Scope *sc)
10283: { Expression *e;
10284:
10285: #if LOGSEMANTIC
10286: printf("AddExp::semantic('%s')\n", toChars());
10287: #endif
10288: if (!type)
10289: {
10290: BinExp::semanticp(sc);
10291:
10292: e = op_overload(sc);
10293: if (e)
10294: return e;
10295:
10296: Type *tb1 = e1->type->toBasetype();
10297: Type *tb2 = e2->type->toBasetype();
10298:
10299: if ((tb1->ty == Tarray || tb1->ty == Tsarray) &&
10300: (tb2->ty == Tarray || tb2->ty == Tsarray) &&
10301: tb1->nextOf()->equals(tb2->nextOf())
10302: )
10303: {
10304: type = e1->type;
10305: e = this;
10306: }
10307: else if (tb1->ty == Tpointer && e2->type->isintegral() ||
10308: tb2->ty == Tpointer && e1->type->isintegral())
10309: e = scaleFactor(sc);
10310: else if (tb1->ty == Tpointer && tb2->ty == Tpointer)
10311: {
10312: incompatibleTypes();
10313: type = e1->type;
10314: e = this;
10315: }
10316: else
10317: {
10318: typeCombine(sc);
10319: if ((e1->type->isreal() && e2->type->isimaginary()) ||
10320: (e1->type->isimaginary() && e2->type->isreal()))
10321: {
10322: switch (type->toBasetype()->ty)
10323: {
10324: case Tfloat32:
10325: case Timaginary32:
10326: type = Type::tcomplex32;
10327: break;
10328:
10329: case Tfloat64:
10330: case Timaginary64:
10331: type = Type::tcomplex64;
10332: break;
10333:
10334: case Tfloat80:
10335: case Timaginary80:
10336: type = Type::tcomplex80;
10337: break;
10338:
10339: default:
10340: assert(0);
10341: }
10342: }
10343: e = this;
10344: }
10345: return e;
10346: }
10347: return this;
10348: }
10349:
10350: /************************************************************/
10351:
10352: MinExp::MinExp(Loc loc, Expression *e1, Expression *e2)
10353: : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2)
10354: {
10355: }
10356:
10357: Expression *MinExp::semantic(Scope *sc)
10358: { Expression *e;
10359: Type *t1;
10360: Type *t2;
10361:
10362: #if LOGSEMANTIC
10363: printf("MinExp::semantic('%s')\n", toChars());
10364: #endif
10365: if (type)
10366: return this;
10367:
10368: BinExp::semanticp(sc);
10369:
10370: e = op_overload(sc);
10371: if (e)
10372: return e;
10373:
10374: e = this;
10375: t1 = e1->type->toBasetype();
10376: t2 = e2->type->toBasetype();
10377: if (t1->ty == Tpointer)
10378: {
10379: if (t2->ty == Tpointer)
10380: { // Need to divide the result by the stride
10381: // Replace (ptr - ptr) with (ptr - ptr) / stride
10382: d_int64 stride;
10383: Expression *e;
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '10358' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 10358
10384:
10385: typeCombine(sc); // make sure pointer types are compatible
10386: type = Type::tptrdiff_t;
10387: stride = t2->nextOf()->size();
10388: if (stride == 0)
10389: {
10390: e = new IntegerExp(loc, 0, Type::tptrdiff_t);
10391: }
10392: else
10393: {
10394: e = new DivExp(loc, this, new IntegerExp(0, stride, Type::tptrdiff_t));
10395: e->type = Type::tptrdiff_t;
10396: }
10397: return e;
10398: }
10399: else if (t2->isintegral())
10400: e = scaleFactor(sc);
10401: else
10402: { error("incompatible types for minus");
10403: return new ErrorExp();
10404: }
10405: }
10406: else if (t2->ty == Tpointer)
10407: {
10408: type = e2->type;
10409: error("can't subtract pointer from %s", e1->type->toChars());
10410: return new ErrorExp();
10411: }
10412: else
10413: {
10414: typeCombine(sc);
10415: t1 = e1->type->toBasetype();
10416: t2 = e2->type->toBasetype();
10417: if ((t1->isreal() && t2->isimaginary()) ||
10418: (t1->isimaginary() && t2->isreal()))
10419: {
10420: switch (type->ty)
10421: {
10422: case Tfloat32:
10423: case Timaginary32:
10424: type = Type::tcomplex32;
10425: break;
10426:
10427: case Tfloat64:
10428: case Timaginary64:
10429: type = Type::tcomplex64;
10430: break;
10431:
10432: case Tfloat80:
10433: case Timaginary80:
10434: type = Type::tcomplex80;
10435: break;
10436:
10437: default:
10438: assert(0);
10439: }
10440: }
10441: }
10442: return e;
10443: }
10444:
10445: /************************* CatExp *****************************/
10446:
10447: CatExp::CatExp(Loc loc, Expression *e1, Expression *e2)
10448: : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2)
10449: {
10450: }
10451:
10452: Expression *CatExp::semantic(Scope *sc)
10453: { Expression *e;
10454:
10455: //printf("CatExp::semantic() %s\n", toChars());
10456: if (!type)
10457: {
10458: BinExp::semanticp(sc);
10459: e = op_overload(sc);
10460: if (e)
10461: return e;
10462:
10463: Type *tb1 = e1->type->toBasetype();
10464: Type *tb2 = e2->type->toBasetype();
10465:
10466:
10467: /* BUG: Should handle things like:
10468: * char c;
10469: * c ~ ' '
10470: * ' ' ~ c;
10471: */
10472:
10473: #if 0
10474: e1->type->print();
10475: e2->type->print();
10476: #endif
10477: Type *tb1next = tb1->nextOf();
10478: Type *tb2next = tb2->nextOf();
10479:
10480: if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
10481: e2->implicitConvTo(tb1next) >= MATCHconvert)
10482: {
10483: e2 = e2->implicitCastTo(sc, tb1next);
10484: type = tb1next->arrayOf();
10485: if (tb2->ty == Tarray)
10486: { // Make e2 into [e2]
10487: e2 = new ArrayLiteralExp(e2->loc, e2);
10488: e2->type = type;
10489: }
10490: return this;
10491: }
10492: else if ((tb2->ty == Tsarray || tb2->ty == Tarray) &&
10493: e1->implicitConvTo(tb2next) >= MATCHconvert)
10494: {
10495: e1 = e1->implicitCastTo(sc, tb2next);
10496: type = tb2next->arrayOf();
10497: if (tb1->ty == Tarray)
10498: { // Make e1 into [e1]
10499: e1 = new ArrayLiteralExp(e1->loc, e1);
10500: e1->type = type;
10501: }
10502: return this;
10503: }
10504:
10505: if ((tb1->ty == Tsarray || tb1->ty == Tarray) &&
10506: (tb2->ty == Tsarray || tb2->ty == Tarray) &&
10507: (tb1next->mod || tb2next->mod) &&
10508: (tb1next->mod != tb2next->mod)
10509: )
10510: {
10511: Type *t1 = tb1next->mutableOf()->constOf()->arrayOf();
10512: Type *t2 = tb2next->mutableOf()->constOf()->arrayOf();
10513: if (e1->op == TOKstring && !((StringExp *)e1)->committed)
10514: e1->type = t1;
10515: else
10516: e1 = e1->castTo(sc, t1);
10517: if (e2->op == TOKstring && !((StringExp *)e2)->committed)
10518: e2->type = t2;
10519: else
10520: e2 = e2->castTo(sc, t2);
10521: }
10522:
10523: typeCombine(sc);
10524: type = type->toHeadMutable();
10525:
10526: Type *tb = type->toBasetype();
10527: if (tb->ty == Tsarray)
10528: type = tb->nextOf()->arrayOf();
10529: if (type->ty == Tarray && tb1next && tb2next &&
10530: tb1next->mod != tb2next->mod)
10531: {
10532: type = type->nextOf()->toHeadMutable()->arrayOf();
10533: }
10534: #if 0
10535: e1->type->print();
10536: e2->type->print();
10537: type->print();
10538: print();
10539: #endif
10540: Type *t1 = e1->type->toBasetype();
10541: Type *t2 = e2->type->toBasetype();
10542: if (e1->op == TOKstring && e2->op == TOKstring)
10543: e = optimize(WANTvalue);
10544: else if ((t1->ty == Tarray || t1->ty == Tsarray) &&
10545: (t2->ty == Tarray || t2->ty == Tsarray))
10546: {
10547: e = this;
10548: }
10549: else
10550: {
10551: //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars());
10552: incompatibleTypes();
10553: return new ErrorExp();
10554: }
10555: e->type = e->type->semantic(loc, sc);
10556: return e;
10557: }
10558: return this;
10559: }
10560:
10561: /************************************************************/
10562:
10563: MulExp::MulExp(Loc loc, Expression *e1, Expression *e2)
10564: : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2)
10565: {
10566: }
10567:
10568: Expression *MulExp::semantic(Scope *sc)
10569: { Expression *e;
10570:
10571: #if 0
10572: printf("MulExp::semantic() %s\n", toChars());
10573: #endif
10574: if (type)
10575: {
10576: return this;
10577: }
10578:
10579: BinExp::semanticp(sc);
10580: e = op_overload(sc);
10581: if (e)
10582: return e;
10583:
10584: typeCombine(sc);
10585: if (!e1->isArrayOperand())
10586: e1->checkArithmetic();
10587: if (!e2->isArrayOperand())
10588: e2->checkArithmetic();
10589: if (type->isfloating())
10590: { Type *t1 = e1->type;
10591: Type *t2 = e2->type;
10592:
10593: if (t1->isreal())
10594: {
10595: type = t2;
10596: }
10597: else if (t2->isreal())
10598: {
10599: type = t1;
10600: }
10601: else if (t1->isimaginary())
10602: {
10603: if (t2->isimaginary())
10604: { Expression *e;
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '10569' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 10569
10605:
10606: switch (t1->toBasetype()->ty)
10607: {
10608: case Timaginary32: type = Type::tfloat32; break;
10609: case Timaginary64: type = Type::tfloat64; break;
10610: case Timaginary80: type = Type::tfloat80; break;
10611: default: assert(0);
10612: }
10613:
10614: // iy * iv = -yv
10615: e1->type = type;
10616: e2->type = type;
10617: e = new NegExp(loc, this);
10618: e = e->semantic(sc);
10619: return e;
10620: }
10621: else
10622: type = t2; // t2 is complex
10623: }
10624: else if (t2->isimaginary())
10625: {
10626: type = t1; // t1 is complex
10627: }
10628: }
10629: return this;
10630: }
10631:
10632: /************************************************************/
10633:
10634: DivExp::DivExp(Loc loc, Expression *e1, Expression *e2)
10635: : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2)
10636: {
10637: }
10638:
10639: Expression *DivExp::semantic(Scope *sc)
10640: { Expression *e;
10641:
10642: if (type)
10643: return this;
10644:
10645: BinExp::semanticp(sc);
10646: e = op_overload(sc);
10647: if (e)
10648: return e;
10649:
10650: typeCombine(sc);
10651: if (!e1->isArrayOperand())
10652: e1->checkArithmetic();
10653: if (!e2->isArrayOperand())
10654: e2->checkArithmetic();
10655: if (type->isfloating())
10656: { Type *t1 = e1->type;
10657: Type *t2 = e2->type;
10658:
10659: if (t1->isreal())
10660: {
10661: type = t2;
10662: if (t2->isimaginary())
10663: { Expression *e;
warning C6246: Local declaration of 'e' hides declaration of the same name in outer scope. For additional information, see previous declaration at line '10640' of 'c:\projects\extern\d\dmd\src\expression.c': Lines: 10640
10664:
10665: // x/iv = i(-x/v)
10666: e2->type = t1;
10667: e = new NegExp(loc, this);
10668: e = e->semantic(sc);
10669: return e;
10670: }
10671: }
10672: else if (t2->isreal())
10673: {
10674: type = t1;
10675: }
10676: else if (t1->isimaginary())
10677: {
10678: if (t2->isimaginary())
10679: {
10680: switch (t1->toBasetype()->ty)
10681: {
10682: case Timaginary32: type = Type::tfloat32; break;
10683: case Timaginary64: type = Type::tfloat64; break;
10684: case Timaginary80: type = Type::tfloat80; break;
10685: default: assert(0);
10686: }
10687: }
10688: else
10689: type = t2; // t2 is complex
10690: }
10691: else if (t2->isimaginary())
10692: {
10693: type = t1; // t1 is complex
10694: }
10695: }
10696: return this;
10697: }
10698:
10699: /************************************************************/
10700:
10701: ModExp::ModExp(Loc loc, Expression *e1, Expression *e2)
10702: : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2)
10703: {
10704: }
10705:
10706: Expression *ModExp::semantic(Scope *sc)
10707: { Expression *e;
10708:
10709: if (type)
10710: return this;
10711:
10712: BinExp::semanticp(sc);
10713: e = op_overload(sc);
10714: if (e)
10715: return e;
10716:
10717: typeCombine(sc);
10718: if (!e1->isArrayOperand())
10719: e1->checkArithmetic();
10720: if (!e2->isArrayOperand())
10721: e2->checkArithmetic();
10722: if (type->isfloating())
10723: { type = e1->type;
10724: if (e2->type->iscomplex())
10725: { error("cannot perform modulo complex arithmetic");
10726: return new ErrorExp();
10727: }
10728: }
10729: return this;
10730: }
10731:
10732: PowExp::PowExp(Loc loc, Expression *e1, Expression *e2)
10733: : BinExp(loc, TOKpow, sizeof(PowExp), e1, e2)
10734: {
10735: }
10736:
10737: Expression *PowExp::semantic(Scope *sc)
10738: { Expression *e;
10739:
10740: if (type)
10741: return this;
10742:
10743: //printf("PowExp::semantic() %s\n", toChars());
10744: BinExp::semanticp(sc);
10745: e = op_overload(sc);
10746: if (e)
10747: return e;
10748:
10749: assert(e1->type && e2->type);
10750: if ( (e1->type->isintegral() || e1->type->isfloating()) &&
10751: (e2->type->isintegral() || e2->type->isfloating()))
10752: {
10753: // For built-in numeric types, there are several cases.
10754: // TODO: backend support, especially for e1 ^^ 2.
10755:
10756: bool wantSqrt = false;
10757: e1 = e1->optimize(0);
10758: e2 = e2->optimize(0);
10759:
10760: // Replace 1 ^^ x or 1.0^^x by (x, 1)
10761: if ((e1->op == TOKint64 && e1->toInteger() == 1) ||
10762: (e1->op == TOKfloat64 && e1->toReal() == 1.0))
10763: {
10764: typeCombine(sc);
10765: e = new CommaExp(loc, e2, e1);
10766: e = e->semantic(sc);
10767: return e;
10768: }
10769: // Replace -1 ^^ x by (x&1) ? -1 : 1, where x is integral
10770: if (e2->type->isintegral() && e1->op == TOKint64 && (sinteger_t)e1->toInteger() == -1L)
10771: {
10772: typeCombine(sc);
10773: Type* resultType = type;
10774: e = new AndExp(loc, e2, new IntegerExp(loc, 1, e2->type));
10775: e = new CondExp(loc, e, new IntegerExp(loc, -1L, resultType), new IntegerExp(loc, 1L, resultType));
10776: e = e->semantic(sc);
10777: return e;
10778: }
10779: // Replace x ^^ 0 or x^^0.0 by (x, 1)
10780: if ((e2->op == TOKint64 && e2->toInteger() == 0) ||
10781: (e2->op == TOKfloat64 && e2->toReal() == 0.0))
10782: {
10783: if (e1->type->isintegral())
10784: e = new IntegerExp(loc, 1, e1->type);
10785: else
10786: e = new RealExp(loc, 1.0, e1->type);
10787:
10788: typeCombine(sc);
10789: e = new CommaExp(loc, e1, e);
10790: e = e->semantic(sc);
10791: return e;
10792: }
10793: // Replace x ^^ 1 or x^^1.0 by (x)
10794: if ((e2->op == TOKint64 && e2->toInteger() == 1) ||
10795: (e2->op == TOKfloat64 && e2->toReal() == 1.0))
10796: {
10797: typeCombine(sc);
10798: return e1;
10799: }
10800: // Replace x ^^ -1.0 by (1.0 / x)
10801: if ((e2->op == TOKfloat64 && e2->toReal() == -1.0))
10802: {
10803: typeCombine(sc);
10804: e = new DivExp(loc, new RealExp(loc, 1.0, e2->type), e1);
10805: e = e->semantic(sc);
10806: return e;
10807: }
10808: // All other negative integral powers are illegal
10809: if ((e1->type->isintegral()) && (e2->op == TOKint64) && (sinteger_t)e2->toInteger() < 0)
10810: {
10811: error("cannot raise %s to a negative integer power. Did you mean (cast(real)%s)^^%s ?",
10812: e1->type->toBasetype()->toChars(), e1->toChars(), e2->toChars());
10813: return new ErrorExp();
10814: }
10815:
10816: // Determine if we're raising to an integer power.
10817: sinteger_t intpow = 0;
10818: if (e2->op == TOKint64 && ((sinteger_t)e2->toInteger() == 2 || (sinteger_t)e2->toInteger() == 3))
10819: intpow = e2->toInteger();
10820: else if (e2->op == TOKfloat64 && (e2->toReal() == (sinteger_t)(e2->toReal())))
10821: intpow = (sinteger_t)(e2->toReal());
10822:
10823: // Deal with x^^2, x^^3 immediately, since they are of practical importance.
10824: if (intpow == 2 || intpow == 3)
10825: {
10826: typeCombine(sc);
10827: // Replace x^^2 with (tmp = x, tmp*tmp)
10828: // Replace x^^3 with (tmp = x, tmp*tmp*tmp)
10829: Identifier *idtmp = Lexer::uniqueId("__powtmp");
10830: VarDeclaration *tmp = new VarDeclaration(loc, e1->type->toBasetype(), idtmp, new ExpInitializer(0, e1));
10831: tmp->storage_class = STCctfe;
10832: Expression *ve = new VarExp(loc, tmp);
10833: Expression *ae = new DeclarationExp(loc, tmp);
10834: /* Note that we're reusing ve. This should be ok.
10835: */
10836: Expression *me = new MulExp(loc, ve, ve);
10837: if (intpow == 3)
10838: me = new MulExp(loc, me, ve);
10839: e = new CommaExp(loc, ae, me);
10840: e = e->semantic(sc);
10841: return e;
10842: }
10843:
10844: static int importMathChecked = 0;
10845: if (!importMathChecked)
10846: {
10847: importMathChecked = 1;
10848: for (int i = 0; i < Module::amodules.dim; i++)
warning C4018: '<' : signed/unsigned mismatch
10849: { Module *mi = Module::amodules.tdata()[i];
10850: //printf("\t[%d] %s\n", i, mi->toChars());
10851: if (mi->ident == Id::math &&
10852: mi->parent->ident == Id::std &&
10853: !mi->parent->parent)
10854: goto L1;
10855: }
10856: error("must import std.math to use ^^ operator");
10857: return new ErrorExp();
10858:
10859: L1: ;
10860: }
10861:
10862: e = new IdentifierExp(loc, Id::empty);
10863: e = new DotIdExp(loc, e, Id::std);
10864: e = new DotIdExp(loc, e, Id::math);
10865: if (e2->op == TOKfloat64 && e2->toReal() == 0.5)
10866: { // Replace e1 ^^ 0.5 with .std.math.sqrt(x)
10867: typeCombine(sc);
10868: e = new CallExp(loc, new DotIdExp(loc, e, Id::_sqrt), e1);
10869: }
10870: else
10871: {
10872: // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
10873: // We don't combine the types if raising to an integer power (because
10874: // integer powers are treated specially by std.math.pow).
10875: if (!e2->type->isintegral())
10876: typeCombine(sc);
10877: // In fact, if it *could* have been an integer, make it one.
10878: if (e2->op == TOKfloat64 && intpow != 0)
10879: e2 = new IntegerExp(loc, intpow, Type::tint64);
10880: e = new CallExp(loc, new DotIdExp(loc, e, Id::_pow), e1, e2);
10881: }
10882: e = e->semantic(sc);
10883: // Always constant fold integer powers of literals. This will run the interpreter
10884: // on .std.math.pow
10885: if ((e1->op == TOKfloat64 || e1->op == TOKint64) && (e2->op == TOKint64))
10886: e = e->optimize(WANTvalue | WANTinterpret);
10887:
10888: return e;
10889: }
10890: incompatibleTypes();
10891: return new ErrorExp();
10892: }
10893:
10894: /************************************************************/
10895:
10896: ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2)
10897: : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2)
10898: {
10899: }
10900:
10901: Expression *ShlExp::semantic(Scope *sc)
10902: { Expression *e;
10903:
10904: //printf("ShlExp::semantic(), type = %p\n", type);
10905: if (!type)
10906: { BinExp::semanticp(sc);
10907: e = op_overload(sc);
10908: if (e)
10909: return e;
10910: e1 = e1->checkIntegral();
10911: e2 = e2->checkIntegral();
10912: e1 = e1->integralPromotions(sc);
10913: e2 = e2->castTo(sc, Type::tshiftcnt);
10914: type = e1->type;
10915: }
10916: return this;
10917: }
10918:
10919: /************************************************************/
10920:
10921: ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2)
10922: : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2)
10923: {
10924: }
10925:
10926: Expression *ShrExp::semantic(Scope *sc)
10927: { Expression *e;
10928:
10929: if (!type)
10930: { BinExp::semanticp(sc);
10931: e = op_overload(sc);
10932: if (e)
10933: return e;
10934: e1 = e1->checkIntegral();
10935: e2 = e2->checkIntegral();
10936: e1 = e1->integralPromotions(sc);
10937: e2 = e2->castTo(sc, Type::tshiftcnt);
10938: type = e1->type;
10939: }
10940: return this;
10941: }
10942:
10943: /************************************************************/
10944:
10945: UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2)
10946: : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2)
10947: {
10948: }
10949:
10950: Expression *UshrExp::semantic(Scope *sc)
10951: { Expression *e;
10952:
10953: if (!type)
10954: { BinExp::semanticp(sc);
10955: e = op_overload(sc);
10956: if (e)
10957: return e;
10958: e1 = e1->checkIntegral();
10959: e2 = e2->checkIntegral();
10960: e1 = e1->integralPromotions(sc);
10961: e2 = e2->castTo(sc, Type::tshiftcnt);
10962: type = e1->type;
10963: }
10964: return this;
10965: }
10966:
10967: /************************************************************/
10968:
10969: AndExp::AndExp(Loc loc, Expression *e1, Expression *e2)
10970: : BinExp(loc, TOKand, sizeof(AndExp), e1, e2)
10971: {
10972: }
10973:
10974: Expression *AndExp::semantic(Scope *sc)
10975: { Expression *e;
10976:
10977: if (!type)
10978: { BinExp::semanticp(sc);
10979: e = op_overload(sc);
10980: if (e)
10981: return e;
10982: if (e1->type->toBasetype()->ty == Tbool &&
10983: e2->type->toBasetype()->ty == Tbool)
10984: {
10985: type = e1->type;
10986: e = this;
10987: }
10988: else
10989: {
10990: typeCombine(sc);
10991: if (!e1->isArrayOperand())
10992: e1->checkIntegral();
10993: if (!e2->isArrayOperand())
10994: e2->checkIntegral();
10995: }
10996: }
10997: return this;
10998: }
10999:
11000: /************************************************************/
11001:
11002: OrExp::OrExp(Loc loc, Expression *e1, Expression *e2)
11003: : BinExp(loc, TOKor, sizeof(OrExp), e1, e2)
11004: {
11005: }
11006:
11007: Expression *OrExp::semantic(Scope *sc)
11008: { Expression *e;
11009:
11010: if (!type)
11011: { BinExp::semanticp(sc);
11012: e = op_overload(sc);
11013: if (e)
11014: return e;
11015: if (e1->type->toBasetype()->ty == Tbool &&
11016: e2->type->toBasetype()->ty == Tbool)
11017: {
11018: type = e1->type;
11019: e = this;
11020: }
11021: else
11022: {
11023: typeCombine(sc);
11024: if (!e1->isArrayOperand())
11025: e1->checkIntegral();
11026: if (!e2->isArrayOperand())
11027: e2->checkIntegral();
11028: }
11029: }
11030: return this;
11031: }
11032:
11033: /************************************************************/
11034:
11035: XorExp::XorExp(Loc loc, Expression *e1, Expression *e2)
11036: : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2)
11037: {
11038: }
11039:
11040: Expression *XorExp::semantic(Scope *sc)
11041: { Expression *e;
11042:
11043: if (!type)
11044: { BinExp::semanticp(sc);
11045: e = op_overload(sc);
11046: if (e)
11047: return e;
11048: if (e1->type->toBasetype()->ty == Tbool &&
11049: e2->type->toBasetype()->ty == Tbool)
11050: {
11051: type = e1->type;
11052: e = this;
11053: }
11054: else
11055: {
11056: typeCombine(sc);
11057: if (!e1->isArrayOperand())
11058: e1->checkIntegral();
11059: if (!e2->isArrayOperand())
11060: e2->checkIntegral();
11061: }
11062: }
11063: return this;
11064: }
11065:
11066:
11067: /************************************************************/
11068:
11069: OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2)
11070: : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2)
11071: {
11072: }
11073:
11074: Expression *OrOrExp::semantic(Scope *sc)
11075: {
11076: unsigned cs1;
11077:
11078: // same as for AndAnd
11079: e1 = e1->semantic(sc);
11080: e1 = resolveProperties(sc, e1);
11081: e1 = e1->checkToPointer();
11082: e1 = e1->checkToBoolean(sc);
11083: cs1 = sc->callSuper;
11084:
11085: if (sc->flags & SCOPEstaticif)
11086: {
11087: /* If in static if, don't evaluate e2 if we don't have to.
11088: */
11089: e1 = e1->optimize(WANTflags);
11090: if (e1->isBool(TRUE))
11091: {
11092: return new IntegerExp(loc, 1, Type::tboolean);
11093: }
11094: }
11095:
11096: e2 = e2->semantic(sc);
11097: sc->mergeCallSuper(loc, cs1);
11098: e2 = resolveProperties(sc, e2);
11099: e2 = e2->checkToPointer();
11100:
11101: if (e2->type->ty == Tvoid)
11102: type = Type::tvoid;
11103: else
11104: {
11105: e2 = e2->checkToBoolean(sc);
11106: type = Type::tboolean;
11107: }
11108: if (e2->op == TOKtype || e2->op == TOKimport)
11109: { error("%s is not an expression", e2->toChars());
11110: return new ErrorExp();
11111: }
11112: if (e1->op == TOKerror)
11113: return e1;
11114: if (e2->op == TOKerror)
11115: return e2;
11116: return this;
11117: }
11118:
11119: Expression *OrOrExp::checkToBoolean(Scope *sc)
11120: {
11121: e2 = e2->checkToBoolean(sc);
11122: return this;
11123: }
11124:
11125: int OrOrExp::isBit()
11126: {
11127: return TRUE;
11128: }
11129:
11130: int OrOrExp::checkSideEffect(int flag)
11131: {
11132: if (flag == 2)
11133: {
11134: return e1->checkSideEffect(2) || e2->checkSideEffect(2);
11135: }
11136: else
11137: { e1->checkSideEffect(1);
11138: return e2->checkSideEffect(flag);
11139: }
11140: }
11141:
11142: /************************************************************/
11143:
11144: AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2)
11145: : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2)
11146: {
11147: }
11148:
11149: Expression *AndAndExp::semantic(Scope *sc)
11150: {
11151: unsigned cs1;
11152:
11153: // same as for OrOr
11154: e1 = e1->semantic(sc);
11155: e1 = resolveProperties(sc, e1);
11156: e1 = e1->checkToPointer();
11157: e1 = e1->checkToBoolean(sc);
11158: cs1 = sc->callSuper;
11159:
11160: if (sc->flags & SCOPEstaticif)
11161: {
11162: /* If in static if, don't evaluate e2 if we don't have to.
11163: */
11164: e1 = e1->optimize(WANTflags);
11165: if (e1->isBool(FALSE))
11166: {
11167: return new IntegerExp(loc, 0, Type::tboolean);
11168: }
11169: }
11170:
11171: e2 = e2->semantic(sc);
11172: sc->mergeCallSuper(loc, cs1);
11173: e2 = resolveProperties(sc, e2);
11174: e2 = e2->checkToPointer();
11175:
11176: if (e2->type->ty == Tvoid)
11177: type = Type::tvoid;
11178: else
11179: {
11180: e2 = e2->checkToBoolean(sc);
11181: type = Type::tboolean;
11182: }
11183: if (e2->op == TOKtype || e2->op == TOKimport)
11184: { error("%s is not an expression", e2->toChars());
11185: return new ErrorExp();
11186: }
11187: if (e1->op == TOKerror)
11188: return e1;
11189: if (e2->op == TOKerror)
11190: return e2;
11191: return this;
11192: }
11193:
11194: Expression *AndAndExp::checkToBoolean(Scope *sc)
11195: {
11196: e2 = e2->checkToBoolean(sc);
11197: return this;
11198: }
11199:
11200: int AndAndExp::isBit()
11201: {
11202: return TRUE;
11203: }
11204:
11205: int AndAndExp::checkSideEffect(int flag)
11206: {
11207: if (flag == 2)
11208: {
11209: return e1->checkSideEffect(2) || e2->checkSideEffect(2);
11210: }
11211: else
11212: {
11213: e1->checkSideEffect(1);
11214: return e2->checkSideEffect(flag);
11215: }
11216: }
11217:
11218: /************************************************************/
11219:
11220: InExp::InExp(Loc loc, Expression *e1, Expression *e2)
11221: : BinExp(loc, TOKin, sizeof(InExp), e1, e2)
11222: {
11223: }
11224:
11225: Expression *InExp::semantic(Scope *sc)
11226: { Expression *e;
11227:
11228: if (type)
11229: return this;
11230:
11231: BinExp::semanticp(sc);
11232: e = op_overload(sc);
11233: if (e)
11234: return e;
11235:
11236: //type = Type::tboolean;
11237: Type *t2b = e2->type->toBasetype();
11238: switch (t2b->ty)
11239: {
11240: case Taarray:
11241: {
11242: TypeAArray *ta = (TypeAArray *)t2b;
11243:
11244: #if DMDV2
11245: // Special handling for array keys
11246: if (!arrayTypeCompatible(e1->loc, e1->type, ta->index))
11247: #endif
11248: {
11249: // Convert key to type of key
11250: e1 = e1->implicitCastTo(sc, ta->index);
11251: }
11252:
11253: // Return type is pointer to value
11254: type = ta->nextOf()->pointerTo();
11255: break;
11256: }
11257:
11258: default:
11259: error("rvalue of in expression must be an associative array, not %s", e2->type->toChars());
11260: case Terror:
11261: return new ErrorExp();
11262: }
11263: return this;
11264: }
11265:
11266: int InExp::isBit()
11267: {
11268: return FALSE;
11269: }
11270:
11271:
11272: /************************************************************/
11273:
11274: /* This deletes the key e1 from the associative array e2
11275: */
11276:
11277: RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2)
11278: : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2)
11279: {
11280: type = Type::tvoid;
11281: }
11282:
11283: void RemoveExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
11284: {
11285: expToCBuffer(buf, hgs, e1, PREC_primary);
11286: buf->writestring(".remove(");
11287: expToCBuffer(buf, hgs, e2, PREC_assign);
11288: buf->writestring(")");
11289: }
11290:
11291: /************************************************************/
11292:
11293: CmpExp::CmpExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
11294: : BinExp(loc, op, sizeof(CmpExp), e1, e2)
11295: {
11296: }
11297:
11298: Expression *CmpExp::semantic(Scope *sc)
11299: { Expression *e;
11300:
11301: #if LOGSEMANTIC
11302: printf("CmpExp::semantic('%s')\n", toChars());
11303: #endif
11304: if (type)
11305: return this;
11306:
11307: BinExp::semanticp(sc);
11308:
11309: Type *t1 = e1->type->toBasetype();
11310: Type *t2 = e2->type->toBasetype();
11311: if (t1->ty == Tclass && e2->op == TOKnull ||
11312: t2->ty == Tclass && e1->op == TOKnull)
11313: {
11314: error("do not use null when comparing class types");
11315: return new ErrorExp();
11316: }
11317:
11318: e = op_overload(sc);
11319: if (e)
11320: {
11321: if (!e->type->isscalar() && e->type->equals(e1->type))
11322: {
11323: error("recursive opCmp expansion");
11324: e = new ErrorExp();
11325: }
11326: else
11327: { e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type::tint32));
11328: e = e->semantic(sc);
11329: }
11330: return e;
11331: }
11332:
11333: /* Disallow comparing T[]==T and T==T[]
11334: */
11335: if (e1->op == TOKslice && t1->ty == Tarray && e2->implicitConvTo(t1->nextOf()) ||
11336: e2->op == TOKslice && t2->ty == Tarray && e1->implicitConvTo(t2->nextOf()))
11337: {
11338: incompatibleTypes();
11339: return new ErrorExp();
11340: }
11341:
11342: typeCombine(sc);
11343: type = Type::tboolean;
11344:
11345: // Special handling for array comparisons
11346: t1 = e1->type->toBasetype();
11347: t2 = e2->type->toBasetype();
11348: if ((t1->ty == Tarray || t1->ty == Tsarray || t1->ty == Tpointer) &&
11349: (t2->ty == Tarray || t2->ty == Tsarray || t2->ty == Tpointer))
11350: {
11351: if (t1->nextOf()->implicitConvTo(t2->nextOf()) < MATCHconst &&
11352: t2->nextOf()->implicitConvTo(t1->nextOf()) < MATCHconst &&
11353: (t1->nextOf()->ty != Tvoid && t2->nextOf()->ty != Tvoid))
11354: error("array comparison type mismatch, %s vs %s", t1->nextOf()->toChars(), t2->nextOf()->toChars());
11355: e = this;
11356: }
11357: else if (t1->ty == Tstruct || t2->ty == Tstruct ||
11358: (t1->ty == Tclass && t2->ty == Tclass))
11359: {
11360: if (t2->ty == Tstruct)
11361: error("need member function opCmp() for %s %s to compare", t2->toDsymbol(sc)->kind(), t2->toChars());
11362: else
11363: error("need member function opCmp() for %s %s to compare", t1->toDsymbol(sc)->kind(), t1->toChars());
11364: e = new ErrorExp();
11365: }
11366: #if 1
11367: else if (t1->iscomplex() || t2->iscomplex())
11368: {
11369: error("compare not defined for complex operands");
11370: e = new ErrorExp();
11371: }
11372: #endif
11373: else
11374: { e1->rvalue();
11375: e2->rvalue();
11376: e = this;
11377: }
11378: //printf("CmpExp: %s, type = %s\n", e->toChars(), e->type->toChars());
11379: return e;
11380: }
11381:
11382: int CmpExp::isBit()
11383: {
11384: return TRUE;
11385: }
11386:
11387:
11388: /************************************************************/
11389:
11390: EqualExp::EqualExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
11391: : BinExp(loc, op, sizeof(EqualExp), e1, e2)
11392: {
11393: assert(op == TOKequal || op == TOKnotequal);
11394: }
11395:
11396: Expression *EqualExp::semantic(Scope *sc)
11397: { Expression *e;
11398:
11399: //printf("EqualExp::semantic('%s')\n", toChars());
11400: if (type)
11401: return this;
11402:
11403: BinExp::semanticp(sc);
11404:
11405: /* Before checking for operator overloading, check to see if we're
11406: * comparing the addresses of two statics. If so, we can just see
11407: * if they are the same symbol.
11408: */
11409: if (e1->op == TOKaddress && e2->op == TOKaddress)
11410: { AddrExp *ae1 = (AddrExp *)e1;
11411: AddrExp *ae2 = (AddrExp *)e2;
11412:
11413: if (ae1->e1->op == TOKvar && ae2->e1->op == TOKvar)
11414: { VarExp *ve1 = (VarExp *)ae1->e1;
11415: VarExp *ve2 = (VarExp *)ae2->e1;
11416:
11417: if (ve1->var == ve2->var /*|| ve1->var->toSymbol() == ve2->var->toSymbol()*/)
11418: {
11419: // They are the same, result is 'true' for ==, 'false' for !=
11420: e = new IntegerExp(loc, (op == TOKequal), Type::tboolean);
11421: return e;
11422: }
11423: }
11424: }
11425:
11426: Type *t1 = e1->type->toBasetype();
11427: Type *t2 = e2->type->toBasetype();
11428: if (t1->ty == Tclass && e2->op == TOKnull ||
11429: t2->ty == Tclass && e1->op == TOKnull)
11430: {
11431: error("use '%s' instead of '%s' when comparing with null",
11432: Token::toChars(op == TOKequal ? TOKidentity : TOKnotidentity),
11433: Token::toChars(op));
11434: return new ErrorExp();
11435: }
11436:
11437: if ((t1->ty == Tarray || t1->ty == Tsarray) &&
11438: (t2->ty == Tarray || t2->ty == Tsarray))
11439: { Type *t1n = t1->nextOf()->toBasetype();
11440: Type *t2n = t2->nextOf()->toBasetype();
11441: if (t1n->constOf() != t2n->constOf() &&
11442: !((t1n->ty == Tchar || t1n->ty == Twchar || t1n->ty == Tdchar) &&
11443: (t2n->ty == Tchar || t2n->ty == Twchar || t2n->ty == Tdchar)) &&
11444: !(t1n->ty == Tvoid || t2n->ty == Tvoid)
11445: )
11446: { /* Rewrite as:
11447: * _ArrayEq(e1, e2)
11448: */
11449: Expression *eq = new IdentifierExp(loc, Id::_ArrayEq);
11450: Expressions *args = new Expressions();
11451: args->push(e1);
11452: args->push(e2);
11453: e = new CallExp(loc, eq, args);
11454: if (op == TOKnotequal)
11455: e = new NotExp(loc, e);
11456: e = e->semantic(sc);
11457: return e;
11458: }
11459: }
11460:
11461: //if (e2->op != TOKnull)
11462: {
11463: e = op_overload(sc);
11464: if (e)
11465: {
11466: if (op == TOKnotequal)
11467: {
11468: e = new NotExp(e->loc, e);
11469: e = e->semantic(sc);
11470: }
11471: return e;
11472: }
11473: }
11474:
11475: /* Disallow comparing T[]==T and T==T[]
11476: */
11477: if (e1->op == TOKslice && t1->ty == Tarray && e2->implicitConvTo(t1->nextOf()) ||
11478: e2->op == TOKslice && t2->ty == Tarray && e1->implicitConvTo(t2->nextOf()))
11479: {
11480: incompatibleTypes();
11481: return new ErrorExp();
11482: }
11483:
11484: e = typeCombine(sc);
11485: type = Type::tboolean;
11486:
11487: // Special handling for array comparisons
11488: if (!arrayTypeCompatible(loc, e1->type, e2->type))
11489: {
11490: if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
11491: {
11492: // Cast both to complex
11493: e1 = e1->castTo(sc, Type::tcomplex80);
11494: e2 = e2->castTo(sc, Type::tcomplex80);
11495: }
11496: }
11497: return e;
11498: }
11499:
11500: int EqualExp::isBit()
11501: {
11502: return TRUE;
11503: }
11504:
11505:
11506:
11507: /************************************************************/
11508:
11509: IdentityExp::IdentityExp(enum TOK op, Loc loc, Expression *e1, Expression *e2)
11510: : BinExp(loc, op, sizeof(IdentityExp), e1, e2)
11511: {
11512: }
11513:
11514: Expression *IdentityExp::semantic(Scope *sc)
11515: {
11516: if (type)
11517: return this;
11518:
11519: BinExp::semanticp(sc);
11520: type = Type::tboolean;
11521: typeCombine(sc);
11522: if (e1->type != e2->type && e1->type->isfloating() && e2->type->isfloating())
11523: {
11524: // Cast both to complex
11525: e1 = e1->castTo(sc, Type::tcomplex80);
11526: e2 = e2->castTo(sc, Type::tcomplex80);
11527: }
11528: return this;
11529: }
11530:
11531: int IdentityExp::isBit()
11532: {
11533: return TRUE;
11534: }
11535:
11536:
11537: /****************************************************************/
11538:
11539: CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2)
11540: : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2)
11541: {
11542: this->econd = econd;
11543: }
11544:
11545: Expression *CondExp::syntaxCopy()
11546: {
11547: return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy());
11548: }
11549:
11550:
11551: Expression *CondExp::semantic(Scope *sc)
11552: { Type *t1;
11553: Type *t2;
11554: unsigned cs0;
11555: unsigned cs1;
11556:
11557: #if LOGSEMANTIC
11558: printf("CondExp::semantic('%s')\n", toChars());
11559: #endif
11560: if (type)
11561: return this;
11562:
11563: econd = econd->semantic(sc);
11564: econd = resolveProperties(sc, econd);
11565: econd = econd->checkToPointer();
11566: econd = econd->checkToBoolean(sc);
11567:
11568: #if 0 /* this cannot work right because the types of e1 and e2
11569: * both contribute to the type of the result.
11570: */
11571: if (sc->flags & SCOPEstaticif)
11572: {
11573: /* If in static if, don't evaluate what we don't have to.
11574: */
11575: econd = econd->optimize(WANTflags);
11576: if (econd->isBool(TRUE))
11577: {
11578: e1 = e1->semantic(sc);
11579: e1 = resolveProperties(sc, e1);
11580: return e1;
11581: }
11582: else if (econd->isBool(FALSE))
11583: {
11584: e2 = e2->semantic(sc);
11585: e2 = resolveProperties(sc, e2);
11586: return e2;
11587: }
11588: }
11589: #endif
11590:
11591:
11592: cs0 = sc->callSuper;
11593: e1 = e1->semantic(sc);
11594: e1 = resolveProperties(sc, e1);
11595: cs1 = sc->callSuper;
11596: sc->callSuper = cs0;
11597: e2 = e2->semantic(sc);
11598: e2 = resolveProperties(sc, e2);
11599: sc->mergeCallSuper(loc, cs1);
11600:
11601:
11602: // If either operand is void, the result is void
11603: t1 = e1->type;
11604: t2 = e2->type;
11605: if (t1->ty == Tvoid || t2->ty == Tvoid)
11606: type = Type::tvoid;
11607: else if (t1 == t2)
11608: type = t1;
11609: else
11610: {
11611: typeCombine(sc);
11612: switch (e1->type->toBasetype()->ty)
11613: {
11614: case Tcomplex32:
11615: case Tcomplex64:
11616: case Tcomplex80:
11617: e2 = e2->castTo(sc, e1->type);
11618: break;
11619: }
11620: switch (e2->type->toBasetype()->ty)
11621: {
11622: case Tcomplex32:
11623: case Tcomplex64:
11624: case Tcomplex80:
11625: e1 = e1->castTo(sc, e2->type);
11626: break;
11627: }
11628: if (type->toBasetype()->ty == Tarray)
11629: {
11630: e1 = e1->castTo(sc, type);
11631: e2 = e2->castTo(sc, type);
11632: }
11633: }
11634: #if 0
11635: printf("res: %s\n", type->toChars());
11636: printf("e1 : %s\n", e1->type->toChars());
11637: printf("e2 : %s\n", e2->type->toChars());
11638: #endif
11639: return this;
11640: }
11641:
11642: #if DMDV2
11643: int CondExp::isLvalue()
11644: {
11645: return e1->isLvalue() && e2->isLvalue();
11646: }
11647: #endif
11648:
11649: Expression *CondExp::toLvalue(Scope *sc, Expression *ex)
11650: {
11651: PtrExp *e;
11652:
11653: // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
11654: e = new PtrExp(loc, this, type);
11655:
11656: e1 = e1->addressOf(sc);
11657: //e1 = e1->toLvalue(sc, NULL);
11658:
11659: e2 = e2->addressOf(sc);
11660: //e2 = e2->toLvalue(sc, NULL);
11661:
11662: typeCombine(sc);
11663:
11664: type = e2->type;
11665: return e;
11666: }
11667:
11668: Expression *CondExp::modifiableLvalue(Scope *sc, Expression *e)
11669: {
11670: //error("conditional expression %s is not a modifiable lvalue", toChars());
11671: e1 = e1->modifiableLvalue(sc, e1);
11672: e2 = e2->modifiableLvalue(sc, e1);
11673: return toLvalue(sc, this);
11674: }
11675:
11676: void CondExp::checkEscape()
11677: {
11678: e1->checkEscape();
11679: e2->checkEscape();
11680: }
11681:
11682: void CondExp::checkEscapeRef()
11683: {
11684: e1->checkEscapeRef();
11685: e2->checkEscapeRef();
11686: }
11687:
11688:
11689: Expression *CondExp::checkToBoolean(Scope *sc)
11690: {
11691: e1 = e1->checkToBoolean(sc);
11692: e2 = e2->checkToBoolean(sc);
11693: return this;
11694: }
11695:
11696: int CondExp::checkSideEffect(int flag)
11697: {
11698: if (flag == 2)
11699: {
11700: return econd->checkSideEffect(2) ||
11701: e1->checkSideEffect(2) ||
11702: e2->checkSideEffect(2);
11703: }
11704: else
11705: {
11706: econd->checkSideEffect(1);
11707: e1->checkSideEffect(flag);
11708: return e2->checkSideEffect(flag);
11709: }
11710: }
11711:
11712: #if DMDV2
11713: int CondExp::canThrow(bool mustNotThrow)
11714: {
11715: return econd->canThrow(mustNotThrow) || e1->canThrow(mustNotThrow) || e2->canThrow(mustNotThrow);
11716: }
11717: #endif
11718:
11719: void CondExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
11720: {
11721: expToCBuffer(buf, hgs, econd, PREC_oror);
11722: buf->writestring(" ? ");
11723: expToCBuffer(buf, hgs, e1, PREC_expr);
11724: buf->writestring(" : ");
11725: expToCBuffer(buf, hgs, e2, PREC_cond);
11726: }
11727:
11728:
11729: /****************************************************************/
11730:
11731: DefaultInitExp::DefaultInitExp(Loc loc, enum TOK subop, int size)
11732: : Expression(loc, TOKdefault, size)
11733: {
11734: this->subop = subop;
11735: }
11736:
11737: void DefaultInitExp::toCBuffer(OutBuffer *buf, HdrGenState *hgs)
11738: {
11739: buf->writestring(Token::toChars(subop));
11740: }
11741:
11742: /****************************************************************/
11743:
11744: FileInitExp::FileInitExp(Loc loc)
11745: : DefaultInitExp(loc, TOKfile, sizeof(FileInitExp))
11746: {
11747: }
11748:
11749: Expression *FileInitExp::semantic(Scope *sc)
11750: {
11751: //printf("FileInitExp::semantic()\n");
11752: type = Type::tchar->invariantOf()->arrayOf();
11753: return this;
11754: }
11755:
11756: Expression *FileInitExp::resolveLoc(Loc loc, Scope *sc)
11757: {
11758: //printf("FileInitExp::resolve() %s\n", toChars());
11759: const char *s = loc.filename ? loc.filename : sc->module->ident->toChars();
11760: Expression *e = new StringExp(loc, (char *)s);
11761: e = e->semantic(sc);
11762: e = e->castTo(sc, type);
11763: return e;
11764: }
11765:
11766: /****************************************************************/
11767:
11768: LineInitExp::LineInitExp(Loc loc)
11769: : DefaultInitExp(loc, TOKline, sizeof(LineInitExp))
11770: {
11771: }
11772:
11773: Expression *LineInitExp::semantic(Scope *sc)
11774: {
11775: type = Type::tint32;
11776: return this;
11777: }
11778:
11779: Expression *LineInitExp::resolveLoc(Loc loc, Scope *sc)
11780: {
11781: Expression *e = new IntegerExp(loc, loc.linnum, Type::tint32);
11782: e = e->castTo(sc, type);
11783: return e;
11784: }
11785:
11786:
11787: