Merge dmd upstream 6243fa6d2
[official-gcc.git] / gcc / d / dmd / expression.c
blob359e4cc91fdbbb2a88035410b3cf9a4790d73825
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2018 by The D Language Foundation, All Rights Reserved
4 * written by Walter Bright
5 * http://www.digitalmars.com
6 * Distributed under the Boost Software License, Version 1.0.
7 * http://www.boost.org/LICENSE_1_0.txt
8 * https://github.com/D-Programming-Language/dmd/blob/master/src/expression.c
9 */
11 #include "root/dsystem.h"
12 #include "root/rmem.h"
13 #include "root/root.h"
15 #include "errors.h"
16 #include "mtype.h"
17 #include "init.h"
18 #include "expression.h"
19 #include "template.h"
20 #include "utf.h"
21 #include "enum.h"
22 #include "scope.h"
23 #include "statement.h"
24 #include "declaration.h"
25 #include "aggregate.h"
26 #include "import.h"
27 #include "id.h"
28 #include "dsymbol.h"
29 #include "module.h"
30 #include "attrib.h"
31 #include "hdrgen.h"
32 #include "parse.h"
33 #include "doc.h"
34 #include "root/aav.h"
35 #include "nspace.h"
36 #include "ctfe.h"
37 #include "target.h"
39 bool walkPostorder(Expression *e, StoppableVisitor *v);
40 bool checkParamArgumentEscape(Scope *sc, FuncDeclaration *fdc, Identifier *par, Expression *arg, bool gag);
41 bool checkAccess(AggregateDeclaration *ad, Loc loc, Scope *sc, Dsymbol *smember);
42 VarDeclaration *copyToTemp(StorageClass stc, const char *name, Expression *e);
43 Expression *extractSideEffect(Scope *sc, const char *name, Expression **e0, Expression *e, bool alwaysCopy = false);
44 char *MODtoChars(MOD mod);
45 bool MODimplicitConv(MOD modfrom, MOD modto);
46 MOD MODmerge(MOD mod1, MOD mod2);
47 void MODMatchToBuffer(OutBuffer *buf, unsigned char lhsMod, unsigned char rhsMod);
48 Expression *trySemantic(Expression *e, Scope *sc);
49 Expression *semantic(Expression *e, Scope *sc);
50 Expression *semanticX(DotIdExp *exp, Scope *sc);
51 Expression *semanticY(DotIdExp *exp, Scope *sc, int flag);
52 Expression *semanticY(DotTemplateInstanceExp *exp, Scope *sc, int flag);
53 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads);
54 bool checkUnsafeAccess(Scope *sc, Expression *e, bool readonly, bool printmsg);
56 /*************************************************************
57 * Given var, we need to get the
58 * right 'this' pointer if var is in an outer class, but our
59 * existing 'this' pointer is in an inner class.
60 * Input:
61 * e1 existing 'this'
62 * ad struct or class we need the correct 'this' for
63 * var the specific member of ad we're accessing
66 Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
67 Expression *e1, Declaration *var, int flag = 0)
69 //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
70 L1:
71 Type *t = e1->type->toBasetype();
72 //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
74 /* If e1 is not the 'this' pointer for ad
76 if (ad &&
77 !(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
78 ((TypeStruct *)t->nextOf())->sym == ad)
80 !(t->ty == Tstruct &&
81 ((TypeStruct *)t)->sym == ad)
84 ClassDeclaration *cd = ad->isClassDeclaration();
85 ClassDeclaration *tcd = t->isClassHandle();
87 /* e1 is the right this if ad is a base class of e1
89 if (!cd || !tcd ||
90 !(tcd == cd || cd->isBaseOf(tcd, NULL))
93 /* Only classes can be inner classes with an 'outer'
94 * member pointing to the enclosing class instance
96 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.
102 e1 = new DotVarExp(loc, e1, tcd->vthis);
103 e1->type = tcd->vthis->type;
104 e1->type = e1->type->addMod(t->mod);
105 // Do not call checkNestedRef()
106 //e1 = semantic(e1, sc);
108 // Skip up over nested functions, and get the enclosing
109 // class type.
110 int n = 0;
111 Dsymbol *s;
112 for (s = tcd->toParent();
113 s && s->isFuncDeclaration();
114 s = s->toParent())
116 FuncDeclaration *f = s->isFuncDeclaration();
117 if (f->vthis)
119 //printf("rewriting e1 to %s's this\n", f->toChars());
120 n++;
121 e1 = new VarExp(loc, f->vthis);
123 else
125 e1->error("need 'this' of type %s to access member %s"
126 " from static function %s",
127 ad->toChars(), var->toChars(), f->toChars());
128 e1 = new ErrorExp();
129 return e1;
132 if (s && s->isClassDeclaration())
134 e1->type = s->isClassDeclaration()->type;
135 e1->type = e1->type->addMod(t->mod);
136 if (n > 1)
137 e1 = semantic(e1, sc);
139 else
140 e1 = semantic(e1, sc);
141 goto L1;
144 /* Can't find a path from e1 to ad
146 if (flag)
147 return NULL;
148 e1->error("this for %s needs to be type %s not type %s",
149 var->toChars(), ad->toChars(), t->toChars());
150 return new ErrorExp();
153 return e1;
156 /*****************************************
157 * Determine if 'this' is available.
158 * If it is, return the FuncDeclaration that has it.
161 FuncDeclaration *hasThis(Scope *sc)
163 //printf("hasThis()\n");
164 Dsymbol *p = sc->parent;
165 while (p && p->isTemplateMixin())
166 p = p->parent;
167 FuncDeclaration *fdthis = p ? p->isFuncDeclaration() : NULL;
168 //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : "");
170 // Go upwards until we find the enclosing member function
171 FuncDeclaration *fd = fdthis;
172 while (1)
174 if (!fd)
176 goto Lno;
178 if (!fd->isNested())
179 break;
181 Dsymbol *parent = fd->parent;
182 while (1)
184 if (!parent)
185 goto Lno;
186 TemplateInstance *ti = parent->isTemplateInstance();
187 if (ti)
188 parent = ti->parent;
189 else
190 break;
192 fd = parent->isFuncDeclaration();
195 if (!fd->isThis())
196 { //printf("test '%s'\n", fd->toChars());
197 goto Lno;
200 assert(fd->vthis);
201 return fd;
203 Lno:
204 return NULL; // don't have 'this' available
207 bool isNeedThisScope(Scope *sc, Declaration *d)
209 if (sc->intypeof == 1)
210 return false;
212 AggregateDeclaration *ad = d->isThis();
213 if (!ad)
214 return false;
215 //printf("d = %s, ad = %s\n", d->toChars(), ad->toChars());
217 for (Dsymbol *s = sc->parent; s; s = s->toParent2())
219 //printf("\ts = %s %s, toParent2() = %p\n", s->kind(), s->toChars(), s->toParent2());
220 if (AggregateDeclaration *ad2 = s->isAggregateDeclaration())
222 if (ad2 == ad)
223 return false;
224 else if (ad2->isNested())
225 continue;
226 else
227 return true;
229 if (FuncDeclaration *f = s->isFuncDeclaration())
231 if (f->isMember2())
232 break;
235 return true;
238 /***************************************
239 * Pull out any properties.
242 Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
244 //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token::toChars(e1->op), e1->toChars(), e2 ? e2->toChars() : NULL);
245 Loc loc = e1->loc;
247 OverloadSet *os;
248 Dsymbol *s;
249 Objects *tiargs;
250 Type *tthis;
251 if (e1->op == TOKdot)
253 DotExp *de = (DotExp *)e1;
254 if (de->e2->op == TOKoverloadset)
256 tiargs = NULL;
257 tthis = de->e1->type;
258 os = ((OverExp *)de->e2)->vars;
259 goto Los;
262 else if (e1->op == TOKoverloadset)
264 tiargs = NULL;
265 tthis = NULL;
266 os = ((OverExp *)e1)->vars;
267 Los:
268 assert(os);
269 FuncDeclaration *fd = NULL;
270 if (e2)
272 e2 = semantic(e2, sc);
273 if (e2->op == TOKerror)
274 return new ErrorExp();
275 e2 = resolveProperties(sc, e2);
277 Expressions a;
278 a.push(e2);
280 for (size_t i = 0; i < os->a.dim; i++)
282 FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, &a, 1);
283 if (f)
285 if (f->errors)
286 return new ErrorExp();
287 fd = f;
288 assert(fd->type->ty == Tfunction);
291 if (fd)
293 Expression *e = new CallExp(loc, e1, e2);
294 return semantic(e, sc);
298 for (size_t i = 0; i < os->a.dim; i++)
300 FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, NULL, 1);
301 if (f)
303 if (f->errors)
304 return new ErrorExp();
305 fd = f;
306 assert(fd->type->ty == Tfunction);
307 TypeFunction *tf = (TypeFunction *)fd->type;
308 if (!tf->isref && e2)
309 goto Leproplvalue;
312 if (fd)
314 Expression *e = new CallExp(loc, e1);
315 if (e2)
316 e = new AssignExp(loc, e, e2);
317 return semantic(e, sc);
320 if (e2)
321 goto Leprop;
323 else if (e1->op == TOKdotti)
325 DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1;
326 if (!dti->findTempDecl(sc))
327 goto Leprop;
328 if (!dti->ti->semanticTiargs(sc))
329 goto Leprop;
330 tiargs = dti->ti->tiargs;
331 tthis = dti->e1->type;
332 if ((os = dti->ti->tempdecl->isOverloadSet()) != NULL)
333 goto Los;
334 if ((s = dti->ti->tempdecl) != NULL)
335 goto Lfd;
337 else if (e1->op == TOKdottd)
339 DotTemplateExp *dte = (DotTemplateExp *)e1;
340 s = dte->td;
341 tiargs = NULL;
342 tthis = dte->e1->type;
343 goto Lfd;
345 else if (e1->op == TOKscope)
347 s = ((ScopeExp *)e1)->sds;
348 TemplateInstance *ti = s->isTemplateInstance();
349 if (ti && !ti->semanticRun && ti->tempdecl)
351 //assert(ti->needsTypeInference(sc));
352 if (!ti->semanticTiargs(sc))
353 goto Leprop;
354 tiargs = ti->tiargs;
355 tthis = NULL;
356 if ((os = ti->tempdecl->isOverloadSet()) != NULL)
357 goto Los;
358 if ((s = ti->tempdecl) != NULL)
359 goto Lfd;
362 else if (e1->op == TOKtemplate)
364 s = ((TemplateExp *)e1)->td;
365 tiargs = NULL;
366 tthis = NULL;
367 goto Lfd;
369 else if (e1->op == TOKdotvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
371 DotVarExp *dve = (DotVarExp *)e1;
372 s = dve->var->isFuncDeclaration();
373 tiargs = NULL;
374 tthis = dve->e1->type;
375 goto Lfd;
377 else if (e1->op == TOKvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
379 s = ((VarExp *)e1)->var->isFuncDeclaration();
380 tiargs = NULL;
381 tthis = NULL;
382 Lfd:
383 assert(s);
384 if (e2)
386 e2 = semantic(e2, sc);
387 if (e2->op == TOKerror)
388 return new ErrorExp();
389 e2 = resolveProperties(sc, e2);
391 Expressions a;
392 a.push(e2);
394 FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, 1);
395 if (fd && fd->type)
397 if (fd->errors)
398 return new ErrorExp();
399 assert(fd->type->ty == Tfunction);
400 Expression *e = new CallExp(loc, e1, e2);
401 return semantic(e, sc);
405 FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, NULL, 1);
406 if (fd && fd->type)
408 if (fd->errors)
409 return new ErrorExp();
410 assert(fd->type->ty == Tfunction);
411 TypeFunction *tf = (TypeFunction *)fd->type;
412 if (!e2 || tf->isref)
414 Expression *e = new CallExp(loc, e1);
415 if (e2)
416 e = new AssignExp(loc, e, e2);
417 return semantic(e, sc);
421 if (FuncDeclaration *fd = s->isFuncDeclaration())
423 // Keep better diagnostic message for invalid property usage of functions
424 assert(fd->type->ty == Tfunction);
425 Expression *e = new CallExp(loc, e1, e2);
426 return semantic(e, sc);
428 if (e2)
429 goto Leprop;
431 if (e1->op == TOKvar)
433 VarExp *ve = (VarExp *)e1;
434 VarDeclaration *v = ve->var->isVarDeclaration();
435 if (v && ve->checkPurity(sc, v))
436 return new ErrorExp();
438 if (e2)
439 return NULL;
441 if (e1->type &&
442 e1->op != TOKtype) // function type is not a property
444 /* Look for e1 being a lazy parameter; rewrite as delegate call
446 if (e1->op == TOKvar)
448 VarExp *ve = (VarExp *)e1;
450 if (ve->var->storage_class & STClazy)
452 Expression *e = new CallExp(loc, e1);
453 return semantic(e, sc);
456 else if (e1->op == TOKdotvar)
458 // Check for reading overlapped pointer field in @safe code.
459 if (checkUnsafeAccess(sc, e1, true, true))
460 return new ErrorExp();
462 else if (e1->op == TOKdot)
464 e1->error("expression has no value");
465 return new ErrorExp();
467 else if (e1->op == TOKcall)
469 CallExp *ce = (CallExp *)e1;
470 // Check for reading overlapped pointer field in @safe code.
471 if (checkUnsafeAccess(sc, ce->e1, true, true))
472 return new ErrorExp();
476 if (!e1->type)
478 error(loc, "cannot resolve type for %s", e1->toChars());
479 e1 = new ErrorExp();
481 return e1;
483 Leprop:
484 error(loc, "not a property %s", e1->toChars());
485 return new ErrorExp();
487 Leproplvalue:
488 error(loc, "%s is not an lvalue", e1->toChars());
489 return new ErrorExp();
492 Expression *resolveProperties(Scope *sc, Expression *e)
494 //printf("resolveProperties(%s)\n", e->toChars());
496 e = resolvePropertiesX(sc, e);
497 if (e->checkRightThis(sc))
498 return new ErrorExp();
499 return e;
502 /******************************
503 * Check the tail CallExp is really property function call.
505 static bool checkPropertyCall(Expression *e)
507 while (e->op == TOKcomma)
508 e = ((CommaExp *)e)->e2;
510 if (e->op == TOKcall)
512 CallExp *ce = (CallExp *)e;
513 TypeFunction *tf;
514 if (ce->f)
516 tf = (TypeFunction *)ce->f->type;
517 /* If a forward reference to ce->f, try to resolve it
519 if (!tf->deco && ce->f->_scope)
521 ce->f->semantic(ce->f->_scope);
522 tf = (TypeFunction *)ce->f->type;
525 else if (ce->e1->type->ty == Tfunction)
526 tf = (TypeFunction *)ce->e1->type;
527 else if (ce->e1->type->ty == Tdelegate)
528 tf = (TypeFunction *)ce->e1->type->nextOf();
529 else if (ce->e1->type->ty == Tpointer && ce->e1->type->nextOf()->ty == Tfunction)
530 tf = (TypeFunction *)ce->e1->type->nextOf();
531 else
532 assert(0);
534 return false;
537 /******************************
538 * If e1 is a property function (template), resolve it.
541 Expression *resolvePropertiesOnly(Scope *sc, Expression *e1)
543 //printf("e1 = %s %s\n", Token::toChars(e1->op), e1->toChars());
544 OverloadSet *os;
545 FuncDeclaration *fd;
546 TemplateDeclaration *td;
548 if (e1->op == TOKdot)
550 DotExp *de = (DotExp *)e1;
551 if (de->e2->op == TOKoverloadset)
553 os = ((OverExp *)de->e2)->vars;
554 goto Los;
557 else if (e1->op == TOKoverloadset)
559 os = ((OverExp *)e1)->vars;
560 Los:
561 assert(os);
562 for (size_t i = 0; i < os->a.dim; i++)
564 Dsymbol *s = os->a[i];
565 fd = s->isFuncDeclaration();
566 td = s->isTemplateDeclaration();
567 if (fd)
569 if (((TypeFunction *)fd->type)->isproperty)
570 return resolveProperties(sc, e1);
572 else if (td && td->onemember &&
573 (fd = td->onemember->isFuncDeclaration()) != NULL)
575 if (((TypeFunction *)fd->type)->isproperty ||
576 (fd->storage_class2 & STCproperty) ||
577 (td->_scope->stc & STCproperty))
579 return resolveProperties(sc, e1);
584 else if (e1->op == TOKdotti)
586 DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1;
587 if (dti->ti->tempdecl && (td = dti->ti->tempdecl->isTemplateDeclaration()) != NULL)
588 goto Ltd;
590 else if (e1->op == TOKdottd)
592 td = ((DotTemplateExp *)e1)->td;
593 goto Ltd;
595 else if (e1->op == TOKscope)
597 Dsymbol *s = ((ScopeExp *)e1)->sds;
598 TemplateInstance *ti = s->isTemplateInstance();
599 if (ti && !ti->semanticRun && ti->tempdecl)
601 if ((td = ti->tempdecl->isTemplateDeclaration()) != NULL)
602 goto Ltd;
605 else if (e1->op == TOKtemplate)
607 td = ((TemplateExp *)e1)->td;
608 Ltd:
609 assert(td);
610 if (td->onemember &&
611 (fd = td->onemember->isFuncDeclaration()) != NULL)
613 if (((TypeFunction *)fd->type)->isproperty ||
614 (fd->storage_class2 & STCproperty) ||
615 (td->_scope->stc & STCproperty))
617 return resolveProperties(sc, e1);
621 else if (e1->op == TOKdotvar && e1->type->ty == Tfunction)
623 DotVarExp *dve = (DotVarExp *)e1;
624 fd = dve->var->isFuncDeclaration();
625 goto Lfd;
627 else if (e1->op == TOKvar && e1->type->ty == Tfunction &&
628 (sc->intypeof || !((VarExp *)e1)->var->needThis()))
630 fd = ((VarExp *)e1)->var->isFuncDeclaration();
631 Lfd:
632 assert(fd);
633 if (((TypeFunction *)fd->type)->isproperty)
634 return resolveProperties(sc, e1);
636 return e1;
640 // TODO: merge with Scope::search::searchScopes()
641 static Dsymbol *searchScopes(Scope *sc, Loc loc, Identifier *ident, int flags)
643 Dsymbol *s = NULL;
644 for (Scope *scx = sc; scx; scx = scx->enclosing)
646 if (!scx->scopesym)
647 continue;
648 if (scx->scopesym->isModule())
649 flags |= SearchUnqualifiedModule; // tell Module.search() that SearchLocalsOnly is to be obeyed
650 s = scx->scopesym->search(loc, ident, flags);
651 if (s)
653 // overload set contains only module scope symbols.
654 if (s->isOverloadSet())
655 break;
656 // selective/renamed imports also be picked up
657 if (AliasDeclaration *ad = s->isAliasDeclaration())
659 if (ad->_import)
660 break;
662 // See only module scope symbols for UFCS target.
663 Dsymbol *p = s->toParent2();
664 if (p && p->isModule())
665 break;
667 s = NULL;
669 // Stop when we hit a module, but keep going if that is not just under the global scope
670 if (scx->scopesym->isModule() && !(scx->enclosing && !scx->enclosing->enclosing))
671 break;
673 return s;
676 /******************************
677 * Find symbol in accordance with the UFCS name look up rule
680 Expression *searchUFCS(Scope *sc, UnaExp *ue, Identifier *ident)
682 //printf("searchUFCS(ident = %s)\n", ident->toChars());
683 Loc loc = ue->loc;
684 int flags = 0;
685 Dsymbol *s = NULL;
687 if (sc->flags & SCOPEignoresymbolvisibility)
688 flags |= IgnoreSymbolVisibility;
690 Dsymbol *sold = NULL;
691 if (global.params.bug10378 || global.params.check10378)
693 sold = searchScopes(sc, loc, ident, flags | IgnoreSymbolVisibility);
694 if (!global.params.check10378)
696 s = sold;
697 goto Lsearchdone;
701 // First look in local scopes
702 s = searchScopes(sc, loc, ident, flags | SearchLocalsOnly);
703 if (!s)
705 // Second look in imported modules
706 s = searchScopes(sc, loc, ident, flags | SearchImportsOnly);
708 /** Still find private symbols, so that symbols that weren't access
709 * checked by the compiler remain usable. Once the deprecation is over,
710 * this should be moved to search_correct instead.
712 if (!s && !(flags & IgnoreSymbolVisibility))
714 s = searchScopes(sc, loc, ident, flags | SearchLocalsOnly | IgnoreSymbolVisibility);
715 if (!s)
716 s = searchScopes(sc, loc, ident, flags | SearchImportsOnly | IgnoreSymbolVisibility);
717 if (s)
718 ::deprecation(loc, "%s is not visible from module %s", s->toPrettyChars(), sc->_module->toChars());
721 if (global.params.check10378)
723 Dsymbol *snew = s;
724 if (sold != snew)
725 Scope::deprecation10378(loc, sold, snew);
726 if (global.params.bug10378)
727 s = sold;
729 Lsearchdone:
731 if (!s)
732 return ue->e1->type->Type::getProperty(loc, ident, 0);
734 FuncDeclaration *f = s->isFuncDeclaration();
735 if (f)
737 TemplateDeclaration *td = getFuncTemplateDecl(f);
738 if (td)
740 if (td->overroot)
741 td = td->overroot;
742 s = td;
746 if (ue->op == TOKdotti)
748 DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ue;
749 TemplateInstance *ti = new TemplateInstance(loc, s->ident);
750 ti->tiargs = dti->ti->tiargs; // for better diagnostic message
751 if (!ti->updateTempDecl(sc, s))
752 return new ErrorExp();
753 return new ScopeExp(loc, ti);
755 else
757 //printf("-searchUFCS() %s\n", s->toChars());
758 return new DsymbolExp(loc, s);
762 /******************************
763 * check e is exp.opDispatch!(tiargs) or not
764 * It's used to switch to UFCS the semantic analysis path
767 bool isDotOpDispatch(Expression *e)
769 return e->op == TOKdotti &&
770 ((DotTemplateInstanceExp *)e)->ti->name == Id::opDispatch;
773 /******************************
774 * Pull out callable entity with UFCS.
777 Expression *resolveUFCS(Scope *sc, CallExp *ce)
779 Loc loc = ce->loc;
780 Expression *eleft;
781 Expression *e;
783 if (ce->e1->op == TOKdotid)
785 DotIdExp *die = (DotIdExp *)ce->e1;
786 Identifier *ident = die->ident;
788 Expression *ex = semanticX(die, sc);
789 if (ex != die)
791 ce->e1 = ex;
792 return NULL;
794 eleft = die->e1;
796 Type *t = eleft->type->toBasetype();
797 if (t->ty == Tarray || t->ty == Tsarray ||
798 t->ty == Tnull || (t->isTypeBasic() && t->ty != Tvoid))
800 /* Built-in types and arrays have no callable properties, so do shortcut.
801 * It is necessary in: e.init()
804 else if (t->ty == Taarray)
806 if (ident == Id::remove)
808 /* Transform:
809 * aa.remove(arg) into delete aa[arg]
811 if (!ce->arguments || ce->arguments->dim != 1)
813 ce->error("expected key as argument to aa.remove()");
814 return new ErrorExp();
816 if (!eleft->type->isMutable())
818 ce->error("cannot remove key from %s associative array %s",
819 MODtoChars(t->mod), eleft->toChars());
820 return new ErrorExp();
822 Expression *key = (*ce->arguments)[0];
823 key = semantic(key, sc);
824 key = resolveProperties(sc, key);
826 TypeAArray *taa = (TypeAArray *)t;
827 key = key->implicitCastTo(sc, taa->index);
829 if (key->checkValue())
830 return new ErrorExp();
832 semanticTypeInfo(sc, taa->index);
834 return new RemoveExp(loc, eleft, key);
837 else
839 if (Expression *ey = semanticY(die, sc, 1))
841 if (ey->op == TOKerror)
842 return ey;
843 ce->e1 = ey;
844 if (isDotOpDispatch(ey))
846 unsigned errors = global.startGagging();
847 e = semantic(ce->syntaxCopy(), sc);
848 if (!global.endGagging(errors))
849 return e;
850 /* fall down to UFCS */
852 else
853 return NULL;
856 e = searchUFCS(sc, die, ident);
858 else if (ce->e1->op == TOKdotti)
860 DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ce->e1;
861 if (Expression *ey = semanticY(dti, sc, 1))
863 ce->e1 = ey;
864 return NULL;
866 eleft = dti->e1;
867 e = searchUFCS(sc, dti, dti->ti->name);
869 else
870 return NULL;
872 // Rewrite
873 ce->e1 = e;
874 if (!ce->arguments)
875 ce->arguments = new Expressions();
876 ce->arguments->shift(eleft);
878 return NULL;
881 /******************************
882 * Pull out property with UFCS.
885 Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NULL)
887 Loc loc = e1->loc;
888 Expression *eleft;
889 Expression *e;
891 if (e1->op == TOKdotid)
893 DotIdExp *die = (DotIdExp *)e1;
894 eleft = die->e1;
895 e = searchUFCS(sc, die, die->ident);
897 else if (e1->op == TOKdotti)
899 DotTemplateInstanceExp *dti;
900 dti = (DotTemplateInstanceExp *)e1;
901 eleft = dti->e1;
902 e = searchUFCS(sc, dti, dti->ti->name);
904 else
905 return NULL;
907 if (e == NULL)
908 return NULL;
910 // Rewrite
911 if (e2)
913 // run semantic without gagging
914 e2 = semantic(e2, sc);
916 /* f(e1) = e2
918 Expression *ex = e->copy();
919 Expressions *a1 = new Expressions();
920 a1->setDim(1);
921 (*a1)[0] = eleft;
922 ex = new CallExp(loc, ex, a1);
923 ex = trySemantic(ex, sc);
925 /* f(e1, e2)
927 Expressions *a2 = new Expressions();
928 a2->setDim(2);
929 (*a2)[0] = eleft;
930 (*a2)[1] = e2;
931 e = new CallExp(loc, e, a2);
932 if (ex)
933 { // if fallback setter exists, gag errors
934 e = trySemantic(e, sc);
935 if (!e)
936 { checkPropertyCall(ex);
937 ex = new AssignExp(loc, ex, e2);
938 return semantic(ex, sc);
941 else
942 { // strict setter prints errors if fails
943 e = semantic(e, sc);
945 checkPropertyCall(e);
946 return e;
948 else
950 /* f(e1)
952 Expressions *arguments = new Expressions();
953 arguments->setDim(1);
954 (*arguments)[0] = eleft;
955 e = new CallExp(loc, e, arguments);
956 e = semantic(e, sc);
957 checkPropertyCall(e);
958 return semantic(e, sc);
962 /******************************
963 * Perform semantic() on an array of Expressions.
966 bool arrayExpressionSemantic(Expressions *exps, Scope *sc, bool preserveErrors)
968 bool err = false;
969 if (exps)
971 for (size_t i = 0; i < exps->dim; i++)
973 Expression *e = (*exps)[i];
974 if (e)
976 e = semantic(e, sc);
977 if (e->op == TOKerror)
978 err = true;
979 if (preserveErrors || e->op != TOKerror)
980 (*exps)[i] = e;
984 return err;
987 /****************************************
988 * Expand tuples.
989 * Input:
990 * exps aray of Expressions
991 * Output:
992 * exps rewritten in place
995 void expandTuples(Expressions *exps)
997 //printf("expandTuples()\n");
998 if (exps)
1000 for (size_t i = 0; i < exps->dim; i++)
1002 Expression *arg = (*exps)[i];
1003 if (!arg)
1004 continue;
1006 // Look for tuple with 0 members
1007 if (arg->op == TOKtype)
1009 TypeExp *e = (TypeExp *)arg;
1010 if (e->type->toBasetype()->ty == Ttuple)
1012 TypeTuple *tt = (TypeTuple *)e->type->toBasetype();
1014 if (!tt->arguments || tt->arguments->dim == 0)
1016 exps->remove(i);
1017 if (i == exps->dim)
1018 return;
1019 i--;
1020 continue;
1025 // Inline expand all the tuples
1026 while (arg->op == TOKtuple)
1028 TupleExp *te = (TupleExp *)arg;
1029 exps->remove(i); // remove arg
1030 exps->insert(i, te->exps); // replace with tuple contents
1031 if (i == exps->dim)
1032 return; // empty tuple, no more arguments
1033 (*exps)[i] = Expression::combine(te->e0, (*exps)[i]);
1034 arg = (*exps)[i];
1040 /****************************************
1041 * Expand alias this tuples.
1044 TupleDeclaration *isAliasThisTuple(Expression *e)
1046 if (!e->type)
1047 return NULL;
1049 Type *t = e->type->toBasetype();
1050 Lagain:
1051 if (Dsymbol *s = t->toDsymbol(NULL))
1053 AggregateDeclaration *ad = s->isAggregateDeclaration();
1054 if (ad)
1056 s = ad->aliasthis;
1057 if (s && s->isVarDeclaration())
1059 TupleDeclaration *td = s->isVarDeclaration()->toAlias()->isTupleDeclaration();
1060 if (td && td->isexp)
1061 return td;
1063 if (Type *att = t->aliasthisOf())
1065 t = att;
1066 goto Lagain;
1070 return NULL;
1073 int expandAliasThisTuples(Expressions *exps, size_t starti)
1075 if (!exps || exps->dim == 0)
1076 return -1;
1078 for (size_t u = starti; u < exps->dim; u++)
1080 Expression *exp = (*exps)[u];
1081 TupleDeclaration *td = isAliasThisTuple(exp);
1082 if (td)
1084 exps->remove(u);
1085 for (size_t i = 0; i<td->objects->dim; ++i)
1087 Expression *e = isExpression((*td->objects)[i]);
1088 assert(e);
1089 assert(e->op == TOKdsymbol);
1090 DsymbolExp *se = (DsymbolExp *)e;
1091 Declaration *d = se->s->isDeclaration();
1092 assert(d);
1093 e = new DotVarExp(exp->loc, exp, d);
1094 assert(d->type);
1095 e->type = d->type;
1096 exps->insert(u + i, e);
1098 return (int)u;
1102 return -1;
1105 /****************************************
1106 * The common type is determined by applying ?: to each pair.
1107 * Output:
1108 * exps[] properties resolved, implicitly cast to common type, rewritten in place
1109 * *pt if pt is not NULL, set to the common type
1110 * Returns:
1111 * true a semantic error was detected
1114 bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
1116 /* Still have a problem with:
1117 * ubyte[][] = [ cast(ubyte[])"hello", [1]];
1118 * which works if the array literal is initialized top down with the ubyte[][]
1119 * type, but fails with this function doing bottom up typing.
1121 //printf("arrayExpressionToCommonType()\n");
1122 IntegerExp integerexp(0);
1123 CondExp condexp(Loc(), &integerexp, NULL, NULL);
1125 Type *t0 = NULL;
1126 Expression *e0 = NULL; // dead-store to prevent spurious warning
1127 size_t j0 = ~0; // dead-store to prevent spurious warning
1128 for (size_t i = 0; i < exps->dim; i++)
1130 Expression *e = (*exps)[i];
1131 if (!e)
1132 continue;
1134 e = resolveProperties(sc, e);
1135 if (!e->type)
1137 e->error("%s has no value", e->toChars());
1138 t0 = Type::terror;
1139 continue;
1141 if (e->op == TOKtype)
1143 e->checkValue(); // report an error "type T has no value"
1144 t0 = Type::terror;
1145 continue;
1147 if (e->type->ty == Tvoid)
1149 // void expressions do not concur to the determination of the common
1150 // type.
1151 continue;
1153 if (checkNonAssignmentArrayOp(e))
1155 t0 = Type::terror;
1156 continue;
1159 e = doCopyOrMove(sc, e);
1161 if (t0 && !t0->equals(e->type))
1163 /* This applies ?: to merge the types. It's backwards;
1164 * ?: should call this function to merge types.
1166 condexp.type = NULL;
1167 condexp.e1 = e0;
1168 condexp.e2 = e;
1169 condexp.loc = e->loc;
1170 Expression *ex = semantic(&condexp, sc);
1171 if (ex->op == TOKerror)
1172 e = ex;
1173 else
1175 (*exps)[j0] = condexp.e1;
1176 e = condexp.e2;
1179 j0 = i;
1180 e0 = e;
1181 t0 = e->type;
1182 if (e->op != TOKerror)
1183 (*exps)[i] = e;
1186 if (!t0)
1187 t0 = Type::tvoid; // [] is typed as void[]
1188 else if (t0->ty != Terror)
1190 for (size_t i = 0; i < exps->dim; i++)
1192 Expression *e = (*exps)[i];
1193 if (!e)
1194 continue;
1196 e = e->implicitCastTo(sc, t0);
1197 //assert(e->op != TOKerror);
1198 if (e->op == TOKerror)
1200 /* Bugzilla 13024: a workaround for the bug in typeMerge -
1201 * it should paint e1 and e2 by deduced common type,
1202 * but doesn't in this particular case.
1204 t0 = Type::terror;
1205 break;
1207 (*exps)[i] = e;
1210 if (pt)
1211 *pt = t0;
1213 return (t0 == Type::terror);
1216 /****************************************
1217 * Get TemplateDeclaration enclosing FuncDeclaration.
1220 TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s)
1222 FuncDeclaration *f = s->isFuncDeclaration();
1223 if (f && f->parent)
1225 TemplateInstance *ti = f->parent->isTemplateInstance();
1226 if (ti && !ti->isTemplateMixin() &&
1227 ti->tempdecl && ((TemplateDeclaration *)ti->tempdecl)->onemember &&
1228 ti->tempdecl->ident == f->ident)
1230 return (TemplateDeclaration *)ti->tempdecl;
1233 return NULL;
1236 /************************************************
1237 * If we want the value of this expression, but do not want to call
1238 * the destructor on it.
1241 Expression *valueNoDtor(Expression *e)
1243 if (e->op == TOKcall)
1245 /* The struct value returned from the function is transferred
1246 * so do not call the destructor on it.
1247 * Recognize:
1248 * ((S _ctmp = S.init), _ctmp).this(...)
1249 * and make sure the destructor is not called on _ctmp
1250 * BUG: if e is a CommaExp, we should go down the right side.
1252 CallExp *ce = (CallExp *)e;
1253 if (ce->e1->op == TOKdotvar)
1255 DotVarExp *dve = (DotVarExp *)ce->e1;
1256 if (dve->var->isCtorDeclaration())
1258 // It's a constructor call
1259 if (dve->e1->op == TOKcomma)
1261 CommaExp *comma = (CommaExp *)dve->e1;
1262 if (comma->e2->op == TOKvar)
1264 VarExp *ve = (VarExp *)comma->e2;
1265 VarDeclaration *ctmp = ve->var->isVarDeclaration();
1266 if (ctmp)
1268 ctmp->storage_class |= STCnodtor;
1269 assert(!ce->isLvalue());
1276 else if (e->op == TOKvar)
1278 VarDeclaration *vtmp = ((VarExp *)e)->var->isVarDeclaration();
1279 if (vtmp && vtmp->storage_class & STCrvalue)
1281 vtmp->storage_class |= STCnodtor;
1284 return e;
1287 /********************************************
1288 * Issue an error if default construction is disabled for type t.
1289 * Default construction is required for arrays and 'out' parameters.
1290 * Returns:
1291 * true an error was issued
1293 bool checkDefCtor(Loc loc, Type *t)
1295 t = t->baseElemOf();
1296 if (t->ty == Tstruct)
1298 StructDeclaration *sd = ((TypeStruct *)t)->sym;
1299 if (sd->noDefaultCtor)
1301 sd->error(loc, "default construction is disabled");
1302 return true;
1305 return false;
1308 /*********************************************
1309 * If e is an instance of a struct, and that struct has a copy constructor,
1310 * rewrite e as:
1311 * (tmp = e),tmp
1312 * Input:
1313 * sc just used to specify the scope of created temporary variable
1315 Expression *callCpCtor(Scope *sc, Expression *e)
1317 Type *tv = e->type->baseElemOf();
1318 if (tv->ty == Tstruct)
1320 StructDeclaration *sd = ((TypeStruct *)tv)->sym;
1321 if (sd->postblit)
1323 /* Create a variable tmp, and replace the argument e with:
1324 * (tmp = e),tmp
1325 * and let AssignExp() handle the construction.
1326 * This is not the most efficent, ideally tmp would be constructed
1327 * directly onto the stack.
1329 VarDeclaration *tmp = copyToTemp(STCrvalue, "__copytmp", e);
1330 tmp->storage_class |= STCnodtor;
1331 tmp->semantic(sc);
1332 Expression *de = new DeclarationExp(e->loc, tmp);
1333 Expression *ve = new VarExp(e->loc, tmp);
1334 de->type = Type::tvoid;
1335 ve->type = e->type;
1336 e = Expression::combine(de, ve);
1339 return e;
1342 /************************************************
1343 * Handle the postblit call on lvalue, or the move of rvalue.
1345 Expression *doCopyOrMove(Scope *sc, Expression *e)
1347 if (e->op == TOKquestion)
1349 CondExp *ce = (CondExp *)e;
1350 ce->e1 = doCopyOrMove(sc, ce->e1);
1351 ce->e2 = doCopyOrMove(sc, ce->e2);
1353 else
1355 e = e->isLvalue() ? callCpCtor(sc, e) : valueNoDtor(e);
1357 return e;
1360 /****************************************
1361 * Now that we know the exact type of the function we're calling,
1362 * the arguments[] need to be adjusted:
1363 * 1. implicitly convert argument to the corresponding parameter type
1364 * 2. add default arguments for any missing arguments
1365 * 3. do default promotions on arguments corresponding to ...
1366 * 4. add hidden _arguments[] argument
1367 * 5. call copy constructor for struct value arguments
1368 * Input:
1369 * tf type of the function
1370 * fd the function being called, NULL if called indirectly
1371 * Output:
1372 * *prettype return type of function
1373 * *peprefix expression to execute before arguments[] are evaluated, NULL if none
1374 * Returns:
1375 * true errors happened
1378 bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
1379 Type *tthis, Expressions *arguments, FuncDeclaration *fd, Type **prettype, Expression **peprefix)
1381 //printf("functionParameters()\n");
1382 assert(arguments);
1383 assert(fd || tf->next);
1384 size_t nargs = arguments ? arguments->dim : 0;
1385 size_t nparams = Parameter::dim(tf->parameters);
1386 unsigned olderrors = global.errors;
1387 bool err = false;
1388 *prettype = Type::terror;
1389 Expression *eprefix = NULL;
1390 *peprefix = NULL;
1392 if (nargs > nparams && tf->varargs == 0)
1394 error(loc, "expected %llu arguments, not %llu for non-variadic function type %s", (ulonglong)nparams, (ulonglong)nargs, tf->toChars());
1395 return true;
1398 // If inferring return type, and semantic3() needs to be run if not already run
1399 if (!tf->next && fd->inferRetType)
1401 fd->functionSemantic();
1403 else if (fd && fd->parent)
1405 TemplateInstance *ti = fd->parent->isTemplateInstance();
1406 if (ti && ti->tempdecl)
1408 fd->functionSemantic3();
1411 bool isCtorCall = fd && fd->needThis() && fd->isCtorDeclaration();
1413 size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
1415 /* If the function return type has wildcards in it, we'll need to figure out the actual type
1416 * based on the actual argument types.
1418 MOD wildmatch = 0;
1419 if (tthis && tf->isWild() && !isCtorCall)
1421 Type *t = tthis;
1422 if (t->isImmutable())
1423 wildmatch = MODimmutable;
1424 else if (t->isWildConst())
1425 wildmatch = MODwildconst;
1426 else if (t->isWild())
1427 wildmatch = MODwild;
1428 else if (t->isConst())
1429 wildmatch = MODconst;
1430 else
1431 wildmatch = MODmutable;
1434 int done = 0;
1435 for (size_t i = 0; i < n; i++)
1437 Expression *arg;
1439 if (i < nargs)
1440 arg = (*arguments)[i];
1441 else
1442 arg = NULL;
1444 if (i < nparams)
1446 Parameter *p = Parameter::getNth(tf->parameters, i);
1448 if (!arg)
1450 if (!p->defaultArg)
1452 if (tf->varargs == 2 && i + 1 == nparams)
1453 goto L2;
1454 error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
1455 return true;
1457 arg = p->defaultArg;
1458 arg = inlineCopy(arg, sc);
1459 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
1460 arg = arg->resolveLoc(loc, sc);
1461 arguments->push(arg);
1462 nargs++;
1465 if (tf->varargs == 2 && i + 1 == nparams)
1467 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
1469 MATCH m;
1470 if ((m = arg->implicitConvTo(p->type)) > MATCHnomatch)
1472 if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m)
1473 goto L2;
1474 else if (nargs != nparams)
1475 { error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
1476 return true;
1478 goto L1;
1482 Type *tb = p->type->toBasetype();
1483 Type *tret = p->isLazyArray();
1484 switch (tb->ty)
1486 case Tsarray:
1487 case Tarray:
1489 /* Create a static array variable v of type arg->type:
1490 * T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
1492 * The array literal in the initializer of the hidden variable
1493 * is now optimized. See Bugzilla 2356.
1495 Type *tbn = ((TypeArray *)tb)->next;
1496 Type *tsa = tbn->sarrayOf(nargs - i);
1498 Expressions *elements = new Expressions();
1499 elements->setDim(nargs - i);
1500 for (size_t u = 0; u < elements->dim; u++)
1502 Expression *a = (*arguments)[i + u];
1503 if (tret && a->implicitConvTo(tret))
1505 a = a->implicitCastTo(sc, tret);
1506 a = a->optimize(WANTvalue);
1507 a = toDelegate(a, a->type, sc);
1509 else
1510 a = a->implicitCastTo(sc, tbn);
1511 (*elements)[u] = a;
1513 // Bugzilla 14395: Convert to a static array literal, or its slice.
1514 arg = new ArrayLiteralExp(loc, elements);
1515 arg->type = tsa;
1516 if (tb->ty == Tarray)
1518 arg = new SliceExp(loc, arg, NULL, NULL);
1519 arg->type = p->type;
1521 break;
1523 case Tclass:
1525 /* Set arg to be:
1526 * new Tclass(arg0, arg1, ..., argn)
1528 Expressions *args = new Expressions();
1529 args->setDim(nargs - i);
1530 for (size_t u = i; u < nargs; u++)
1531 (*args)[u - i] = (*arguments)[u];
1532 arg = new NewExp(loc, NULL, NULL, p->type, args);
1533 break;
1535 default:
1536 if (!arg)
1538 error(loc, "not enough arguments");
1539 return true;
1541 break;
1543 arg = semantic(arg, sc);
1544 //printf("\targ = '%s'\n", arg->toChars());
1545 arguments->setDim(i + 1);
1546 (*arguments)[i] = arg;
1547 nargs = i + 1;
1548 done = 1;
1552 if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
1554 bool isRef = (p->storageClass & (STCref | STCout)) != 0;
1555 if (unsigned char wm = arg->type->deduceWild(p->type, isRef))
1557 if (wildmatch)
1558 wildmatch = MODmerge(wildmatch, wm);
1559 else
1560 wildmatch = wm;
1561 //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p->type->toChars(), arg->type->toChars(), wm, wildmatch);
1565 if (done)
1566 break;
1568 if ((wildmatch == MODmutable || wildmatch == MODimmutable) &&
1569 tf->next->hasWild() &&
1570 (tf->isref || !tf->next->implicitConvTo(tf->next->immutableOf())))
1572 if (fd)
1574 /* If the called function may return the reference to
1575 * outer inout data, it should be rejected.
1577 * void foo(ref inout(int) x) {
1578 * ref inout(int) bar(inout(int)) { return x; }
1579 * struct S { ref inout(int) bar() inout { return x; } }
1580 * bar(int.init) = 1; // bad!
1581 * S().bar() = 1; // bad!
1584 Dsymbol *s = NULL;
1585 if (fd->isThis() || fd->isNested())
1586 s = fd->toParent2();
1587 for (; s; s = s->toParent2())
1589 if (AggregateDeclaration *ad = s->isAggregateDeclaration())
1591 if (ad->isNested())
1592 continue;
1593 break;
1595 if (FuncDeclaration *ff = s->isFuncDeclaration())
1597 if (((TypeFunction *)ff->type)->iswild)
1598 goto Linouterr;
1600 if (ff->isNested() || ff->isThis())
1601 continue;
1603 break;
1606 else if (tf->isWild())
1608 Linouterr:
1609 const char *s = wildmatch == MODmutable ? "mutable" : MODtoChars(wildmatch);
1610 error(loc, "modify inout to %s is not allowed inside inout function", s);
1611 return true;
1615 assert(nargs >= nparams);
1616 for (size_t i = 0; i < nargs; i++)
1618 Expression *arg = (*arguments)[i];
1619 assert(arg);
1620 if (i < nparams)
1622 Parameter *p = Parameter::getNth(tf->parameters, i);
1624 if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
1626 Type *tprm = p->type;
1627 if (p->type->hasWild())
1628 tprm = p->type->substWildTo(wildmatch);
1629 if (!tprm->equals(arg->type))
1631 //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
1632 arg = arg->implicitCastTo(sc, tprm);
1633 arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0);
1636 if (p->storageClass & STCref)
1638 arg = arg->toLvalue(sc, arg);
1640 // Look for mutable misaligned pointer, etc., in @safe mode
1641 err |= checkUnsafeAccess(sc, arg, false, true);
1643 else if (p->storageClass & STCout)
1645 Type *t = arg->type;
1646 if (!t->isMutable() || !t->isAssignable()) // check blit assignable
1648 arg->error("cannot modify struct %s with immutable members", arg->toChars());
1649 err = true;
1651 else
1653 // Look for misaligned pointer, etc., in @safe mode
1654 err |= checkUnsafeAccess(sc, arg, false, true);
1655 err |= checkDefCtor(arg->loc, t); // t must be default constructible
1657 arg = arg->toLvalue(sc, arg);
1659 else if (p->storageClass & STClazy)
1661 // Convert lazy argument to a delegate
1662 if (p->type->ty == Tvoid)
1663 arg = toDelegate(arg, p->type, sc);
1664 else
1665 arg = toDelegate(arg, arg->type, sc);
1668 //printf("arg: %s\n", arg->toChars());
1669 //printf("type: %s\n", arg->type->toChars());
1670 if (tf->parameterEscapes(p))
1672 /* Argument value can escape from the called function.
1673 * Check arg to see if it matters.
1675 if (global.params.vsafe)
1676 err |= checkParamArgumentEscape(sc, fd, p->ident, arg, false);
1678 else
1680 /* Argument value cannot escape from the called function.
1682 Expression *a = arg;
1683 if (a->op == TOKcast)
1684 a = ((CastExp *)a)->e1;
1686 if (a->op == TOKfunction)
1688 /* Function literals can only appear once, so if this
1689 * appearance was scoped, there cannot be any others.
1691 FuncExp *fe = (FuncExp *)a;
1692 fe->fd->tookAddressOf = 0;
1694 else if (a->op == TOKdelegate)
1696 /* For passing a delegate to a scoped parameter,
1697 * this doesn't count as taking the address of it.
1698 * We only worry about 'escaping' references to the function.
1700 DelegateExp *de = (DelegateExp *)a;
1701 if (de->e1->op == TOKvar)
1702 { VarExp *ve = (VarExp *)de->e1;
1703 FuncDeclaration *f = ve->var->isFuncDeclaration();
1704 if (f)
1705 { f->tookAddressOf--;
1706 //printf("tookAddressOf = %d\n", f->tookAddressOf);
1711 arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0);
1713 else
1715 // These will be the trailing ... arguments
1717 // If not D linkage, do promotions
1718 if (tf->linkage != LINKd)
1720 // Promote bytes, words, etc., to ints
1721 arg = integralPromotions(arg, sc);
1723 // Promote floats to doubles
1724 switch (arg->type->ty)
1726 case Tfloat32:
1727 arg = arg->castTo(sc, Type::tfloat64);
1728 break;
1730 case Timaginary32:
1731 arg = arg->castTo(sc, Type::timaginary64);
1732 break;
1735 if (tf->varargs == 1)
1737 const char *p = tf->linkage == LINKc ? "extern(C)" : "extern(C++)";
1738 if (arg->type->ty == Tarray)
1740 arg->error("cannot pass dynamic arrays to %s vararg functions", p);
1741 err = true;
1743 if (arg->type->ty == Tsarray)
1745 arg->error("cannot pass static arrays to %s vararg functions", p);
1746 err = true;
1751 // Do not allow types that need destructors
1752 if (arg->type->needsDestruction())
1754 arg->error("cannot pass types that need destruction as variadic arguments");
1755 err = true;
1758 // Convert static arrays to dynamic arrays
1759 // BUG: I don't think this is right for D2
1760 Type *tb = arg->type->toBasetype();
1761 if (tb->ty == Tsarray)
1763 TypeSArray *ts = (TypeSArray *)tb;
1764 Type *ta = ts->next->arrayOf();
1765 if (ts->size(arg->loc) == 0)
1766 arg = new NullExp(arg->loc, ta);
1767 else
1768 arg = arg->castTo(sc, ta);
1770 if (tb->ty == Tstruct)
1772 //arg = callCpCtor(sc, arg);
1775 // Give error for overloaded function addresses
1776 if (arg->op == TOKsymoff)
1777 { SymOffExp *se = (SymOffExp *)arg;
1778 if (se->hasOverloads &&
1779 !se->var->isFuncDeclaration()->isUnique())
1780 { arg->error("function %s is overloaded", arg->toChars());
1781 err = true;
1784 if (arg->checkValue())
1785 err = true;
1786 arg = arg->optimize(WANTvalue);
1788 (*arguments)[i] = arg;
1791 /* Remaining problems:
1792 * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
1793 * implemented by calling a function) we'll defer this for now.
1794 * 2. value structs (or static arrays of them) that need to be copy constructed
1795 * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
1796 * function gets called (functions normally destroy their parameters)
1797 * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
1798 * up properly. Pushing arguments on the stack then cannot fail.
1800 if (1)
1802 /* TODO: tackle problem 1)
1804 const bool leftToRight = true; // TODO: something like !fd.isArrayOp
1805 if (!leftToRight)
1806 assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
1808 const ptrdiff_t start = (leftToRight ? 0 : (ptrdiff_t)nargs - 1);
1809 const ptrdiff_t end = (leftToRight ? (ptrdiff_t)nargs : -1);
1810 const ptrdiff_t step = (leftToRight ? 1 : -1);
1812 /* Compute indices of last throwing argument and first arg needing destruction.
1813 * Used to not set up destructors unless an arg needs destruction on a throw
1814 * in a later argument.
1816 ptrdiff_t lastthrow = -1;
1817 ptrdiff_t firstdtor = -1;
1818 for (ptrdiff_t i = start; i != end; i += step)
1820 Expression *arg = (*arguments)[i];
1821 if (canThrow(arg, sc->func, false))
1822 lastthrow = i;
1823 if (firstdtor == -1 && arg->type->needsDestruction())
1825 Parameter *p = (i >= (ptrdiff_t)nparams ? NULL : Parameter::getNth(tf->parameters, i));
1826 if (!(p && (p->storageClass & (STClazy | STCref | STCout))))
1827 firstdtor = i;
1831 /* Does problem 3) apply to this call?
1833 const bool needsPrefix = (firstdtor >= 0 && lastthrow >= 0
1834 && (lastthrow - firstdtor) * step > 0);
1836 /* If so, initialize 'eprefix' by declaring the gate
1838 VarDeclaration *gate = NULL;
1839 if (needsPrefix)
1841 // eprefix => bool __gate [= false]
1842 Identifier *idtmp = Identifier::generateId("__gate");
1843 gate = new VarDeclaration(loc, Type::tbool, idtmp, NULL);
1844 gate->storage_class |= STCtemp | STCctfe | STCvolatile;
1845 gate->semantic(sc);
1847 Expression *ae = new DeclarationExp(loc, gate);
1848 eprefix = semantic(ae, sc);
1851 for (ptrdiff_t i = start; i != end; i += step)
1853 Expression *arg = (*arguments)[i];
1855 Parameter *parameter = (i >= (ptrdiff_t)nparams ? NULL : Parameter::getNth(tf->parameters, i));
1856 const bool isRef = (parameter && (parameter->storageClass & (STCref | STCout)));
1857 const bool isLazy = (parameter && (parameter->storageClass & STClazy));
1859 /* Skip lazy parameters
1861 if (isLazy)
1862 continue;
1864 /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg.
1865 * Declare a temporary variable for this arg and append that declaration to 'eprefix',
1866 * which will implicitly take care of potential problem 2) for this arg.
1867 * 'eprefix' will therefore finally contain all args up to and including the last
1868 * potentially throwing arg, excluding all lazy parameters.
1870 if (gate)
1872 const bool needsDtor = (!isRef && arg->type->needsDestruction() && i != lastthrow);
1874 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
1876 VarDeclaration *tmp = copyToTemp(0,
1877 needsDtor ? "__pfx" : "__pfy",
1878 !isRef ? arg : arg->addressOf());
1879 tmp->semantic(sc);
1881 /* Modify the destructor so it only runs if gate==false, i.e.,
1882 * only if there was a throw while constructing the args
1884 if (!needsDtor)
1886 if (tmp->edtor)
1888 assert(i == lastthrow);
1889 tmp->edtor = NULL;
1892 else
1894 // edtor => (__gate || edtor)
1895 assert(tmp->edtor);
1896 Expression *e = tmp->edtor;
1897 e = new OrOrExp(e->loc, new VarExp(e->loc, gate), e);
1898 tmp->edtor = semantic(e, sc);
1899 //printf("edtor: %s\n", tmp->edtor->toChars());
1902 // eprefix => (eprefix, auto __pfx/y = arg)
1903 DeclarationExp *ae = new DeclarationExp(loc, tmp);
1904 eprefix = Expression::combine(eprefix, semantic(ae, sc));
1906 // arg => __pfx/y
1907 arg = new VarExp(loc, tmp);
1908 arg = semantic(arg, sc);
1909 if (isRef)
1911 arg = new PtrExp(loc, arg);
1912 arg = semantic(arg, sc);
1915 /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true),
1916 * i.e., disable the dtors right after constructing the last throwing arg.
1917 * From now on, the callee will take care of destructing the args because
1918 * the args are implicitly moved into function parameters.
1920 * Set gate to null to let the next iterations know they don't need to
1921 * append to eprefix anymore.
1923 if (i == lastthrow)
1925 Expression *e = new AssignExp(gate->loc, new VarExp(gate->loc, gate), new IntegerExp(gate->loc, 1, Type::tbool));
1926 eprefix = Expression::combine(eprefix, semantic(e, sc));
1927 gate = NULL;
1930 else
1932 /* No gate, no prefix to append to.
1933 * Handle problem 2) by calling the copy constructor for value structs
1934 * (or static arrays of them) if appropriate.
1936 Type *tv = arg->type->baseElemOf();
1937 if (!isRef && tv->ty == Tstruct)
1938 arg = doCopyOrMove(sc, arg);
1941 (*arguments)[i] = arg;
1944 //if (eprefix) printf("eprefix: %s\n", eprefix->toChars());
1946 // If D linkage and variadic, add _arguments[] as first argument
1947 if (tf->linkage == LINKd && tf->varargs == 1)
1949 assert(arguments->dim >= nparams);
1951 Parameters *args = new Parameters;
1952 args->setDim(arguments->dim - nparams);
1953 for (size_t i = 0; i < arguments->dim - nparams; i++)
1955 Parameter *arg = new Parameter(STCin, (*arguments)[nparams + i]->type, NULL, NULL);
1956 (*args)[i] = arg;
1959 TypeTuple *tup = new TypeTuple(args);
1960 Expression *e = new TypeidExp(loc, tup);
1961 e = semantic(e, sc);
1962 arguments->insert(0, e);
1965 Type *tret = tf->next;
1966 if (isCtorCall)
1968 //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd->toChars(), fd->type->toChars(),
1969 // wildmatch, tf->isWild(), fd->isolateReturn());
1970 if (!tthis)
1972 assert(sc->intypeof || global.errors);
1973 tthis = fd->isThis()->type->addMod(fd->type->mod);
1975 if (tf->isWild() && !fd->isolateReturn())
1977 if (wildmatch)
1978 tret = tret->substWildTo(wildmatch);
1979 int offset;
1980 if (!tret->implicitConvTo(tthis) &&
1981 !(MODimplicitConv(tret->mod, tthis->mod) && tret->isBaseOf(tthis, &offset) && offset == 0))
1983 const char* s1 = tret ->isNaked() ? " mutable" : tret ->modToChars();
1984 const char* s2 = tthis->isNaked() ? " mutable" : tthis->modToChars();
1985 ::error(loc, "inout constructor %s creates%s object, not%s",
1986 fd->toPrettyChars(), s1, s2);
1987 err = true;
1990 tret = tthis;
1992 else if (wildmatch && tret)
1994 /* Adjust function return type based on wildmatch
1996 //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret->toChars());
1997 tret = tret->substWildTo(wildmatch);
1999 *prettype = tret;
2000 *peprefix = eprefix;
2001 return (err || olderrors != global.errors);
2004 /******************************** Expression **************************/
2006 Expression::Expression(Loc loc, TOK op, int size)
2008 //printf("Expression::Expression(op = %d) this = %p\n", op, this);
2009 this->loc = loc;
2010 this->op = op;
2011 this->size = (unsigned char)size;
2012 this->parens = 0;
2013 type = NULL;
2016 void Expression::_init()
2018 CTFEExp::cantexp = new CTFEExp(TOKcantexp);
2019 CTFEExp::voidexp = new CTFEExp(TOKvoidexp);
2020 CTFEExp::breakexp = new CTFEExp(TOKbreak);
2021 CTFEExp::continueexp = new CTFEExp(TOKcontinue);
2022 CTFEExp::gotoexp = new CTFEExp(TOKgoto);
2025 Expression *Expression::syntaxCopy()
2027 //printf("Expression::syntaxCopy()\n");
2028 //print();
2029 return copy();
2032 /*********************************
2033 * Does *not* do a deep copy.
2036 Expression *Expression::copy()
2038 Expression *e;
2039 if (!size)
2041 assert(0);
2043 void *pe = mem.xmalloc(size);
2044 //printf("Expression::copy(op = %d) e = %p\n", op, pe);
2045 e = (Expression *)memcpy(pe, (void *)this, size);
2046 return e;
2049 void Expression::print()
2051 fprintf(stderr, "%s\n", toChars());
2052 fflush(stderr);
2055 const char *Expression::toChars()
2057 OutBuffer buf;
2058 HdrGenState hgs;
2059 toCBuffer(this, &buf, &hgs);
2060 return buf.extractString();
2063 void Expression::error(const char *format, ...) const
2065 if (type != Type::terror)
2067 va_list ap;
2068 va_start(ap, format);
2069 ::verror(loc, format, ap);
2070 va_end( ap );
2074 void Expression::warning(const char *format, ...) const
2076 if (type != Type::terror)
2078 va_list ap;
2079 va_start(ap, format);
2080 ::vwarning(loc, format, ap);
2081 va_end( ap );
2085 void Expression::deprecation(const char *format, ...) const
2087 if (type != Type::terror)
2089 va_list ap;
2090 va_start(ap, format);
2091 ::vdeprecation(loc, format, ap);
2092 va_end( ap );
2096 /**********************************
2097 * Combine e1 and e2 by CommaExp if both are not NULL.
2099 Expression *Expression::combine(Expression *e1, Expression *e2)
2101 if (e1)
2103 if (e2)
2105 e1 = new CommaExp(e1->loc, e1, e2);
2106 e1->type = e2->type;
2109 else
2110 e1 = e2;
2111 return e1;
2114 /**********************************
2115 * If 'e' is a tree of commas, returns the leftmost expression
2116 * by stripping off it from the tree. The remained part of the tree
2117 * is returned via *pe0.
2118 * Otherwise 'e' is directly returned and *pe0 is set to NULL.
2120 Expression *Expression::extractLast(Expression *e, Expression **pe0)
2122 if (e->op != TOKcomma)
2124 *pe0 = NULL;
2125 return e;
2128 CommaExp *ce = (CommaExp *)e;
2129 if (ce->e2->op != TOKcomma)
2131 *pe0 = ce->e1;
2132 return ce->e2;
2134 else
2136 *pe0 = e;
2138 Expression **pce = &ce->e2;
2139 while (((CommaExp *)(*pce))->e2->op == TOKcomma)
2141 pce = &((CommaExp *)(*pce))->e2;
2143 assert((*pce)->op == TOKcomma);
2144 ce = (CommaExp *)(*pce);
2145 *pce = ce->e1;
2147 return ce->e2;
2151 dinteger_t Expression::toInteger()
2153 //printf("Expression %s\n", Token::toChars(op));
2154 error("integer constant expression expected instead of %s", toChars());
2155 return 0;
2158 uinteger_t Expression::toUInteger()
2160 //printf("Expression %s\n", Token::toChars(op));
2161 return (uinteger_t)toInteger();
2164 real_t Expression::toReal()
2166 error("floating point constant expression expected instead of %s", toChars());
2167 return CTFloat::zero;
2170 real_t Expression::toImaginary()
2172 error("floating point constant expression expected instead of %s", toChars());
2173 return CTFloat::zero;
2176 complex_t Expression::toComplex()
2178 error("floating point constant expression expected instead of %s", toChars());
2179 return complex_t(CTFloat::zero);
2182 StringExp *Expression::toStringExp()
2184 return NULL;
2187 /***************************************
2188 * Return !=0 if expression is an lvalue.
2191 bool Expression::isLvalue()
2193 return false;
2196 /*******************************
2197 * Give error if we're not an lvalue.
2198 * If we can, convert expression to be an lvalue.
2201 Expression *Expression::toLvalue(Scope *, Expression *e)
2203 if (!e)
2204 e = this;
2205 else if (!loc.filename)
2206 loc = e->loc;
2208 if (e->op == TOKtype)
2209 error("%s '%s' is a type, not an lvalue", e->type->kind(), e->type->toChars());
2210 else
2211 error("%s is not an lvalue", e->toChars());
2213 return new ErrorExp();
2216 /***************************************
2217 * Parameters:
2218 * sc: scope
2219 * flag: 1: do not issue error message for invalid modification
2220 * Returns:
2221 * 0: is not modifiable
2222 * 1: is modifiable in default == being related to type->isMutable()
2223 * 2: is modifiable, because this is a part of initializing.
2226 int Expression::checkModifiable(Scope *, int)
2228 return type ? 1 : 0; // default modifiable
2231 Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
2233 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
2235 // See if this expression is a modifiable lvalue (i.e. not const)
2236 if (checkModifiable(sc) == 1)
2238 assert(type);
2239 if (!type->isMutable())
2241 error("cannot modify %s expression %s", MODtoChars(type->mod), toChars());
2242 return new ErrorExp();
2244 else if (!type->isAssignable())
2246 error("cannot modify struct %s %s with immutable members", toChars(), type->toChars());
2247 return new ErrorExp();
2250 return toLvalue(sc, e);
2253 /****************************************
2254 * Check that the expression has a valid type.
2255 * If not, generates an error "... has no type".
2256 * Returns:
2257 * true if the expression is not valid.
2258 * Note:
2259 * When this function returns true, `checkValue()` should also return true.
2261 bool Expression::checkType()
2263 return false;
2266 /****************************************
2267 * Check that the expression has a valid value.
2268 * If not, generates an error "... has no value".
2269 * Returns:
2270 * true if the expression is not valid or has void type.
2272 bool Expression::checkValue()
2274 if (type && type->toBasetype()->ty == Tvoid)
2276 error("expression %s is void and has no value", toChars());
2277 //print(); halt();
2278 if (!global.gag)
2279 type = Type::terror;
2280 return true;
2282 return false;
2285 bool Expression::checkScalar()
2287 if (op == TOKerror)
2288 return true;
2289 if (type->toBasetype()->ty == Terror)
2290 return true;
2291 if (!type->isscalar())
2293 error("'%s' is not a scalar, it is a %s", toChars(), type->toChars());
2294 return true;
2296 return checkValue();
2299 bool Expression::checkNoBool()
2301 if (op == TOKerror)
2302 return true;
2303 if (type->toBasetype()->ty == Terror)
2304 return true;
2305 if (type->toBasetype()->ty == Tbool)
2307 error("operation not allowed on bool '%s'", toChars());
2308 return true;
2310 return false;
2313 bool Expression::checkIntegral()
2315 if (op == TOKerror)
2316 return true;
2317 if (type->toBasetype()->ty == Terror)
2318 return true;
2319 if (!type->isintegral())
2321 error("'%s' is not of integral type, it is a %s", toChars(), type->toChars());
2322 return true;
2324 return checkValue();
2327 bool Expression::checkArithmetic()
2329 if (op == TOKerror)
2330 return true;
2331 if (type->toBasetype()->ty == Terror)
2332 return true;
2333 if (!type->isintegral() && !type->isfloating())
2335 error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
2336 return true;
2338 return checkValue();
2341 void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
2343 s->checkDeprecated(loc, sc);
2346 /*********************************************
2347 * Calling function f.
2348 * Check the purity, i.e. if we're in a pure function
2349 * we can only call other pure functions.
2350 * Returns true if error occurs.
2352 bool Expression::checkPurity(Scope *sc, FuncDeclaration *f)
2354 if (!sc->func)
2355 return false;
2356 if (sc->func == f)
2357 return false;
2358 if (sc->intypeof == 1)
2359 return false;
2360 if (sc->flags & (SCOPEctfe | SCOPEdebug))
2361 return false;
2363 /* Given:
2364 * void f() {
2365 * pure void g() {
2366 * /+pure+/ void h() {
2367 * /+pure+/ void i() { }
2371 * g() can call h() but not f()
2372 * i() can call h() and g() but not f()
2375 // Find the closest pure parent of the calling function
2376 FuncDeclaration *outerfunc = sc->func;
2377 FuncDeclaration *calledparent = f;
2379 if (outerfunc->isInstantiated())
2381 // The attributes of outerfunc should be inferred from the call of f.
2383 else if (f->isInstantiated())
2385 // The attributes of f are inferred from its body.
2387 else if (f->isFuncLiteralDeclaration())
2389 // The attributes of f are always inferred in its declared place.
2391 else
2393 /* Today, static local functions are impure by default, but they cannot
2394 * violate purity of enclosing functions.
2396 * auto foo() pure { // non instantiated funciton
2397 * static auto bar() { // static, without pure attribute
2398 * impureFunc(); // impure call
2399 * // Although impureFunc is called inside bar, f(= impureFunc)
2400 * // is not callable inside pure outerfunc(= foo <- bar).
2403 * bar();
2404 * // Although bar is called inside foo, f(= bar) is callable
2405 * // bacause calledparent(= foo) is same with outerfunc(= foo).
2409 while (outerfunc->toParent2() &&
2410 outerfunc->isPureBypassingInference() == PUREimpure &&
2411 outerfunc->toParent2()->isFuncDeclaration())
2413 outerfunc = outerfunc->toParent2()->isFuncDeclaration();
2414 if (outerfunc->type->ty == Terror)
2415 return true;
2417 while (calledparent->toParent2() &&
2418 calledparent->isPureBypassingInference() == PUREimpure &&
2419 calledparent->toParent2()->isFuncDeclaration())
2421 calledparent = calledparent->toParent2()->isFuncDeclaration();
2422 if (calledparent->type->ty == Terror)
2423 return true;
2427 // If the caller has a pure parent, then either the called func must be pure,
2428 // OR, they must have the same pure parent.
2429 if (!f->isPure() && calledparent != outerfunc)
2431 FuncDeclaration *ff = outerfunc;
2432 if (sc->flags & SCOPEcompile ? ff->isPureBypassingInference() >= PUREweak : ff->setImpure())
2434 error("pure %s '%s' cannot call impure %s '%s'",
2435 ff->kind(), ff->toPrettyChars(), f->kind(), f->toPrettyChars());
2436 return true;
2439 return false;
2442 /*******************************************
2443 * Accessing variable v.
2444 * Check for purity and safety violations.
2445 * Returns true if error occurs.
2447 bool Expression::checkPurity(Scope *sc, VarDeclaration *v)
2449 //printf("v = %s %s\n", v->type->toChars(), v->toChars());
2451 /* Look for purity and safety violations when accessing variable v
2452 * from current function.
2454 if (!sc->func)
2455 return false;
2456 if (sc->intypeof == 1)
2457 return false; // allow violations inside typeof(expression)
2458 if (sc->flags & (SCOPEctfe | SCOPEdebug))
2459 return false; // allow violations inside compile-time evaluated expressions and debug conditionals
2460 if (v->ident == Id::ctfe)
2461 return false; // magic variable never violates pure and safe
2462 if (v->isImmutable())
2463 return false; // always safe and pure to access immutables...
2464 if (v->isConst() && !v->isRef() && (v->isDataseg() || v->isParameter()) &&
2465 v->type->implicitConvTo(v->type->immutableOf()))
2466 return false; // or const global/parameter values which have no mutable indirections
2467 if (v->storage_class & STCmanifest)
2468 return false; // ...or manifest constants
2470 bool err = false;
2471 if (v->isDataseg())
2473 // Bugzilla 7533: Accessing implicit generated __gate is pure.
2474 if (v->ident == Id::gate)
2475 return false;
2477 /* Accessing global mutable state.
2478 * Therefore, this function and all its immediately enclosing
2479 * functions must be pure.
2481 /* Today, static local functions are impure by default, but they cannot
2482 * violate purity of enclosing functions.
2484 * auto foo() pure { // non instantiated funciton
2485 * static auto bar() { // static, without pure attribute
2486 * globalData++; // impure access
2487 * // Although globalData is accessed inside bar,
2488 * // it is not accessible inside pure foo.
2492 for (Dsymbol *s = sc->func; s; s = s->toParent2())
2494 FuncDeclaration *ff = s->isFuncDeclaration();
2495 if (!ff)
2496 break;
2497 if (sc->flags & SCOPEcompile ? ff->isPureBypassingInference() >= PUREweak : ff->setImpure())
2499 error("pure %s '%s' cannot access mutable static data '%s'",
2500 ff->kind(), ff->toPrettyChars(), v->toChars());
2501 err = true;
2502 break;
2504 /* If the enclosing is an instantiated function or a lambda, its
2505 * attribute inference result is preferred.
2507 if (ff->isInstantiated())
2508 break;
2509 if (ff->isFuncLiteralDeclaration())
2510 break;
2513 else
2515 /* Given:
2516 * void f() {
2517 * int fx;
2518 * pure void g() {
2519 * int gx;
2520 * /+pure+/ void h() {
2521 * int hx;
2522 * /+pure+/ void i() { }
2526 * i() can modify hx and gx but not fx
2529 Dsymbol *vparent = v->toParent2();
2530 for (Dsymbol *s = sc->func; !err && s; s = s->toParent2())
2532 if (s == vparent)
2533 break;
2535 if (AggregateDeclaration *ad = s->isAggregateDeclaration())
2537 if (ad->isNested())
2538 continue;
2539 break;
2541 FuncDeclaration *ff = s->isFuncDeclaration();
2542 if (!ff)
2543 break;
2544 if (ff->isNested() || ff->isThis())
2546 if (ff->type->isImmutable() ||
2547 (ff->type->isShared() && !MODimplicitConv(ff->type->mod, v->type->mod)))
2549 OutBuffer ffbuf;
2550 OutBuffer vbuf;
2551 MODMatchToBuffer(&ffbuf, ff->type->mod, v->type->mod);
2552 MODMatchToBuffer(&vbuf, v->type->mod, ff->type->mod);
2553 error("%s%s '%s' cannot access %sdata '%s'",
2554 ffbuf.peekString(), ff->kind(), ff->toPrettyChars(), vbuf.peekString(), v->toChars());
2555 err = true;
2556 break;
2558 continue;
2560 break;
2564 /* Do not allow safe functions to access __gshared data
2566 if (v->storage_class & STCgshared)
2568 if (sc->func->setUnsafe())
2570 error("safe %s '%s' cannot access __gshared data '%s'",
2571 sc->func->kind(), sc->func->toChars(), v->toChars());
2572 err = true;
2576 return err;
2579 /*********************************************
2580 * Calling function f.
2581 * Check the safety, i.e. if we're in a @safe function
2582 * we can only call @safe or @trusted functions.
2583 * Returns true if error occurs.
2585 bool Expression::checkSafety(Scope *sc, FuncDeclaration *f)
2587 if (!sc->func)
2588 return false;
2589 if (sc->func == f)
2590 return false;
2591 if (sc->intypeof == 1)
2592 return false;
2593 if (sc->flags & SCOPEctfe)
2594 return false;
2596 if (!f->isSafe() && !f->isTrusted())
2598 if (sc->flags & SCOPEcompile ? sc->func->isSafeBypassingInference() : sc->func->setUnsafe())
2600 if (loc.linnum == 0) // e.g. implicitly generated dtor
2601 loc = sc->func->loc;
2603 error("@safe %s '%s' cannot call @system %s '%s'",
2604 sc->func->kind(), sc->func->toPrettyChars(), f->kind(), f->toPrettyChars());
2605 return true;
2608 return false;
2611 /*********************************************
2612 * Calling function f.
2613 * Check the @nogc-ness, i.e. if we're in a @nogc function
2614 * we can only call other @nogc functions.
2615 * Returns true if error occurs.
2617 bool Expression::checkNogc(Scope *sc, FuncDeclaration *f)
2619 if (!sc->func)
2620 return false;
2621 if (sc->func == f)
2622 return false;
2623 if (sc->intypeof == 1)
2624 return false;
2625 if (sc->flags & SCOPEctfe)
2626 return false;
2628 if (!f->isNogc())
2630 if (sc->flags & SCOPEcompile ? sc->func->isNogcBypassingInference() : sc->func->setGC())
2632 if (loc.linnum == 0) // e.g. implicitly generated dtor
2633 loc = sc->func->loc;
2635 error("@nogc %s '%s' cannot call non-@nogc %s '%s'",
2636 sc->func->kind(), sc->func->toPrettyChars(), f->kind(), f->toPrettyChars());
2637 return true;
2640 return false;
2643 /********************************************
2644 * Check that the postblit is callable if t is an array of structs.
2645 * Returns true if error happens.
2647 bool Expression::checkPostblit(Scope *sc, Type *t)
2649 t = t->baseElemOf();
2650 if (t->ty == Tstruct)
2652 // Bugzilla 11395: Require TypeInfo generation for array concatenation
2653 semanticTypeInfo(sc, t);
2655 StructDeclaration *sd = ((TypeStruct *)t)->sym;
2656 if (sd->postblit)
2658 if (sd->postblit->storage_class & STCdisable)
2660 sd->error(loc, "is not copyable because it is annotated with @disable");
2661 return true;
2663 //checkDeprecated(sc, sd->postblit); // necessary?
2664 checkPurity(sc, sd->postblit);
2665 checkSafety(sc, sd->postblit);
2666 checkNogc(sc, sd->postblit);
2667 //checkAccess(sd, loc, sc, sd->postblit); // necessary?
2668 return false;
2671 return false;
2674 bool Expression::checkRightThis(Scope *sc)
2676 if (op == TOKerror)
2677 return true;
2678 if (op == TOKvar && type->ty != Terror)
2680 VarExp *ve = (VarExp *)this;
2681 if (isNeedThisScope(sc, ve->var))
2683 //printf("checkRightThis sc->intypeof = %d, ad = %p, func = %p, fdthis = %p\n",
2684 // sc->intypeof, sc->getStructClassScope(), func, fdthis);
2685 error("need 'this' for '%s' of type '%s'", ve->var->toChars(), ve->var->type->toChars());
2686 return true;
2689 return false;
2692 /*******************************
2693 * Check whether the expression allows RMW operations, error with rmw operator diagnostic if not.
2694 * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics)
2695 * Returns true if error occurs.
2697 bool Expression::checkReadModifyWrite(TOK rmwOp, Expression *ex)
2699 //printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex->toChars() : "");
2700 if (!type || !type->isShared())
2701 return false;
2703 // atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal.
2704 switch (rmwOp)
2706 case TOKplusplus:
2707 case TOKpreplusplus:
2708 rmwOp = TOKaddass;
2709 break;
2711 case TOKminusminus:
2712 case TOKpreminusminus:
2713 rmwOp = TOKminass;
2714 break;
2716 default:
2717 break;
2720 deprecation("read-modify-write operations are not allowed for shared variables. "
2721 "Use core.atomic.atomicOp!\"%s\"(%s, %s) instead.",
2722 Token::tochars[rmwOp], toChars(), ex ? ex->toChars() : "1");
2723 return false;
2725 // note: enable when deprecation becomes an error.
2726 // return true;
2729 /*****************************
2730 * If expression can be tested for true or false,
2731 * returns the modified expression.
2732 * Otherwise returns ErrorExp.
2734 Expression *Expression::toBoolean(Scope *sc)
2736 // Default is 'yes' - do nothing
2737 Expression *e = this;
2738 Type *t = type;
2739 Type *tb = type->toBasetype();
2740 Type *att = NULL;
2741 Lagain:
2742 // Structs can be converted to bool using opCast(bool)()
2743 if (tb->ty == Tstruct)
2745 AggregateDeclaration *ad = ((TypeStruct *)tb)->sym;
2746 /* Don't really need to check for opCast first, but by doing so we
2747 * get better error messages if it isn't there.
2749 Dsymbol *fd = search_function(ad, Id::_cast);
2750 if (fd)
2752 e = new CastExp(loc, e, Type::tbool);
2753 e = semantic(e, sc);
2754 return e;
2757 // Forward to aliasthis.
2758 if (ad->aliasthis && tb != att)
2760 if (!att && tb->checkAliasThisRec())
2761 att = tb;
2762 e = resolveAliasThis(sc, e);
2763 t = e->type;
2764 tb = e->type->toBasetype();
2765 goto Lagain;
2769 if (!t->isBoolean())
2771 if (tb != Type::terror)
2772 error("expression %s of type %s does not have a boolean value", toChars(), t->toChars());
2773 return new ErrorExp();
2775 return e;
2778 /******************************
2779 * Take address of expression.
2782 Expression *Expression::addressOf()
2784 //printf("Expression::addressOf()\n");
2785 Expression *e = new AddrExp(loc, this);
2786 e->type = type->pointerTo();
2787 return e;
2790 /******************************
2791 * If this is a reference, dereference it.
2794 Expression *Expression::deref()
2796 //printf("Expression::deref()\n");
2797 // type could be null if forward referencing an 'auto' variable
2798 if (type && type->ty == Treference)
2800 Expression *e = new PtrExp(loc, this);
2801 e->type = ((TypeReference *)type)->next;
2802 return e;
2804 return this;
2807 /********************************
2808 * Does this expression statically evaluate to a boolean 'result' (true or false)?
2810 bool Expression::isBool(bool)
2812 return false;
2815 /****************************************
2816 * Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__ to loc.
2819 Expression *Expression::resolveLoc(Loc, Scope *)
2821 return this;
2824 Expressions *Expression::arraySyntaxCopy(Expressions *exps)
2826 Expressions *a = NULL;
2827 if (exps)
2829 a = new Expressions();
2830 a->setDim(exps->dim);
2831 for (size_t i = 0; i < a->dim; i++)
2833 Expression *e = (*exps)[i];
2834 (*a)[i] = e ? e->syntaxCopy() : NULL;
2837 return a;
2840 /************************************************
2841 * Destructors are attached to VarDeclarations.
2842 * Hence, if expression returns a temp that needs a destructor,
2843 * make sure and create a VarDeclaration for that temp.
2846 Expression *Expression::addDtorHook(Scope *)
2848 return this;
2851 /******************************** IntegerExp **************************/
2853 IntegerExp::IntegerExp(Loc loc, dinteger_t value, Type *type)
2854 : Expression(loc, TOKint64, sizeof(IntegerExp))
2856 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
2857 assert(type);
2858 if (!type->isscalar())
2860 //printf("%s, loc = %d\n", toChars(), loc.linnum);
2861 if (type->ty != Terror)
2862 error("integral constant must be scalar type, not %s", type->toChars());
2863 type = Type::terror;
2865 this->type = type;
2866 setInteger(value);
2869 IntegerExp::IntegerExp(dinteger_t value)
2870 : Expression(Loc(), TOKint64, sizeof(IntegerExp))
2872 this->type = Type::tint32;
2873 this->value = (d_int32) value;
2876 IntegerExp *IntegerExp::create(Loc loc, dinteger_t value, Type *type)
2878 return new IntegerExp(loc, value, type);
2881 bool IntegerExp::equals(RootObject *o)
2883 if (this == o)
2884 return true;
2885 if (((Expression *)o)->op == TOKint64)
2887 IntegerExp *ne = (IntegerExp *)o;
2888 if (type->toHeadMutable()->equals(ne->type->toHeadMutable()) &&
2889 value == ne->value)
2891 return true;
2894 return false;
2897 void IntegerExp::setInteger(dinteger_t value)
2899 this->value = value;
2900 normalize();
2903 void IntegerExp::normalize()
2905 /* 'Normalize' the value of the integer to be in range of the type
2907 switch (type->toBasetype()->ty)
2909 case Tbool: value = (value != 0); break;
2910 case Tint8: value = (d_int8) value; break;
2911 case Tchar:
2912 case Tuns8: value = (d_uns8) value; break;
2913 case Tint16: value = (d_int16) value; break;
2914 case Twchar:
2915 case Tuns16: value = (d_uns16) value; break;
2916 case Tint32: value = (d_int32) value; break;
2917 case Tdchar:
2918 case Tuns32: value = (d_uns32) value; break;
2919 case Tint64: value = (d_int64) value; break;
2920 case Tuns64: value = (d_uns64) value; break;
2921 case Tpointer:
2922 if (Target::ptrsize == 4)
2923 value = (d_uns32) value;
2924 else if (Target::ptrsize == 8)
2925 value = (d_uns64) value;
2926 else
2927 assert(0);
2928 break;
2929 default:
2930 break;
2934 dinteger_t IntegerExp::toInteger()
2936 normalize(); // necessary until we fix all the paints of 'type'
2937 return value;
2940 real_t IntegerExp::toReal()
2942 normalize(); // necessary until we fix all the paints of 'type'
2943 Type *t = type->toBasetype();
2944 if (t->ty == Tuns64)
2945 return ldouble((d_uns64)value);
2946 else
2947 return ldouble((d_int64)value);
2950 real_t IntegerExp::toImaginary()
2952 return CTFloat::zero;
2955 complex_t IntegerExp::toComplex()
2957 return (complex_t)toReal();
2960 bool IntegerExp::isBool(bool result)
2962 bool r = toInteger() != 0;
2963 return result ? r : !r;
2966 Expression *IntegerExp::toLvalue(Scope *, Expression *e)
2968 if (!e)
2969 e = this;
2970 else if (!loc.filename)
2971 loc = e->loc;
2972 e->error("constant %s is not an lvalue", e->toChars());
2973 return new ErrorExp();
2976 /******************************** ErrorExp **************************/
2978 /* Use this expression for error recovery.
2979 * It should behave as a 'sink' to prevent further cascaded error messages.
2982 ErrorExp::ErrorExp()
2983 : Expression(Loc(), TOKerror, sizeof(ErrorExp))
2985 type = Type::terror;
2988 Expression *ErrorExp::toLvalue(Scope *, Expression *)
2990 return this;
2993 /******************************** RealExp **************************/
2995 RealExp::RealExp(Loc loc, real_t value, Type *type)
2996 : Expression(loc, TOKfloat64, sizeof(RealExp))
2998 //printf("RealExp::RealExp(%Lg)\n", value);
2999 this->value = value;
3000 this->type = type;
3003 RealExp *RealExp::create(Loc loc, real_t value, Type *type)
3005 return new RealExp(loc, value,type);
3008 dinteger_t RealExp::toInteger()
3010 return (sinteger_t) toReal();
3013 uinteger_t RealExp::toUInteger()
3015 return (uinteger_t) toReal();
3018 real_t RealExp::toReal()
3020 return type->isreal() ? value : CTFloat::zero;
3023 real_t RealExp::toImaginary()
3025 return type->isreal() ? CTFloat::zero : value;
3028 complex_t RealExp::toComplex()
3030 return complex_t(toReal(), toImaginary());
3033 /********************************
3034 * Test to see if two reals are the same.
3035 * Regard NaN's as equivalent.
3036 * Regard +0 and -0 as different.
3039 int RealEquals(real_t x1, real_t x2)
3041 return (CTFloat::isNaN(x1) && CTFloat::isNaN(x2)) ||
3042 CTFloat::isIdentical(x1, x2);
3045 bool RealExp::equals(RootObject *o)
3047 if (this == o)
3048 return true;
3049 if (((Expression *)o)->op == TOKfloat64)
3051 RealExp *ne = (RealExp *)o;
3052 if (type->toHeadMutable()->equals(ne->type->toHeadMutable()) &&
3053 RealEquals(value, ne->value))
3055 return true;
3058 return false;
3061 bool RealExp::isBool(bool result)
3063 return result ? (bool)value : !(bool)value;
3066 /******************************** ComplexExp **************************/
3068 ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type)
3069 : Expression(loc, TOKcomplex80, sizeof(ComplexExp)), value(value)
3071 this->type = type;
3072 //printf("ComplexExp::ComplexExp(%s)\n", toChars());
3075 ComplexExp *ComplexExp::create(Loc loc, complex_t value, Type *type)
3077 return new ComplexExp(loc, value, type);
3080 dinteger_t ComplexExp::toInteger()
3082 return (sinteger_t) toReal();
3085 uinteger_t ComplexExp::toUInteger()
3087 return (uinteger_t) toReal();
3090 real_t ComplexExp::toReal()
3092 return creall(value);
3095 real_t ComplexExp::toImaginary()
3097 return cimagl(value);
3100 complex_t ComplexExp::toComplex()
3102 return value;
3105 bool ComplexExp::equals(RootObject *o)
3107 if (this == o)
3108 return true;
3109 if (((Expression *)o)->op == TOKcomplex80)
3111 ComplexExp *ne = (ComplexExp *)o;
3112 if (type->toHeadMutable()->equals(ne->type->toHeadMutable()) &&
3113 RealEquals(creall(value), creall(ne->value)) &&
3114 RealEquals(cimagl(value), cimagl(ne->value)))
3116 return true;
3119 return false;
3122 bool ComplexExp::isBool(bool result)
3124 if (result)
3125 return (bool)(value);
3126 else
3127 return !value;
3130 /******************************** IdentifierExp **************************/
3132 IdentifierExp::IdentifierExp(Loc loc, Identifier *ident)
3133 : Expression(loc, TOKidentifier, sizeof(IdentifierExp))
3135 this->ident = ident;
3138 IdentifierExp *IdentifierExp::create(Loc loc, Identifier *ident)
3140 return new IdentifierExp(loc, ident);
3143 bool IdentifierExp::isLvalue()
3145 return true;
3148 Expression *IdentifierExp::toLvalue(Scope *, Expression *)
3150 return this;
3153 /******************************** DollarExp **************************/
3155 DollarExp::DollarExp(Loc loc)
3156 : IdentifierExp(loc, Id::dollar)
3160 /******************************** DsymbolExp **************************/
3162 DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, bool hasOverloads)
3163 : Expression(loc, TOKdsymbol, sizeof(DsymbolExp))
3165 this->s = s;
3166 this->hasOverloads = hasOverloads;
3169 /****************************************
3170 * Resolve a symbol `s` and wraps it in an expression object.
3171 * Params:
3172 * hasOverloads = works if the aliased symbol is a function.
3173 * true: it's overloaded and will be resolved later.
3174 * false: it's exact function symbol.
3176 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads)
3178 Lagain:
3179 Expression *e;
3181 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
3182 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
3183 Dsymbol *olds = s;
3184 Declaration *d = s->isDeclaration();
3185 if (d && (d->storage_class & STCtemplateparameter))
3187 s = s->toAlias();
3189 else
3191 if (!s->isFuncDeclaration()) // functions are checked after overloading
3192 s->checkDeprecated(loc, sc);
3194 // Bugzilla 12023: if 's' is a tuple variable, the tuple is returned.
3195 s = s->toAlias();
3197 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
3198 if (s != olds && !s->isFuncDeclaration())
3199 s->checkDeprecated(loc, sc);
3202 if (EnumMember *em = s->isEnumMember())
3204 return em->getVarExp(loc, sc);
3206 if (VarDeclaration *v = s->isVarDeclaration())
3208 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
3209 if (!v->type || // during variable type inference
3210 (!v->type->deco && v->inuse)) // during variable type semantic
3212 if (v->inuse) // variable type depends on the variable itself
3213 ::error(loc, "circular reference to %s '%s'", v->kind(), v->toPrettyChars());
3214 else // variable type cannot be determined
3215 ::error(loc, "forward reference to %s '%s'", v->kind(), v->toPrettyChars());
3216 return new ErrorExp();
3218 if (v->type->ty == Terror)
3219 return new ErrorExp();
3221 if ((v->storage_class & STCmanifest) && v->_init)
3223 if (v->inuse)
3225 ::error(loc, "circular initialization of %s '%s'", v->kind(), v->toPrettyChars());
3226 return new ErrorExp();
3229 e = v->expandInitializer(loc);
3230 v->inuse++;
3231 e = semantic(e, sc);
3232 v->inuse--;
3233 return e;
3236 // Change the ancestor lambdas to delegate before hasThis(sc) call.
3237 if (v->checkNestedReference(sc, loc))
3238 return new ErrorExp();
3240 if (v->needThis() && hasThis(sc))
3241 e = new DotVarExp(loc, new ThisExp(loc), v);
3242 else
3243 e = new VarExp(loc, v);
3244 e = semantic(e, sc);
3245 return e;
3247 if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration())
3249 //printf("'%s' is a function literal\n", fld->toChars());
3250 e = new FuncExp(loc, fld);
3251 return semantic(e, sc);
3253 if (FuncDeclaration *f = s->isFuncDeclaration())
3255 f = f->toAliasFunc();
3256 if (!f->functionSemantic())
3257 return new ErrorExp();
3259 if (!hasOverloads && f->checkForwardRef(loc))
3260 return new ErrorExp();
3262 FuncDeclaration *fd = s->isFuncDeclaration();
3263 fd->type = f->type;
3264 return new VarExp(loc, fd, hasOverloads);
3266 if (OverDeclaration *od = s->isOverDeclaration())
3268 e = new VarExp(loc, od, true);
3269 e->type = Type::tvoid;
3270 return e;
3272 if (OverloadSet *o = s->isOverloadSet())
3274 //printf("'%s' is an overload set\n", o->toChars());
3275 return new OverExp(loc, o);
3278 if (Import *imp = s->isImport())
3280 if (!imp->pkg)
3282 ::error(loc, "forward reference of import %s", imp->toChars());
3283 return new ErrorExp();
3285 ScopeExp *ie = new ScopeExp(loc, imp->pkg);
3286 return semantic(ie, sc);
3288 if (Package *pkg = s->isPackage())
3290 ScopeExp *ie = new ScopeExp(loc, pkg);
3291 return semantic(ie, sc);
3293 if (Module *mod = s->isModule())
3295 ScopeExp *ie = new ScopeExp(loc, mod);
3296 return semantic(ie, sc);
3299 if (Nspace *ns = s->isNspace())
3301 ScopeExp *ie = new ScopeExp(loc, ns);
3302 return semantic(ie, sc);
3305 if (Type *t = s->getType())
3307 return semantic(new TypeExp(loc, t), sc);
3310 if (TupleDeclaration *tup = s->isTupleDeclaration())
3312 if (tup->needThis() && hasThis(sc))
3313 e = new DotVarExp(loc, new ThisExp(loc), tup);
3314 else
3315 e = new TupleExp(loc, tup);
3316 e = semantic(e, sc);
3317 return e;
3320 if (TemplateInstance *ti = s->isTemplateInstance())
3322 ti->semantic(sc);
3323 if (!ti->inst || ti->errors)
3324 return new ErrorExp();
3325 s = ti->toAlias();
3326 if (!s->isTemplateInstance())
3327 goto Lagain;
3328 e = new ScopeExp(loc, ti);
3329 e = semantic(e, sc);
3330 return e;
3332 if (TemplateDeclaration *td = s->isTemplateDeclaration())
3334 Dsymbol *p = td->toParent2();
3335 FuncDeclaration *fdthis = hasThis(sc);
3336 AggregateDeclaration *ad = p ? p->isAggregateDeclaration() : NULL;
3337 if (fdthis && ad && isAggregate(fdthis->vthis->type) == ad &&
3338 (td->_scope->stc & STCstatic) == 0)
3340 e = new DotTemplateExp(loc, new ThisExp(loc), td);
3342 else
3343 e = new TemplateExp(loc, td);
3344 e = semantic(e, sc);
3345 return e;
3348 ::error(loc, "%s '%s' is not a variable", s->kind(), s->toChars());
3349 return new ErrorExp();
3352 bool DsymbolExp::isLvalue()
3354 return true;
3357 Expression *DsymbolExp::toLvalue(Scope *, Expression *)
3359 return this;
3362 /******************************** ThisExp **************************/
3364 ThisExp::ThisExp(Loc loc)
3365 : Expression(loc, TOKthis, sizeof(ThisExp))
3367 //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
3368 var = NULL;
3371 bool ThisExp::isBool(bool result)
3373 return result ? true : false;
3376 bool ThisExp::isLvalue()
3378 // Class `this` should be an rvalue; struct `this` should be an lvalue.
3379 return type->toBasetype()->ty != Tclass;
3382 Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
3384 if (type->toBasetype()->ty == Tclass)
3386 // Class `this` is an rvalue; struct `this` is an lvalue.
3387 return Expression::toLvalue(sc, e);
3389 return this;
3392 /******************************** SuperExp **************************/
3394 SuperExp::SuperExp(Loc loc)
3395 : ThisExp(loc)
3397 op = TOKsuper;
3400 /******************************** NullExp **************************/
3402 NullExp::NullExp(Loc loc, Type *type)
3403 : Expression(loc, TOKnull, sizeof(NullExp))
3405 committed = 0;
3406 this->type = type;
3409 bool NullExp::equals(RootObject *o)
3411 if (o && o->dyncast() == DYNCAST_EXPRESSION)
3413 Expression *e = (Expression *)o;
3414 if (e->op == TOKnull &&
3415 type->equals(e->type))
3417 return true;
3420 return false;
3423 bool NullExp::isBool(bool result)
3425 return result ? false : true;
3428 StringExp *NullExp::toStringExp()
3430 if (implicitConvTo(Type::tstring))
3432 StringExp *se = new StringExp(loc, (char*)mem.xcalloc(1, 1), 0);
3433 se->type = Type::tstring;
3434 return se;
3436 return NULL;
3439 /******************************** StringExp **************************/
3441 StringExp::StringExp(Loc loc, char *string)
3442 : Expression(loc, TOKstring, sizeof(StringExp))
3444 this->string = string;
3445 this->len = strlen(string);
3446 this->sz = 1;
3447 this->committed = 0;
3448 this->postfix = 0;
3449 this->ownedByCtfe = OWNEDcode;
3452 StringExp::StringExp(Loc loc, void *string, size_t len)
3453 : Expression(loc, TOKstring, sizeof(StringExp))
3455 this->string = string;
3456 this->len = len;
3457 this->sz = 1;
3458 this->committed = 0;
3459 this->postfix = 0;
3460 this->ownedByCtfe = OWNEDcode;
3463 StringExp::StringExp(Loc loc, void *string, size_t len, utf8_t postfix)
3464 : Expression(loc, TOKstring, sizeof(StringExp))
3466 this->string = string;
3467 this->len = len;
3468 this->sz = 1;
3469 this->committed = 0;
3470 this->postfix = postfix;
3471 this->ownedByCtfe = OWNEDcode;
3474 StringExp *StringExp::create(Loc loc, char *s)
3476 return new StringExp(loc, s);
3479 StringExp *StringExp::create(Loc loc, void *string, size_t len)
3481 return new StringExp(loc, string, len);
3484 bool StringExp::equals(RootObject *o)
3486 //printf("StringExp::equals('%s') %s\n", o->toChars(), toChars());
3487 if (o && o->dyncast() == DYNCAST_EXPRESSION)
3489 Expression *e = (Expression *)o;
3490 if (e->op == TOKstring)
3492 return compare(o) == 0;
3495 return false;
3498 /**********************************
3499 * Return the number of code units the string would be if it were re-encoded
3500 * as tynto.
3501 * Params:
3502 * tynto = code unit type of the target encoding
3503 * Returns:
3504 * number of code units
3507 size_t StringExp::numberOfCodeUnits(int tynto) const
3509 int encSize;
3510 switch (tynto)
3512 case 0: return len;
3513 case Tchar: encSize = 1; break;
3514 case Twchar: encSize = 2; break;
3515 case Tdchar: encSize = 4; break;
3516 default:
3517 assert(0);
3519 if (sz == encSize)
3520 return len;
3522 size_t result = 0;
3523 dchar_t c;
3525 switch (sz)
3527 case 1:
3528 for (size_t u = 0; u < len;)
3530 if (const char *p = utf_decodeChar((utf8_t *)string, len, &u, &c))
3532 error("%s", p);
3533 return 0;
3535 result += utf_codeLength(encSize, c);
3537 break;
3539 case 2:
3540 for (size_t u = 0; u < len;)
3542 if (const char *p = utf_decodeWchar((utf16_t *)string, len, &u, &c))
3544 error("%s", p);
3545 return 0;
3547 result += utf_codeLength(encSize, c);
3549 break;
3551 case 4:
3552 for (size_t u = 0; u < len;)
3554 c = *((utf32_t *)((char *)string + u));
3555 u += 4;
3556 result += utf_codeLength(encSize, c);
3558 break;
3560 default:
3561 assert(0);
3563 return result;
3566 /**********************************************
3567 * Write the contents of the string to dest.
3568 * Use numberOfCodeUnits() to determine size of result.
3569 * Params:
3570 * dest = destination
3571 * tyto = encoding type of the result
3572 * zero = add terminating 0
3574 void StringExp::writeTo(void *dest, bool zero, int tyto) const
3576 int encSize;
3577 switch (tyto)
3579 case 0: encSize = sz; break;
3580 case Tchar: encSize = 1; break;
3581 case Twchar: encSize = 2; break;
3582 case Tdchar: encSize = 4; break;
3583 default:
3584 assert(0);
3586 if (sz == encSize)
3588 memcpy(dest, string, len * sz);
3589 if (zero)
3590 memset((char *)dest + len * sz, 0, sz);
3592 else
3593 assert(0);
3596 /**************************************************
3597 * If the string data is UTF-8 and can be accessed directly,
3598 * return a pointer to it.
3599 * Do not assume a terminating 0.
3600 * Returns:
3601 * pointer to string data if possible, null if not
3603 char *StringExp::toPtr()
3605 return (sz == 1) ? (char*)string : NULL;
3608 StringExp *StringExp::toStringExp()
3610 return this;
3613 /****************************************
3614 * Convert string to char[].
3617 StringExp *StringExp::toUTF8(Scope *sc)
3619 if (sz != 1)
3620 { // Convert to UTF-8 string
3621 committed = 0;
3622 Expression *e = castTo(sc, Type::tchar->arrayOf());
3623 e = e->optimize(WANTvalue);
3624 assert(e->op == TOKstring);
3625 StringExp *se = (StringExp *)e;
3626 assert(se->sz == 1);
3627 return se;
3629 return this;
3632 int StringExp::compare(RootObject *obj)
3634 //printf("StringExp::compare()\n");
3635 // Used to sort case statement expressions so we can do an efficient lookup
3636 StringExp *se2 = (StringExp *)(obj);
3638 // This is a kludge so isExpression() in template.c will return 5
3639 // for StringExp's.
3640 if (!se2)
3641 return 5;
3643 assert(se2->op == TOKstring);
3645 size_t len1 = len;
3646 size_t len2 = se2->len;
3648 //printf("sz = %d, len1 = %d, len2 = %d\n", sz, (int)len1, (int)len2);
3649 if (len1 == len2)
3651 switch (sz)
3653 case 1:
3654 return memcmp((char *)string, (char *)se2->string, len1);
3656 case 2:
3658 d_uns16 *s1 = (d_uns16 *)string;
3659 d_uns16 *s2 = (d_uns16 *)se2->string;
3661 for (size_t u = 0; u < len; u++)
3663 if (s1[u] != s2[u])
3664 return s1[u] - s2[u];
3667 break;
3669 case 4:
3671 d_uns32 *s1 = (d_uns32 *)string;
3672 d_uns32 *s2 = (d_uns32 *)se2->string;
3674 for (size_t u = 0; u < len; u++)
3676 if (s1[u] != s2[u])
3677 return s1[u] - s2[u];
3680 break;
3682 default:
3683 assert(0);
3686 return (int)(len1 - len2);
3689 bool StringExp::isBool(bool result)
3691 return result ? true : false;
3695 bool StringExp::isLvalue()
3697 /* string literal is rvalue in default, but
3698 * conversion to reference of static array is only allowed.
3700 return (type && type->toBasetype()->ty == Tsarray);
3703 Expression *StringExp::toLvalue(Scope *sc, Expression *e)
3705 //printf("StringExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL);
3706 return (type && type->toBasetype()->ty == Tsarray)
3707 ? this : Expression::toLvalue(sc, e);
3710 Expression *StringExp::modifiableLvalue(Scope *, Expression *)
3712 error("cannot modify string literal %s", toChars());
3713 return new ErrorExp();
3716 unsigned StringExp::charAt(uinteger_t i) const
3717 { unsigned value;
3719 switch (sz)
3721 case 1:
3722 value = ((utf8_t *)string)[(size_t)i];
3723 break;
3725 case 2:
3726 value = ((unsigned short *)string)[(size_t)i];
3727 break;
3729 case 4:
3730 value = ((unsigned int *)string)[(size_t)i];
3731 break;
3733 default:
3734 assert(0);
3735 break;
3737 return value;
3740 /************************ ArrayLiteralExp ************************************/
3742 // [ e1, e2, e3, ... ]
3744 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expressions *elements)
3745 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
3747 this->basis = NULL;
3748 this->elements = elements;
3749 this->ownedByCtfe = OWNEDcode;
3752 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *e)
3753 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
3755 this->basis = NULL;
3756 elements = new Expressions;
3757 elements->push(e);
3758 this->ownedByCtfe = OWNEDcode;
3761 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Expression *basis, Expressions *elements)
3762 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
3764 this->basis = basis;
3765 this->elements = elements;
3766 this->ownedByCtfe = OWNEDcode;
3769 ArrayLiteralExp *ArrayLiteralExp::create(Loc loc, Expressions *elements)
3771 return new ArrayLiteralExp(loc, elements);
3774 bool ArrayLiteralExp::equals(RootObject *o)
3776 if (this == o)
3777 return true;
3778 if (o && o->dyncast() == DYNCAST_EXPRESSION &&
3779 ((Expression *)o)->op == TOKarrayliteral)
3781 ArrayLiteralExp *ae = (ArrayLiteralExp *)o;
3782 if (elements->dim != ae->elements->dim)
3783 return false;
3784 if (elements->dim == 0 &&
3785 !type->equals(ae->type))
3787 return false;
3789 for (size_t i = 0; i < elements->dim; i++)
3791 Expression *e1 = (*elements)[i];
3792 Expression *e2 = (*ae->elements)[i];
3793 if (!e1)
3794 e1 = basis;
3795 if (!e2)
3796 e2 = basis;
3797 if (e1 != e2 &&
3798 (!e1 || !e2 || !e1->equals(e2)))
3799 return false;
3801 return true;
3803 return false;
3806 Expression *ArrayLiteralExp::syntaxCopy()
3808 return new ArrayLiteralExp(loc,
3809 basis ? basis->syntaxCopy() : NULL,
3810 arraySyntaxCopy(elements));
3813 Expression *ArrayLiteralExp::getElement(d_size_t i)
3815 Expression *el = (*elements)[i];
3816 if (!el)
3817 el = basis;
3818 return el;
3821 static void appendArrayLiteral(Expressions *elems, ArrayLiteralExp *ale)
3823 if (!ale->elements)
3824 return;
3825 size_t d = elems->dim;
3826 elems->append(ale->elements);
3827 for (size_t i = d; i < elems->dim; i++)
3829 Expression *el = (*elems)[i];
3830 if (!el)
3831 (*elems)[i] = ale->basis;
3835 /* Copy element `Expressions` in the parameters when they're `ArrayLiteralExp`s.
3836 * Params:
3837 * e1 = If it's ArrayLiteralExp, its `elements` will be copied.
3838 * Otherwise, `e1` itself will be pushed into the new `Expressions`.
3839 * e2 = If it's not `null`, it will be pushed/appended to the new
3840 * `Expressions` by the same way with `e1`.
3841 * Returns:
3842 * Newly allocated `Expressions`. Note that it points to the original
3843 * `Expression` values in e1 and e2.
3845 Expressions* ArrayLiteralExp::copyElements(Expression *e1, Expression *e2)
3847 Expressions *elems = new Expressions();
3849 if (e1->op == TOKarrayliteral)
3850 appendArrayLiteral(elems, (ArrayLiteralExp *)e1);
3851 else
3852 elems->push(e1);
3854 if (e2)
3856 if (e2->op == TOKarrayliteral)
3857 appendArrayLiteral(elems, (ArrayLiteralExp *)e2);
3858 else
3859 elems->push(e2);
3862 return elems;
3865 bool ArrayLiteralExp::isBool(bool result)
3867 size_t dim = elements ? elements->dim : 0;
3868 return result ? (dim != 0) : (dim == 0);
3871 StringExp *ArrayLiteralExp::toStringExp()
3873 TY telem = type->nextOf()->toBasetype()->ty;
3875 if (telem == Tchar || telem == Twchar || telem == Tdchar ||
3876 (telem == Tvoid && (!elements || elements->dim == 0)))
3878 unsigned char sz = 1;
3879 if (telem == Twchar) sz = 2;
3880 else if (telem == Tdchar) sz = 4;
3882 OutBuffer buf;
3883 if (elements)
3885 for (size_t i = 0; i < elements->dim; ++i)
3887 Expression *ch = getElement(i);
3888 if (ch->op != TOKint64)
3889 return NULL;
3890 if (sz == 1)
3891 buf.writeByte((unsigned)ch->toInteger());
3892 else if (sz == 2)
3893 buf.writeword((unsigned)ch->toInteger());
3894 else
3895 buf.write4((unsigned)ch->toInteger());
3898 char prefix;
3899 if (sz == 1) { prefix = 'c'; buf.writeByte(0); }
3900 else if (sz == 2) { prefix = 'w'; buf.writeword(0); }
3901 else { prefix = 'd'; buf.write4(0); }
3903 const size_t len = buf.offset / sz - 1;
3904 StringExp *se = new StringExp(loc, buf.extractData(), len, prefix);
3905 se->sz = sz;
3906 se->type = type;
3907 return se;
3909 return NULL;
3912 /************************ AssocArrayLiteralExp ************************************/
3914 // [ key0 : value0, key1 : value1, ... ]
3916 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc,
3917 Expressions *keys, Expressions *values)
3918 : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp))
3920 assert(keys->dim == values->dim);
3921 this->keys = keys;
3922 this->values = values;
3923 this->ownedByCtfe = OWNEDcode;
3926 bool AssocArrayLiteralExp::equals(RootObject *o)
3928 if (this == o)
3929 return true;
3930 if (o && o->dyncast() == DYNCAST_EXPRESSION &&
3931 ((Expression *)o)->op == TOKassocarrayliteral)
3933 AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)o;
3934 if (keys->dim != ae->keys->dim)
3935 return false;
3936 size_t count = 0;
3937 for (size_t i = 0; i < keys->dim; i++)
3939 for (size_t j = 0; j < ae->keys->dim; j++)
3941 if ((*keys)[i]->equals((*ae->keys)[j]))
3943 if (!(*values)[i]->equals((*ae->values)[j]))
3944 return false;
3945 ++count;
3949 return count == keys->dim;
3951 return false;
3954 Expression *AssocArrayLiteralExp::syntaxCopy()
3956 return new AssocArrayLiteralExp(loc,
3957 arraySyntaxCopy(keys), arraySyntaxCopy(values));
3960 bool AssocArrayLiteralExp::isBool(bool result)
3962 size_t dim = keys->dim;
3963 return result ? (dim != 0) : (dim == 0);
3966 /************************ StructLiteralExp ************************************/
3968 // sd( e1, e2, e3, ... )
3970 StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype)
3971 : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp))
3973 this->sd = sd;
3974 if (!elements)
3975 elements = new Expressions();
3976 this->elements = elements;
3977 this->stype = stype;
3978 this->useStaticInit = false;
3979 this->sym = NULL;
3980 this->ownedByCtfe = OWNEDcode;
3981 this->origin = this;
3982 this->stageflags = 0;
3983 this->inlinecopy = NULL;
3984 //printf("StructLiteralExp::StructLiteralExp(%s)\n", toChars());
3987 StructLiteralExp *StructLiteralExp::create(Loc loc, StructDeclaration *sd, void *elements, Type *stype)
3989 return new StructLiteralExp(loc, sd, (Expressions *)elements, stype);
3992 bool StructLiteralExp::equals(RootObject *o)
3994 if (this == o)
3995 return true;
3996 if (o && o->dyncast() == DYNCAST_EXPRESSION &&
3997 ((Expression *)o)->op == TOKstructliteral)
3999 StructLiteralExp *se = (StructLiteralExp *)o;
4000 if (!type->equals(se->type))
4001 return false;
4002 if (elements->dim != se->elements->dim)
4003 return false;
4004 for (size_t i = 0; i < elements->dim; i++)
4006 Expression *e1 = (*elements)[i];
4007 Expression *e2 = (*se->elements)[i];
4008 if (e1 != e2 &&
4009 (!e1 || !e2 || !e1->equals(e2)))
4010 return false;
4012 return true;
4014 return false;
4017 Expression *StructLiteralExp::syntaxCopy()
4019 StructLiteralExp *exp = new StructLiteralExp(loc, sd, arraySyntaxCopy(elements), type ? type : stype);
4020 exp->origin = this;
4021 return exp;
4024 Expression *StructLiteralExp::addDtorHook(Scope *sc)
4026 /* If struct requires a destructor, rewrite as:
4027 * (S tmp = S()),tmp
4028 * so that the destructor can be hung on tmp.
4030 if (sd->dtor && sc->func)
4032 /* Make an identifier for the temporary of the form:
4033 * __sl%s%d, where %s is the struct name
4035 const size_t len = 10;
4036 char buf[len + 1];
4037 buf[len] = 0;
4038 strcpy(buf, "__sl");
4039 strncat(buf, sd->ident->toChars(), len - 4 - 1);
4040 assert(buf[len] == 0);
4042 VarDeclaration *tmp = copyToTemp(0, buf, this);
4043 Expression *ae = new DeclarationExp(loc, tmp);
4044 Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp));
4045 e = semantic(e, sc);
4046 return e;
4048 return this;
4051 /**************************************
4052 * Gets expression at offset of type.
4053 * Returns NULL if not found.
4056 Expression *StructLiteralExp::getField(Type *type, unsigned offset)
4058 //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
4059 // /*toChars()*/"", type->toChars(), offset);
4060 Expression *e = NULL;
4061 int i = getFieldIndex(type, offset);
4063 if (i != -1)
4065 //printf("\ti = %d\n", i);
4066 if (i == (int)sd->fields.dim - 1 && sd->isNested())
4067 return NULL;
4069 assert(i < (int)elements->dim);
4070 e = (*elements)[i];
4071 if (e)
4073 //printf("e = %s, e->type = %s\n", e->toChars(), e->type->toChars());
4075 /* If type is a static array, and e is an initializer for that array,
4076 * then the field initializer should be an array literal of e.
4078 if (e->type->castMod(0) != type->castMod(0) && type->ty == Tsarray)
4079 { TypeSArray *tsa = (TypeSArray *)type;
4080 size_t length = (size_t)tsa->dim->toInteger();
4081 Expressions *z = new Expressions;
4082 z->setDim(length);
4083 for (size_t q = 0; q < length; ++q)
4084 (*z)[q] = e->copy();
4085 e = new ArrayLiteralExp(loc, z);
4086 e->type = type;
4088 else
4090 e = e->copy();
4091 e->type = type;
4093 if (useStaticInit && e->op == TOKstructliteral &&
4094 e->type->needsNested())
4096 StructLiteralExp *se = (StructLiteralExp *)e;
4097 se->useStaticInit = true;
4101 return e;
4104 /************************************
4105 * Get index of field.
4106 * Returns -1 if not found.
4109 int StructLiteralExp::getFieldIndex(Type *type, unsigned offset)
4111 /* Find which field offset is by looking at the field offsets
4113 if (elements->dim)
4115 for (size_t i = 0; i < sd->fields.dim; i++)
4117 VarDeclaration *v = sd->fields[i];
4119 if (offset == v->offset &&
4120 type->size() == v->type->size())
4122 /* context field might not be filled. */
4123 if (i == sd->fields.dim - 1 && sd->isNested())
4124 return (int)i;
4125 Expression *e = (*elements)[i];
4126 if (e)
4128 return (int)i;
4130 break;
4134 return -1;
4137 /************************ TypeDotIdExp ************************************/
4139 /* Things like:
4140 * int.size
4141 * foo.size
4142 * (foo).size
4143 * cast(foo).size
4146 DotIdExp *typeDotIdExp(Loc loc, Type *type, Identifier *ident)
4148 return new DotIdExp(loc, new TypeExp(loc, type), ident);
4152 /************************************************************/
4154 // Mainly just a placeholder
4156 TypeExp::TypeExp(Loc loc, Type *type)
4157 : Expression(loc, TOKtype, sizeof(TypeExp))
4159 //printf("TypeExp::TypeExp(%s)\n", type->toChars());
4160 this->type = type;
4163 Expression *TypeExp::syntaxCopy()
4165 return new TypeExp(loc, type->syntaxCopy());
4168 bool TypeExp::checkType()
4170 error("type %s is not an expression", toChars());
4171 return true;
4174 bool TypeExp::checkValue()
4176 error("type %s has no value", toChars());
4177 return true;
4180 /************************************************************/
4182 /***********************************************************
4183 * Mainly just a placeholder of
4184 * Package, Module, Nspace, and TemplateInstance (including TemplateMixin)
4186 * A template instance that requires IFTI:
4187 * foo!tiargs(fargs) // foo!tiargs
4188 * is left until CallExp::semantic() or resolveProperties()
4190 ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *sds)
4191 : Expression(loc, TOKscope, sizeof(ScopeExp))
4193 //printf("ScopeExp::ScopeExp(sds = '%s')\n", sds->toChars());
4194 //static int count; if (++count == 38) *(char*)0=0;
4195 this->sds = sds;
4196 assert(!sds->isTemplateDeclaration()); // instead, you should use TemplateExp
4199 Expression *ScopeExp::syntaxCopy()
4201 return new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL));
4204 bool ScopeExp::checkType()
4206 if (sds->isPackage())
4208 error("%s %s has no type", sds->kind(), sds->toChars());
4209 return true;
4211 if (TemplateInstance *ti = sds->isTemplateInstance())
4213 //assert(ti->needsTypeInference(sc));
4214 if (ti->tempdecl &&
4215 ti->semantictiargsdone &&
4216 ti->semanticRun == PASSinit)
4218 error("partial %s %s has no type", sds->kind(), toChars());
4219 return true;
4222 return false;
4225 bool ScopeExp::checkValue()
4227 error("%s %s has no value", sds->kind(), sds->toChars());
4228 return true;
4231 /********************** TemplateExp **************************************/
4233 // Mainly just a placeholder
4235 TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td, FuncDeclaration *fd)
4236 : Expression(loc, TOKtemplate, sizeof(TemplateExp))
4238 //printf("TemplateExp(): %s\n", td->toChars());
4239 this->td = td;
4240 this->fd = fd;
4243 bool TemplateExp::checkType()
4245 error("%s %s has no type", td->kind(), toChars());
4246 return true;
4249 bool TemplateExp::checkValue()
4251 error("%s %s has no value", td->kind(), toChars());
4252 return true;
4255 bool TemplateExp::isLvalue()
4257 return fd != NULL;
4260 Expression *TemplateExp::toLvalue(Scope *sc, Expression *e)
4262 if (!fd)
4263 return Expression::toLvalue(sc, e);
4265 assert(sc);
4266 return resolve(loc, sc, fd, true);
4269 /********************** NewExp **************************************/
4271 /* thisexp.new(newargs) newtype(arguments) */
4273 NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
4274 Type *newtype, Expressions *arguments)
4275 : Expression(loc, TOKnew, sizeof(NewExp))
4277 this->thisexp = thisexp;
4278 this->newargs = newargs;
4279 this->newtype = newtype;
4280 this->arguments = arguments;
4281 argprefix = NULL;
4282 member = NULL;
4283 allocator = NULL;
4284 onstack = 0;
4287 NewExp *NewExp::create(Loc loc, Expression *thisexp, Expressions *newargs,
4288 Type *newtype, Expressions *arguments)
4290 return new NewExp(loc, thisexp, newargs, newtype, arguments);
4293 Expression *NewExp::syntaxCopy()
4295 return new NewExp(loc,
4296 thisexp ? thisexp->syntaxCopy() : NULL,
4297 arraySyntaxCopy(newargs),
4298 newtype->syntaxCopy(), arraySyntaxCopy(arguments));
4301 /********************** NewAnonClassExp **************************************/
4303 NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp,
4304 Expressions *newargs, ClassDeclaration *cd, Expressions *arguments)
4305 : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp))
4307 this->thisexp = thisexp;
4308 this->newargs = newargs;
4309 this->cd = cd;
4310 this->arguments = arguments;
4313 Expression *NewAnonClassExp::syntaxCopy()
4315 return new NewAnonClassExp(loc,
4316 thisexp ? thisexp->syntaxCopy() : NULL,
4317 arraySyntaxCopy(newargs),
4318 (ClassDeclaration *)cd->syntaxCopy(NULL),
4319 arraySyntaxCopy(arguments));
4322 /********************** SymbolExp **************************************/
4324 SymbolExp::SymbolExp(Loc loc, TOK op, int size, Declaration *var, bool hasOverloads)
4325 : Expression(loc, op, size)
4327 assert(var);
4328 this->var = var;
4329 this->hasOverloads = hasOverloads;
4332 /********************** SymOffExp **************************************/
4334 SymOffExp::SymOffExp(Loc loc, Declaration *var, dinteger_t offset, bool hasOverloads)
4335 : SymbolExp(loc, TOKsymoff, sizeof(SymOffExp), var,
4336 var->isVarDeclaration() ? false : hasOverloads)
4338 if (VarDeclaration *v = var->isVarDeclaration())
4340 // FIXME: This error report will never be handled anyone.
4341 // It should be done before the SymOffExp construction.
4342 if (v->needThis())
4343 ::error(loc, "need 'this' for address of %s", v->toChars());
4345 this->offset = offset;
4348 bool SymOffExp::isBool(bool result)
4350 return result ? true : false;
4353 /******************************** VarExp **************************/
4355 VarExp::VarExp(Loc loc, Declaration *var, bool hasOverloads)
4356 : SymbolExp(loc, TOKvar, sizeof(VarExp), var,
4357 var->isVarDeclaration() ? false : hasOverloads)
4359 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
4360 //if (strcmp(var->ident->toChars(), "func") == 0) halt();
4361 this->type = var->type;
4364 VarExp *VarExp::create(Loc loc, Declaration *var, bool hasOverloads)
4366 return new VarExp(loc, var, hasOverloads);
4369 bool VarExp::equals(RootObject *o)
4371 if (this == o)
4372 return true;
4373 if (((Expression *)o)->op == TOKvar)
4375 VarExp *ne = (VarExp *)o;
4376 if (type->toHeadMutable()->equals(ne->type->toHeadMutable()) &&
4377 var == ne->var)
4379 return true;
4382 return false;
4385 bool VarExp::isLvalue()
4387 if (var->storage_class & (STClazy | STCrvalue | STCmanifest))
4388 return false;
4389 return true;
4392 Expression *VarExp::toLvalue(Scope *, Expression *)
4394 if (var->storage_class & STCmanifest)
4396 error("manifest constant '%s' is not lvalue", var->toChars());
4397 return new ErrorExp();
4399 if (var->storage_class & STClazy)
4401 error("lazy variables cannot be lvalues");
4402 return new ErrorExp();
4404 if (var->ident == Id::ctfe)
4406 error("compiler-generated variable __ctfe is not an lvalue");
4407 return new ErrorExp();
4409 if (var->ident == Id::dollar) // Bugzilla 13574
4411 error("'$' is not an lvalue");
4412 return new ErrorExp();
4414 return this;
4417 int VarExp::checkModifiable(Scope *sc, int flag)
4419 //printf("VarExp::checkModifiable %s", toChars());
4420 assert(type);
4421 return var->checkModify(loc, sc, type, NULL, flag);
4424 Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
4426 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
4427 if (var->storage_class & STCmanifest)
4429 error("cannot modify manifest constant '%s'", toChars());
4430 return new ErrorExp();
4432 // See if this expression is a modifiable lvalue (i.e. not const)
4433 return Expression::modifiableLvalue(sc, e);
4437 /******************************** OverExp **************************/
4439 OverExp::OverExp(Loc loc, OverloadSet *s)
4440 : Expression(loc, TOKoverloadset, sizeof(OverExp))
4442 //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
4443 vars = s;
4444 type = Type::tvoid;
4447 bool OverExp::isLvalue()
4449 return true;
4452 Expression *OverExp::toLvalue(Scope *, Expression *)
4454 return this;
4457 /******************************** TupleExp **************************/
4459 TupleExp::TupleExp(Loc loc, Expression *e0, Expressions *exps)
4460 : Expression(loc, TOKtuple, sizeof(TupleExp))
4462 //printf("TupleExp(this = %p)\n", this);
4463 this->e0 = e0;
4464 this->exps = exps;
4467 TupleExp::TupleExp(Loc loc, Expressions *exps)
4468 : Expression(loc, TOKtuple, sizeof(TupleExp))
4470 //printf("TupleExp(this = %p)\n", this);
4471 this->e0 = NULL;
4472 this->exps = exps;
4475 TupleExp::TupleExp(Loc loc, TupleDeclaration *tup)
4476 : Expression(loc, TOKtuple, sizeof(TupleExp))
4478 this->e0 = NULL;
4479 this->exps = new Expressions();
4481 this->exps->reserve(tup->objects->dim);
4482 for (size_t i = 0; i < tup->objects->dim; i++)
4483 { RootObject *o = (*tup->objects)[i];
4484 if (Dsymbol *s = getDsymbol(o))
4486 /* If tuple element represents a symbol, translate to DsymbolExp
4487 * to supply implicit 'this' if needed later.
4489 Expression *e = new DsymbolExp(loc, s);
4490 this->exps->push(e);
4492 else if (o->dyncast() == DYNCAST_EXPRESSION)
4494 Expression *e = ((Expression *)o)->copy();
4495 e->loc = loc; // Bugzilla 15669
4496 this->exps->push(e);
4498 else if (o->dyncast() == DYNCAST_TYPE)
4500 Type *t = (Type *)o;
4501 Expression *e = new TypeExp(loc, t);
4502 this->exps->push(e);
4504 else
4506 error("%s is not an expression", o->toChars());
4511 bool TupleExp::equals(RootObject *o)
4513 if (this == o)
4514 return true;
4515 if (((Expression *)o)->op == TOKtuple)
4517 TupleExp *te = (TupleExp *)o;
4518 if (exps->dim != te->exps->dim)
4519 return false;
4520 if ((e0 && !e0->equals(te->e0)) || (!e0 && te->e0))
4521 return false;
4522 for (size_t i = 0; i < exps->dim; i++)
4524 Expression *e1 = (*exps)[i];
4525 Expression *e2 = (*te->exps)[i];
4526 if (!e1->equals(e2))
4527 return false;
4529 return true;
4531 return false;
4534 Expression *TupleExp::syntaxCopy()
4536 return new TupleExp(loc, e0 ? e0->syntaxCopy() : NULL, arraySyntaxCopy(exps));
4539 /******************************** FuncExp *********************************/
4541 FuncExp::FuncExp(Loc loc, Dsymbol *s)
4542 : Expression(loc, TOKfunction, sizeof(FuncExp))
4544 this->td = s->isTemplateDeclaration();
4545 this->fd = s->isFuncLiteralDeclaration();
4546 if (td)
4548 assert(td->literal);
4549 assert(td->members && td->members->dim == 1);
4550 fd = (*td->members)[0]->isFuncLiteralDeclaration();
4552 tok = fd->tok; // save original kind of function/delegate/(infer)
4553 assert(fd->fbody);
4556 bool FuncExp::equals(RootObject *o)
4558 if (this == o)
4559 return true;
4560 if (o->dyncast() != DYNCAST_EXPRESSION)
4561 return false;
4562 if (((Expression *)o)->op == TOKfunction)
4564 FuncExp *fe = (FuncExp *)o;
4565 return fd == fe->fd;
4567 return false;
4570 void FuncExp::genIdent(Scope *sc)
4572 if (fd->ident == Id::empty)
4574 const char *s;
4575 if (fd->fes) s = "__foreachbody";
4576 else if (fd->tok == TOKreserved) s = "__lambda";
4577 else if (fd->tok == TOKdelegate) s = "__dgliteral";
4578 else s = "__funcliteral";
4580 DsymbolTable *symtab;
4581 if (FuncDeclaration *func = sc->parent->isFuncDeclaration())
4583 if (func->localsymtab == NULL)
4585 // Inside template constraint, symtab is not set yet.
4586 // Initialize it lazily.
4587 func->localsymtab = new DsymbolTable();
4589 symtab = func->localsymtab;
4591 else
4593 ScopeDsymbol *sds = sc->parent->isScopeDsymbol();
4594 if (!sds->symtab)
4596 // Inside template constraint, symtab may not be set yet.
4597 // Initialize it lazily.
4598 assert(sds->isTemplateInstance());
4599 sds->symtab = new DsymbolTable();
4601 symtab = sds->symtab;
4603 assert(symtab);
4604 int num = (int)dmd_aaLen(symtab->tab) + 1;
4605 Identifier *id = Identifier::generateId(s, num);
4606 fd->ident = id;
4607 if (td) td->ident = id;
4608 symtab->insert(td ? (Dsymbol *)td : (Dsymbol *)fd);
4612 Expression *FuncExp::syntaxCopy()
4614 if (td)
4615 return new FuncExp(loc, td->syntaxCopy(NULL));
4616 else if (fd->semanticRun == PASSinit)
4617 return new FuncExp(loc, fd->syntaxCopy(NULL));
4618 else // Bugzilla 13481: Prevent multiple semantic analysis of lambda body.
4619 return new FuncExp(loc, fd);
4622 MATCH FuncExp::matchType(Type *to, Scope *sc, FuncExp **presult, int flag)
4624 //printf("FuncExp::matchType('%s'), to=%s\n", type ? type->toChars() : "null", to->toChars());
4625 if (presult)
4626 *presult = NULL;
4628 TypeFunction *tof = NULL;
4629 if (to->ty == Tdelegate)
4631 if (tok == TOKfunction)
4633 if (!flag)
4634 error("cannot match function literal to delegate type '%s'", to->toChars());
4635 return MATCHnomatch;
4637 tof = (TypeFunction *)to->nextOf();
4639 else if (to->ty == Tpointer && to->nextOf()->ty == Tfunction)
4641 if (tok == TOKdelegate)
4643 if (!flag)
4644 error("cannot match delegate literal to function pointer type '%s'", to->toChars());
4645 return MATCHnomatch;
4647 tof = (TypeFunction *)to->nextOf();
4650 if (td)
4652 if (!tof)
4655 if (!flag)
4656 error("cannot infer parameter types from %s", to->toChars());
4657 return MATCHnomatch;
4660 // Parameter types inference from 'tof'
4661 assert(td->_scope);
4662 TypeFunction *tf = (TypeFunction *)fd->type;
4663 //printf("\ttof = %s\n", tof->toChars());
4664 //printf("\ttf = %s\n", tf->toChars());
4665 size_t dim = Parameter::dim(tf->parameters);
4667 if (Parameter::dim(tof->parameters) != dim ||
4668 tof->varargs != tf->varargs)
4669 goto L1;
4671 Objects *tiargs = new Objects();
4672 tiargs->reserve(td->parameters->dim);
4674 for (size_t i = 0; i < td->parameters->dim; i++)
4676 TemplateParameter *tp = (*td->parameters)[i];
4677 size_t u = 0;
4678 for (; u < dim; u++)
4680 Parameter *p = Parameter::getNth(tf->parameters, u);
4681 if (p->type->ty == Tident &&
4682 ((TypeIdentifier *)p->type)->ident == tp->ident)
4684 break;
4687 assert(u < dim);
4688 Parameter *pto = Parameter::getNth(tof->parameters, u);
4689 Type *t = pto->type;
4690 if (t->ty == Terror)
4691 goto L1;
4692 tiargs->push(t);
4695 // Set target of return type inference
4696 if (!tf->next && tof->next)
4697 fd->treq = to;
4699 TemplateInstance *ti = new TemplateInstance(loc, td, tiargs);
4700 Expression *ex = new ScopeExp(loc, ti);
4701 ex = ::semantic(ex, td->_scope);
4703 // Reset inference target for the later re-semantic
4704 fd->treq = NULL;
4706 if (ex->op == TOKerror)
4707 return MATCHnomatch;
4708 if (ex->op != TOKfunction)
4709 goto L1;
4710 return ((FuncExp *)ex)->matchType(to, sc, presult, flag);
4713 if (!tof || !tof->next)
4714 return MATCHnomatch;
4716 assert(type && type != Type::tvoid);
4717 TypeFunction *tfx = (TypeFunction *)fd->type;
4718 bool convertMatch = (type->ty != to->ty);
4720 if (fd->inferRetType && tfx->next->implicitConvTo(tof->next) == MATCHconvert)
4722 /* If return type is inferred and covariant return,
4723 * tweak return statements to required return type.
4725 * interface I {}
4726 * class C : Object, I{}
4728 * I delegate() dg = delegate() { return new class C(); }
4730 convertMatch = true;
4732 TypeFunction *tfy = new TypeFunction(tfx->parameters, tof->next, tfx->varargs, tfx->linkage, STCundefined);
4733 tfy->mod = tfx->mod;
4734 tfy->isnothrow = tfx->isnothrow;
4735 tfy->isnogc = tfx->isnogc;
4736 tfy->purity = tfx->purity;
4737 tfy->isproperty = tfx->isproperty;
4738 tfy->isref = tfx->isref;
4739 tfy->iswild = tfx->iswild;
4740 tfy->deco = tfy->merge()->deco;
4742 tfx = tfy;
4745 Type *tx;
4746 if (tok == TOKdelegate ||
4747 (tok == TOKreserved && (type->ty == Tdelegate ||
4748 (type->ty == Tpointer && to->ty == Tdelegate))))
4750 // Allow conversion from implicit function pointer to delegate
4751 tx = new TypeDelegate(tfx);
4752 tx->deco = tx->merge()->deco;
4754 else
4756 assert(tok == TOKfunction ||
4757 (tok == TOKreserved && type->ty == Tpointer));
4758 tx = tfx->pointerTo();
4760 //printf("\ttx = %s, to = %s\n", tx->toChars(), to->toChars());
4762 MATCH m = tx->implicitConvTo(to);
4763 if (m > MATCHnomatch)
4765 // MATCHexact: exact type match
4766 // MATCHconst: covairiant type match (eg. attributes difference)
4767 // MATCHconvert: context conversion
4768 m = convertMatch ? MATCHconvert : tx->equals(to) ? MATCHexact : MATCHconst;
4770 if (presult)
4772 (*presult) = (FuncExp *)copy();
4773 (*presult)->type = to;
4775 // Bugzilla 12508: Tweak function body for covariant returns.
4776 (*presult)->fd->modifyReturns(sc, tof->next);
4779 else if (!flag)
4781 error("cannot implicitly convert expression (%s) of type %s to %s",
4782 toChars(), tx->toChars(), to->toChars());
4784 return m;
4787 const char *FuncExp::toChars()
4789 return fd->toChars();
4792 bool FuncExp::checkType()
4794 if (td)
4796 error("template lambda has no type");
4797 return true;
4799 return false;
4802 bool FuncExp::checkValue()
4804 if (td)
4806 error("template lambda has no value");
4807 return true;
4809 return false;
4812 /******************************** DeclarationExp **************************/
4814 DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration)
4815 : Expression(loc, TOKdeclaration, sizeof(DeclarationExp))
4817 this->declaration = declaration;
4820 Expression *DeclarationExp::syntaxCopy()
4822 return new DeclarationExp(loc, declaration->syntaxCopy(NULL));
4825 bool DeclarationExp::hasCode()
4827 if (VarDeclaration *vd = declaration->isVarDeclaration())
4829 return !(vd->storage_class & (STCmanifest | STCstatic));
4831 return false;
4834 /************************ TypeidExp ************************************/
4837 * typeid(int)
4840 TypeidExp::TypeidExp(Loc loc, RootObject *o)
4841 : Expression(loc, TOKtypeid, sizeof(TypeidExp))
4843 this->obj = o;
4846 Expression *TypeidExp::syntaxCopy()
4848 return new TypeidExp(loc, objectSyntaxCopy(obj));
4851 /************************ TraitsExp ************************************/
4853 * __traits(identifier, args...)
4856 TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args)
4857 : Expression(loc, TOKtraits, sizeof(TraitsExp))
4859 this->ident = ident;
4860 this->args = args;
4863 Expression *TraitsExp::syntaxCopy()
4865 return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args));
4868 /************************************************************/
4870 HaltExp::HaltExp(Loc loc)
4871 : Expression(loc, TOKhalt, sizeof(HaltExp))
4875 /************************************************************/
4877 IsExp::IsExp(Loc loc, Type *targ, Identifier *id, TOK tok,
4878 Type *tspec, TOK tok2, TemplateParameters *parameters)
4879 : Expression(loc, TOKis, sizeof(IsExp))
4881 this->targ = targ;
4882 this->id = id;
4883 this->tok = tok;
4884 this->tspec = tspec;
4885 this->tok2 = tok2;
4886 this->parameters = parameters;
4889 Expression *IsExp::syntaxCopy()
4891 // This section is identical to that in TemplateDeclaration::syntaxCopy()
4892 TemplateParameters *p = NULL;
4893 if (parameters)
4895 p = new TemplateParameters();
4896 p->setDim(parameters->dim);
4897 for (size_t i = 0; i < p->dim; i++)
4898 (*p)[i] = (*parameters)[i]->syntaxCopy();
4900 return new IsExp(loc,
4901 targ->syntaxCopy(),
4903 tok,
4904 tspec ? tspec->syntaxCopy() : NULL,
4905 tok2,
4909 void unSpeculative(Scope *sc, RootObject *o);
4911 /************************************************************/
4913 UnaExp::UnaExp(Loc loc, TOK op, int size, Expression *e1)
4914 : Expression(loc, op, size)
4916 this->e1 = e1;
4917 this->att1 = NULL;
4920 Expression *UnaExp::syntaxCopy()
4922 UnaExp *e = (UnaExp *)copy();
4923 e->type = NULL;
4924 e->e1 = e->e1->syntaxCopy();
4925 return e;
4928 /********************************
4929 * The type for a unary expression is incompatible.
4930 * Print error message.
4931 * Returns:
4932 * ErrorExp
4934 Expression *UnaExp::incompatibleTypes()
4936 if (e1->type->toBasetype() == Type::terror)
4937 return e1;
4939 if (e1->op == TOKtype)
4941 error("incompatible type for (%s(%s)): cannot use '%s' with types",
4942 Token::toChars(op), e1->toChars(), Token::toChars(op));
4944 else
4946 error("incompatible type for (%s(%s)): '%s'",
4947 Token::toChars(op), e1->toChars(), e1->type->toChars());
4949 return new ErrorExp();
4952 Expression *UnaExp::resolveLoc(Loc loc, Scope *sc)
4954 e1 = e1->resolveLoc(loc, sc);
4955 return this;
4958 /************************************************************/
4960 BinExp::BinExp(Loc loc, TOK op, int size, Expression *e1, Expression *e2)
4961 : Expression(loc, op, size)
4963 this->e1 = e1;
4964 this->e2 = e2;
4966 this->att1 = NULL;
4967 this->att2 = NULL;
4970 Expression *BinExp::syntaxCopy()
4972 BinExp *e = (BinExp *)copy();
4973 e->type = NULL;
4974 e->e1 = e->e1->syntaxCopy();
4975 e->e2 = e->e2->syntaxCopy();
4976 return e;
4979 Expression *BinExp::checkOpAssignTypes(Scope *sc)
4981 // At that point t1 and t2 are the merged types. type is the original type of the lhs.
4982 Type *t1 = e1->type;
4983 Type *t2 = e2->type;
4985 // T opAssign floating yields a floating. Prevent truncating conversions (float to int).
4986 // See issue 3841.
4987 // Should we also prevent double to float (type->isfloating() && type->size() < t2 ->size()) ?
4988 if (op == TOKaddass || op == TOKminass ||
4989 op == TOKmulass || op == TOKdivass || op == TOKmodass ||
4990 op == TOKpowass)
4992 if ((type->isintegral() && t2->isfloating()))
4994 warning("%s %s %s is performing truncating conversion",
4995 type->toChars(), Token::toChars(op), t2->toChars());
4999 // generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary
5000 if (op == TOKmulass || op == TOKdivass || op == TOKmodass)
5002 // Any multiplication by an imaginary or complex number yields a complex result.
5003 // r *= c, i*=c, r*=i, i*=i are all forbidden operations.
5004 const char *opstr = Token::toChars(op);
5005 if (t1->isreal() && t2->iscomplex())
5007 error("%s %s %s is undefined. Did you mean %s %s %s.re ?",
5008 t1->toChars(), opstr, t2->toChars(),
5009 t1->toChars(), opstr, t2->toChars());
5010 return new ErrorExp();
5012 else if (t1->isimaginary() && t2->iscomplex())
5014 error("%s %s %s is undefined. Did you mean %s %s %s.im ?",
5015 t1->toChars(), opstr, t2->toChars(),
5016 t1->toChars(), opstr, t2->toChars());
5017 return new ErrorExp();
5019 else if ((t1->isreal() || t1->isimaginary()) &&
5020 t2->isimaginary())
5022 error("%s %s %s is an undefined operation", t1->toChars(), opstr, t2->toChars());
5023 return new ErrorExp();
5027 // generate an error if this is a nonsensical += or -=, eg real += imaginary
5028 if (op == TOKaddass || op == TOKminass)
5030 // Addition or subtraction of a real and an imaginary is a complex result.
5031 // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
5032 if ((t1->isreal() && (t2->isimaginary() || t2->iscomplex())) ||
5033 (t1->isimaginary() && (t2->isreal() || t2->iscomplex())))
5035 error("%s %s %s is undefined (result is complex)",
5036 t1->toChars(), Token::toChars(op), t2->toChars());
5037 return new ErrorExp();
5039 if (type->isreal() || type->isimaginary())
5041 assert(global.errors || t2->isfloating());
5042 e2 = e2->castTo(sc, t1);
5046 if (op == TOKmulass)
5048 if (t2->isfloating())
5050 if (t1->isreal())
5052 if (t2->isimaginary() || t2->iscomplex())
5054 e2 = e2->castTo(sc, t1);
5057 else if (t1->isimaginary())
5059 if (t2->isimaginary() || t2->iscomplex())
5061 switch (t1->ty)
5063 case Timaginary32: t2 = Type::tfloat32; break;
5064 case Timaginary64: t2 = Type::tfloat64; break;
5065 case Timaginary80: t2 = Type::tfloat80; break;
5066 default:
5067 assert(0);
5069 e2 = e2->castTo(sc, t2);
5074 else if (op == TOKdivass)
5076 if (t2->isimaginary())
5078 if (t1->isreal())
5080 // x/iv = i(-x/v)
5081 // Therefore, the result is 0
5082 e2 = new CommaExp(loc, e2, new RealExp(loc, CTFloat::zero, t1));
5083 e2->type = t1;
5084 Expression *e = new AssignExp(loc, e1, e2);
5085 e->type = t1;
5086 return e;
5088 else if (t1->isimaginary())
5090 Type *t3;
5091 switch (t1->ty)
5093 case Timaginary32: t3 = Type::tfloat32; break;
5094 case Timaginary64: t3 = Type::tfloat64; break;
5095 case Timaginary80: t3 = Type::tfloat80; break;
5096 default:
5097 assert(0);
5099 e2 = e2->castTo(sc, t3);
5100 Expression *e = new AssignExp(loc, e1, e2);
5101 e->type = t1;
5102 return e;
5106 else if (op == TOKmodass)
5108 if (t2->iscomplex())
5110 error("cannot perform modulo complex arithmetic");
5111 return new ErrorExp();
5114 return this;
5117 /********************************
5118 * The types for a binary expression are incompatible.
5119 * Print error message.
5120 * Returns:
5121 * ErrorExp
5123 Expression *BinExp::incompatibleTypes()
5125 if (e1->type->toBasetype() == Type::terror)
5126 return e1;
5127 if (e2->type->toBasetype() == Type::terror)
5128 return e2;
5130 // CondExp uses 'a ? b : c' but we're comparing 'b : c'
5131 TOK thisOp = (op == TOKquestion) ? TOKcolon : op;
5132 if (e1->op == TOKtype || e2->op == TOKtype)
5134 error("incompatible types for ((%s) %s (%s)): cannot use '%s' with types",
5135 e1->toChars(), Token::toChars(thisOp), e2->toChars(), Token::toChars(op));
5137 else
5139 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
5140 e1->toChars(), Token::toChars(thisOp), e2->toChars(),
5141 e1->type->toChars(), e2->type->toChars());
5143 return new ErrorExp();
5146 bool BinExp::checkIntegralBin()
5148 bool r1 = e1->checkIntegral();
5149 bool r2 = e2->checkIntegral();
5150 return (r1 || r2);
5153 bool BinExp::checkArithmeticBin()
5155 bool r1 = e1->checkArithmetic();
5156 bool r2 = e2->checkArithmetic();
5157 return (r1 || r2);
5160 /********************** BinAssignExp **************************************/
5162 BinAssignExp::BinAssignExp(Loc loc, TOK op, int size, Expression *e1, Expression *e2)
5163 : BinExp(loc, op, size, e1, e2)
5167 bool BinAssignExp::isLvalue()
5169 return true;
5172 Expression *BinAssignExp::toLvalue(Scope *, Expression *)
5174 // Lvalue-ness will be handled in glue layer.
5175 return this;
5178 Expression *BinAssignExp::modifiableLvalue(Scope *sc, Expression *)
5180 // should check e1->checkModifiable() ?
5181 return toLvalue(sc, this);
5184 /************************************************************/
5186 CompileExp::CompileExp(Loc loc, Expression *e)
5187 : UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
5191 /************************************************************/
5193 ImportExp::ImportExp(Loc loc, Expression *e)
5194 : UnaExp(loc, TOKimport, sizeof(ImportExp), e)
5198 /************************************************************/
5200 AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg)
5201 : UnaExp(loc, TOKassert, sizeof(AssertExp), e)
5203 this->msg = msg;
5206 Expression *AssertExp::syntaxCopy()
5208 return new AssertExp(loc, e1->syntaxCopy(), msg ? msg->syntaxCopy() : NULL);
5211 /************************************************************/
5213 DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident)
5214 : UnaExp(loc, TOKdotid, sizeof(DotIdExp), e)
5216 this->ident = ident;
5217 this->wantsym = false;
5218 this->noderef = false;
5221 DotIdExp *DotIdExp::create(Loc loc, Expression *e, Identifier *ident)
5223 return new DotIdExp(loc, e, ident);
5226 /********************** DotTemplateExp ***********************************/
5228 // Mainly just a placeholder
5230 DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td)
5231 : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e)
5234 this->td = td;
5237 /************************************************************/
5239 DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *var, bool hasOverloads)
5240 : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e)
5242 //printf("DotVarExp()\n");
5243 this->var = var;
5244 this->hasOverloads = var->isVarDeclaration() ? false : hasOverloads;
5247 bool DotVarExp::isLvalue()
5249 return true;
5252 Expression *DotVarExp::toLvalue(Scope *, Expression *)
5254 //printf("DotVarExp::toLvalue(%s)\n", toChars());
5255 return this;
5258 /***********************************************
5259 * Mark variable v as modified if it is inside a constructor that var
5260 * is a field in.
5262 int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1)
5264 //printf("modifyFieldVar(var = %s)\n", var->toChars());
5265 Dsymbol *s = sc->func;
5266 while (1)
5268 FuncDeclaration *fd = NULL;
5269 if (s)
5270 fd = s->isFuncDeclaration();
5271 if (fd &&
5272 ((fd->isCtorDeclaration() && var->isField()) ||
5273 (fd->isStaticCtorDeclaration() && !var->isField())) &&
5274 fd->toParent2() == var->toParent2() &&
5275 (!e1 || e1->op == TOKthis)
5278 bool result = true;
5280 var->ctorinit = true;
5281 //printf("setting ctorinit\n");
5283 if (var->isField() && sc->fieldinit && !sc->intypeof)
5285 assert(e1);
5286 bool mustInit = ((var->storage_class & STCnodefaultctor) != 0 ||
5287 var->type->needsNested());
5289 size_t dim = sc->fieldinit_dim;
5290 AggregateDeclaration *ad = fd->isMember2();
5291 assert(ad);
5292 size_t i;
5293 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ?
5295 if (ad->fields[i] == var)
5296 break;
5298 assert(i < dim);
5299 unsigned fi = sc->fieldinit[i];
5301 if (fi & CSXthis_ctor)
5303 if (var->type->isMutable() && e1->type->isMutable())
5304 result = false;
5305 else
5307 const char *modStr = !var->type->isMutable() ? MODtoChars(var->type->mod) : MODtoChars(e1->type->mod);
5308 ::error(loc, "%s field '%s' initialized multiple times", modStr, var->toChars());
5311 else if (sc->noctor || (fi & CSXlabel))
5313 if (!mustInit && var->type->isMutable() && e1->type->isMutable())
5314 result = false;
5315 else
5317 const char *modStr = !var->type->isMutable() ? MODtoChars(var->type->mod) : MODtoChars(e1->type->mod);
5318 ::error(loc, "%s field '%s' initialization is not allowed in loops or after labels", modStr, var->toChars());
5321 sc->fieldinit[i] |= CSXthis_ctor;
5322 if (var->overlapped) // Bugzilla 15258
5324 for (size_t j = 0; j < ad->fields.dim; j++)
5326 VarDeclaration *v = ad->fields[j];
5327 if (v == var || !var->isOverlappedWith(v))
5328 continue;
5329 v->ctorinit = true;
5330 sc->fieldinit[j] = CSXthis_ctor;
5334 else if (fd != sc->func)
5336 if (var->type->isMutable())
5337 result = false;
5338 else if (sc->func->fes)
5340 const char *p = var->isField() ? "field" : var->kind();
5341 ::error(loc, "%s %s '%s' initialization is not allowed in foreach loop",
5342 MODtoChars(var->type->mod), p, var->toChars());
5344 else
5346 const char *p = var->isField() ? "field" : var->kind();
5347 ::error(loc, "%s %s '%s' initialization is not allowed in nested function '%s'",
5348 MODtoChars(var->type->mod), p, var->toChars(), sc->func->toChars());
5351 return result;
5353 else
5355 if (s)
5357 s = s->toParent2();
5358 continue;
5361 break;
5363 return false;
5366 int DotVarExp::checkModifiable(Scope *sc, int flag)
5368 //printf("DotVarExp::checkModifiable %s %s\n", toChars(), type->toChars());
5369 if (checkUnsafeAccess(sc, this, false, !flag))
5370 return 2;
5372 if (e1->op == TOKthis)
5373 return var->checkModify(loc, sc, type, e1, flag);
5375 //printf("\te1 = %s\n", e1->toChars());
5376 return e1->checkModifiable(sc, flag);
5379 Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
5381 return Expression::modifiableLvalue(sc, e);
5384 /************************************************************/
5386 /* Things like:
5387 * foo.bar!(args)
5390 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, Identifier *name, Objects *tiargs)
5391 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e)
5393 //printf("DotTemplateInstanceExp()\n");
5394 this->ti = new TemplateInstance(loc, name);
5395 this->ti->tiargs = tiargs;
5398 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti)
5399 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e)
5401 this->ti = ti;
5404 Expression *DotTemplateInstanceExp::syntaxCopy()
5406 return new DotTemplateInstanceExp(loc,
5407 e1->syntaxCopy(),
5408 ti->name,
5409 TemplateInstance::arraySyntaxCopy(ti->tiargs));
5412 bool DotTemplateInstanceExp::findTempDecl(Scope *sc)
5414 if (ti->tempdecl)
5415 return true;
5417 Expression *e = new DotIdExp(loc, e1, ti->name);
5418 e = semantic(e, sc);
5419 if (e->op == TOKdot)
5420 e = ((DotExp *)e)->e2;
5422 Dsymbol *s = NULL;
5423 switch (e->op)
5425 case TOKoverloadset: s = ((OverExp *)e)->vars; break;
5426 case TOKdottd: s = ((DotTemplateExp *)e)->td; break;
5427 case TOKscope: s = ((ScopeExp *)e)->sds; break;
5428 case TOKdotvar: s = ((DotVarExp *)e)->var; break;
5429 case TOKvar: s = ((VarExp *)e)->var; break;
5430 default: return false;
5432 return ti->updateTempDecl(sc, s);
5435 /************************************************************/
5437 DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f, bool hasOverloads)
5438 : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
5440 this->func = f;
5441 this->hasOverloads = hasOverloads;
5444 /************************************************************/
5446 DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s)
5447 : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e)
5449 this->sym = s;
5450 this->type = NULL;
5453 /************************************************************/
5455 CallExp::CallExp(Loc loc, Expression *e, Expressions *exps)
5456 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5458 this->arguments = exps;
5459 this->f = NULL;
5460 this->directcall = false;
5463 CallExp::CallExp(Loc loc, Expression *e)
5464 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5466 this->arguments = NULL;
5467 this->f = NULL;
5468 this->directcall = false;
5471 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1)
5472 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5474 Expressions *arguments = new Expressions();
5475 if (earg1)
5477 arguments->setDim(1);
5478 (*arguments)[0] = earg1;
5480 this->arguments = arguments;
5481 this->f = NULL;
5482 this->directcall = false;
5485 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2)
5486 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5488 Expressions *arguments = new Expressions();
5489 arguments->setDim(2);
5490 (*arguments)[0] = earg1;
5491 (*arguments)[1] = earg2;
5493 this->arguments = arguments;
5494 this->f = NULL;
5495 this->directcall = false;
5498 CallExp *CallExp::create(Loc loc, Expression *e, Expressions *exps)
5500 return new CallExp(loc, e, exps);
5503 CallExp *CallExp::create(Loc loc, Expression *e)
5505 return new CallExp(loc, e);
5508 CallExp *CallExp::create(Loc loc, Expression *e, Expression *earg1)
5510 return new CallExp(loc, e, earg1);
5513 Expression *CallExp::syntaxCopy()
5515 return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
5518 bool CallExp::isLvalue()
5520 Type *tb = e1->type->toBasetype();
5521 if (tb->ty == Tdelegate || tb->ty == Tpointer)
5522 tb = tb->nextOf();
5523 if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref)
5525 if (e1->op == TOKdotvar)
5526 if (((DotVarExp *)e1)->var->isCtorDeclaration())
5527 return false;
5528 return true; // function returns a reference
5530 return false;
5533 Expression *CallExp::toLvalue(Scope *sc, Expression *e)
5535 if (isLvalue())
5536 return this;
5537 return Expression::toLvalue(sc, e);
5540 Expression *CallExp::addDtorHook(Scope *sc)
5542 /* Only need to add dtor hook if it's a type that needs destruction.
5543 * Use same logic as VarDeclaration::callScopeDtor()
5546 if (e1->type && e1->type->ty == Tfunction)
5548 TypeFunction *tf = (TypeFunction *)e1->type;
5549 if (tf->isref)
5550 return this;
5553 Type *tv = type->baseElemOf();
5554 if (tv->ty == Tstruct)
5556 TypeStruct *ts = (TypeStruct *)tv;
5557 StructDeclaration *sd = ts->sym;
5558 if (sd->dtor)
5560 /* Type needs destruction, so declare a tmp
5561 * which the back end will recognize and call dtor on
5563 VarDeclaration *tmp = copyToTemp(0, "__tmpfordtor", this);
5564 DeclarationExp *de = new DeclarationExp(loc, tmp);
5565 VarExp *ve = new VarExp(loc, tmp);
5566 Expression *e = new CommaExp(loc, de, ve);
5567 e = semantic(e, sc);
5568 return e;
5571 return this;
5574 FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL)
5576 if (e->op == TOKaddress)
5578 Expression *ae1 = ((AddrExp *)e)->e1;
5579 if (ae1->op == TOKvar)
5581 VarExp *ve = (VarExp *)ae1;
5582 if (hasOverloads)
5583 *hasOverloads = ve->hasOverloads;
5584 return ve->var->isFuncDeclaration();
5586 if (ae1->op == TOKdotvar)
5588 DotVarExp *dve = (DotVarExp *)ae1;
5589 if (hasOverloads)
5590 *hasOverloads = dve->hasOverloads;
5591 return dve->var->isFuncDeclaration();
5594 else
5596 if (e->op == TOKsymoff)
5598 SymOffExp *soe = (SymOffExp *)e;
5599 if (hasOverloads)
5600 *hasOverloads = soe->hasOverloads;
5601 return soe->var->isFuncDeclaration();
5603 if (e->op == TOKdelegate)
5605 DelegateExp *dge = (DelegateExp *)e;
5606 if (hasOverloads)
5607 *hasOverloads = dge->hasOverloads;
5608 return dge->func->isFuncDeclaration();
5611 return NULL;
5614 /************************************************************/
5616 AddrExp::AddrExp(Loc loc, Expression *e)
5617 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e)
5621 AddrExp::AddrExp(Loc loc, Expression *e, Type *t)
5622 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e)
5624 type = t;
5627 /************************************************************/
5629 PtrExp::PtrExp(Loc loc, Expression *e)
5630 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
5632 // if (e->type)
5633 // type = ((TypePointer *)e->type)->next;
5636 PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
5637 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
5639 type = t;
5642 bool PtrExp::isLvalue()
5644 return true;
5647 Expression *PtrExp::toLvalue(Scope *, Expression *)
5649 return this;
5652 int PtrExp::checkModifiable(Scope *sc, int flag)
5654 if (e1->op == TOKsymoff)
5655 { SymOffExp *se = (SymOffExp *)e1;
5656 return se->var->checkModify(loc, sc, type, NULL, flag);
5658 else if (e1->op == TOKaddress)
5660 AddrExp *ae = (AddrExp *)e1;
5661 return ae->e1->checkModifiable(sc, flag);
5663 return 1;
5666 Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e)
5668 //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
5669 return Expression::modifiableLvalue(sc, e);
5672 /************************************************************/
5674 NegExp::NegExp(Loc loc, Expression *e)
5675 : UnaExp(loc, TOKneg, sizeof(NegExp), e)
5679 /************************************************************/
5681 UAddExp::UAddExp(Loc loc, Expression *e)
5682 : UnaExp(loc, TOKuadd, sizeof(UAddExp), e)
5686 /************************************************************/
5688 ComExp::ComExp(Loc loc, Expression *e)
5689 : UnaExp(loc, TOKtilde, sizeof(ComExp), e)
5693 /************************************************************/
5695 NotExp::NotExp(Loc loc, Expression *e)
5696 : UnaExp(loc, TOKnot, sizeof(NotExp), e)
5700 /************************************************************/
5702 DeleteExp::DeleteExp(Loc loc, Expression *e, bool isRAII)
5703 : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e)
5705 this->isRAII = isRAII;
5708 Expression *DeleteExp::toBoolean(Scope *)
5710 error("delete does not give a boolean result");
5711 return new ErrorExp();
5714 /************************************************************/
5716 CastExp::CastExp(Loc loc, Expression *e, Type *t)
5717 : UnaExp(loc, TOKcast, sizeof(CastExp), e)
5719 this->to = t;
5720 this->mod = (unsigned char)~0;
5723 /* For cast(const) and cast(immutable)
5725 CastExp::CastExp(Loc loc, Expression *e, unsigned char mod)
5726 : UnaExp(loc, TOKcast, sizeof(CastExp), e)
5728 this->to = NULL;
5729 this->mod = mod;
5732 Expression *CastExp::syntaxCopy()
5734 return to ? new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy())
5735 : new CastExp(loc, e1->syntaxCopy(), mod);
5738 /************************************************************/
5740 VectorExp::VectorExp(Loc loc, Expression *e, Type *t)
5741 : UnaExp(loc, TOKvector, sizeof(VectorExp), e)
5743 assert(t->ty == Tvector);
5744 to = (TypeVector *)t;
5745 dim = ~0;
5748 VectorExp *VectorExp::create(Loc loc, Expression *e, Type *t)
5750 return new VectorExp(loc, e, t);
5753 Expression *VectorExp::syntaxCopy()
5755 return new VectorExp(loc, e1->syntaxCopy(), to->syntaxCopy());
5758 /************************************************************/
5760 SliceExp::SliceExp(Loc loc, Expression *e1, IntervalExp *ie)
5761 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1)
5763 this->upr = ie ? ie->upr : NULL;
5764 this->lwr = ie ? ie->lwr : NULL;
5765 lengthVar = NULL;
5766 upperIsInBounds = false;
5767 lowerIsLessThanUpper = false;
5768 arrayop = false;
5771 SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr)
5772 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1)
5774 this->upr = upr;
5775 this->lwr = lwr;
5776 lengthVar = NULL;
5777 upperIsInBounds = false;
5778 lowerIsLessThanUpper = false;
5779 arrayop = false;
5782 Expression *SliceExp::syntaxCopy()
5784 SliceExp *se = new SliceExp(loc, e1->syntaxCopy(),
5785 lwr ? lwr->syntaxCopy() : NULL,
5786 upr ? upr->syntaxCopy() : NULL);
5787 se->lengthVar = this->lengthVar; // bug7871
5788 return se;
5791 int SliceExp::checkModifiable(Scope *sc, int flag)
5793 //printf("SliceExp::checkModifiable %s\n", toChars());
5794 if (e1->type->ty == Tsarray ||
5795 (e1->op == TOKindex && e1->type->ty != Tarray) ||
5796 e1->op == TOKslice)
5798 return e1->checkModifiable(sc, flag);
5800 return 1;
5803 bool SliceExp::isLvalue()
5805 /* slice expression is rvalue in default, but
5806 * conversion to reference of static array is only allowed.
5808 return (type && type->toBasetype()->ty == Tsarray);
5811 Expression *SliceExp::toLvalue(Scope *sc, Expression *e)
5813 //printf("SliceExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL);
5814 return (type && type->toBasetype()->ty == Tsarray)
5815 ? this : Expression::toLvalue(sc, e);
5818 Expression *SliceExp::modifiableLvalue(Scope *, Expression *)
5820 error("slice expression %s is not a modifiable lvalue", toChars());
5821 return this;
5824 bool SliceExp::isBool(bool result)
5826 return e1->isBool(result);
5829 /********************** ArrayLength **************************************/
5831 ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1)
5832 : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1)
5836 Expression *opAssignToOp(Loc loc, TOK op, Expression *e1, Expression *e2)
5837 { Expression *e;
5839 switch (op)
5841 case TOKaddass: e = new AddExp(loc, e1, e2); break;
5842 case TOKminass: e = new MinExp(loc, e1, e2); break;
5843 case TOKmulass: e = new MulExp(loc, e1, e2); break;
5844 case TOKdivass: e = new DivExp(loc, e1, e2); break;
5845 case TOKmodass: e = new ModExp(loc, e1, e2); break;
5846 case TOKandass: e = new AndExp(loc, e1, e2); break;
5847 case TOKorass: e = new OrExp (loc, e1, e2); break;
5848 case TOKxorass: e = new XorExp(loc, e1, e2); break;
5849 case TOKshlass: e = new ShlExp(loc, e1, e2); break;
5850 case TOKshrass: e = new ShrExp(loc, e1, e2); break;
5851 case TOKushrass: e = new UshrExp(loc, e1, e2); break;
5852 default: assert(0);
5854 return e;
5857 /*********************
5858 * Rewrite:
5859 * array.length op= e2
5860 * as:
5861 * array.length = array.length op e2
5862 * or:
5863 * auto tmp = &array;
5864 * (*tmp).length = (*tmp).length op e2
5867 Expression *ArrayLengthExp::rewriteOpAssign(BinExp *exp)
5869 Expression *e;
5871 assert(exp->e1->op == TOKarraylength);
5872 ArrayLengthExp *ale = (ArrayLengthExp *)exp->e1;
5873 if (ale->e1->op == TOKvar)
5875 e = opAssignToOp(exp->loc, exp->op, ale, exp->e2);
5876 e = new AssignExp(exp->loc, ale->syntaxCopy(), e);
5878 else
5880 /* auto tmp = &array;
5881 * (*tmp).length = (*tmp).length op e2
5883 VarDeclaration *tmp = copyToTemp(0, "__arraylength", new AddrExp(ale->loc, ale->e1));
5885 Expression *e1 = new ArrayLengthExp(ale->loc, new PtrExp(ale->loc, new VarExp(ale->loc, tmp)));
5886 Expression *elvalue = e1->syntaxCopy();
5887 e = opAssignToOp(exp->loc, exp->op, e1, exp->e2);
5888 e = new AssignExp(exp->loc, elvalue, e);
5889 e = new CommaExp(exp->loc, new DeclarationExp(ale->loc, tmp), e);
5891 return e;
5894 /*********************** IntervalExp ********************************/
5896 // Mainly just a placeholder
5898 IntervalExp::IntervalExp(Loc loc, Expression *lwr, Expression *upr)
5899 : Expression(loc, TOKinterval, sizeof(IntervalExp))
5901 this->lwr = lwr;
5902 this->upr = upr;
5905 Expression *IntervalExp::syntaxCopy()
5907 return new IntervalExp(loc, lwr->syntaxCopy(), upr->syntaxCopy());
5910 /********************** DelegatePtrExp **************************************/
5912 DelegatePtrExp::DelegatePtrExp(Loc loc, Expression *e1)
5913 : UnaExp(loc, TOKdelegateptr, sizeof(DelegatePtrExp), e1)
5917 bool DelegatePtrExp::isLvalue()
5919 return e1->isLvalue();
5922 Expression *DelegatePtrExp::toLvalue(Scope *sc, Expression *e)
5924 e1 = e1->toLvalue(sc, e);
5925 return this;
5928 Expression *DelegatePtrExp::modifiableLvalue(Scope *sc, Expression *e)
5930 if (sc->func->setUnsafe())
5932 error("cannot modify delegate pointer in @safe code %s", toChars());
5933 return new ErrorExp();
5935 return Expression::modifiableLvalue(sc, e);
5938 /********************** DelegateFuncptrExp **************************************/
5940 DelegateFuncptrExp::DelegateFuncptrExp(Loc loc, Expression *e1)
5941 : UnaExp(loc, TOKdelegatefuncptr, sizeof(DelegateFuncptrExp), e1)
5945 bool DelegateFuncptrExp::isLvalue()
5947 return e1->isLvalue();
5950 Expression *DelegateFuncptrExp::toLvalue(Scope *sc, Expression *e)
5952 e1 = e1->toLvalue(sc, e);
5953 return this;
5956 Expression *DelegateFuncptrExp::modifiableLvalue(Scope *sc, Expression *e)
5958 if (sc->func->setUnsafe())
5960 error("cannot modify delegate function pointer in @safe code %s", toChars());
5961 return new ErrorExp();
5963 return Expression::modifiableLvalue(sc, e);
5966 /*********************** ArrayExp *************************************/
5968 // e1 [ i1, i2, i3, ... ]
5970 ArrayExp::ArrayExp(Loc loc, Expression *e1, Expression *index)
5971 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1)
5973 arguments = new Expressions();
5974 if (index)
5975 arguments->push(index);
5976 lengthVar = NULL;
5977 currentDimension = 0;
5980 ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args)
5981 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1)
5983 arguments = args;
5984 lengthVar = NULL;
5985 currentDimension = 0;
5988 Expression *ArrayExp::syntaxCopy()
5990 ArrayExp *ae = new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
5991 ae->lengthVar = this->lengthVar; // bug7871
5992 return ae;
5995 bool ArrayExp::isLvalue()
5997 if (type && type->toBasetype()->ty == Tvoid)
5998 return false;
5999 return true;
6002 Expression *ArrayExp::toLvalue(Scope *, Expression *)
6004 if (type && type->toBasetype()->ty == Tvoid)
6005 error("voids have no value");
6006 return this;
6009 /************************* DotExp ***********************************/
6011 DotExp::DotExp(Loc loc, Expression *e1, Expression *e2)
6012 : BinExp(loc, TOKdot, sizeof(DotExp), e1, e2)
6016 /************************* CommaExp ***********************************/
6018 CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2, bool generated)
6019 : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2)
6021 isGenerated = generated;
6022 allowCommaExp = generated;
6025 bool CommaExp::isLvalue()
6027 return e2->isLvalue();
6030 Expression *CommaExp::toLvalue(Scope *sc, Expression *)
6032 e2 = e2->toLvalue(sc, NULL);
6033 return this;
6036 int CommaExp::checkModifiable(Scope *sc, int flag)
6038 return e2->checkModifiable(sc, flag);
6041 Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e)
6043 e2 = e2->modifiableLvalue(sc, e);
6044 return this;
6047 bool CommaExp::isBool(bool result)
6049 return e2->isBool(result);
6052 Expression *CommaExp::toBoolean(Scope *sc)
6054 Expression *ex2 = e2->toBoolean(sc);
6055 if (ex2->op == TOKerror)
6056 return ex2;
6057 e2 = ex2;
6058 type = e2->type;
6059 return this;
6062 Expression *CommaExp::addDtorHook(Scope *sc)
6064 e2 = e2->addDtorHook(sc);
6065 return this;
6068 /************************** IndexExp **********************************/
6070 // e1 [ e2 ]
6072 IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2)
6073 : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2)
6075 //printf("IndexExp::IndexExp('%s')\n", toChars());
6076 lengthVar = NULL;
6077 modifiable = false; // assume it is an rvalue
6078 indexIsInBounds = false;
6081 Expression *IndexExp::syntaxCopy()
6083 IndexExp *ie = new IndexExp(loc, e1->syntaxCopy(), e2->syntaxCopy());
6084 ie->lengthVar = this->lengthVar; // bug7871
6085 return ie;
6088 bool IndexExp::isLvalue()
6090 return true;
6093 Expression *IndexExp::toLvalue(Scope *, Expression *)
6095 return this;
6098 int IndexExp::checkModifiable(Scope *sc, int flag)
6100 if (e1->type->ty == Tsarray ||
6101 e1->type->ty == Taarray ||
6102 (e1->op == TOKindex && e1->type->ty != Tarray) ||
6103 e1->op == TOKslice)
6105 return e1->checkModifiable(sc, flag);
6107 return 1;
6110 Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
6112 //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
6113 Expression *ex = markSettingAAElem();
6114 if (ex->op == TOKerror)
6115 return ex;
6117 return Expression::modifiableLvalue(sc, e);
6120 Expression *IndexExp::markSettingAAElem()
6122 if (e1->type->toBasetype()->ty == Taarray)
6124 Type *t2b = e2->type->toBasetype();
6125 if (t2b->ty == Tarray && t2b->nextOf()->isMutable())
6127 error("associative arrays can only be assigned values with immutable keys, not %s", e2->type->toChars());
6128 return new ErrorExp();
6130 modifiable = true;
6132 if (e1->op == TOKindex)
6134 Expression *ex = ((IndexExp *)e1)->markSettingAAElem();
6135 if (ex->op == TOKerror)
6136 return ex;
6137 assert(ex == e1);
6140 return this;
6143 /************************* PostExp ***********************************/
6145 PostExp::PostExp(TOK op, Loc loc, Expression *e)
6146 : BinExp(loc, op, sizeof(PostExp), e,
6147 new IntegerExp(loc, 1, Type::tint32))
6151 /************************* PreExp ***********************************/
6153 PreExp::PreExp(TOK op, Loc loc, Expression *e)
6154 : UnaExp(loc, op, sizeof(PreExp), e)
6158 /************************************************************/
6160 /* op can be TOKassign, TOKconstruct, or TOKblit */
6162 AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2)
6163 : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2)
6165 memset = 0;
6168 bool AssignExp::isLvalue()
6170 // Array-op 'x[] = y[]' should make an rvalue.
6171 // Setting array length 'x.length = v' should make an rvalue.
6172 if (e1->op == TOKslice ||
6173 e1->op == TOKarraylength)
6175 return false;
6177 return true;
6180 Expression *AssignExp::toLvalue(Scope *sc, Expression *ex)
6182 if (e1->op == TOKslice ||
6183 e1->op == TOKarraylength)
6185 return Expression::toLvalue(sc, ex);
6188 /* In front-end level, AssignExp should make an lvalue of e1.
6189 * Taking the address of e1 will be handled in low level layer,
6190 * so this function does nothing.
6192 return this;
6195 Expression *AssignExp::toBoolean(Scope *)
6197 // Things like:
6198 // if (a = b) ...
6199 // are usually mistakes.
6201 error("assignment cannot be used as a condition, perhaps == was meant?");
6202 return new ErrorExp();
6205 /************************************************************/
6207 ConstructExp::ConstructExp(Loc loc, Expression *e1, Expression *e2)
6208 : AssignExp(loc, e1, e2)
6210 op = TOKconstruct;
6213 ConstructExp::ConstructExp(Loc loc, VarDeclaration *v, Expression *e2)
6214 : AssignExp(loc, new VarExp(loc, v), e2)
6216 assert(v->type && e1->type);
6217 op = TOKconstruct;
6219 if (v->storage_class & (STCref | STCout))
6220 memset |= referenceInit;
6223 /************************************************************/
6225 BlitExp::BlitExp(Loc loc, Expression *e1, Expression *e2)
6226 : AssignExp(loc, e1, e2)
6228 op = TOKblit;
6231 BlitExp::BlitExp(Loc loc, VarDeclaration *v, Expression *e2)
6232 : AssignExp(loc, new VarExp(loc, v), e2)
6234 assert(v->type && e1->type);
6235 op = TOKblit;
6237 if (v->storage_class & (STCref | STCout))
6238 memset |= referenceInit;
6241 /************************************************************/
6243 AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
6244 : BinAssignExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
6248 /************************************************************/
6250 MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
6251 : BinAssignExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
6255 /************************************************************/
6257 CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
6258 : BinAssignExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
6262 /************************************************************/
6264 MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
6265 : BinAssignExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
6269 /************************************************************/
6271 DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
6272 : BinAssignExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
6276 /************************************************************/
6278 ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
6279 : BinAssignExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
6283 /************************************************************/
6285 ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
6286 : BinAssignExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
6290 /************************************************************/
6292 ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
6293 : BinAssignExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
6297 /************************************************************/
6299 UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
6300 : BinAssignExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
6304 /************************************************************/
6306 AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
6307 : BinAssignExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
6311 /************************************************************/
6313 OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
6314 : BinAssignExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
6318 /************************************************************/
6320 XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
6321 : BinAssignExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
6325 /***************** PowAssignExp *******************************************/
6327 PowAssignExp::PowAssignExp(Loc loc, Expression *e1, Expression *e2)
6328 : BinAssignExp(loc, TOKpowass, sizeof(PowAssignExp), e1, e2)
6332 /************************* AddExp *****************************/
6334 AddExp::AddExp(Loc loc, Expression *e1, Expression *e2)
6335 : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2)
6339 /************************************************************/
6341 MinExp::MinExp(Loc loc, Expression *e1, Expression *e2)
6342 : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2)
6346 /************************* CatExp *****************************/
6348 CatExp::CatExp(Loc loc, Expression *e1, Expression *e2)
6349 : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2)
6353 /************************************************************/
6355 MulExp::MulExp(Loc loc, Expression *e1, Expression *e2)
6356 : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2)
6360 /************************************************************/
6362 DivExp::DivExp(Loc loc, Expression *e1, Expression *e2)
6363 : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2)
6367 /************************************************************/
6369 ModExp::ModExp(Loc loc, Expression *e1, Expression *e2)
6370 : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2)
6374 /************************************************************/
6376 PowExp::PowExp(Loc loc, Expression *e1, Expression *e2)
6377 : BinExp(loc, TOKpow, sizeof(PowExp), e1, e2)
6381 /************************************************************/
6383 ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2)
6384 : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2)
6388 /************************************************************/
6390 ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2)
6391 : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2)
6395 /************************************************************/
6397 UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2)
6398 : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2)
6402 /************************************************************/
6404 AndExp::AndExp(Loc loc, Expression *e1, Expression *e2)
6405 : BinExp(loc, TOKand, sizeof(AndExp), e1, e2)
6409 /************************************************************/
6411 OrExp::OrExp(Loc loc, Expression *e1, Expression *e2)
6412 : BinExp(loc, TOKor, sizeof(OrExp), e1, e2)
6416 /************************************************************/
6418 XorExp::XorExp(Loc loc, Expression *e1, Expression *e2)
6419 : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2)
6423 /************************************************************/
6425 OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2)
6426 : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2)
6430 Expression *OrOrExp::toBoolean(Scope *sc)
6432 Expression *ex2 = e2->toBoolean(sc);
6433 if (ex2->op == TOKerror)
6434 return ex2;
6435 e2 = ex2;
6436 return this;
6439 /************************************************************/
6441 AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2)
6442 : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2)
6446 Expression *AndAndExp::toBoolean(Scope *sc)
6448 Expression *ex2 = e2->toBoolean(sc);
6449 if (ex2->op == TOKerror)
6450 return ex2;
6451 e2 = ex2;
6452 return this;
6455 /************************************************************/
6457 InExp::InExp(Loc loc, Expression *e1, Expression *e2)
6458 : BinExp(loc, TOKin, sizeof(InExp), e1, e2)
6462 /************************************************************/
6464 /* This deletes the key e1 from the associative array e2
6467 RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2)
6468 : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2)
6470 type = Type::tbool;
6473 /************************************************************/
6475 CmpExp::CmpExp(TOK op, Loc loc, Expression *e1, Expression *e2)
6476 : BinExp(loc, op, sizeof(CmpExp), e1, e2)
6480 /************************************************************/
6482 EqualExp::EqualExp(TOK op, Loc loc, Expression *e1, Expression *e2)
6483 : BinExp(loc, op, sizeof(EqualExp), e1, e2)
6485 assert(op == TOKequal || op == TOKnotequal);
6488 /************************************************************/
6490 IdentityExp::IdentityExp(TOK op, Loc loc, Expression *e1, Expression *e2)
6491 : BinExp(loc, op, sizeof(IdentityExp), e1, e2)
6495 /****************************************************************/
6497 CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2)
6498 : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2)
6500 this->econd = econd;
6503 Expression *CondExp::syntaxCopy()
6505 return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy());
6508 void CondExp::hookDtors(Scope *sc)
6510 class DtorVisitor : public StoppableVisitor
6512 public:
6513 Scope *sc;
6514 CondExp *ce;
6515 VarDeclaration *vcond;
6516 bool isThen;
6518 DtorVisitor(Scope *sc, CondExp *ce)
6520 this->sc = sc;
6521 this->ce = ce;
6522 this->vcond = NULL;
6525 void visit(Expression *)
6527 //printf("(e = %s)\n", e->toChars());
6530 void visit(DeclarationExp *e)
6532 VarDeclaration *v = e->declaration->isVarDeclaration();
6533 if (v && !v->isDataseg())
6535 if (v->_init)
6537 ExpInitializer *ei = v->_init->isExpInitializer();
6538 if (ei)
6539 ei->exp->accept(this);
6542 if (v->needsScopeDtor())
6544 if (!vcond)
6546 vcond = copyToTemp(STCvolatile, "__cond", ce->econd);
6547 vcond->semantic(sc);
6549 Expression *de = new DeclarationExp(ce->econd->loc, vcond);
6550 de = semantic(de, sc);
6552 Expression *ve = new VarExp(ce->econd->loc, vcond);
6553 ce->econd = Expression::combine(de, ve);
6556 //printf("\t++v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
6557 Expression *ve = new VarExp(vcond->loc, vcond);
6558 if (isThen)
6559 v->edtor = new AndAndExp(v->edtor->loc, ve, v->edtor);
6560 else
6561 v->edtor = new OrOrExp(v->edtor->loc, ve, v->edtor);
6562 v->edtor = semantic(v->edtor, sc);
6563 //printf("\t--v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
6569 DtorVisitor v(sc, this);
6570 //printf("+%s\n", toChars());
6571 v.isThen = true; walkPostorder(e1, &v);
6572 v.isThen = false; walkPostorder(e2, &v);
6573 //printf("-%s\n", toChars());
6576 bool CondExp::isLvalue()
6578 return e1->isLvalue() && e2->isLvalue();
6582 Expression *CondExp::toLvalue(Scope *sc, Expression *)
6584 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
6585 CondExp *e = (CondExp *)copy();
6586 e->e1 = e1->toLvalue(sc, NULL)->addressOf();
6587 e->e2 = e2->toLvalue(sc, NULL)->addressOf();
6588 e->type = type->pointerTo();
6589 return new PtrExp(loc, e, type);
6592 int CondExp::checkModifiable(Scope *sc, int flag)
6594 return e1->checkModifiable(sc, flag) && e2->checkModifiable(sc, flag);
6597 Expression *CondExp::modifiableLvalue(Scope *sc, Expression *)
6599 //error("conditional expression %s is not a modifiable lvalue", toChars());
6600 e1 = e1->modifiableLvalue(sc, e1);
6601 e2 = e2->modifiableLvalue(sc, e2);
6602 return toLvalue(sc, this);
6605 Expression *CondExp::toBoolean(Scope *sc)
6607 Expression *ex1 = e1->toBoolean(sc);
6608 Expression *ex2 = e2->toBoolean(sc);
6609 if (ex1->op == TOKerror)
6610 return ex1;
6611 if (ex2->op == TOKerror)
6612 return ex2;
6613 e1 = ex1;
6614 e2 = ex2;
6615 return this;
6618 /****************************************************************/
6620 DefaultInitExp::DefaultInitExp(Loc loc, TOK subop, int size)
6621 : Expression(loc, TOKdefault, size)
6623 this->subop = subop;
6626 /****************************************************************/
6628 FileInitExp::FileInitExp(Loc loc, TOK tok)
6629 : DefaultInitExp(loc, tok, sizeof(FileInitExp))
6633 Expression *FileInitExp::resolveLoc(Loc loc, Scope *sc)
6635 //printf("FileInitExp::resolve() %s\n", toChars());
6636 const char *s = loc.filename ? loc.filename : sc->_module->ident->toChars();
6637 if (subop == TOKfilefullpath)
6638 s = FileName::combine(sc->_module->srcfilePath, s);
6639 Expression *e = new StringExp(loc, const_cast<char *>(s));
6640 e = semantic(e, sc);
6641 e = e->castTo(sc, type);
6642 return e;
6645 /****************************************************************/
6647 LineInitExp::LineInitExp(Loc loc)
6648 : DefaultInitExp(loc, TOKline, sizeof(LineInitExp))
6652 Expression *LineInitExp::resolveLoc(Loc loc, Scope *sc)
6654 Expression *e = new IntegerExp(loc, loc.linnum, Type::tint32);
6655 e = e->castTo(sc, type);
6656 return e;
6659 /****************************************************************/
6661 ModuleInitExp::ModuleInitExp(Loc loc)
6662 : DefaultInitExp(loc, TOKmodulestring, sizeof(ModuleInitExp))
6666 Expression *ModuleInitExp::resolveLoc(Loc loc, Scope *sc)
6668 const char *s;
6669 if (sc->callsc)
6670 s = sc->callsc->_module->toPrettyChars();
6671 else
6672 s = sc->_module->toPrettyChars();
6673 Expression *e = new StringExp(loc, const_cast<char *>(s));
6674 e = semantic(e, sc);
6675 e = e->castTo(sc, type);
6676 return e;
6679 /****************************************************************/
6681 FuncInitExp::FuncInitExp(Loc loc)
6682 : DefaultInitExp(loc, TOKfuncstring, sizeof(FuncInitExp))
6686 Expression *FuncInitExp::resolveLoc(Loc loc, Scope *sc)
6688 const char *s;
6689 if (sc->callsc && sc->callsc->func)
6690 s = sc->callsc->func->Dsymbol::toPrettyChars();
6691 else if (sc->func)
6692 s = sc->func->Dsymbol::toPrettyChars();
6693 else
6694 s = "";
6695 Expression *e = new StringExp(loc, const_cast<char *>(s));
6696 e = semantic(e, sc);
6697 e = e->castTo(sc, type);
6698 return e;
6701 /****************************************************************/
6703 PrettyFuncInitExp::PrettyFuncInitExp(Loc loc)
6704 : DefaultInitExp(loc, TOKprettyfunc, sizeof(PrettyFuncInitExp))
6708 Expression *PrettyFuncInitExp::resolveLoc(Loc loc, Scope *sc)
6710 FuncDeclaration *fd;
6711 if (sc->callsc && sc->callsc->func)
6712 fd = sc->callsc->func;
6713 else
6714 fd = sc->func;
6716 const char *s;
6717 if (fd)
6719 const char *funcStr = fd->Dsymbol::toPrettyChars();
6720 OutBuffer buf;
6721 functionToBufferWithIdent((TypeFunction *)fd->type, &buf, funcStr);
6722 s = buf.extractString();
6724 else
6726 s = "";
6729 Expression *e = new StringExp(loc, const_cast<char *>(s));
6730 e = semantic(e, sc);
6731 e = e->castTo(sc, type);
6732 return e;
6735 /****************************************************************/
6737 Expression *extractOpDollarSideEffect(Scope *sc, UnaExp *ue)
6739 Expression *e0;
6740 Expression *e1 = Expression::extractLast(ue->e1, &e0);
6741 // Bugzilla 12585: Extract the side effect part if ue->e1 is comma.
6743 if (!isTrivialExp(e1))
6745 /* Even if opDollar is needed, 'e1' should be evaluate only once. So
6746 * Rewrite:
6747 * e1.opIndex( ... use of $ ... )
6748 * e1.opSlice( ... use of $ ... )
6749 * as:
6750 * (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
6751 * (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
6753 e1 = extractSideEffect(sc, "__dop", &e0, e1, false);
6754 assert(e1->op == TOKvar);
6755 VarExp *ve = (VarExp *)e1;
6756 ve->var->storage_class |= STCexptemp; // lifetime limited to expression
6758 ue->e1 = e1;
6759 return e0;
6762 /**************************************
6763 * Runs semantic on ae->arguments. Declares temporary variables
6764 * if '$' was used.
6766 Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0)
6768 assert(!ae->lengthVar);
6770 *pe0 = NULL;
6772 AggregateDeclaration *ad = isAggregate(ae->e1->type);
6773 Dsymbol *slice = search_function(ad, Id::slice);
6774 //printf("slice = %s %s\n", slice->kind(), slice->toChars());
6776 for (size_t i = 0; i < ae->arguments->dim; i++)
6778 if (i == 0)
6779 *pe0 = extractOpDollarSideEffect(sc, ae);
6781 Expression *e = (*ae->arguments)[i];
6782 if (e->op == TOKinterval && !(slice && slice->isTemplateDeclaration()))
6784 Lfallback:
6785 if (ae->arguments->dim == 1)
6786 return NULL;
6787 ae->error("multi-dimensional slicing requires template opSlice");
6788 return new ErrorExp();
6790 //printf("[%d] e = %s\n", i, e->toChars());
6792 // Create scope for '$' variable for this dimension
6793 ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae);
6794 sym->loc = ae->loc;
6795 sym->parent = sc->scopesym;
6796 sc = sc->push(sym);
6797 ae->lengthVar = NULL; // Create it only if required
6798 ae->currentDimension = i; // Dimension for $, if required
6800 e = semantic(e, sc);
6801 e = resolveProperties(sc, e);
6803 if (ae->lengthVar && sc->func)
6805 // If $ was used, declare it now
6806 Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
6807 de = semantic(de, sc);
6808 *pe0 = Expression::combine(*pe0, de);
6810 sc = sc->pop();
6812 if (e->op == TOKinterval)
6814 IntervalExp *ie = (IntervalExp *)e;
6816 Objects *tiargs = new Objects();
6817 Expression *edim = new IntegerExp(ae->loc, i, Type::tsize_t);
6818 edim = semantic(edim, sc);
6819 tiargs->push(edim);
6821 Expressions *fargs = new Expressions();
6822 fargs->push(ie->lwr);
6823 fargs->push(ie->upr);
6825 unsigned xerrors = global.startGagging();
6826 sc = sc->push();
6827 FuncDeclaration *fslice = resolveFuncCall(ae->loc, sc, slice, tiargs, ae->e1->type, fargs, 1);
6828 sc = sc->pop();
6829 global.endGagging(xerrors);
6830 if (!fslice)
6831 goto Lfallback;
6833 e = new DotTemplateInstanceExp(ae->loc, ae->e1, slice->ident, tiargs);
6834 e = new CallExp(ae->loc, e, fargs);
6835 e = semantic(e, sc);
6838 if (!e->type)
6840 ae->error("%s has no value", e->toChars());
6841 e = new ErrorExp();
6843 if (e->op == TOKerror)
6844 return e;
6846 (*ae->arguments)[i] = e;
6849 return ae;
6852 /**************************************
6853 * Runs semantic on se->lwr and se->upr. Declares a temporary variable
6854 * if '$' was used.
6856 Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, IntervalExp *ie, Expression **pe0)
6858 //assert(!ae->lengthVar);
6859 if (!ie)
6860 return ae;
6862 VarDeclaration *lengthVar = ae->lengthVar;
6864 // create scope for '$'
6865 ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae);
6866 sym->loc = ae->loc;
6867 sym->parent = sc->scopesym;
6868 sc = sc->push(sym);
6870 for (size_t i = 0; i < 2; ++i)
6872 Expression *e = i == 0 ? ie->lwr : ie->upr;
6873 e = semantic(e, sc);
6874 e = resolveProperties(sc, e);
6875 if (!e->type)
6877 ae->error("%s has no value", e->toChars());
6878 return new ErrorExp();
6880 (i == 0 ? ie->lwr : ie->upr) = e;
6883 if (lengthVar != ae->lengthVar && sc->func)
6885 // If $ was used, declare it now
6886 Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
6887 de = semantic(de, sc);
6888 *pe0 = Expression::combine(*pe0, de);
6890 sc = sc->pop();
6892 return ae;
6895 Expression *BinExp::reorderSettingAAElem(Scope *sc)
6897 BinExp *be = this;
6899 if (be->e1->op != TOKindex)
6900 return be;
6901 IndexExp *ie = (IndexExp *)be->e1;
6902 if (ie->e1->type->toBasetype()->ty != Taarray)
6903 return be;
6905 /* Fix evaluation order of setting AA element. (Bugzilla 3825)
6906 * Rewrite:
6907 * aa[k1][k2][k3] op= val;
6908 * as:
6909 * auto ref __aatmp = aa;
6910 * auto ref __aakey3 = k1, __aakey2 = k2, __aakey1 = k3;
6911 * auto ref __aaval = val;
6912 * __aatmp[__aakey3][__aakey2][__aakey1] op= __aaval; // assignment
6915 Expression *e0 = NULL;
6916 while (1)
6918 Expression *de = NULL;
6919 ie->e2 = extractSideEffect(sc, "__aakey", &de, ie->e2);
6920 e0 = Expression::combine(de, e0);
6922 Expression *ie1 = ie->e1;
6923 if (ie1->op != TOKindex ||
6924 ((IndexExp *)ie1)->e1->type->toBasetype()->ty != Taarray)
6926 break;
6928 ie = (IndexExp *)ie1;
6930 assert(ie->e1->type->toBasetype()->ty == Taarray);
6932 Expression *de = NULL;
6933 ie->e1 = extractSideEffect(sc, "__aatmp", &de, ie->e1);
6934 e0 = Expression::combine(de, e0);
6936 be->e2 = extractSideEffect(sc, "__aaval", &e0, be->e2, true);
6938 //printf("-e0 = %s, be = %s\n", e0->toChars(), be->toChars());
6939 return Expression::combine(e0, be);