1
2 /* Compiler implementation of the D programming language
3 * Copyright (C) 1999-2019 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 */
10
11 #include "root/dsystem.h"
12 #include "root/rmem.h"
13 #include "root/root.h"
14
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"
38
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);
55
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
64 */
65
66 Expression *getRightThis(Loc loc, Scope *sc, AggregateDeclaration *ad,
67 Expression *e1, Declaration *var, int flag = 0)
68 {
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());
73
74 /* If e1 is not the 'this' pointer for ad
75 */
76 if (ad &&
77 !(t->ty == Tpointer && t->nextOf()->ty == Tstruct &&
78 ((TypeStruct *)t->nextOf())->sym == ad)
79 &&
80 !(t->ty == Tstruct &&
81 ((TypeStruct *)t)->sym == ad)
82 )
83 {
84 ClassDeclaration *cd = ad->isClassDeclaration();
85 ClassDeclaration *tcd = t->isClassHandle();
86
87 /* e1 is the right this if ad is a base class of e1
88 */
89 if (!cd || !tcd ||
90 !(tcd == cd || cd->isBaseOf(tcd, NULL))
91 )
92 {
93 /* Only classes can be inner classes with an 'outer'
94 * member pointing to the enclosing class instance
95 */
96 if (tcd && tcd->isNested())
97 {
98 /* e1 is the 'this' pointer for an inner class: tcd.
99 * Rewrite it as the 'this' pointer for the outer class.
100 */
101
102 e1 = new DotVarExp(loc, e1, tcd->vthis);
103 e1->type = tcd->vthis->type;
104 e1->type = e1->type->addMod(t->mod);
105 // Do not call checkNestedRef()
106 //e1 = semantic(e1, sc);
107
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())
115 {
116 FuncDeclaration *f = s->isFuncDeclaration();
117 if (f->vthis)
118 {
119 //printf("rewriting e1 to %s's this\n", f->toChars());
120 n++;
121 e1 = new VarExp(loc, f->vthis);
122 }
123 else
124 {
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;
130 }
131 }
132 if (s && s->isClassDeclaration())
133 {
134 e1->type = s->isClassDeclaration()->type;
135 e1->type = e1->type->addMod(t->mod);
136 if (n > 1)
137 e1 = semantic(e1, sc);
138 }
139 else
140 e1 = semantic(e1, sc);
141 goto L1;
142 }
143
144 /* Can't find a path from e1 to ad
145 */
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();
151 }
152 }
153 return e1;
154 }
155
156 /*****************************************
157 * Determine if 'this' is available.
158 * If it is, return the FuncDeclaration that has it.
159 */
160
hasThis(Scope * sc)161 FuncDeclaration *hasThis(Scope *sc)
162 {
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() : "");
169
170 // Go upwards until we find the enclosing member function
171 FuncDeclaration *fd = fdthis;
172 while (1)
173 {
174 if (!fd)
175 {
176 goto Lno;
177 }
178 if (!fd->isNested())
179 break;
180
181 Dsymbol *parent = fd->parent;
182 while (1)
183 {
184 if (!parent)
185 goto Lno;
186 TemplateInstance *ti = parent->isTemplateInstance();
187 if (ti)
188 parent = ti->parent;
189 else
190 break;
191 }
192 fd = parent->isFuncDeclaration();
193 }
194
195 if (!fd->isThis())
196 { //printf("test '%s'\n", fd->toChars());
197 goto Lno;
198 }
199
200 assert(fd->vthis);
201 return fd;
202
203 Lno:
204 return NULL; // don't have 'this' available
205 }
206
isNeedThisScope(Scope * sc,Declaration * d)207 bool isNeedThisScope(Scope *sc, Declaration *d)
208 {
209 if (sc->intypeof == 1)
210 return false;
211
212 AggregateDeclaration *ad = d->isThis();
213 if (!ad)
214 return false;
215 //printf("d = %s, ad = %s\n", d->toChars(), ad->toChars());
216
217 for (Dsymbol *s = sc->parent; s; s = s->toParent2())
218 {
219 //printf("\ts = %s %s, toParent2() = %p\n", s->kind(), s->toChars(), s->toParent2());
220 if (AggregateDeclaration *ad2 = s->isAggregateDeclaration())
221 {
222 if (ad2 == ad)
223 return false;
224 else if (ad2->isNested())
225 continue;
226 else
227 return true;
228 }
229 if (FuncDeclaration *f = s->isFuncDeclaration())
230 {
231 if (f->isMember2())
232 break;
233 }
234 }
235 return true;
236 }
237
238 /***************************************
239 * Pull out any properties.
240 */
241
242 Expression *resolvePropertiesX(Scope *sc, Expression *e1, Expression *e2 = NULL)
243 {
244 //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token::toChars(e1->op), e1->toChars(), e2 ? e2->toChars() : NULL);
245 Loc loc = e1->loc;
246
247 OverloadSet *os;
248 Dsymbol *s;
249 Objects *tiargs;
250 Type *tthis;
251 if (e1->op == TOKdot)
252 {
253 DotExp *de = (DotExp *)e1;
254 if (de->e2->op == TOKoverloadset)
255 {
256 tiargs = NULL;
257 tthis = de->e1->type;
258 os = ((OverExp *)de->e2)->vars;
259 goto Los;
260 }
261 }
262 else if (e1->op == TOKoverloadset)
263 {
264 tiargs = NULL;
265 tthis = NULL;
266 os = ((OverExp *)e1)->vars;
267 Los:
268 assert(os);
269 FuncDeclaration *fd = NULL;
270 if (e2)
271 {
272 e2 = semantic(e2, sc);
273 if (e2->op == TOKerror)
274 return new ErrorExp();
275 e2 = resolveProperties(sc, e2);
276
277 Expressions a;
278 a.push(e2);
279
280 for (size_t i = 0; i < os->a.dim; i++)
281 {
282 FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, &a, 1);
283 if (f)
284 {
285 if (f->errors)
286 return new ErrorExp();
287 fd = f;
288 assert(fd->type->ty == Tfunction);
289 }
290 }
291 if (fd)
292 {
293 Expression *e = new CallExp(loc, e1, e2);
294 return semantic(e, sc);
295 }
296 }
297 {
298 for (size_t i = 0; i < os->a.dim; i++)
299 {
300 FuncDeclaration *f = resolveFuncCall(loc, sc, os->a[i], tiargs, tthis, NULL, 1);
301 if (f)
302 {
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;
310 }
311 }
312 if (fd)
313 {
314 Expression *e = new CallExp(loc, e1);
315 if (e2)
316 e = new AssignExp(loc, e, e2);
317 return semantic(e, sc);
318 }
319 }
320 if (e2)
321 goto Leprop;
322 }
323 else if (e1->op == TOKdotti)
324 {
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;
336 }
337 else if (e1->op == TOKdottd)
338 {
339 DotTemplateExp *dte = (DotTemplateExp *)e1;
340 s = dte->td;
341 tiargs = NULL;
342 tthis = dte->e1->type;
343 goto Lfd;
344 }
345 else if (e1->op == TOKscope)
346 {
347 s = ((ScopeExp *)e1)->sds;
348 TemplateInstance *ti = s->isTemplateInstance();
349 if (ti && !ti->semanticRun && ti->tempdecl)
350 {
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;
360 }
361 }
362 else if (e1->op == TOKtemplate)
363 {
364 s = ((TemplateExp *)e1)->td;
365 tiargs = NULL;
366 tthis = NULL;
367 goto Lfd;
368 }
369 else if (e1->op == TOKdotvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
370 {
371 DotVarExp *dve = (DotVarExp *)e1;
372 s = dve->var->isFuncDeclaration();
373 tiargs = NULL;
374 tthis = dve->e1->type;
375 goto Lfd;
376 }
377 else if (e1->op == TOKvar && e1->type && e1->type->toBasetype()->ty == Tfunction)
378 {
379 s = ((VarExp *)e1)->var->isFuncDeclaration();
380 tiargs = NULL;
381 tthis = NULL;
382 Lfd:
383 assert(s);
384 if (e2)
385 {
386 e2 = semantic(e2, sc);
387 if (e2->op == TOKerror)
388 return new ErrorExp();
389 e2 = resolveProperties(sc, e2);
390
391 Expressions a;
392 a.push(e2);
393
394 FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, 1);
395 if (fd && fd->type)
396 {
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);
402 }
403 }
404 {
405 FuncDeclaration *fd = resolveFuncCall(loc, sc, s, tiargs, tthis, NULL, 1);
406 if (fd && fd->type)
407 {
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)
413 {
414 Expression *e = new CallExp(loc, e1);
415 if (e2)
416 e = new AssignExp(loc, e, e2);
417 return semantic(e, sc);
418 }
419 }
420 }
421 if (FuncDeclaration *fd = s->isFuncDeclaration())
422 {
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);
427 }
428 if (e2)
429 goto Leprop;
430 }
431 if (e1->op == TOKvar)
432 {
433 VarExp *ve = (VarExp *)e1;
434 VarDeclaration *v = ve->var->isVarDeclaration();
435 if (v && ve->checkPurity(sc, v))
436 return new ErrorExp();
437 }
438 if (e2)
439 return NULL;
440
441 if (e1->type &&
442 e1->op != TOKtype) // function type is not a property
443 {
444 /* Look for e1 being a lazy parameter; rewrite as delegate call
445 */
446 if (e1->op == TOKvar)
447 {
448 VarExp *ve = (VarExp *)e1;
449
450 if (ve->var->storage_class & STClazy)
451 {
452 Expression *e = new CallExp(loc, e1);
453 return semantic(e, sc);
454 }
455 }
456 else if (e1->op == TOKdotvar)
457 {
458 // Check for reading overlapped pointer field in @safe code.
459 if (checkUnsafeAccess(sc, e1, true, true))
460 return new ErrorExp();
461 }
462 else if (e1->op == TOKdot)
463 {
464 e1->error("expression has no value");
465 return new ErrorExp();
466 }
467 else if (e1->op == TOKcall)
468 {
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();
473 }
474 }
475
476 if (!e1->type)
477 {
478 error(loc, "cannot resolve type for %s", e1->toChars());
479 e1 = new ErrorExp();
480 }
481 return e1;
482
483 Leprop:
484 error(loc, "not a property %s", e1->toChars());
485 return new ErrorExp();
486
487 Leproplvalue:
488 error(loc, "%s is not an lvalue", e1->toChars());
489 return new ErrorExp();
490 }
491
resolveProperties(Scope * sc,Expression * e)492 Expression *resolveProperties(Scope *sc, Expression *e)
493 {
494 //printf("resolveProperties(%s)\n", e->toChars());
495
496 e = resolvePropertiesX(sc, e);
497 if (e->checkRightThis(sc))
498 return new ErrorExp();
499 return e;
500 }
501
502 /******************************
503 * Check the tail CallExp is really property function call.
504 */
checkPropertyCall(Expression * e)505 static bool checkPropertyCall(Expression *e)
506 {
507 while (e->op == TOKcomma)
508 e = ((CommaExp *)e)->e2;
509
510 if (e->op == TOKcall)
511 {
512 CallExp *ce = (CallExp *)e;
513 TypeFunction *tf;
514 if (ce->f)
515 {
516 tf = (TypeFunction *)ce->f->type;
517 /* If a forward reference to ce->f, try to resolve it
518 */
519 if (!tf->deco && ce->f->semanticRun < PASSsemanticdone)
520 {
521 ce->f->semantic(NULL);
522 tf = (TypeFunction *)ce->f->type;
523 }
524 }
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);
533 }
534 return false;
535 }
536
537 /******************************
538 * If e1 is a property function (template), resolve it.
539 */
540
resolvePropertiesOnly(Scope * sc,Expression * e1)541 Expression *resolvePropertiesOnly(Scope *sc, Expression *e1)
542 {
543 //printf("e1 = %s %s\n", Token::toChars(e1->op), e1->toChars());
544 OverloadSet *os;
545 FuncDeclaration *fd;
546 TemplateDeclaration *td;
547
548 if (e1->op == TOKdot)
549 {
550 DotExp *de = (DotExp *)e1;
551 if (de->e2->op == TOKoverloadset)
552 {
553 os = ((OverExp *)de->e2)->vars;
554 goto Los;
555 }
556 }
557 else if (e1->op == TOKoverloadset)
558 {
559 os = ((OverExp *)e1)->vars;
560 Los:
561 assert(os);
562 for (size_t i = 0; i < os->a.dim; i++)
563 {
564 Dsymbol *s = os->a[i];
565 fd = s->isFuncDeclaration();
566 td = s->isTemplateDeclaration();
567 if (fd)
568 {
569 if (((TypeFunction *)fd->type)->isproperty)
570 return resolveProperties(sc, e1);
571 }
572 else if (td && td->onemember &&
573 (fd = td->onemember->isFuncDeclaration()) != NULL)
574 {
575 if (((TypeFunction *)fd->type)->isproperty ||
576 (fd->storage_class2 & STCproperty) ||
577 (td->_scope->stc & STCproperty))
578 {
579 return resolveProperties(sc, e1);
580 }
581 }
582 }
583 }
584 else if (e1->op == TOKdotti)
585 {
586 DotTemplateInstanceExp* dti = (DotTemplateInstanceExp *)e1;
587 if (dti->ti->tempdecl && (td = dti->ti->tempdecl->isTemplateDeclaration()) != NULL)
588 goto Ltd;
589 }
590 else if (e1->op == TOKdottd)
591 {
592 td = ((DotTemplateExp *)e1)->td;
593 goto Ltd;
594 }
595 else if (e1->op == TOKscope)
596 {
597 Dsymbol *s = ((ScopeExp *)e1)->sds;
598 TemplateInstance *ti = s->isTemplateInstance();
599 if (ti && !ti->semanticRun && ti->tempdecl)
600 {
601 if ((td = ti->tempdecl->isTemplateDeclaration()) != NULL)
602 goto Ltd;
603 }
604 }
605 else if (e1->op == TOKtemplate)
606 {
607 td = ((TemplateExp *)e1)->td;
608 Ltd:
609 assert(td);
610 if (td->onemember &&
611 (fd = td->onemember->isFuncDeclaration()) != NULL)
612 {
613 if (((TypeFunction *)fd->type)->isproperty ||
614 (fd->storage_class2 & STCproperty) ||
615 (td->_scope->stc & STCproperty))
616 {
617 return resolveProperties(sc, e1);
618 }
619 }
620 }
621 else if (e1->op == TOKdotvar && e1->type->ty == Tfunction)
622 {
623 DotVarExp *dve = (DotVarExp *)e1;
624 fd = dve->var->isFuncDeclaration();
625 goto Lfd;
626 }
627 else if (e1->op == TOKvar && e1->type->ty == Tfunction &&
628 (sc->intypeof || !((VarExp *)e1)->var->needThis()))
629 {
630 fd = ((VarExp *)e1)->var->isFuncDeclaration();
631 Lfd:
632 assert(fd);
633 if (((TypeFunction *)fd->type)->isproperty)
634 return resolveProperties(sc, e1);
635 }
636 return e1;
637 }
638
639
640 // TODO: merge with Scope::search::searchScopes()
searchScopes(Scope * sc,Loc loc,Identifier * ident,int flags)641 static Dsymbol *searchScopes(Scope *sc, Loc loc, Identifier *ident, int flags)
642 {
643 Dsymbol *s = NULL;
644 for (Scope *scx = sc; scx; scx = scx->enclosing)
645 {
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)
652 {
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())
658 {
659 if (ad->_import)
660 break;
661 }
662 // See only module scope symbols for UFCS target.
663 Dsymbol *p = s->toParent2();
664 if (p && p->isModule())
665 break;
666 }
667 s = NULL;
668
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;
672 }
673 return s;
674 }
675
676 /******************************
677 * Find symbol in accordance with the UFCS name look up rule
678 */
679
searchUFCS(Scope * sc,UnaExp * ue,Identifier * ident)680 Expression *searchUFCS(Scope *sc, UnaExp *ue, Identifier *ident)
681 {
682 //printf("searchUFCS(ident = %s)\n", ident->toChars());
683 Loc loc = ue->loc;
684 int flags = 0;
685 Dsymbol *s = NULL;
686
687 if (sc->flags & SCOPEignoresymbolvisibility)
688 flags |= IgnoreSymbolVisibility;
689
690 Dsymbol *sold = NULL;
691 if (global.params.bug10378 || global.params.check10378)
692 {
693 sold = searchScopes(sc, loc, ident, flags | IgnoreSymbolVisibility);
694 if (!global.params.check10378)
695 {
696 s = sold;
697 goto Lsearchdone;
698 }
699 }
700
701 // First look in local scopes
702 s = searchScopes(sc, loc, ident, flags | SearchLocalsOnly);
703 if (!s)
704 {
705 // Second look in imported modules
706 s = searchScopes(sc, loc, ident, flags | SearchImportsOnly);
707
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.
711 */
712 if (!s && !(flags & IgnoreSymbolVisibility))
713 {
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());
719 }
720 }
721 if (global.params.check10378)
722 {
723 Dsymbol *snew = s;
724 if (sold != snew)
725 Scope::deprecation10378(loc, sold, snew);
726 if (global.params.bug10378)
727 s = sold;
728 }
729 Lsearchdone:
730
731 if (!s)
732 return ue->e1->type->Type::getProperty(loc, ident, 0);
733
734 FuncDeclaration *f = s->isFuncDeclaration();
735 if (f)
736 {
737 TemplateDeclaration *td = getFuncTemplateDecl(f);
738 if (td)
739 {
740 if (td->overroot)
741 td = td->overroot;
742 s = td;
743 }
744 }
745
746 if (ue->op == TOKdotti)
747 {
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);
754 }
755 else
756 {
757 //printf("-searchUFCS() %s\n", s->toChars());
758 return new DsymbolExp(loc, s);
759 }
760 }
761
762 /******************************
763 * check e is exp.opDispatch!(tiargs) or not
764 * It's used to switch to UFCS the semantic analysis path
765 */
766
isDotOpDispatch(Expression * e)767 bool isDotOpDispatch(Expression *e)
768 {
769 return e->op == TOKdotti &&
770 ((DotTemplateInstanceExp *)e)->ti->name == Id::opDispatch;
771 }
772
773 /******************************
774 * Pull out callable entity with UFCS.
775 */
776
resolveUFCS(Scope * sc,CallExp * ce)777 Expression *resolveUFCS(Scope *sc, CallExp *ce)
778 {
779 Loc loc = ce->loc;
780 Expression *eleft;
781 Expression *e;
782
783 if (ce->e1->op == TOKdotid)
784 {
785 DotIdExp *die = (DotIdExp *)ce->e1;
786 Identifier *ident = die->ident;
787
788 Expression *ex = semanticX(die, sc);
789 if (ex != die)
790 {
791 ce->e1 = ex;
792 return NULL;
793 }
794 eleft = die->e1;
795
796 Type *t = eleft->type->toBasetype();
797 if (t->ty == Tarray || t->ty == Tsarray ||
798 t->ty == Tnull || (t->isTypeBasic() && t->ty != Tvoid))
799 {
800 /* Built-in types and arrays have no callable properties, so do shortcut.
801 * It is necessary in: e.init()
802 */
803 }
804 else if (t->ty == Taarray)
805 {
806 if (ident == Id::remove)
807 {
808 /* Transform:
809 * aa.remove(arg) into delete aa[arg]
810 */
811 if (!ce->arguments || ce->arguments->dim != 1)
812 {
813 ce->error("expected key as argument to aa.remove()");
814 return new ErrorExp();
815 }
816 if (!eleft->type->isMutable())
817 {
818 ce->error("cannot remove key from %s associative array %s",
819 MODtoChars(t->mod), eleft->toChars());
820 return new ErrorExp();
821 }
822 Expression *key = (*ce->arguments)[0];
823 key = semantic(key, sc);
824 key = resolveProperties(sc, key);
825
826 TypeAArray *taa = (TypeAArray *)t;
827 key = key->implicitCastTo(sc, taa->index);
828
829 if (key->checkValue())
830 return new ErrorExp();
831
832 semanticTypeInfo(sc, taa->index);
833
834 return new RemoveExp(loc, eleft, key);
835 }
836 }
837 else
838 {
839 if (Expression *ey = semanticY(die, sc, 1))
840 {
841 if (ey->op == TOKerror)
842 return ey;
843 ce->e1 = ey;
844 if (isDotOpDispatch(ey))
845 {
846 unsigned errors = global.startGagging();
847 e = semantic(ce->syntaxCopy(), sc);
848 if (!global.endGagging(errors))
849 return e;
850 /* fall down to UFCS */
851 }
852 else
853 return NULL;
854 }
855 }
856 e = searchUFCS(sc, die, ident);
857 }
858 else if (ce->e1->op == TOKdotti)
859 {
860 DotTemplateInstanceExp *dti = (DotTemplateInstanceExp *)ce->e1;
861 if (Expression *ey = semanticY(dti, sc, 1))
862 {
863 ce->e1 = ey;
864 return NULL;
865 }
866 eleft = dti->e1;
867 e = searchUFCS(sc, dti, dti->ti->name);
868 }
869 else
870 return NULL;
871
872 // Rewrite
873 ce->e1 = e;
874 if (!ce->arguments)
875 ce->arguments = new Expressions();
876 ce->arguments->shift(eleft);
877
878 return NULL;
879 }
880
881 /******************************
882 * Pull out property with UFCS.
883 */
884
885 Expression *resolveUFCSProperties(Scope *sc, Expression *e1, Expression *e2 = NULL)
886 {
887 Loc loc = e1->loc;
888 Expression *eleft;
889 Expression *e;
890
891 if (e1->op == TOKdotid)
892 {
893 DotIdExp *die = (DotIdExp *)e1;
894 eleft = die->e1;
895 e = searchUFCS(sc, die, die->ident);
896 }
897 else if (e1->op == TOKdotti)
898 {
899 DotTemplateInstanceExp *dti;
900 dti = (DotTemplateInstanceExp *)e1;
901 eleft = dti->e1;
902 e = searchUFCS(sc, dti, dti->ti->name);
903 }
904 else
905 return NULL;
906
907 if (e == NULL)
908 return NULL;
909
910 // Rewrite
911 if (e2)
912 {
913 // run semantic without gagging
914 e2 = semantic(e2, sc);
915
916 /* f(e1) = e2
917 */
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);
924
925 /* f(e1, e2)
926 */
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);
939 }
940 }
941 else
942 { // strict setter prints errors if fails
943 e = semantic(e, sc);
944 }
945 checkPropertyCall(e);
946 return e;
947 }
948 else
949 {
950 /* f(e1)
951 */
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);
959 }
960 }
961
962 /******************************
963 * Perform semantic() on an array of Expressions.
964 */
965
arrayExpressionSemantic(Expressions * exps,Scope * sc,bool preserveErrors)966 bool arrayExpressionSemantic(Expressions *exps, Scope *sc, bool preserveErrors)
967 {
968 bool err = false;
969 if (exps)
970 {
971 for (size_t i = 0; i < exps->dim; i++)
972 {
973 Expression *e = (*exps)[i];
974 if (e)
975 {
976 e = semantic(e, sc);
977 if (e->op == TOKerror)
978 err = true;
979 if (preserveErrors || e->op != TOKerror)
980 (*exps)[i] = e;
981 }
982 }
983 }
984 return err;
985 }
986
987 /****************************************
988 * Expand tuples.
989 * Input:
990 * exps aray of Expressions
991 * Output:
992 * exps rewritten in place
993 */
994
expandTuples(Expressions * exps)995 void expandTuples(Expressions *exps)
996 {
997 //printf("expandTuples()\n");
998 if (exps)
999 {
1000 for (size_t i = 0; i < exps->dim; i++)
1001 {
1002 Expression *arg = (*exps)[i];
1003 if (!arg)
1004 continue;
1005
1006 // Look for tuple with 0 members
1007 if (arg->op == TOKtype)
1008 {
1009 TypeExp *e = (TypeExp *)arg;
1010 if (e->type->toBasetype()->ty == Ttuple)
1011 {
1012 TypeTuple *tt = (TypeTuple *)e->type->toBasetype();
1013
1014 if (!tt->arguments || tt->arguments->dim == 0)
1015 {
1016 exps->remove(i);
1017 if (i == exps->dim)
1018 return;
1019 i--;
1020 continue;
1021 }
1022 }
1023 }
1024
1025 // Inline expand all the tuples
1026 while (arg->op == TOKtuple)
1027 {
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];
1035 }
1036 }
1037 }
1038 }
1039
1040 /****************************************
1041 * Expand alias this tuples.
1042 */
1043
isAliasThisTuple(Expression * e)1044 TupleDeclaration *isAliasThisTuple(Expression *e)
1045 {
1046 if (!e->type)
1047 return NULL;
1048
1049 Type *t = e->type->toBasetype();
1050 Lagain:
1051 if (Dsymbol *s = t->toDsymbol(NULL))
1052 {
1053 AggregateDeclaration *ad = s->isAggregateDeclaration();
1054 if (ad)
1055 {
1056 s = ad->aliasthis;
1057 if (s && s->isVarDeclaration())
1058 {
1059 TupleDeclaration *td = s->isVarDeclaration()->toAlias()->isTupleDeclaration();
1060 if (td && td->isexp)
1061 return td;
1062 }
1063 if (Type *att = t->aliasthisOf())
1064 {
1065 t = att;
1066 goto Lagain;
1067 }
1068 }
1069 }
1070 return NULL;
1071 }
1072
expandAliasThisTuples(Expressions * exps,size_t starti)1073 int expandAliasThisTuples(Expressions *exps, size_t starti)
1074 {
1075 if (!exps || exps->dim == 0)
1076 return -1;
1077
1078 for (size_t u = starti; u < exps->dim; u++)
1079 {
1080 Expression *exp = (*exps)[u];
1081 TupleDeclaration *td = isAliasThisTuple(exp);
1082 if (td)
1083 {
1084 exps->remove(u);
1085 for (size_t i = 0; i<td->objects->dim; ++i)
1086 {
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);
1097 }
1098 return (int)u;
1099 }
1100 }
1101
1102 return -1;
1103 }
1104
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
1112 */
1113
arrayExpressionToCommonType(Scope * sc,Expressions * exps,Type ** pt)1114 bool arrayExpressionToCommonType(Scope *sc, Expressions *exps, Type **pt)
1115 {
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.
1120 */
1121 //printf("arrayExpressionToCommonType()\n");
1122 IntegerExp integerexp(0);
1123 CondExp condexp(Loc(), &integerexp, NULL, NULL);
1124
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 bool foundType = false;
1129
1130 for (size_t i = 0; i < exps->dim; i++)
1131 {
1132 Expression *e = (*exps)[i];
1133 if (!e)
1134 continue;
1135
1136 e = resolveProperties(sc, e);
1137 if (!e->type)
1138 {
1139 e->error("%s has no value", e->toChars());
1140 t0 = Type::terror;
1141 continue;
1142 }
1143 if (e->op == TOKtype)
1144 {
1145 foundType = true; // do not break immediately, there might be more errors
1146 e->checkValue(); // report an error "type T has no value"
1147 t0 = Type::terror;
1148 continue;
1149 }
1150 if (e->type->ty == Tvoid)
1151 {
1152 // void expressions do not concur to the determination of the common
1153 // type.
1154 continue;
1155 }
1156 if (checkNonAssignmentArrayOp(e))
1157 {
1158 t0 = Type::terror;
1159 continue;
1160 }
1161
1162 e = doCopyOrMove(sc, e);
1163
1164 if (!foundType && t0 && !t0->equals(e->type))
1165 {
1166 /* This applies ?: to merge the types. It's backwards;
1167 * ?: should call this function to merge types.
1168 */
1169 condexp.type = NULL;
1170 condexp.e1 = e0;
1171 condexp.e2 = e;
1172 condexp.loc = e->loc;
1173 Expression *ex = semantic(&condexp, sc);
1174 if (ex->op == TOKerror)
1175 e = ex;
1176 else
1177 {
1178 (*exps)[j0] = condexp.e1;
1179 e = condexp.e2;
1180 }
1181 }
1182 j0 = i;
1183 e0 = e;
1184 t0 = e->type;
1185 if (e->op != TOKerror)
1186 (*exps)[i] = e;
1187 }
1188
1189 if (!t0)
1190 t0 = Type::tvoid; // [] is typed as void[]
1191 else if (t0->ty != Terror)
1192 {
1193 for (size_t i = 0; i < exps->dim; i++)
1194 {
1195 Expression *e = (*exps)[i];
1196 if (!e)
1197 continue;
1198
1199 e = e->implicitCastTo(sc, t0);
1200 //assert(e->op != TOKerror);
1201 if (e->op == TOKerror)
1202 {
1203 /* Bugzilla 13024: a workaround for the bug in typeMerge -
1204 * it should paint e1 and e2 by deduced common type,
1205 * but doesn't in this particular case.
1206 */
1207 t0 = Type::terror;
1208 break;
1209 }
1210 (*exps)[i] = e;
1211 }
1212 }
1213 if (pt)
1214 *pt = t0;
1215
1216 return (t0 == Type::terror);
1217 }
1218
1219 /****************************************
1220 * Get TemplateDeclaration enclosing FuncDeclaration.
1221 */
1222
getFuncTemplateDecl(Dsymbol * s)1223 TemplateDeclaration *getFuncTemplateDecl(Dsymbol *s)
1224 {
1225 FuncDeclaration *f = s->isFuncDeclaration();
1226 if (f && f->parent)
1227 {
1228 TemplateInstance *ti = f->parent->isTemplateInstance();
1229 if (ti && !ti->isTemplateMixin() &&
1230 ti->tempdecl && ((TemplateDeclaration *)ti->tempdecl)->onemember &&
1231 ti->tempdecl->ident == f->ident)
1232 {
1233 return (TemplateDeclaration *)ti->tempdecl;
1234 }
1235 }
1236 return NULL;
1237 }
1238
1239 /************************************************
1240 * If we want the value of this expression, but do not want to call
1241 * the destructor on it.
1242 */
1243
valueNoDtor(Expression * e)1244 Expression *valueNoDtor(Expression *e)
1245 {
1246 if (e->op == TOKcall)
1247 {
1248 /* The struct value returned from the function is transferred
1249 * so do not call the destructor on it.
1250 * Recognize:
1251 * ((S _ctmp = S.init), _ctmp).this(...)
1252 * and make sure the destructor is not called on _ctmp
1253 * BUG: if e is a CommaExp, we should go down the right side.
1254 */
1255 CallExp *ce = (CallExp *)e;
1256 if (ce->e1->op == TOKdotvar)
1257 {
1258 DotVarExp *dve = (DotVarExp *)ce->e1;
1259 if (dve->var->isCtorDeclaration())
1260 {
1261 // It's a constructor call
1262 if (dve->e1->op == TOKcomma)
1263 {
1264 CommaExp *comma = (CommaExp *)dve->e1;
1265 if (comma->e2->op == TOKvar)
1266 {
1267 VarExp *ve = (VarExp *)comma->e2;
1268 VarDeclaration *ctmp = ve->var->isVarDeclaration();
1269 if (ctmp)
1270 {
1271 ctmp->storage_class |= STCnodtor;
1272 assert(!ce->isLvalue());
1273 }
1274 }
1275 }
1276 }
1277 }
1278 }
1279 else if (e->op == TOKvar)
1280 {
1281 VarDeclaration *vtmp = ((VarExp *)e)->var->isVarDeclaration();
1282 if (vtmp && vtmp->storage_class & STCrvalue)
1283 {
1284 vtmp->storage_class |= STCnodtor;
1285 }
1286 }
1287 return e;
1288 }
1289
1290 /********************************************
1291 * Issue an error if default construction is disabled for type t.
1292 * Default construction is required for arrays and 'out' parameters.
1293 * Returns:
1294 * true an error was issued
1295 */
checkDefCtor(Loc loc,Type * t)1296 bool checkDefCtor(Loc loc, Type *t)
1297 {
1298 t = t->baseElemOf();
1299 if (t->ty == Tstruct)
1300 {
1301 StructDeclaration *sd = ((TypeStruct *)t)->sym;
1302 if (sd->noDefaultCtor)
1303 {
1304 sd->error(loc, "default construction is disabled");
1305 return true;
1306 }
1307 }
1308 return false;
1309 }
1310
1311 /*********************************************
1312 * If e is an instance of a struct, and that struct has a copy constructor,
1313 * rewrite e as:
1314 * (tmp = e),tmp
1315 * Input:
1316 * sc just used to specify the scope of created temporary variable
1317 */
callCpCtor(Scope * sc,Expression * e)1318 Expression *callCpCtor(Scope *sc, Expression *e)
1319 {
1320 Type *tv = e->type->baseElemOf();
1321 if (tv->ty == Tstruct)
1322 {
1323 StructDeclaration *sd = ((TypeStruct *)tv)->sym;
1324 if (sd->postblit)
1325 {
1326 /* Create a variable tmp, and replace the argument e with:
1327 * (tmp = e),tmp
1328 * and let AssignExp() handle the construction.
1329 * This is not the most efficent, ideally tmp would be constructed
1330 * directly onto the stack.
1331 */
1332 VarDeclaration *tmp = copyToTemp(STCrvalue, "__copytmp", e);
1333 tmp->storage_class |= STCnodtor;
1334 tmp->semantic(sc);
1335 Expression *de = new DeclarationExp(e->loc, tmp);
1336 Expression *ve = new VarExp(e->loc, tmp);
1337 de->type = Type::tvoid;
1338 ve->type = e->type;
1339 e = Expression::combine(de, ve);
1340 }
1341 }
1342 return e;
1343 }
1344
1345 /************************************************
1346 * Handle the postblit call on lvalue, or the move of rvalue.
1347 */
doCopyOrMove(Scope * sc,Expression * e)1348 Expression *doCopyOrMove(Scope *sc, Expression *e)
1349 {
1350 if (e->op == TOKquestion)
1351 {
1352 CondExp *ce = (CondExp *)e;
1353 ce->e1 = doCopyOrMove(sc, ce->e1);
1354 ce->e2 = doCopyOrMove(sc, ce->e2);
1355 }
1356 else
1357 {
1358 e = e->isLvalue() ? callCpCtor(sc, e) : valueNoDtor(e);
1359 }
1360 return e;
1361 }
1362
1363 /****************************************
1364 * Now that we know the exact type of the function we're calling,
1365 * the arguments[] need to be adjusted:
1366 * 1. implicitly convert argument to the corresponding parameter type
1367 * 2. add default arguments for any missing arguments
1368 * 3. do default promotions on arguments corresponding to ...
1369 * 4. add hidden _arguments[] argument
1370 * 5. call copy constructor for struct value arguments
1371 * Input:
1372 * tf type of the function
1373 * fd the function being called, NULL if called indirectly
1374 * Output:
1375 * *prettype return type of function
1376 * *peprefix expression to execute before arguments[] are evaluated, NULL if none
1377 * Returns:
1378 * true errors happened
1379 */
1380
functionParameters(Loc loc,Scope * sc,TypeFunction * tf,Type * tthis,Expressions * arguments,FuncDeclaration * fd,Type ** prettype,Expression ** peprefix)1381 bool functionParameters(Loc loc, Scope *sc, TypeFunction *tf,
1382 Type *tthis, Expressions *arguments, FuncDeclaration *fd, Type **prettype, Expression **peprefix)
1383 {
1384 //printf("functionParameters()\n");
1385 assert(arguments);
1386 assert(fd || tf->next);
1387 size_t nargs = arguments ? arguments->dim : 0;
1388 size_t nparams = Parameter::dim(tf->parameters);
1389 unsigned olderrors = global.errors;
1390 bool err = false;
1391 *prettype = Type::terror;
1392 Expression *eprefix = NULL;
1393 *peprefix = NULL;
1394
1395 if (nargs > nparams && tf->varargs == 0)
1396 {
1397 error(loc, "expected %llu arguments, not %llu for non-variadic function type %s", (ulonglong)nparams, (ulonglong)nargs, tf->toChars());
1398 return true;
1399 }
1400
1401 // If inferring return type, and semantic3() needs to be run if not already run
1402 if (!tf->next && fd->inferRetType)
1403 {
1404 fd->functionSemantic();
1405 }
1406 else if (fd && fd->parent)
1407 {
1408 TemplateInstance *ti = fd->parent->isTemplateInstance();
1409 if (ti && ti->tempdecl)
1410 {
1411 fd->functionSemantic3();
1412 }
1413 }
1414 bool isCtorCall = fd && fd->needThis() && fd->isCtorDeclaration();
1415
1416 size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
1417
1418 /* If the function return type has wildcards in it, we'll need to figure out the actual type
1419 * based on the actual argument types.
1420 */
1421 MOD wildmatch = 0;
1422 if (tthis && tf->isWild() && !isCtorCall)
1423 {
1424 Type *t = tthis;
1425 if (t->isImmutable())
1426 wildmatch = MODimmutable;
1427 else if (t->isWildConst())
1428 wildmatch = MODwildconst;
1429 else if (t->isWild())
1430 wildmatch = MODwild;
1431 else if (t->isConst())
1432 wildmatch = MODconst;
1433 else
1434 wildmatch = MODmutable;
1435 }
1436
1437 int done = 0;
1438 for (size_t i = 0; i < n; i++)
1439 {
1440 Expression *arg;
1441
1442 if (i < nargs)
1443 arg = (*arguments)[i];
1444 else
1445 arg = NULL;
1446
1447 if (i < nparams)
1448 {
1449 Parameter *p = Parameter::getNth(tf->parameters, i);
1450
1451 if (!arg)
1452 {
1453 if (!p->defaultArg)
1454 {
1455 if (tf->varargs == 2 && i + 1 == nparams)
1456 goto L2;
1457 error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
1458 return true;
1459 }
1460 arg = p->defaultArg;
1461 arg = inlineCopy(arg, sc);
1462 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
1463 arg = arg->resolveLoc(loc, sc);
1464 arguments->push(arg);
1465 nargs++;
1466 }
1467
1468 if (tf->varargs == 2 && i + 1 == nparams)
1469 {
1470 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
1471 {
1472 MATCH m;
1473 if ((m = arg->implicitConvTo(p->type)) > MATCHnomatch)
1474 {
1475 if (p->type->nextOf() && arg->implicitConvTo(p->type->nextOf()) >= m)
1476 goto L2;
1477 else if (nargs != nparams)
1478 { error(loc, "expected %llu function arguments, not %llu", (ulonglong)nparams, (ulonglong)nargs);
1479 return true;
1480 }
1481 goto L1;
1482 }
1483 }
1484 L2:
1485 Type *tb = p->type->toBasetype();
1486 Type *tret = p->isLazyArray();
1487 switch (tb->ty)
1488 {
1489 case Tsarray:
1490 case Tarray:
1491 {
1492 /* Create a static array variable v of type arg->type:
1493 * T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
1494 *
1495 * The array literal in the initializer of the hidden variable
1496 * is now optimized. See Bugzilla 2356.
1497 */
1498 Type *tbn = ((TypeArray *)tb)->next;
1499
1500 Expressions *elements = new Expressions();
1501 elements->setDim(nargs - i);
1502 for (size_t u = 0; u < elements->dim; u++)
1503 {
1504 Expression *a = (*arguments)[i + u];
1505 if (tret && a->implicitConvTo(tret))
1506 {
1507 a = a->implicitCastTo(sc, tret);
1508 a = a->optimize(WANTvalue);
1509 a = toDelegate(a, a->type, sc);
1510 }
1511 else
1512 a = a->implicitCastTo(sc, tbn);
1513 (*elements)[u] = a;
1514 }
1515 // Bugzilla 14395: Convert to a static array literal, or its slice.
1516 arg = new ArrayLiteralExp(loc, tbn->sarrayOf(nargs - i), elements);
1517 if (tb->ty == Tarray)
1518 {
1519 arg = new SliceExp(loc, arg, NULL, NULL);
1520 arg->type = p->type;
1521 }
1522 break;
1523 }
1524 case Tclass:
1525 {
1526 /* Set arg to be:
1527 * new Tclass(arg0, arg1, ..., argn)
1528 */
1529 Expressions *args = new Expressions();
1530 args->setDim(nargs - i);
1531 for (size_t u = i; u < nargs; u++)
1532 (*args)[u - i] = (*arguments)[u];
1533 arg = new NewExp(loc, NULL, NULL, p->type, args);
1534 break;
1535 }
1536 default:
1537 if (!arg)
1538 {
1539 error(loc, "not enough arguments");
1540 return true;
1541 }
1542 break;
1543 }
1544 arg = semantic(arg, sc);
1545 //printf("\targ = '%s'\n", arg->toChars());
1546 arguments->setDim(i + 1);
1547 (*arguments)[i] = arg;
1548 nargs = i + 1;
1549 done = 1;
1550 }
1551
1552 L1:
1553 if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
1554 {
1555 bool isRef = (p->storageClass & (STCref | STCout)) != 0;
1556 if (unsigned char wm = arg->type->deduceWild(p->type, isRef))
1557 {
1558 if (wildmatch)
1559 wildmatch = MODmerge(wildmatch, wm);
1560 else
1561 wildmatch = wm;
1562 //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p->type->toChars(), arg->type->toChars(), wm, wildmatch);
1563 }
1564 }
1565 }
1566 if (done)
1567 break;
1568 }
1569 if ((wildmatch == MODmutable || wildmatch == MODimmutable) &&
1570 tf->next->hasWild() &&
1571 (tf->isref || !tf->next->implicitConvTo(tf->next->immutableOf())))
1572 {
1573 if (fd)
1574 {
1575 /* If the called function may return the reference to
1576 * outer inout data, it should be rejected.
1577 *
1578 * void foo(ref inout(int) x) {
1579 * ref inout(int) bar(inout(int)) { return x; }
1580 * struct S { ref inout(int) bar() inout { return x; } }
1581 * bar(int.init) = 1; // bad!
1582 * S().bar() = 1; // bad!
1583 * }
1584 */
1585 Dsymbol *s = NULL;
1586 if (fd->isThis() || fd->isNested())
1587 s = fd->toParent2();
1588 for (; s; s = s->toParent2())
1589 {
1590 if (AggregateDeclaration *ad = s->isAggregateDeclaration())
1591 {
1592 if (ad->isNested())
1593 continue;
1594 break;
1595 }
1596 if (FuncDeclaration *ff = s->isFuncDeclaration())
1597 {
1598 if (((TypeFunction *)ff->type)->iswild)
1599 goto Linouterr;
1600
1601 if (ff->isNested() || ff->isThis())
1602 continue;
1603 }
1604 break;
1605 }
1606 }
1607 else if (tf->isWild())
1608 {
1609 Linouterr:
1610 const char *s = wildmatch == MODmutable ? "mutable" : MODtoChars(wildmatch);
1611 error(loc, "modify inout to %s is not allowed inside inout function", s);
1612 return true;
1613 }
1614 }
1615
1616 assert(nargs >= nparams);
1617 for (size_t i = 0; i < nargs; i++)
1618 {
1619 Expression *arg = (*arguments)[i];
1620 assert(arg);
1621 if (i < nparams)
1622 {
1623 Parameter *p = Parameter::getNth(tf->parameters, i);
1624
1625 if (!(p->storageClass & STClazy && p->type->ty == Tvoid))
1626 {
1627 Type *tprm = p->type;
1628 if (p->type->hasWild())
1629 tprm = p->type->substWildTo(wildmatch);
1630 if (!tprm->equals(arg->type))
1631 {
1632 //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
1633 arg = arg->implicitCastTo(sc, tprm);
1634 arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0);
1635 }
1636 }
1637 if (p->storageClass & STCref)
1638 {
1639 arg = arg->toLvalue(sc, arg);
1640
1641 // Look for mutable misaligned pointer, etc., in @safe mode
1642 err |= checkUnsafeAccess(sc, arg, false, true);
1643 }
1644 else if (p->storageClass & STCout)
1645 {
1646 Type *t = arg->type;
1647 if (!t->isMutable() || !t->isAssignable()) // check blit assignable
1648 {
1649 arg->error("cannot modify struct %s with immutable members", arg->toChars());
1650 err = true;
1651 }
1652 else
1653 {
1654 // Look for misaligned pointer, etc., in @safe mode
1655 err |= checkUnsafeAccess(sc, arg, false, true);
1656 err |= checkDefCtor(arg->loc, t); // t must be default constructible
1657 }
1658 arg = arg->toLvalue(sc, arg);
1659 }
1660 else if (p->storageClass & STClazy)
1661 {
1662 // Convert lazy argument to a delegate
1663 if (p->type->ty == Tvoid)
1664 arg = toDelegate(arg, p->type, sc);
1665 else
1666 arg = toDelegate(arg, arg->type, sc);
1667 }
1668
1669 //printf("arg: %s\n", arg->toChars());
1670 //printf("type: %s\n", arg->type->toChars());
1671 if (tf->parameterEscapes(p))
1672 {
1673 /* Argument value can escape from the called function.
1674 * Check arg to see if it matters.
1675 */
1676 if (global.params.vsafe)
1677 err |= checkParamArgumentEscape(sc, fd, p->ident, arg, false);
1678 }
1679 else
1680 {
1681 /* Argument value cannot escape from the called function.
1682 */
1683 Expression *a = arg;
1684 if (a->op == TOKcast)
1685 a = ((CastExp *)a)->e1;
1686
1687 if (a->op == TOKfunction)
1688 {
1689 /* Function literals can only appear once, so if this
1690 * appearance was scoped, there cannot be any others.
1691 */
1692 FuncExp *fe = (FuncExp *)a;
1693 fe->fd->tookAddressOf = 0;
1694 }
1695 else if (a->op == TOKdelegate)
1696 {
1697 /* For passing a delegate to a scoped parameter,
1698 * this doesn't count as taking the address of it.
1699 * We only worry about 'escaping' references to the function.
1700 */
1701 DelegateExp *de = (DelegateExp *)a;
1702 if (de->e1->op == TOKvar)
1703 { VarExp *ve = (VarExp *)de->e1;
1704 FuncDeclaration *f = ve->var->isFuncDeclaration();
1705 if (f)
1706 { f->tookAddressOf--;
1707 //printf("tookAddressOf = %d\n", f->tookAddressOf);
1708 }
1709 }
1710 }
1711 }
1712 arg = arg->optimize(WANTvalue, (p->storageClass & (STCref | STCout)) != 0);
1713 }
1714 else
1715 {
1716 // These will be the trailing ... arguments
1717
1718 // If not D linkage, do promotions
1719 if (tf->linkage != LINKd)
1720 {
1721 // Promote bytes, words, etc., to ints
1722 arg = integralPromotions(arg, sc);
1723
1724 // Promote floats to doubles
1725 switch (arg->type->ty)
1726 {
1727 case Tfloat32:
1728 arg = arg->castTo(sc, Type::tfloat64);
1729 break;
1730
1731 case Timaginary32:
1732 arg = arg->castTo(sc, Type::timaginary64);
1733 break;
1734 }
1735
1736 if (tf->varargs == 1)
1737 {
1738 const char *p = tf->linkage == LINKc ? "extern(C)" : "extern(C++)";
1739 if (arg->type->ty == Tarray)
1740 {
1741 arg->error("cannot pass dynamic arrays to %s vararg functions", p);
1742 err = true;
1743 }
1744 if (arg->type->ty == Tsarray)
1745 {
1746 arg->error("cannot pass static arrays to %s vararg functions", p);
1747 err = true;
1748 }
1749 }
1750 }
1751
1752 // Do not allow types that need destructors
1753 if (arg->type->needsDestruction())
1754 {
1755 arg->error("cannot pass types that need destruction as variadic arguments");
1756 err = true;
1757 }
1758
1759 // Convert static arrays to dynamic arrays
1760 // BUG: I don't think this is right for D2
1761 Type *tb = arg->type->toBasetype();
1762 if (tb->ty == Tsarray)
1763 {
1764 TypeSArray *ts = (TypeSArray *)tb;
1765 Type *ta = ts->next->arrayOf();
1766 if (ts->size(arg->loc) == 0)
1767 arg = new NullExp(arg->loc, ta);
1768 else
1769 arg = arg->castTo(sc, ta);
1770 }
1771 if (tb->ty == Tstruct)
1772 {
1773 //arg = callCpCtor(sc, arg);
1774 }
1775
1776 // Give error for overloaded function addresses
1777 if (arg->op == TOKsymoff)
1778 { SymOffExp *se = (SymOffExp *)arg;
1779 if (se->hasOverloads &&
1780 !se->var->isFuncDeclaration()->isUnique())
1781 { arg->error("function %s is overloaded", arg->toChars());
1782 err = true;
1783 }
1784 }
1785 if (arg->checkValue())
1786 err = true;
1787 arg = arg->optimize(WANTvalue);
1788 }
1789 (*arguments)[i] = arg;
1790 }
1791
1792 /* Remaining problems:
1793 * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
1794 * implemented by calling a function) we'll defer this for now.
1795 * 2. value structs (or static arrays of them) that need to be copy constructed
1796 * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
1797 * function gets called (functions normally destroy their parameters)
1798 * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
1799 * up properly. Pushing arguments on the stack then cannot fail.
1800 */
1801 if (1)
1802 {
1803 /* TODO: tackle problem 1)
1804 */
1805 const bool leftToRight = true; // TODO: something like !fd.isArrayOp
1806 if (!leftToRight)
1807 assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
1808
1809 const ptrdiff_t start = (leftToRight ? 0 : (ptrdiff_t)nargs - 1);
1810 const ptrdiff_t end = (leftToRight ? (ptrdiff_t)nargs : -1);
1811 const ptrdiff_t step = (leftToRight ? 1 : -1);
1812
1813 /* Compute indices of last throwing argument and first arg needing destruction.
1814 * Used to not set up destructors unless an arg needs destruction on a throw
1815 * in a later argument.
1816 */
1817 ptrdiff_t lastthrow = -1;
1818 ptrdiff_t firstdtor = -1;
1819 for (ptrdiff_t i = start; i != end; i += step)
1820 {
1821 Expression *arg = (*arguments)[i];
1822 if (canThrow(arg, sc->func, false))
1823 lastthrow = i;
1824 if (firstdtor == -1 && arg->type->needsDestruction())
1825 {
1826 Parameter *p = (i >= (ptrdiff_t)nparams ? NULL : Parameter::getNth(tf->parameters, i));
1827 if (!(p && (p->storageClass & (STClazy | STCref | STCout))))
1828 firstdtor = i;
1829 }
1830 }
1831
1832 /* Does problem 3) apply to this call?
1833 */
1834 const bool needsPrefix = (firstdtor >= 0 && lastthrow >= 0
1835 && (lastthrow - firstdtor) * step > 0);
1836
1837 /* If so, initialize 'eprefix' by declaring the gate
1838 */
1839 VarDeclaration *gate = NULL;
1840 if (needsPrefix)
1841 {
1842 // eprefix => bool __gate [= false]
1843 Identifier *idtmp = Identifier::generateId("__gate");
1844 gate = new VarDeclaration(loc, Type::tbool, idtmp, NULL);
1845 gate->storage_class |= STCtemp | STCctfe | STCvolatile;
1846 gate->semantic(sc);
1847
1848 Expression *ae = new DeclarationExp(loc, gate);
1849 eprefix = semantic(ae, sc);
1850 }
1851
1852 for (ptrdiff_t i = start; i != end; i += step)
1853 {
1854 Expression *arg = (*arguments)[i];
1855
1856 Parameter *parameter = (i >= (ptrdiff_t)nparams ? NULL : Parameter::getNth(tf->parameters, i));
1857 const bool isRef = (parameter && (parameter->storageClass & (STCref | STCout)));
1858 const bool isLazy = (parameter && (parameter->storageClass & STClazy));
1859
1860 /* Skip lazy parameters
1861 */
1862 if (isLazy)
1863 continue;
1864
1865 /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg.
1866 * Declare a temporary variable for this arg and append that declaration to 'eprefix',
1867 * which will implicitly take care of potential problem 2) for this arg.
1868 * 'eprefix' will therefore finally contain all args up to and including the last
1869 * potentially throwing arg, excluding all lazy parameters.
1870 */
1871 if (gate)
1872 {
1873 const bool needsDtor = (!isRef && arg->type->needsDestruction() && i != lastthrow);
1874
1875 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
1876 */
1877 VarDeclaration *tmp = copyToTemp(0,
1878 needsDtor ? "__pfx" : "__pfy",
1879 !isRef ? arg : arg->addressOf());
1880 tmp->semantic(sc);
1881
1882 /* Modify the destructor so it only runs if gate==false, i.e.,
1883 * only if there was a throw while constructing the args
1884 */
1885 if (!needsDtor)
1886 {
1887 if (tmp->edtor)
1888 {
1889 assert(i == lastthrow);
1890 tmp->edtor = NULL;
1891 }
1892 }
1893 else
1894 {
1895 // edtor => (__gate || edtor)
1896 assert(tmp->edtor);
1897 Expression *e = tmp->edtor;
1898 e = new OrOrExp(e->loc, new VarExp(e->loc, gate), e);
1899 tmp->edtor = semantic(e, sc);
1900 //printf("edtor: %s\n", tmp->edtor->toChars());
1901 }
1902
1903 // eprefix => (eprefix, auto __pfx/y = arg)
1904 DeclarationExp *ae = new DeclarationExp(loc, tmp);
1905 eprefix = Expression::combine(eprefix, semantic(ae, sc));
1906
1907 // arg => __pfx/y
1908 arg = new VarExp(loc, tmp);
1909 arg = semantic(arg, sc);
1910 if (isRef)
1911 {
1912 arg = new PtrExp(loc, arg);
1913 arg = semantic(arg, sc);
1914 }
1915
1916 /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true),
1917 * i.e., disable the dtors right after constructing the last throwing arg.
1918 * From now on, the callee will take care of destructing the args because
1919 * the args are implicitly moved into function parameters.
1920 *
1921 * Set gate to null to let the next iterations know they don't need to
1922 * append to eprefix anymore.
1923 */
1924 if (i == lastthrow)
1925 {
1926 Expression *e = new AssignExp(gate->loc, new VarExp(gate->loc, gate), new IntegerExp(gate->loc, 1, Type::tbool));
1927 eprefix = Expression::combine(eprefix, semantic(e, sc));
1928 gate = NULL;
1929 }
1930 }
1931 else
1932 {
1933 /* No gate, no prefix to append to.
1934 * Handle problem 2) by calling the copy constructor for value structs
1935 * (or static arrays of them) if appropriate.
1936 */
1937 Type *tv = arg->type->baseElemOf();
1938 if (!isRef && tv->ty == Tstruct)
1939 arg = doCopyOrMove(sc, arg);
1940 }
1941
1942 (*arguments)[i] = arg;
1943 }
1944 }
1945 //if (eprefix) printf("eprefix: %s\n", eprefix->toChars());
1946
1947 // If D linkage and variadic, add _arguments[] as first argument
1948 if (tf->linkage == LINKd && tf->varargs == 1)
1949 {
1950 assert(arguments->dim >= nparams);
1951
1952 Parameters *args = new Parameters;
1953 args->setDim(arguments->dim - nparams);
1954 for (size_t i = 0; i < arguments->dim - nparams; i++)
1955 {
1956 Parameter *arg = new Parameter(STCin, (*arguments)[nparams + i]->type, NULL, NULL);
1957 (*args)[i] = arg;
1958 }
1959
1960 TypeTuple *tup = new TypeTuple(args);
1961 Expression *e = new TypeidExp(loc, tup);
1962 e = semantic(e, sc);
1963 arguments->insert(0, e);
1964 }
1965
1966 Type *tret = tf->next;
1967 if (isCtorCall)
1968 {
1969 //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd->toChars(), fd->type->toChars(),
1970 // wildmatch, tf->isWild(), fd->isolateReturn());
1971 if (!tthis)
1972 {
1973 assert(sc->intypeof || global.errors);
1974 tthis = fd->isThis()->type->addMod(fd->type->mod);
1975 }
1976 if (tf->isWild() && !fd->isolateReturn())
1977 {
1978 if (wildmatch)
1979 tret = tret->substWildTo(wildmatch);
1980 int offset;
1981 if (!tret->implicitConvTo(tthis) &&
1982 !(MODimplicitConv(tret->mod, tthis->mod) && tret->isBaseOf(tthis, &offset) && offset == 0))
1983 {
1984 const char* s1 = tret ->isNaked() ? " mutable" : tret ->modToChars();
1985 const char* s2 = tthis->isNaked() ? " mutable" : tthis->modToChars();
1986 ::error(loc, "inout constructor %s creates%s object, not%s",
1987 fd->toPrettyChars(), s1, s2);
1988 err = true;
1989 }
1990 }
1991 tret = tthis;
1992 }
1993 else if (wildmatch && tret)
1994 {
1995 /* Adjust function return type based on wildmatch
1996 */
1997 //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret->toChars());
1998 tret = tret->substWildTo(wildmatch);
1999 }
2000 *prettype = tret;
2001 *peprefix = eprefix;
2002 return (err || olderrors != global.errors);
2003 }
2004
2005 /******************************** Expression **************************/
2006
Expression(Loc loc,TOK op,int size)2007 Expression::Expression(Loc loc, TOK op, int size)
2008 {
2009 //printf("Expression::Expression(op = %d) this = %p\n", op, this);
2010 this->loc = loc;
2011 this->op = op;
2012 this->size = (unsigned char)size;
2013 this->parens = 0;
2014 type = NULL;
2015 }
2016
_init()2017 void Expression::_init()
2018 {
2019 CTFEExp::cantexp = new CTFEExp(TOKcantexp);
2020 CTFEExp::voidexp = new CTFEExp(TOKvoidexp);
2021 CTFEExp::breakexp = new CTFEExp(TOKbreak);
2022 CTFEExp::continueexp = new CTFEExp(TOKcontinue);
2023 CTFEExp::gotoexp = new CTFEExp(TOKgoto);
2024 }
2025
syntaxCopy()2026 Expression *Expression::syntaxCopy()
2027 {
2028 //printf("Expression::syntaxCopy()\n");
2029 //print();
2030 return copy();
2031 }
2032
2033 /*********************************
2034 * Does *not* do a deep copy.
2035 */
2036
copy()2037 Expression *Expression::copy()
2038 {
2039 Expression *e;
2040 if (!size)
2041 {
2042 assert(0);
2043 }
2044 void *pe = mem.xmalloc(size);
2045 //printf("Expression::copy(op = %d) e = %p\n", op, pe);
2046 e = (Expression *)memcpy(pe, (void *)this, size);
2047 return e;
2048 }
2049
print()2050 void Expression::print()
2051 {
2052 fprintf(stderr, "%s\n", toChars());
2053 fflush(stderr);
2054 }
2055
toChars()2056 const char *Expression::toChars()
2057 {
2058 OutBuffer buf;
2059 HdrGenState hgs;
2060 toCBuffer(this, &buf, &hgs);
2061 return buf.extractString();
2062 }
2063
error(const char * format,...)2064 void Expression::error(const char *format, ...) const
2065 {
2066 if (type != Type::terror)
2067 {
2068 va_list ap;
2069 va_start(ap, format);
2070 ::verror(loc, format, ap);
2071 va_end( ap );
2072 }
2073 }
2074
warning(const char * format,...)2075 void Expression::warning(const char *format, ...) const
2076 {
2077 if (type != Type::terror)
2078 {
2079 va_list ap;
2080 va_start(ap, format);
2081 ::vwarning(loc, format, ap);
2082 va_end( ap );
2083 }
2084 }
2085
deprecation(const char * format,...)2086 void Expression::deprecation(const char *format, ...) const
2087 {
2088 if (type != Type::terror)
2089 {
2090 va_list ap;
2091 va_start(ap, format);
2092 ::vdeprecation(loc, format, ap);
2093 va_end( ap );
2094 }
2095 }
2096
2097 /**********************************
2098 * Combine e1 and e2 by CommaExp if both are not NULL.
2099 */
combine(Expression * e1,Expression * e2)2100 Expression *Expression::combine(Expression *e1, Expression *e2)
2101 {
2102 if (e1)
2103 {
2104 if (e2)
2105 {
2106 e1 = new CommaExp(e1->loc, e1, e2);
2107 e1->type = e2->type;
2108 }
2109 }
2110 else
2111 e1 = e2;
2112 return e1;
2113 }
2114
2115 /**********************************
2116 * If 'e' is a tree of commas, returns the leftmost expression
2117 * by stripping off it from the tree. The remained part of the tree
2118 * is returned via *pe0.
2119 * Otherwise 'e' is directly returned and *pe0 is set to NULL.
2120 */
extractLast(Expression * e,Expression ** pe0)2121 Expression *Expression::extractLast(Expression *e, Expression **pe0)
2122 {
2123 if (e->op != TOKcomma)
2124 {
2125 *pe0 = NULL;
2126 return e;
2127 }
2128
2129 CommaExp *ce = (CommaExp *)e;
2130 if (ce->e2->op != TOKcomma)
2131 {
2132 *pe0 = ce->e1;
2133 return ce->e2;
2134 }
2135 else
2136 {
2137 *pe0 = e;
2138
2139 Expression **pce = &ce->e2;
2140 while (((CommaExp *)(*pce))->e2->op == TOKcomma)
2141 {
2142 pce = &((CommaExp *)(*pce))->e2;
2143 }
2144 assert((*pce)->op == TOKcomma);
2145 ce = (CommaExp *)(*pce);
2146 *pce = ce->e1;
2147
2148 return ce->e2;
2149 }
2150 }
2151
toInteger()2152 dinteger_t Expression::toInteger()
2153 {
2154 //printf("Expression %s\n", Token::toChars(op));
2155 error("integer constant expression expected instead of %s", toChars());
2156 return 0;
2157 }
2158
toUInteger()2159 uinteger_t Expression::toUInteger()
2160 {
2161 //printf("Expression %s\n", Token::toChars(op));
2162 return (uinteger_t)toInteger();
2163 }
2164
toReal()2165 real_t Expression::toReal()
2166 {
2167 error("floating point constant expression expected instead of %s", toChars());
2168 return CTFloat::zero;
2169 }
2170
toImaginary()2171 real_t Expression::toImaginary()
2172 {
2173 error("floating point constant expression expected instead of %s", toChars());
2174 return CTFloat::zero;
2175 }
2176
toComplex()2177 complex_t Expression::toComplex()
2178 {
2179 error("floating point constant expression expected instead of %s", toChars());
2180 return complex_t(CTFloat::zero);
2181 }
2182
toStringExp()2183 StringExp *Expression::toStringExp()
2184 {
2185 return NULL;
2186 }
2187
toTupleExp()2188 TupleExp *Expression::toTupleExp()
2189 {
2190 return NULL;
2191 }
2192
2193 /***************************************
2194 * Return !=0 if expression is an lvalue.
2195 */
2196
isLvalue()2197 bool Expression::isLvalue()
2198 {
2199 return false;
2200 }
2201
2202 /*******************************
2203 * Give error if we're not an lvalue.
2204 * If we can, convert expression to be an lvalue.
2205 */
2206
toLvalue(Scope *,Expression * e)2207 Expression *Expression::toLvalue(Scope *, Expression *e)
2208 {
2209 if (!e)
2210 e = this;
2211 else if (!loc.filename)
2212 loc = e->loc;
2213
2214 if (e->op == TOKtype)
2215 error("%s '%s' is a type, not an lvalue", e->type->kind(), e->type->toChars());
2216 else
2217 error("%s is not an lvalue", e->toChars());
2218
2219 return new ErrorExp();
2220 }
2221
2222 /***************************************
2223 * Parameters:
2224 * sc: scope
2225 * flag: 1: do not issue error message for invalid modification
2226 * Returns:
2227 * 0: is not modifiable
2228 * 1: is modifiable in default == being related to type->isMutable()
2229 * 2: is modifiable, because this is a part of initializing.
2230 */
2231
checkModifiable(Scope *,int)2232 int Expression::checkModifiable(Scope *, int)
2233 {
2234 return type ? 1 : 0; // default modifiable
2235 }
2236
modifiableLvalue(Scope * sc,Expression * e)2237 Expression *Expression::modifiableLvalue(Scope *sc, Expression *e)
2238 {
2239 //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
2240
2241 // See if this expression is a modifiable lvalue (i.e. not const)
2242 if (checkModifiable(sc) == 1)
2243 {
2244 assert(type);
2245 if (!type->isMutable())
2246 {
2247 error("cannot modify %s expression %s", MODtoChars(type->mod), toChars());
2248 return new ErrorExp();
2249 }
2250 else if (!type->isAssignable())
2251 {
2252 error("cannot modify struct %s %s with immutable members", toChars(), type->toChars());
2253 return new ErrorExp();
2254 }
2255 }
2256 return toLvalue(sc, e);
2257 }
2258
2259 /****************************************
2260 * Check that the expression has a valid type.
2261 * If not, generates an error "... has no type".
2262 * Returns:
2263 * true if the expression is not valid.
2264 * Note:
2265 * When this function returns true, `checkValue()` should also return true.
2266 */
checkType()2267 bool Expression::checkType()
2268 {
2269 return false;
2270 }
2271
2272 /****************************************
2273 * Check that the expression has a valid value.
2274 * If not, generates an error "... has no value".
2275 * Returns:
2276 * true if the expression is not valid or has void type.
2277 */
checkValue()2278 bool Expression::checkValue()
2279 {
2280 if (type && type->toBasetype()->ty == Tvoid)
2281 {
2282 error("expression %s is void and has no value", toChars());
2283 //print(); halt();
2284 if (!global.gag)
2285 type = Type::terror;
2286 return true;
2287 }
2288 return false;
2289 }
2290
checkScalar()2291 bool Expression::checkScalar()
2292 {
2293 if (op == TOKerror)
2294 return true;
2295 if (type->toBasetype()->ty == Terror)
2296 return true;
2297 if (!type->isscalar())
2298 {
2299 error("'%s' is not a scalar, it is a %s", toChars(), type->toChars());
2300 return true;
2301 }
2302 return checkValue();
2303 }
2304
checkNoBool()2305 bool Expression::checkNoBool()
2306 {
2307 if (op == TOKerror)
2308 return true;
2309 if (type->toBasetype()->ty == Terror)
2310 return true;
2311 if (type->toBasetype()->ty == Tbool)
2312 {
2313 error("operation not allowed on bool '%s'", toChars());
2314 return true;
2315 }
2316 return false;
2317 }
2318
checkIntegral()2319 bool Expression::checkIntegral()
2320 {
2321 if (op == TOKerror)
2322 return true;
2323 if (type->toBasetype()->ty == Terror)
2324 return true;
2325 if (!type->isintegral())
2326 {
2327 error("'%s' is not of integral type, it is a %s", toChars(), type->toChars());
2328 return true;
2329 }
2330 return checkValue();
2331 }
2332
checkArithmetic()2333 bool Expression::checkArithmetic()
2334 {
2335 if (op == TOKerror)
2336 return true;
2337 if (type->toBasetype()->ty == Terror)
2338 return true;
2339 if (!type->isintegral() && !type->isfloating())
2340 {
2341 error("'%s' is not of arithmetic type, it is a %s", toChars(), type->toChars());
2342 return true;
2343 }
2344 return checkValue();
2345 }
2346
checkDeprecated(Scope * sc,Dsymbol * s)2347 void Expression::checkDeprecated(Scope *sc, Dsymbol *s)
2348 {
2349 s->checkDeprecated(loc, sc);
2350 }
2351
2352 /*********************************************
2353 * Calling function f.
2354 * Check the purity, i.e. if we're in a pure function
2355 * we can only call other pure functions.
2356 * Returns true if error occurs.
2357 */
checkPurity(Scope * sc,FuncDeclaration * f)2358 bool Expression::checkPurity(Scope *sc, FuncDeclaration *f)
2359 {
2360 if (!sc->func)
2361 return false;
2362 if (sc->func == f)
2363 return false;
2364 if (sc->intypeof == 1)
2365 return false;
2366 if (sc->flags & (SCOPEctfe | SCOPEdebug))
2367 return false;
2368
2369 /* Given:
2370 * void f() {
2371 * pure void g() {
2372 * /+pure+/ void h() {
2373 * /+pure+/ void i() { }
2374 * }
2375 * }
2376 * }
2377 * g() can call h() but not f()
2378 * i() can call h() and g() but not f()
2379 */
2380
2381 // Find the closest pure parent of the calling function
2382 FuncDeclaration *outerfunc = sc->func;
2383 FuncDeclaration *calledparent = f;
2384
2385 if (outerfunc->isInstantiated())
2386 {
2387 // The attributes of outerfunc should be inferred from the call of f.
2388 }
2389 else if (f->isInstantiated())
2390 {
2391 // The attributes of f are inferred from its body.
2392 }
2393 else if (f->isFuncLiteralDeclaration())
2394 {
2395 // The attributes of f are always inferred in its declared place.
2396 }
2397 else
2398 {
2399 /* Today, static local functions are impure by default, but they cannot
2400 * violate purity of enclosing functions.
2401 *
2402 * auto foo() pure { // non instantiated funciton
2403 * static auto bar() { // static, without pure attribute
2404 * impureFunc(); // impure call
2405 * // Although impureFunc is called inside bar, f(= impureFunc)
2406 * // is not callable inside pure outerfunc(= foo <- bar).
2407 * }
2408 *
2409 * bar();
2410 * // Although bar is called inside foo, f(= bar) is callable
2411 * // bacause calledparent(= foo) is same with outerfunc(= foo).
2412 * }
2413 */
2414
2415 while (outerfunc->toParent2() &&
2416 outerfunc->isPureBypassingInference() == PUREimpure &&
2417 outerfunc->toParent2()->isFuncDeclaration())
2418 {
2419 outerfunc = outerfunc->toParent2()->isFuncDeclaration();
2420 if (outerfunc->type->ty == Terror)
2421 return true;
2422 }
2423 while (calledparent->toParent2() &&
2424 calledparent->isPureBypassingInference() == PUREimpure &&
2425 calledparent->toParent2()->isFuncDeclaration())
2426 {
2427 calledparent = calledparent->toParent2()->isFuncDeclaration();
2428 if (calledparent->type->ty == Terror)
2429 return true;
2430 }
2431 }
2432
2433 // If the caller has a pure parent, then either the called func must be pure,
2434 // OR, they must have the same pure parent.
2435 if (!f->isPure() && calledparent != outerfunc)
2436 {
2437 FuncDeclaration *ff = outerfunc;
2438 if (sc->flags & SCOPEcompile ? ff->isPureBypassingInference() >= PUREweak : ff->setImpure())
2439 {
2440 error("pure %s '%s' cannot call impure %s '%s'",
2441 ff->kind(), ff->toPrettyChars(), f->kind(), f->toPrettyChars());
2442 return true;
2443 }
2444 }
2445 return false;
2446 }
2447
2448 /*******************************************
2449 * Accessing variable v.
2450 * Check for purity and safety violations.
2451 * Returns true if error occurs.
2452 */
checkPurity(Scope * sc,VarDeclaration * v)2453 bool Expression::checkPurity(Scope *sc, VarDeclaration *v)
2454 {
2455 //printf("v = %s %s\n", v->type->toChars(), v->toChars());
2456
2457 /* Look for purity and safety violations when accessing variable v
2458 * from current function.
2459 */
2460 if (!sc->func)
2461 return false;
2462 if (sc->intypeof == 1)
2463 return false; // allow violations inside typeof(expression)
2464 if (sc->flags & (SCOPEctfe | SCOPEdebug))
2465 return false; // allow violations inside compile-time evaluated expressions and debug conditionals
2466 if (v->ident == Id::ctfe)
2467 return false; // magic variable never violates pure and safe
2468 if (v->isImmutable())
2469 return false; // always safe and pure to access immutables...
2470 if (v->isConst() && !v->isRef() && (v->isDataseg() || v->isParameter()) &&
2471 v->type->implicitConvTo(v->type->immutableOf()))
2472 return false; // or const global/parameter values which have no mutable indirections
2473 if (v->storage_class & STCmanifest)
2474 return false; // ...or manifest constants
2475
2476 bool err = false;
2477 if (v->isDataseg())
2478 {
2479 // Bugzilla 7533: Accessing implicit generated __gate is pure.
2480 if (v->ident == Id::gate)
2481 return false;
2482
2483 /* Accessing global mutable state.
2484 * Therefore, this function and all its immediately enclosing
2485 * functions must be pure.
2486 */
2487 /* Today, static local functions are impure by default, but they cannot
2488 * violate purity of enclosing functions.
2489 *
2490 * auto foo() pure { // non instantiated funciton
2491 * static auto bar() { // static, without pure attribute
2492 * globalData++; // impure access
2493 * // Although globalData is accessed inside bar,
2494 * // it is not accessible inside pure foo.
2495 * }
2496 * }
2497 */
2498 for (Dsymbol *s = sc->func; s; s = s->toParent2())
2499 {
2500 FuncDeclaration *ff = s->isFuncDeclaration();
2501 if (!ff)
2502 break;
2503 if (sc->flags & SCOPEcompile ? ff->isPureBypassingInference() >= PUREweak : ff->setImpure())
2504 {
2505 error("pure %s '%s' cannot access mutable static data '%s'",
2506 ff->kind(), ff->toPrettyChars(), v->toChars());
2507 err = true;
2508 break;
2509 }
2510 /* If the enclosing is an instantiated function or a lambda, its
2511 * attribute inference result is preferred.
2512 */
2513 if (ff->isInstantiated())
2514 break;
2515 if (ff->isFuncLiteralDeclaration())
2516 break;
2517 }
2518 }
2519 else
2520 {
2521 /* Given:
2522 * void f() {
2523 * int fx;
2524 * pure void g() {
2525 * int gx;
2526 * /+pure+/ void h() {
2527 * int hx;
2528 * /+pure+/ void i() { }
2529 * }
2530 * }
2531 * }
2532 * i() can modify hx and gx but not fx
2533 */
2534
2535 Dsymbol *vparent = v->toParent2();
2536 for (Dsymbol *s = sc->func; !err && s; s = s->toParent2())
2537 {
2538 if (s == vparent)
2539 break;
2540
2541 if (AggregateDeclaration *ad = s->isAggregateDeclaration())
2542 {
2543 if (ad->isNested())
2544 continue;
2545 break;
2546 }
2547 FuncDeclaration *ff = s->isFuncDeclaration();
2548 if (!ff)
2549 break;
2550 if (ff->isNested() || ff->isThis())
2551 {
2552 if (ff->type->isImmutable() ||
2553 (ff->type->isShared() && !MODimplicitConv(ff->type->mod, v->type->mod)))
2554 {
2555 OutBuffer ffbuf;
2556 OutBuffer vbuf;
2557 MODMatchToBuffer(&ffbuf, ff->type->mod, v->type->mod);
2558 MODMatchToBuffer(&vbuf, v->type->mod, ff->type->mod);
2559 error("%s%s '%s' cannot access %sdata '%s'",
2560 ffbuf.peekString(), ff->kind(), ff->toPrettyChars(), vbuf.peekString(), v->toChars());
2561 err = true;
2562 break;
2563 }
2564 continue;
2565 }
2566 break;
2567 }
2568 }
2569
2570 /* Do not allow safe functions to access __gshared data
2571 */
2572 if (v->storage_class & STCgshared)
2573 {
2574 if (sc->func->setUnsafe())
2575 {
2576 error("safe %s '%s' cannot access __gshared data '%s'",
2577 sc->func->kind(), sc->func->toChars(), v->toChars());
2578 err = true;
2579 }
2580 }
2581
2582 return err;
2583 }
2584
2585 /*********************************************
2586 * Calling function f.
2587 * Check the safety, i.e. if we're in a @safe function
2588 * we can only call @safe or @trusted functions.
2589 * Returns true if error occurs.
2590 */
checkSafety(Scope * sc,FuncDeclaration * f)2591 bool Expression::checkSafety(Scope *sc, FuncDeclaration *f)
2592 {
2593 if (!sc->func)
2594 return false;
2595 if (sc->func == f)
2596 return false;
2597 if (sc->intypeof == 1)
2598 return false;
2599 if (sc->flags & SCOPEctfe)
2600 return false;
2601
2602 if (!f->isSafe() && !f->isTrusted())
2603 {
2604 if (sc->flags & SCOPEcompile ? sc->func->isSafeBypassingInference() : sc->func->setUnsafe())
2605 {
2606 if (loc.linnum == 0) // e.g. implicitly generated dtor
2607 loc = sc->func->loc;
2608
2609 error("@safe %s '%s' cannot call @system %s '%s'",
2610 sc->func->kind(), sc->func->toPrettyChars(), f->kind(), f->toPrettyChars());
2611 return true;
2612 }
2613 }
2614 return false;
2615 }
2616
2617 /*********************************************
2618 * Calling function f.
2619 * Check the @nogc-ness, i.e. if we're in a @nogc function
2620 * we can only call other @nogc functions.
2621 * Returns true if error occurs.
2622 */
checkNogc(Scope * sc,FuncDeclaration * f)2623 bool Expression::checkNogc(Scope *sc, FuncDeclaration *f)
2624 {
2625 if (!sc->func)
2626 return false;
2627 if (sc->func == f)
2628 return false;
2629 if (sc->intypeof == 1)
2630 return false;
2631 if (sc->flags & SCOPEctfe)
2632 return false;
2633
2634 if (!f->isNogc())
2635 {
2636 if (sc->flags & SCOPEcompile ? sc->func->isNogcBypassingInference() : sc->func->setGC())
2637 {
2638 if (loc.linnum == 0) // e.g. implicitly generated dtor
2639 loc = sc->func->loc;
2640
2641 error("@nogc %s '%s' cannot call non-@nogc %s '%s'",
2642 sc->func->kind(), sc->func->toPrettyChars(), f->kind(), f->toPrettyChars());
2643 return true;
2644 }
2645 }
2646 return false;
2647 }
2648
2649 /********************************************
2650 * Check that the postblit is callable if t is an array of structs.
2651 * Returns true if error happens.
2652 */
checkPostblit(Scope * sc,Type * t)2653 bool Expression::checkPostblit(Scope *sc, Type *t)
2654 {
2655 t = t->baseElemOf();
2656 if (t->ty == Tstruct)
2657 {
2658 // Bugzilla 11395: Require TypeInfo generation for array concatenation
2659 semanticTypeInfo(sc, t);
2660
2661 StructDeclaration *sd = ((TypeStruct *)t)->sym;
2662 if (sd->postblit)
2663 {
2664 if (sd->postblit->storage_class & STCdisable)
2665 {
2666 sd->error(loc, "is not copyable because it is annotated with @disable");
2667 return true;
2668 }
2669 //checkDeprecated(sc, sd->postblit); // necessary?
2670 checkPurity(sc, sd->postblit);
2671 checkSafety(sc, sd->postblit);
2672 checkNogc(sc, sd->postblit);
2673 //checkAccess(sd, loc, sc, sd->postblit); // necessary?
2674 return false;
2675 }
2676 }
2677 return false;
2678 }
2679
checkRightThis(Scope * sc)2680 bool Expression::checkRightThis(Scope *sc)
2681 {
2682 if (op == TOKerror)
2683 return true;
2684 if (op == TOKvar && type->ty != Terror)
2685 {
2686 VarExp *ve = (VarExp *)this;
2687 if (isNeedThisScope(sc, ve->var))
2688 {
2689 //printf("checkRightThis sc->intypeof = %d, ad = %p, func = %p, fdthis = %p\n",
2690 // sc->intypeof, sc->getStructClassScope(), func, fdthis);
2691 error("need 'this' for '%s' of type '%s'", ve->var->toChars(), ve->var->type->toChars());
2692 return true;
2693 }
2694 }
2695 return false;
2696 }
2697
2698 /*******************************
2699 * Check whether the expression allows RMW operations, error with rmw operator diagnostic if not.
2700 * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics)
2701 * Returns true if error occurs.
2702 */
checkReadModifyWrite(TOK rmwOp,Expression * ex)2703 bool Expression::checkReadModifyWrite(TOK rmwOp, Expression *ex)
2704 {
2705 //printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex->toChars() : "");
2706 if (!type || !type->isShared())
2707 return false;
2708
2709 // atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal.
2710 switch (rmwOp)
2711 {
2712 case TOKplusplus:
2713 case TOKpreplusplus:
2714 rmwOp = TOKaddass;
2715 break;
2716
2717 case TOKminusminus:
2718 case TOKpreminusminus:
2719 rmwOp = TOKminass;
2720 break;
2721
2722 default:
2723 break;
2724 }
2725
2726 deprecation("read-modify-write operations are not allowed for shared variables. "
2727 "Use core.atomic.atomicOp!\"%s\"(%s, %s) instead.",
2728 Token::tochars[rmwOp], toChars(), ex ? ex->toChars() : "1");
2729 return false;
2730
2731 // note: enable when deprecation becomes an error.
2732 // return true;
2733 }
2734
2735 /*****************************
2736 * If expression can be tested for true or false,
2737 * returns the modified expression.
2738 * Otherwise returns ErrorExp.
2739 */
toBoolean(Scope * sc)2740 Expression *Expression::toBoolean(Scope *sc)
2741 {
2742 // Default is 'yes' - do nothing
2743 Expression *e = this;
2744 Type *t = type;
2745 Type *tb = type->toBasetype();
2746 Type *att = NULL;
2747 Lagain:
2748 // Structs can be converted to bool using opCast(bool)()
2749 if (tb->ty == Tstruct)
2750 {
2751 AggregateDeclaration *ad = ((TypeStruct *)tb)->sym;
2752 /* Don't really need to check for opCast first, but by doing so we
2753 * get better error messages if it isn't there.
2754 */
2755 Dsymbol *fd = search_function(ad, Id::_cast);
2756 if (fd)
2757 {
2758 e = new CastExp(loc, e, Type::tbool);
2759 e = semantic(e, sc);
2760 return e;
2761 }
2762
2763 // Forward to aliasthis.
2764 if (ad->aliasthis && tb != att)
2765 {
2766 if (!att && tb->checkAliasThisRec())
2767 att = tb;
2768 e = resolveAliasThis(sc, e);
2769 t = e->type;
2770 tb = e->type->toBasetype();
2771 goto Lagain;
2772 }
2773 }
2774
2775 if (!t->isBoolean())
2776 {
2777 if (tb != Type::terror)
2778 error("expression %s of type %s does not have a boolean value", toChars(), t->toChars());
2779 return new ErrorExp();
2780 }
2781 return e;
2782 }
2783
2784 /******************************
2785 * Take address of expression.
2786 */
2787
addressOf()2788 Expression *Expression::addressOf()
2789 {
2790 //printf("Expression::addressOf()\n");
2791 Expression *e = new AddrExp(loc, this);
2792 e->type = type->pointerTo();
2793 return e;
2794 }
2795
2796 /******************************
2797 * If this is a reference, dereference it.
2798 */
2799
deref()2800 Expression *Expression::deref()
2801 {
2802 //printf("Expression::deref()\n");
2803 // type could be null if forward referencing an 'auto' variable
2804 if (type && type->ty == Treference)
2805 {
2806 Expression *e = new PtrExp(loc, this);
2807 e->type = ((TypeReference *)type)->next;
2808 return e;
2809 }
2810 return this;
2811 }
2812
2813 /********************************
2814 * Does this expression statically evaluate to a boolean 'result' (true or false)?
2815 */
isBool(bool)2816 bool Expression::isBool(bool)
2817 {
2818 return false;
2819 }
2820
2821 /****************************************
2822 * Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__ to loc.
2823 */
2824
resolveLoc(Loc,Scope *)2825 Expression *Expression::resolveLoc(Loc, Scope *)
2826 {
2827 return this;
2828 }
2829
arraySyntaxCopy(Expressions * exps)2830 Expressions *Expression::arraySyntaxCopy(Expressions *exps)
2831 {
2832 Expressions *a = NULL;
2833 if (exps)
2834 {
2835 a = new Expressions();
2836 a->setDim(exps->dim);
2837 for (size_t i = 0; i < a->dim; i++)
2838 {
2839 Expression *e = (*exps)[i];
2840 (*a)[i] = e ? e->syntaxCopy() : NULL;
2841 }
2842 }
2843 return a;
2844 }
2845
2846 /************************************************
2847 * Destructors are attached to VarDeclarations.
2848 * Hence, if expression returns a temp that needs a destructor,
2849 * make sure and create a VarDeclaration for that temp.
2850 */
2851
addDtorHook(Scope *)2852 Expression *Expression::addDtorHook(Scope *)
2853 {
2854 return this;
2855 }
2856
2857 /******************************** IntegerExp **************************/
2858
IntegerExp(Loc loc,dinteger_t value,Type * type)2859 IntegerExp::IntegerExp(Loc loc, dinteger_t value, Type *type)
2860 : Expression(loc, TOKint64, sizeof(IntegerExp))
2861 {
2862 //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
2863 assert(type);
2864 if (!type->isscalar())
2865 {
2866 //printf("%s, loc = %d\n", toChars(), loc.linnum);
2867 if (type->ty != Terror)
2868 error("integral constant must be scalar type, not %s", type->toChars());
2869 type = Type::terror;
2870 }
2871 this->type = type;
2872 setInteger(value);
2873 }
2874
IntegerExp(dinteger_t value)2875 IntegerExp::IntegerExp(dinteger_t value)
2876 : Expression(Loc(), TOKint64, sizeof(IntegerExp))
2877 {
2878 this->type = Type::tint32;
2879 this->value = (d_int32) value;
2880 }
2881
create(Loc loc,dinteger_t value,Type * type)2882 IntegerExp *IntegerExp::create(Loc loc, dinteger_t value, Type *type)
2883 {
2884 return new IntegerExp(loc, value, type);
2885 }
2886
equals(RootObject * o)2887 bool IntegerExp::equals(RootObject *o)
2888 {
2889 if (this == o)
2890 return true;
2891 if (((Expression *)o)->op == TOKint64)
2892 {
2893 IntegerExp *ne = (IntegerExp *)o;
2894 if (type->toHeadMutable()->equals(ne->type->toHeadMutable()) &&
2895 value == ne->value)
2896 {
2897 return true;
2898 }
2899 }
2900 return false;
2901 }
2902
setInteger(dinteger_t value)2903 void IntegerExp::setInteger(dinteger_t value)
2904 {
2905 this->value = value;
2906 normalize();
2907 }
2908
normalize()2909 void IntegerExp::normalize()
2910 {
2911 /* 'Normalize' the value of the integer to be in range of the type
2912 */
2913 switch (type->toBasetype()->ty)
2914 {
2915 case Tbool: value = (value != 0); break;
2916 case Tint8: value = (d_int8) value; break;
2917 case Tchar:
2918 case Tuns8: value = (d_uns8) value; break;
2919 case Tint16: value = (d_int16) value; break;
2920 case Twchar:
2921 case Tuns16: value = (d_uns16) value; break;
2922 case Tint32: value = (d_int32) value; break;
2923 case Tdchar:
2924 case Tuns32: value = (d_uns32) value; break;
2925 case Tint64: value = (d_int64) value; break;
2926 case Tuns64: value = (d_uns64) value; break;
2927 case Tpointer:
2928 if (Target::ptrsize == 8)
2929 value = (d_uns64) value;
2930 else if (Target::ptrsize == 4)
2931 value = (d_uns32) value;
2932 else if (Target::ptrsize == 2)
2933 value = (d_uns16) value;
2934 else
2935 assert(0);
2936 break;
2937 default:
2938 break;
2939 }
2940 }
2941
toInteger()2942 dinteger_t IntegerExp::toInteger()
2943 {
2944 normalize(); // necessary until we fix all the paints of 'type'
2945 return value;
2946 }
2947
toReal()2948 real_t IntegerExp::toReal()
2949 {
2950 normalize(); // necessary until we fix all the paints of 'type'
2951 Type *t = type->toBasetype();
2952 if (t->ty == Tuns64)
2953 return ldouble((d_uns64)value);
2954 else
2955 return ldouble((d_int64)value);
2956 }
2957
toImaginary()2958 real_t IntegerExp::toImaginary()
2959 {
2960 return CTFloat::zero;
2961 }
2962
toComplex()2963 complex_t IntegerExp::toComplex()
2964 {
2965 return (complex_t)toReal();
2966 }
2967
isBool(bool result)2968 bool IntegerExp::isBool(bool result)
2969 {
2970 bool r = toInteger() != 0;
2971 return result ? r : !r;
2972 }
2973
toLvalue(Scope *,Expression * e)2974 Expression *IntegerExp::toLvalue(Scope *, Expression *e)
2975 {
2976 if (!e)
2977 e = this;
2978 else if (!loc.filename)
2979 loc = e->loc;
2980 e->error("constant %s is not an lvalue", e->toChars());
2981 return new ErrorExp();
2982 }
2983
2984 /******************************** ErrorExp **************************/
2985
2986 /* Use this expression for error recovery.
2987 * It should behave as a 'sink' to prevent further cascaded error messages.
2988 */
2989
ErrorExp()2990 ErrorExp::ErrorExp()
2991 : Expression(Loc(), TOKerror, sizeof(ErrorExp))
2992 {
2993 type = Type::terror;
2994 }
2995
toLvalue(Scope *,Expression *)2996 Expression *ErrorExp::toLvalue(Scope *, Expression *)
2997 {
2998 return this;
2999 }
3000
3001 /******************************** RealExp **************************/
3002
RealExp(Loc loc,real_t value,Type * type)3003 RealExp::RealExp(Loc loc, real_t value, Type *type)
3004 : Expression(loc, TOKfloat64, sizeof(RealExp))
3005 {
3006 //printf("RealExp::RealExp(%Lg)\n", value);
3007 this->value = value;
3008 this->type = type;
3009 }
3010
create(Loc loc,real_t value,Type * type)3011 RealExp *RealExp::create(Loc loc, real_t value, Type *type)
3012 {
3013 return new RealExp(loc, value,type);
3014 }
3015
toInteger()3016 dinteger_t RealExp::toInteger()
3017 {
3018 return (sinteger_t) toReal();
3019 }
3020
toUInteger()3021 uinteger_t RealExp::toUInteger()
3022 {
3023 return (uinteger_t) toReal();
3024 }
3025
toReal()3026 real_t RealExp::toReal()
3027 {
3028 return type->isreal() ? value : CTFloat::zero;
3029 }
3030
toImaginary()3031 real_t RealExp::toImaginary()
3032 {
3033 return type->isreal() ? CTFloat::zero : value;
3034 }
3035
toComplex()3036 complex_t RealExp::toComplex()
3037 {
3038 return complex_t(toReal(), toImaginary());
3039 }
3040
3041 /********************************
3042 * Test to see if two reals are the same.
3043 * Regard NaN's as equivalent.
3044 * Regard +0 and -0 as different.
3045 */
3046
RealEquals(real_t x1,real_t x2)3047 int RealEquals(real_t x1, real_t x2)
3048 {
3049 return (CTFloat::isNaN(x1) && CTFloat::isNaN(x2)) ||
3050 CTFloat::isIdentical(x1, x2);
3051 }
3052
equals(RootObject * o)3053 bool RealExp::equals(RootObject *o)
3054 {
3055 if (this == o)
3056 return true;
3057 if (((Expression *)o)->op == TOKfloat64)
3058 {
3059 RealExp *ne = (RealExp *)o;
3060 if (type->toHeadMutable()->equals(ne->type->toHeadMutable()) &&
3061 RealEquals(value, ne->value))
3062 {
3063 return true;
3064 }
3065 }
3066 return false;
3067 }
3068
isBool(bool result)3069 bool RealExp::isBool(bool result)
3070 {
3071 return result ? (bool)value : !(bool)value;
3072 }
3073
3074 /******************************** ComplexExp **************************/
3075
ComplexExp(Loc loc,complex_t value,Type * type)3076 ComplexExp::ComplexExp(Loc loc, complex_t value, Type *type)
3077 : Expression(loc, TOKcomplex80, sizeof(ComplexExp)), value(value)
3078 {
3079 this->type = type;
3080 //printf("ComplexExp::ComplexExp(%s)\n", toChars());
3081 }
3082
create(Loc loc,complex_t value,Type * type)3083 ComplexExp *ComplexExp::create(Loc loc, complex_t value, Type *type)
3084 {
3085 return new ComplexExp(loc, value, type);
3086 }
3087
toInteger()3088 dinteger_t ComplexExp::toInteger()
3089 {
3090 return (sinteger_t) toReal();
3091 }
3092
toUInteger()3093 uinteger_t ComplexExp::toUInteger()
3094 {
3095 return (uinteger_t) toReal();
3096 }
3097
toReal()3098 real_t ComplexExp::toReal()
3099 {
3100 return creall(value);
3101 }
3102
toImaginary()3103 real_t ComplexExp::toImaginary()
3104 {
3105 return cimagl(value);
3106 }
3107
toComplex()3108 complex_t ComplexExp::toComplex()
3109 {
3110 return value;
3111 }
3112
equals(RootObject * o)3113 bool ComplexExp::equals(RootObject *o)
3114 {
3115 if (this == o)
3116 return true;
3117 if (((Expression *)o)->op == TOKcomplex80)
3118 {
3119 ComplexExp *ne = (ComplexExp *)o;
3120 if (type->toHeadMutable()->equals(ne->type->toHeadMutable()) &&
3121 RealEquals(creall(value), creall(ne->value)) &&
3122 RealEquals(cimagl(value), cimagl(ne->value)))
3123 {
3124 return true;
3125 }
3126 }
3127 return false;
3128 }
3129
isBool(bool result)3130 bool ComplexExp::isBool(bool result)
3131 {
3132 if (result)
3133 return (bool)(value);
3134 else
3135 return !value;
3136 }
3137
3138 /******************************** IdentifierExp **************************/
3139
IdentifierExp(Loc loc,Identifier * ident)3140 IdentifierExp::IdentifierExp(Loc loc, Identifier *ident)
3141 : Expression(loc, TOKidentifier, sizeof(IdentifierExp))
3142 {
3143 this->ident = ident;
3144 }
3145
create(Loc loc,Identifier * ident)3146 IdentifierExp *IdentifierExp::create(Loc loc, Identifier *ident)
3147 {
3148 return new IdentifierExp(loc, ident);
3149 }
3150
isLvalue()3151 bool IdentifierExp::isLvalue()
3152 {
3153 return true;
3154 }
3155
toLvalue(Scope *,Expression *)3156 Expression *IdentifierExp::toLvalue(Scope *, Expression *)
3157 {
3158 return this;
3159 }
3160
3161 /******************************** DollarExp **************************/
3162
DollarExp(Loc loc)3163 DollarExp::DollarExp(Loc loc)
3164 : IdentifierExp(loc, Id::dollar)
3165 {
3166 }
3167
3168 /******************************** DsymbolExp **************************/
3169
DsymbolExp(Loc loc,Dsymbol * s,bool hasOverloads)3170 DsymbolExp::DsymbolExp(Loc loc, Dsymbol *s, bool hasOverloads)
3171 : Expression(loc, TOKdsymbol, sizeof(DsymbolExp))
3172 {
3173 this->s = s;
3174 this->hasOverloads = hasOverloads;
3175 }
3176
3177 /****************************************
3178 * Resolve a symbol `s` and wraps it in an expression object.
3179 * Params:
3180 * hasOverloads = works if the aliased symbol is a function.
3181 * true: it's overloaded and will be resolved later.
3182 * false: it's exact function symbol.
3183 */
resolve(Loc loc,Scope * sc,Dsymbol * s,bool hasOverloads)3184 Expression *resolve(Loc loc, Scope *sc, Dsymbol *s, bool hasOverloads)
3185 {
3186 Lagain:
3187 Expression *e;
3188
3189 //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
3190 //printf("s = '%s', s->kind = '%s'\n", s->toChars(), s->kind());
3191 Dsymbol *olds = s;
3192 Declaration *d = s->isDeclaration();
3193 if (d && (d->storage_class & STCtemplateparameter))
3194 {
3195 s = s->toAlias();
3196 }
3197 else
3198 {
3199 if (!s->isFuncDeclaration()) // functions are checked after overloading
3200 s->checkDeprecated(loc, sc);
3201
3202 // Bugzilla 12023: if 's' is a tuple variable, the tuple is returned.
3203 s = s->toAlias();
3204
3205 //printf("s = '%s', s->kind = '%s', s->needThis() = %p\n", s->toChars(), s->kind(), s->needThis());
3206 if (s != olds && !s->isFuncDeclaration())
3207 s->checkDeprecated(loc, sc);
3208 }
3209
3210 if (EnumMember *em = s->isEnumMember())
3211 {
3212 return em->getVarExp(loc, sc);
3213 }
3214 if (VarDeclaration *v = s->isVarDeclaration())
3215 {
3216 //printf("Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
3217 if (!v->type || // during variable type inference
3218 (!v->type->deco && v->inuse)) // during variable type semantic
3219 {
3220 if (v->inuse) // variable type depends on the variable itself
3221 ::error(loc, "circular reference to %s '%s'", v->kind(), v->toPrettyChars());
3222 else // variable type cannot be determined
3223 ::error(loc, "forward reference to %s '%s'", v->kind(), v->toPrettyChars());
3224 return new ErrorExp();
3225 }
3226 if (v->type->ty == Terror)
3227 return new ErrorExp();
3228
3229 if ((v->storage_class & STCmanifest) && v->_init)
3230 {
3231 if (v->inuse)
3232 {
3233 ::error(loc, "circular initialization of %s '%s'", v->kind(), v->toPrettyChars());
3234 return new ErrorExp();
3235 }
3236
3237 e = v->expandInitializer(loc);
3238 v->inuse++;
3239 e = semantic(e, sc);
3240 v->inuse--;
3241 return e;
3242 }
3243
3244 // Change the ancestor lambdas to delegate before hasThis(sc) call.
3245 if (v->checkNestedReference(sc, loc))
3246 return new ErrorExp();
3247
3248 if (v->needThis() && hasThis(sc))
3249 e = new DotVarExp(loc, new ThisExp(loc), v);
3250 else
3251 e = new VarExp(loc, v);
3252 e = semantic(e, sc);
3253 return e;
3254 }
3255 if (FuncLiteralDeclaration *fld = s->isFuncLiteralDeclaration())
3256 {
3257 //printf("'%s' is a function literal\n", fld->toChars());
3258 e = new FuncExp(loc, fld);
3259 return semantic(e, sc);
3260 }
3261 if (FuncDeclaration *f = s->isFuncDeclaration())
3262 {
3263 f = f->toAliasFunc();
3264 if (!f->functionSemantic())
3265 return new ErrorExp();
3266
3267 if (!hasOverloads && f->checkForwardRef(loc))
3268 return new ErrorExp();
3269
3270 FuncDeclaration *fd = s->isFuncDeclaration();
3271 fd->type = f->type;
3272 return new VarExp(loc, fd, hasOverloads);
3273 }
3274 if (OverDeclaration *od = s->isOverDeclaration())
3275 {
3276 e = new VarExp(loc, od, true);
3277 e->type = Type::tvoid;
3278 return e;
3279 }
3280 if (OverloadSet *o = s->isOverloadSet())
3281 {
3282 //printf("'%s' is an overload set\n", o->toChars());
3283 return new OverExp(loc, o);
3284 }
3285
3286 if (Import *imp = s->isImport())
3287 {
3288 if (!imp->pkg)
3289 {
3290 ::error(loc, "forward reference of import %s", imp->toChars());
3291 return new ErrorExp();
3292 }
3293 ScopeExp *ie = new ScopeExp(loc, imp->pkg);
3294 return semantic(ie, sc);
3295 }
3296 if (Package *pkg = s->isPackage())
3297 {
3298 ScopeExp *ie = new ScopeExp(loc, pkg);
3299 return semantic(ie, sc);
3300 }
3301 if (Module *mod = s->isModule())
3302 {
3303 ScopeExp *ie = new ScopeExp(loc, mod);
3304 return semantic(ie, sc);
3305 }
3306
3307 if (Nspace *ns = s->isNspace())
3308 {
3309 ScopeExp *ie = new ScopeExp(loc, ns);
3310 return semantic(ie, sc);
3311 }
3312
3313 if (Type *t = s->getType())
3314 {
3315 return semantic(new TypeExp(loc, t), sc);
3316 }
3317
3318 if (TupleDeclaration *tup = s->isTupleDeclaration())
3319 {
3320 if (tup->needThis() && hasThis(sc))
3321 e = new DotVarExp(loc, new ThisExp(loc), tup);
3322 else
3323 e = new TupleExp(loc, tup);
3324 e = semantic(e, sc);
3325 return e;
3326 }
3327
3328 if (TemplateInstance *ti = s->isTemplateInstance())
3329 {
3330 ti->semantic(sc);
3331 if (!ti->inst || ti->errors)
3332 return new ErrorExp();
3333 s = ti->toAlias();
3334 if (!s->isTemplateInstance())
3335 goto Lagain;
3336 e = new ScopeExp(loc, ti);
3337 e = semantic(e, sc);
3338 return e;
3339 }
3340 if (TemplateDeclaration *td = s->isTemplateDeclaration())
3341 {
3342 Dsymbol *p = td->toParent2();
3343 FuncDeclaration *fdthis = hasThis(sc);
3344 AggregateDeclaration *ad = p ? p->isAggregateDeclaration() : NULL;
3345 if (fdthis && ad && isAggregate(fdthis->vthis->type) == ad &&
3346 (td->_scope->stc & STCstatic) == 0)
3347 {
3348 e = new DotTemplateExp(loc, new ThisExp(loc), td);
3349 }
3350 else
3351 e = new TemplateExp(loc, td);
3352 e = semantic(e, sc);
3353 return e;
3354 }
3355
3356 ::error(loc, "%s '%s' is not a variable", s->kind(), s->toChars());
3357 return new ErrorExp();
3358 }
3359
isLvalue()3360 bool DsymbolExp::isLvalue()
3361 {
3362 return true;
3363 }
3364
toLvalue(Scope *,Expression *)3365 Expression *DsymbolExp::toLvalue(Scope *, Expression *)
3366 {
3367 return this;
3368 }
3369
3370 /******************************** ThisExp **************************/
3371
ThisExp(Loc loc)3372 ThisExp::ThisExp(Loc loc)
3373 : Expression(loc, TOKthis, sizeof(ThisExp))
3374 {
3375 //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
3376 var = NULL;
3377 }
3378
isBool(bool result)3379 bool ThisExp::isBool(bool result)
3380 {
3381 return result ? true : false;
3382 }
3383
isLvalue()3384 bool ThisExp::isLvalue()
3385 {
3386 // Class `this` should be an rvalue; struct `this` should be an lvalue.
3387 return type->toBasetype()->ty != Tclass;
3388 }
3389
toLvalue(Scope * sc,Expression * e)3390 Expression *ThisExp::toLvalue(Scope *sc, Expression *e)
3391 {
3392 if (type->toBasetype()->ty == Tclass)
3393 {
3394 // Class `this` is an rvalue; struct `this` is an lvalue.
3395 return Expression::toLvalue(sc, e);
3396 }
3397 return this;
3398 }
3399
3400 /******************************** SuperExp **************************/
3401
SuperExp(Loc loc)3402 SuperExp::SuperExp(Loc loc)
3403 : ThisExp(loc)
3404 {
3405 op = TOKsuper;
3406 }
3407
3408 /******************************** NullExp **************************/
3409
NullExp(Loc loc,Type * type)3410 NullExp::NullExp(Loc loc, Type *type)
3411 : Expression(loc, TOKnull, sizeof(NullExp))
3412 {
3413 committed = 0;
3414 this->type = type;
3415 }
3416
equals(RootObject * o)3417 bool NullExp::equals(RootObject *o)
3418 {
3419 if (o && o->dyncast() == DYNCAST_EXPRESSION)
3420 {
3421 Expression *e = (Expression *)o;
3422 if (e->op == TOKnull &&
3423 type->equals(e->type))
3424 {
3425 return true;
3426 }
3427 }
3428 return false;
3429 }
3430
isBool(bool result)3431 bool NullExp::isBool(bool result)
3432 {
3433 return result ? false : true;
3434 }
3435
toStringExp()3436 StringExp *NullExp::toStringExp()
3437 {
3438 if (implicitConvTo(Type::tstring))
3439 {
3440 StringExp *se = new StringExp(loc, (char*)mem.xcalloc(1, 1), 0);
3441 se->type = Type::tstring;
3442 return se;
3443 }
3444 return NULL;
3445 }
3446
3447 /******************************** StringExp **************************/
3448
StringExp(Loc loc,char * string)3449 StringExp::StringExp(Loc loc, char *string)
3450 : Expression(loc, TOKstring, sizeof(StringExp))
3451 {
3452 this->string = string;
3453 this->len = strlen(string);
3454 this->sz = 1;
3455 this->committed = 0;
3456 this->postfix = 0;
3457 this->ownedByCtfe = OWNEDcode;
3458 }
3459
StringExp(Loc loc,void * string,size_t len)3460 StringExp::StringExp(Loc loc, void *string, size_t len)
3461 : Expression(loc, TOKstring, sizeof(StringExp))
3462 {
3463 this->string = string;
3464 this->len = len;
3465 this->sz = 1;
3466 this->committed = 0;
3467 this->postfix = 0;
3468 this->ownedByCtfe = OWNEDcode;
3469 }
3470
StringExp(Loc loc,void * string,size_t len,utf8_t postfix)3471 StringExp::StringExp(Loc loc, void *string, size_t len, utf8_t postfix)
3472 : Expression(loc, TOKstring, sizeof(StringExp))
3473 {
3474 this->string = string;
3475 this->len = len;
3476 this->sz = 1;
3477 this->committed = 0;
3478 this->postfix = postfix;
3479 this->ownedByCtfe = OWNEDcode;
3480 }
3481
create(Loc loc,char * s)3482 StringExp *StringExp::create(Loc loc, char *s)
3483 {
3484 return new StringExp(loc, s);
3485 }
3486
create(Loc loc,void * string,size_t len)3487 StringExp *StringExp::create(Loc loc, void *string, size_t len)
3488 {
3489 return new StringExp(loc, string, len);
3490 }
3491
equals(RootObject * o)3492 bool StringExp::equals(RootObject *o)
3493 {
3494 //printf("StringExp::equals('%s') %s\n", o->toChars(), toChars());
3495 if (o && o->dyncast() == DYNCAST_EXPRESSION)
3496 {
3497 Expression *e = (Expression *)o;
3498 if (e->op == TOKstring)
3499 {
3500 return compare(o) == 0;
3501 }
3502 }
3503 return false;
3504 }
3505
3506 /**********************************
3507 * Return the number of code units the string would be if it were re-encoded
3508 * as tynto.
3509 * Params:
3510 * tynto = code unit type of the target encoding
3511 * Returns:
3512 * number of code units
3513 */
3514
numberOfCodeUnits(int tynto)3515 size_t StringExp::numberOfCodeUnits(int tynto) const
3516 {
3517 int encSize;
3518 switch (tynto)
3519 {
3520 case 0: return len;
3521 case Tchar: encSize = 1; break;
3522 case Twchar: encSize = 2; break;
3523 case Tdchar: encSize = 4; break;
3524 default:
3525 assert(0);
3526 }
3527 if (sz == encSize)
3528 return len;
3529
3530 size_t result = 0;
3531 dchar_t c;
3532
3533 switch (sz)
3534 {
3535 case 1:
3536 for (size_t u = 0; u < len;)
3537 {
3538 if (const char *p = utf_decodeChar((utf8_t *)string, len, &u, &c))
3539 {
3540 error("%s", p);
3541 return 0;
3542 }
3543 result += utf_codeLength(encSize, c);
3544 }
3545 break;
3546
3547 case 2:
3548 for (size_t u = 0; u < len;)
3549 {
3550 if (const char *p = utf_decodeWchar((utf16_t *)string, len, &u, &c))
3551 {
3552 error("%s", p);
3553 return 0;
3554 }
3555 result += utf_codeLength(encSize, c);
3556 }
3557 break;
3558
3559 case 4:
3560 for (size_t u = 0; u < len;)
3561 {
3562 c = *((utf32_t *)((char *)string + u));
3563 u += 4;
3564 result += utf_codeLength(encSize, c);
3565 }
3566 break;
3567
3568 default:
3569 assert(0);
3570 }
3571 return result;
3572 }
3573
3574 /**********************************************
3575 * Write the contents of the string to dest.
3576 * Use numberOfCodeUnits() to determine size of result.
3577 * Params:
3578 * dest = destination
3579 * tyto = encoding type of the result
3580 * zero = add terminating 0
3581 */
writeTo(void * dest,bool zero,int tyto)3582 void StringExp::writeTo(void *dest, bool zero, int tyto) const
3583 {
3584 int encSize;
3585 switch (tyto)
3586 {
3587 case 0: encSize = sz; break;
3588 case Tchar: encSize = 1; break;
3589 case Twchar: encSize = 2; break;
3590 case Tdchar: encSize = 4; break;
3591 default:
3592 assert(0);
3593 }
3594 if (sz == encSize)
3595 {
3596 memcpy(dest, string, len * sz);
3597 if (zero)
3598 memset((char *)dest + len * sz, 0, sz);
3599 }
3600 else
3601 assert(0);
3602 }
3603
3604 /**************************************************
3605 * If the string data is UTF-8 and can be accessed directly,
3606 * return a pointer to it.
3607 * Do not assume a terminating 0.
3608 * Returns:
3609 * pointer to string data if possible, null if not
3610 */
toPtr()3611 char *StringExp::toPtr()
3612 {
3613 return (sz == 1) ? (char*)string : NULL;
3614 }
3615
toStringExp()3616 StringExp *StringExp::toStringExp()
3617 {
3618 return this;
3619 }
3620
3621 /****************************************
3622 * Convert string to char[].
3623 */
3624
toUTF8(Scope * sc)3625 StringExp *StringExp::toUTF8(Scope *sc)
3626 {
3627 if (sz != 1)
3628 { // Convert to UTF-8 string
3629 committed = 0;
3630 Expression *e = castTo(sc, Type::tchar->arrayOf());
3631 e = e->optimize(WANTvalue);
3632 assert(e->op == TOKstring);
3633 StringExp *se = (StringExp *)e;
3634 assert(se->sz == 1);
3635 return se;
3636 }
3637 return this;
3638 }
3639
compare(RootObject * obj)3640 int StringExp::compare(RootObject *obj)
3641 {
3642 //printf("StringExp::compare()\n");
3643 // Used to sort case statement expressions so we can do an efficient lookup
3644 StringExp *se2 = (StringExp *)(obj);
3645
3646 // This is a kludge so isExpression() in template.c will return 5
3647 // for StringExp's.
3648 if (!se2)
3649 return 5;
3650
3651 assert(se2->op == TOKstring);
3652
3653 size_t len1 = len;
3654 size_t len2 = se2->len;
3655
3656 //printf("sz = %d, len1 = %d, len2 = %d\n", sz, (int)len1, (int)len2);
3657 if (len1 == len2)
3658 {
3659 switch (sz)
3660 {
3661 case 1:
3662 return memcmp((char *)string, (char *)se2->string, len1);
3663
3664 case 2:
3665 {
3666 d_uns16 *s1 = (d_uns16 *)string;
3667 d_uns16 *s2 = (d_uns16 *)se2->string;
3668
3669 for (size_t u = 0; u < len; u++)
3670 {
3671 if (s1[u] != s2[u])
3672 return s1[u] - s2[u];
3673 }
3674 }
3675 break;
3676
3677 case 4:
3678 {
3679 d_uns32 *s1 = (d_uns32 *)string;
3680 d_uns32 *s2 = (d_uns32 *)se2->string;
3681
3682 for (size_t u = 0; u < len; u++)
3683 {
3684 if (s1[u] != s2[u])
3685 return s1[u] - s2[u];
3686 }
3687 }
3688 break;
3689
3690 default:
3691 assert(0);
3692 }
3693 }
3694 return (int)(len1 - len2);
3695 }
3696
isBool(bool result)3697 bool StringExp::isBool(bool result)
3698 {
3699 return result ? true : false;
3700 }
3701
3702
isLvalue()3703 bool StringExp::isLvalue()
3704 {
3705 /* string literal is rvalue in default, but
3706 * conversion to reference of static array is only allowed.
3707 */
3708 return (type && type->toBasetype()->ty == Tsarray);
3709 }
3710
toLvalue(Scope * sc,Expression * e)3711 Expression *StringExp::toLvalue(Scope *sc, Expression *e)
3712 {
3713 //printf("StringExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL);
3714 return (type && type->toBasetype()->ty == Tsarray)
3715 ? this : Expression::toLvalue(sc, e);
3716 }
3717
modifiableLvalue(Scope *,Expression *)3718 Expression *StringExp::modifiableLvalue(Scope *, Expression *)
3719 {
3720 error("cannot modify string literal %s", toChars());
3721 return new ErrorExp();
3722 }
3723
charAt(uinteger_t i)3724 unsigned StringExp::charAt(uinteger_t i) const
3725 { unsigned value;
3726
3727 switch (sz)
3728 {
3729 case 1:
3730 value = ((utf8_t *)string)[(size_t)i];
3731 break;
3732
3733 case 2:
3734 value = ((unsigned short *)string)[(size_t)i];
3735 break;
3736
3737 case 4:
3738 value = ((unsigned int *)string)[(size_t)i];
3739 break;
3740
3741 default:
3742 assert(0);
3743 break;
3744 }
3745 return value;
3746 }
3747
3748 /************************ ArrayLiteralExp ************************************/
3749
3750 // [ e1, e2, e3, ... ]
3751
ArrayLiteralExp(Loc loc,Type * type,Expressions * elements)3752 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Type *type, Expressions *elements)
3753 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
3754 {
3755 this->basis = NULL;
3756 this->type = type;
3757 this->elements = elements;
3758 this->ownedByCtfe = OWNEDcode;
3759 }
3760
ArrayLiteralExp(Loc loc,Type * type,Expression * e)3761 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Type *type, Expression *e)
3762 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
3763 {
3764 this->basis = NULL;
3765 this->type = type;
3766 elements = new Expressions;
3767 elements->push(e);
3768 this->ownedByCtfe = OWNEDcode;
3769 }
3770
ArrayLiteralExp(Loc loc,Type * type,Expression * basis,Expressions * elements)3771 ArrayLiteralExp::ArrayLiteralExp(Loc loc, Type *type, Expression *basis, Expressions *elements)
3772 : Expression(loc, TOKarrayliteral, sizeof(ArrayLiteralExp))
3773 {
3774 this->basis = basis;
3775 this->type = type;
3776 this->elements = elements;
3777 this->ownedByCtfe = OWNEDcode;
3778 }
3779
create(Loc loc,Expressions * elements)3780 ArrayLiteralExp *ArrayLiteralExp::create(Loc loc, Expressions *elements)
3781 {
3782 return new ArrayLiteralExp(loc, NULL, elements);
3783 }
3784
equals(RootObject * o)3785 bool ArrayLiteralExp::equals(RootObject *o)
3786 {
3787 if (this == o)
3788 return true;
3789 if (o && o->dyncast() == DYNCAST_EXPRESSION &&
3790 ((Expression *)o)->op == TOKarrayliteral)
3791 {
3792 ArrayLiteralExp *ae = (ArrayLiteralExp *)o;
3793 if (elements->dim != ae->elements->dim)
3794 return false;
3795 if (elements->dim == 0 &&
3796 !type->equals(ae->type))
3797 {
3798 return false;
3799 }
3800 for (size_t i = 0; i < elements->dim; i++)
3801 {
3802 Expression *e1 = (*elements)[i];
3803 Expression *e2 = (*ae->elements)[i];
3804 if (!e1)
3805 e1 = basis;
3806 if (!e2)
3807 e2 = basis;
3808 if (e1 != e2 &&
3809 (!e1 || !e2 || !e1->equals(e2)))
3810 return false;
3811 }
3812 return true;
3813 }
3814 return false;
3815 }
3816
syntaxCopy()3817 Expression *ArrayLiteralExp::syntaxCopy()
3818 {
3819 return new ArrayLiteralExp(loc,
3820 NULL,
3821 basis ? basis->syntaxCopy() : NULL,
3822 arraySyntaxCopy(elements));
3823 }
3824
getElement(d_size_t i)3825 Expression *ArrayLiteralExp::getElement(d_size_t i)
3826 {
3827 Expression *el = (*elements)[i];
3828 if (!el)
3829 el = basis;
3830 return el;
3831 }
3832
appendArrayLiteral(Expressions * elems,ArrayLiteralExp * ale)3833 static void appendArrayLiteral(Expressions *elems, ArrayLiteralExp *ale)
3834 {
3835 if (!ale->elements)
3836 return;
3837 size_t d = elems->dim;
3838 elems->append(ale->elements);
3839 for (size_t i = d; i < elems->dim; i++)
3840 {
3841 Expression *el = (*elems)[i];
3842 if (!el)
3843 (*elems)[i] = ale->basis;
3844 }
3845 }
3846
3847 /* Copy element `Expressions` in the parameters when they're `ArrayLiteralExp`s.
3848 * Params:
3849 * e1 = If it's ArrayLiteralExp, its `elements` will be copied.
3850 * Otherwise, `e1` itself will be pushed into the new `Expressions`.
3851 * e2 = If it's not `null`, it will be pushed/appended to the new
3852 * `Expressions` by the same way with `e1`.
3853 * Returns:
3854 * Newly allocated `Expressions`. Note that it points to the original
3855 * `Expression` values in e1 and e2.
3856 */
copyElements(Expression * e1,Expression * e2)3857 Expressions* ArrayLiteralExp::copyElements(Expression *e1, Expression *e2)
3858 {
3859 Expressions *elems = new Expressions();
3860
3861 if (e1->op == TOKarrayliteral)
3862 appendArrayLiteral(elems, (ArrayLiteralExp *)e1);
3863 else
3864 elems->push(e1);
3865
3866 if (e2)
3867 {
3868 if (e2->op == TOKarrayliteral)
3869 appendArrayLiteral(elems, (ArrayLiteralExp *)e2);
3870 else
3871 elems->push(e2);
3872 }
3873
3874 return elems;
3875 }
3876
isBool(bool result)3877 bool ArrayLiteralExp::isBool(bool result)
3878 {
3879 size_t dim = elements ? elements->dim : 0;
3880 return result ? (dim != 0) : (dim == 0);
3881 }
3882
toStringExp()3883 StringExp *ArrayLiteralExp::toStringExp()
3884 {
3885 TY telem = type->nextOf()->toBasetype()->ty;
3886
3887 if (telem == Tchar || telem == Twchar || telem == Tdchar ||
3888 (telem == Tvoid && (!elements || elements->dim == 0)))
3889 {
3890 unsigned char sz = 1;
3891 if (telem == Twchar) sz = 2;
3892 else if (telem == Tdchar) sz = 4;
3893
3894 OutBuffer buf;
3895 if (elements)
3896 {
3897 for (size_t i = 0; i < elements->dim; ++i)
3898 {
3899 Expression *ch = getElement(i);
3900 if (ch->op != TOKint64)
3901 return NULL;
3902 if (sz == 1)
3903 buf.writeByte((unsigned)ch->toInteger());
3904 else if (sz == 2)
3905 buf.writeword((unsigned)ch->toInteger());
3906 else
3907 buf.write4((unsigned)ch->toInteger());
3908 }
3909 }
3910 char prefix;
3911 if (sz == 1) { prefix = 'c'; buf.writeByte(0); }
3912 else if (sz == 2) { prefix = 'w'; buf.writeword(0); }
3913 else { prefix = 'd'; buf.write4(0); }
3914
3915 const size_t len = buf.offset / sz - 1;
3916 StringExp *se = new StringExp(loc, buf.extractData(), len, prefix);
3917 se->sz = sz;
3918 se->type = type;
3919 return se;
3920 }
3921 return NULL;
3922 }
3923
3924 /************************ AssocArrayLiteralExp ************************************/
3925
3926 // [ key0 : value0, key1 : value1, ... ]
3927
AssocArrayLiteralExp(Loc loc,Expressions * keys,Expressions * values)3928 AssocArrayLiteralExp::AssocArrayLiteralExp(Loc loc,
3929 Expressions *keys, Expressions *values)
3930 : Expression(loc, TOKassocarrayliteral, sizeof(AssocArrayLiteralExp))
3931 {
3932 assert(keys->dim == values->dim);
3933 this->keys = keys;
3934 this->values = values;
3935 this->ownedByCtfe = OWNEDcode;
3936 }
3937
equals(RootObject * o)3938 bool AssocArrayLiteralExp::equals(RootObject *o)
3939 {
3940 if (this == o)
3941 return true;
3942 if (o && o->dyncast() == DYNCAST_EXPRESSION &&
3943 ((Expression *)o)->op == TOKassocarrayliteral)
3944 {
3945 AssocArrayLiteralExp *ae = (AssocArrayLiteralExp *)o;
3946 if (keys->dim != ae->keys->dim)
3947 return false;
3948 size_t count = 0;
3949 for (size_t i = 0; i < keys->dim; i++)
3950 {
3951 for (size_t j = 0; j < ae->keys->dim; j++)
3952 {
3953 if ((*keys)[i]->equals((*ae->keys)[j]))
3954 {
3955 if (!(*values)[i]->equals((*ae->values)[j]))
3956 return false;
3957 ++count;
3958 }
3959 }
3960 }
3961 return count == keys->dim;
3962 }
3963 return false;
3964 }
3965
syntaxCopy()3966 Expression *AssocArrayLiteralExp::syntaxCopy()
3967 {
3968 return new AssocArrayLiteralExp(loc,
3969 arraySyntaxCopy(keys), arraySyntaxCopy(values));
3970 }
3971
isBool(bool result)3972 bool AssocArrayLiteralExp::isBool(bool result)
3973 {
3974 size_t dim = keys->dim;
3975 return result ? (dim != 0) : (dim == 0);
3976 }
3977
3978 /************************ StructLiteralExp ************************************/
3979
3980 // sd( e1, e2, e3, ... )
3981
StructLiteralExp(Loc loc,StructDeclaration * sd,Expressions * elements,Type * stype)3982 StructLiteralExp::StructLiteralExp(Loc loc, StructDeclaration *sd, Expressions *elements, Type *stype)
3983 : Expression(loc, TOKstructliteral, sizeof(StructLiteralExp))
3984 {
3985 this->sd = sd;
3986 if (!elements)
3987 elements = new Expressions();
3988 this->elements = elements;
3989 this->stype = stype;
3990 this->useStaticInit = false;
3991 this->sym = NULL;
3992 this->ownedByCtfe = OWNEDcode;
3993 this->origin = this;
3994 this->stageflags = 0;
3995 this->inlinecopy = NULL;
3996 //printf("StructLiteralExp::StructLiteralExp(%s)\n", toChars());
3997 }
3998
create(Loc loc,StructDeclaration * sd,void * elements,Type * stype)3999 StructLiteralExp *StructLiteralExp::create(Loc loc, StructDeclaration *sd, void *elements, Type *stype)
4000 {
4001 return new StructLiteralExp(loc, sd, (Expressions *)elements, stype);
4002 }
4003
equals(RootObject * o)4004 bool StructLiteralExp::equals(RootObject *o)
4005 {
4006 if (this == o)
4007 return true;
4008 if (o && o->dyncast() == DYNCAST_EXPRESSION &&
4009 ((Expression *)o)->op == TOKstructliteral)
4010 {
4011 StructLiteralExp *se = (StructLiteralExp *)o;
4012 if (!type->equals(se->type))
4013 return false;
4014 if (elements->dim != se->elements->dim)
4015 return false;
4016 for (size_t i = 0; i < elements->dim; i++)
4017 {
4018 Expression *e1 = (*elements)[i];
4019 Expression *e2 = (*se->elements)[i];
4020 if (e1 != e2 &&
4021 (!e1 || !e2 || !e1->equals(e2)))
4022 return false;
4023 }
4024 return true;
4025 }
4026 return false;
4027 }
4028
syntaxCopy()4029 Expression *StructLiteralExp::syntaxCopy()
4030 {
4031 StructLiteralExp *exp = new StructLiteralExp(loc, sd, arraySyntaxCopy(elements), type ? type : stype);
4032 exp->origin = this;
4033 return exp;
4034 }
4035
addDtorHook(Scope * sc)4036 Expression *StructLiteralExp::addDtorHook(Scope *sc)
4037 {
4038 /* If struct requires a destructor, rewrite as:
4039 * (S tmp = S()),tmp
4040 * so that the destructor can be hung on tmp.
4041 */
4042 if (sd->dtor && sc->func)
4043 {
4044 /* Make an identifier for the temporary of the form:
4045 * __sl%s%d, where %s is the struct name
4046 */
4047 const size_t len = 10;
4048 char buf[len + 1];
4049 buf[len] = 0;
4050 strcpy(buf, "__sl");
4051 strncat(buf, sd->ident->toChars(), len - 4 - 1);
4052 assert(buf[len] == 0);
4053
4054 VarDeclaration *tmp = copyToTemp(0, buf, this);
4055 Expression *ae = new DeclarationExp(loc, tmp);
4056 Expression *e = new CommaExp(loc, ae, new VarExp(loc, tmp));
4057 e = semantic(e, sc);
4058 return e;
4059 }
4060 return this;
4061 }
4062
4063 /**************************************
4064 * Gets expression at offset of type.
4065 * Returns NULL if not found.
4066 */
4067
getField(Type * type,unsigned offset)4068 Expression *StructLiteralExp::getField(Type *type, unsigned offset)
4069 {
4070 //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
4071 // /*toChars()*/"", type->toChars(), offset);
4072 Expression *e = NULL;
4073 int i = getFieldIndex(type, offset);
4074
4075 if (i != -1)
4076 {
4077 //printf("\ti = %d\n", i);
4078 if (i == (int)sd->fields.dim - 1 && sd->isNested())
4079 return NULL;
4080
4081 assert(i < (int)elements->dim);
4082 e = (*elements)[i];
4083 if (e)
4084 {
4085 //printf("e = %s, e->type = %s\n", e->toChars(), e->type->toChars());
4086
4087 /* If type is a static array, and e is an initializer for that array,
4088 * then the field initializer should be an array literal of e.
4089 */
4090 if (e->type->castMod(0) != type->castMod(0) && type->ty == Tsarray)
4091 { TypeSArray *tsa = (TypeSArray *)type;
4092 size_t length = (size_t)tsa->dim->toInteger();
4093 Expressions *z = new Expressions;
4094 z->setDim(length);
4095 for (size_t q = 0; q < length; ++q)
4096 (*z)[q] = e->copy();
4097 e = new ArrayLiteralExp(loc, type, z);
4098 }
4099 else
4100 {
4101 e = e->copy();
4102 e->type = type;
4103 }
4104 if (useStaticInit && e->op == TOKstructliteral &&
4105 e->type->needsNested())
4106 {
4107 StructLiteralExp *se = (StructLiteralExp *)e;
4108 se->useStaticInit = true;
4109 }
4110 }
4111 }
4112 return e;
4113 }
4114
4115 /************************************
4116 * Get index of field.
4117 * Returns -1 if not found.
4118 */
4119
getFieldIndex(Type * type,unsigned offset)4120 int StructLiteralExp::getFieldIndex(Type *type, unsigned offset)
4121 {
4122 /* Find which field offset is by looking at the field offsets
4123 */
4124 if (elements->dim)
4125 {
4126 for (size_t i = 0; i < sd->fields.dim; i++)
4127 {
4128 VarDeclaration *v = sd->fields[i];
4129
4130 if (offset == v->offset &&
4131 type->size() == v->type->size())
4132 {
4133 /* context field might not be filled. */
4134 if (i == sd->fields.dim - 1 && sd->isNested())
4135 return (int)i;
4136 Expression *e = (*elements)[i];
4137 if (e)
4138 {
4139 return (int)i;
4140 }
4141 break;
4142 }
4143 }
4144 }
4145 return -1;
4146 }
4147
4148 /************************ TypeDotIdExp ************************************/
4149
4150 /* Things like:
4151 * int.size
4152 * foo.size
4153 * (foo).size
4154 * cast(foo).size
4155 */
4156
typeDotIdExp(Loc loc,Type * type,Identifier * ident)4157 DotIdExp *typeDotIdExp(Loc loc, Type *type, Identifier *ident)
4158 {
4159 return new DotIdExp(loc, new TypeExp(loc, type), ident);
4160 }
4161
4162
4163 /************************************************************/
4164
4165 // Mainly just a placeholder
4166
TypeExp(Loc loc,Type * type)4167 TypeExp::TypeExp(Loc loc, Type *type)
4168 : Expression(loc, TOKtype, sizeof(TypeExp))
4169 {
4170 //printf("TypeExp::TypeExp(%s)\n", type->toChars());
4171 this->type = type;
4172 }
4173
syntaxCopy()4174 Expression *TypeExp::syntaxCopy()
4175 {
4176 return new TypeExp(loc, type->syntaxCopy());
4177 }
4178
checkType()4179 bool TypeExp::checkType()
4180 {
4181 error("type %s is not an expression", toChars());
4182 return true;
4183 }
4184
checkValue()4185 bool TypeExp::checkValue()
4186 {
4187 error("type %s has no value", toChars());
4188 return true;
4189 }
4190
4191 /************************************************************/
4192
4193 /***********************************************************
4194 * Mainly just a placeholder of
4195 * Package, Module, Nspace, and TemplateInstance (including TemplateMixin)
4196 *
4197 * A template instance that requires IFTI:
4198 * foo!tiargs(fargs) // foo!tiargs
4199 * is left until CallExp::semantic() or resolveProperties()
4200 */
ScopeExp(Loc loc,ScopeDsymbol * sds)4201 ScopeExp::ScopeExp(Loc loc, ScopeDsymbol *sds)
4202 : Expression(loc, TOKscope, sizeof(ScopeExp))
4203 {
4204 //printf("ScopeExp::ScopeExp(sds = '%s')\n", sds->toChars());
4205 //static int count; if (++count == 38) *(char*)0=0;
4206 this->sds = sds;
4207 assert(!sds->isTemplateDeclaration()); // instead, you should use TemplateExp
4208 }
4209
syntaxCopy()4210 Expression *ScopeExp::syntaxCopy()
4211 {
4212 return new ScopeExp(loc, (ScopeDsymbol *)sds->syntaxCopy(NULL));
4213 }
4214
checkType()4215 bool ScopeExp::checkType()
4216 {
4217 if (sds->isPackage())
4218 {
4219 error("%s %s has no type", sds->kind(), sds->toChars());
4220 return true;
4221 }
4222 if (TemplateInstance *ti = sds->isTemplateInstance())
4223 {
4224 //assert(ti->needsTypeInference(sc));
4225 if (ti->tempdecl &&
4226 ti->semantictiargsdone &&
4227 ti->semanticRun == PASSinit)
4228 {
4229 error("partial %s %s has no type", sds->kind(), toChars());
4230 return true;
4231 }
4232 }
4233 return false;
4234 }
4235
checkValue()4236 bool ScopeExp::checkValue()
4237 {
4238 error("%s %s has no value", sds->kind(), sds->toChars());
4239 return true;
4240 }
4241
4242 /********************** TemplateExp **************************************/
4243
4244 // Mainly just a placeholder
4245
TemplateExp(Loc loc,TemplateDeclaration * td,FuncDeclaration * fd)4246 TemplateExp::TemplateExp(Loc loc, TemplateDeclaration *td, FuncDeclaration *fd)
4247 : Expression(loc, TOKtemplate, sizeof(TemplateExp))
4248 {
4249 //printf("TemplateExp(): %s\n", td->toChars());
4250 this->td = td;
4251 this->fd = fd;
4252 }
4253
checkType()4254 bool TemplateExp::checkType()
4255 {
4256 error("%s %s has no type", td->kind(), toChars());
4257 return true;
4258 }
4259
checkValue()4260 bool TemplateExp::checkValue()
4261 {
4262 error("%s %s has no value", td->kind(), toChars());
4263 return true;
4264 }
4265
isLvalue()4266 bool TemplateExp::isLvalue()
4267 {
4268 return fd != NULL;
4269 }
4270
toLvalue(Scope * sc,Expression * e)4271 Expression *TemplateExp::toLvalue(Scope *sc, Expression *e)
4272 {
4273 if (!fd)
4274 return Expression::toLvalue(sc, e);
4275
4276 assert(sc);
4277 return resolve(loc, sc, fd, true);
4278 }
4279
4280 /********************** NewExp **************************************/
4281
4282 /* thisexp.new(newargs) newtype(arguments) */
4283
NewExp(Loc loc,Expression * thisexp,Expressions * newargs,Type * newtype,Expressions * arguments)4284 NewExp::NewExp(Loc loc, Expression *thisexp, Expressions *newargs,
4285 Type *newtype, Expressions *arguments)
4286 : Expression(loc, TOKnew, sizeof(NewExp))
4287 {
4288 this->thisexp = thisexp;
4289 this->newargs = newargs;
4290 this->newtype = newtype;
4291 this->arguments = arguments;
4292 argprefix = NULL;
4293 member = NULL;
4294 allocator = NULL;
4295 onstack = 0;
4296 }
4297
create(Loc loc,Expression * thisexp,Expressions * newargs,Type * newtype,Expressions * arguments)4298 NewExp *NewExp::create(Loc loc, Expression *thisexp, Expressions *newargs,
4299 Type *newtype, Expressions *arguments)
4300 {
4301 return new NewExp(loc, thisexp, newargs, newtype, arguments);
4302 }
4303
syntaxCopy()4304 Expression *NewExp::syntaxCopy()
4305 {
4306 return new NewExp(loc,
4307 thisexp ? thisexp->syntaxCopy() : NULL,
4308 arraySyntaxCopy(newargs),
4309 newtype->syntaxCopy(), arraySyntaxCopy(arguments));
4310 }
4311
4312 /********************** NewAnonClassExp **************************************/
4313
NewAnonClassExp(Loc loc,Expression * thisexp,Expressions * newargs,ClassDeclaration * cd,Expressions * arguments)4314 NewAnonClassExp::NewAnonClassExp(Loc loc, Expression *thisexp,
4315 Expressions *newargs, ClassDeclaration *cd, Expressions *arguments)
4316 : Expression(loc, TOKnewanonclass, sizeof(NewAnonClassExp))
4317 {
4318 this->thisexp = thisexp;
4319 this->newargs = newargs;
4320 this->cd = cd;
4321 this->arguments = arguments;
4322 }
4323
syntaxCopy()4324 Expression *NewAnonClassExp::syntaxCopy()
4325 {
4326 return new NewAnonClassExp(loc,
4327 thisexp ? thisexp->syntaxCopy() : NULL,
4328 arraySyntaxCopy(newargs),
4329 (ClassDeclaration *)cd->syntaxCopy(NULL),
4330 arraySyntaxCopy(arguments));
4331 }
4332
4333 /********************** SymbolExp **************************************/
4334
SymbolExp(Loc loc,TOK op,int size,Declaration * var,bool hasOverloads)4335 SymbolExp::SymbolExp(Loc loc, TOK op, int size, Declaration *var, bool hasOverloads)
4336 : Expression(loc, op, size)
4337 {
4338 assert(var);
4339 this->var = var;
4340 this->hasOverloads = hasOverloads;
4341 }
4342
4343 /********************** SymOffExp **************************************/
4344
SymOffExp(Loc loc,Declaration * var,dinteger_t offset,bool hasOverloads)4345 SymOffExp::SymOffExp(Loc loc, Declaration *var, dinteger_t offset, bool hasOverloads)
4346 : SymbolExp(loc, TOKsymoff, sizeof(SymOffExp), var,
4347 var->isVarDeclaration() ? false : hasOverloads)
4348 {
4349 if (VarDeclaration *v = var->isVarDeclaration())
4350 {
4351 // FIXME: This error report will never be handled anyone.
4352 // It should be done before the SymOffExp construction.
4353 if (v->needThis())
4354 ::error(loc, "need 'this' for address of %s", v->toChars());
4355 }
4356 this->offset = offset;
4357 }
4358
isBool(bool result)4359 bool SymOffExp::isBool(bool result)
4360 {
4361 return result ? true : false;
4362 }
4363
4364 /******************************** VarExp **************************/
4365
VarExp(Loc loc,Declaration * var,bool hasOverloads)4366 VarExp::VarExp(Loc loc, Declaration *var, bool hasOverloads)
4367 : SymbolExp(loc, TOKvar, sizeof(VarExp), var,
4368 var->isVarDeclaration() ? false : hasOverloads)
4369 {
4370 //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
4371 //if (strcmp(var->ident->toChars(), "func") == 0) halt();
4372 this->type = var->type;
4373 }
4374
create(Loc loc,Declaration * var,bool hasOverloads)4375 VarExp *VarExp::create(Loc loc, Declaration *var, bool hasOverloads)
4376 {
4377 return new VarExp(loc, var, hasOverloads);
4378 }
4379
equals(RootObject * o)4380 bool VarExp::equals(RootObject *o)
4381 {
4382 if (this == o)
4383 return true;
4384 if (((Expression *)o)->op == TOKvar)
4385 {
4386 VarExp *ne = (VarExp *)o;
4387 if (type->toHeadMutable()->equals(ne->type->toHeadMutable()) &&
4388 var == ne->var)
4389 {
4390 return true;
4391 }
4392 }
4393 return false;
4394 }
4395
isLvalue()4396 bool VarExp::isLvalue()
4397 {
4398 if (var->storage_class & (STClazy | STCrvalue | STCmanifest))
4399 return false;
4400 return true;
4401 }
4402
toLvalue(Scope *,Expression *)4403 Expression *VarExp::toLvalue(Scope *, Expression *)
4404 {
4405 if (var->storage_class & STCmanifest)
4406 {
4407 error("manifest constant '%s' is not lvalue", var->toChars());
4408 return new ErrorExp();
4409 }
4410 if (var->storage_class & STClazy)
4411 {
4412 error("lazy variables cannot be lvalues");
4413 return new ErrorExp();
4414 }
4415 if (var->ident == Id::ctfe)
4416 {
4417 error("compiler-generated variable __ctfe is not an lvalue");
4418 return new ErrorExp();
4419 }
4420 if (var->ident == Id::dollar) // Bugzilla 13574
4421 {
4422 error("'$' is not an lvalue");
4423 return new ErrorExp();
4424 }
4425 return this;
4426 }
4427
checkModifiable(Scope * sc,int flag)4428 int VarExp::checkModifiable(Scope *sc, int flag)
4429 {
4430 //printf("VarExp::checkModifiable %s", toChars());
4431 assert(type);
4432 return var->checkModify(loc, sc, type, NULL, flag);
4433 }
4434
modifiableLvalue(Scope * sc,Expression * e)4435 Expression *VarExp::modifiableLvalue(Scope *sc, Expression *e)
4436 {
4437 //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
4438 if (var->storage_class & STCmanifest)
4439 {
4440 error("cannot modify manifest constant '%s'", toChars());
4441 return new ErrorExp();
4442 }
4443 // See if this expression is a modifiable lvalue (i.e. not const)
4444 return Expression::modifiableLvalue(sc, e);
4445 }
4446
4447
4448 /******************************** OverExp **************************/
4449
OverExp(Loc loc,OverloadSet * s)4450 OverExp::OverExp(Loc loc, OverloadSet *s)
4451 : Expression(loc, TOKoverloadset, sizeof(OverExp))
4452 {
4453 //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
4454 vars = s;
4455 type = Type::tvoid;
4456 }
4457
isLvalue()4458 bool OverExp::isLvalue()
4459 {
4460 return true;
4461 }
4462
toLvalue(Scope *,Expression *)4463 Expression *OverExp::toLvalue(Scope *, Expression *)
4464 {
4465 return this;
4466 }
4467
4468 /******************************** TupleExp **************************/
4469
TupleExp(Loc loc,Expression * e0,Expressions * exps)4470 TupleExp::TupleExp(Loc loc, Expression *e0, Expressions *exps)
4471 : Expression(loc, TOKtuple, sizeof(TupleExp))
4472 {
4473 //printf("TupleExp(this = %p)\n", this);
4474 this->e0 = e0;
4475 this->exps = exps;
4476 }
4477
TupleExp(Loc loc,Expressions * exps)4478 TupleExp::TupleExp(Loc loc, Expressions *exps)
4479 : Expression(loc, TOKtuple, sizeof(TupleExp))
4480 {
4481 //printf("TupleExp(this = %p)\n", this);
4482 this->e0 = NULL;
4483 this->exps = exps;
4484 }
4485
TupleExp(Loc loc,TupleDeclaration * tup)4486 TupleExp::TupleExp(Loc loc, TupleDeclaration *tup)
4487 : Expression(loc, TOKtuple, sizeof(TupleExp))
4488 {
4489 this->e0 = NULL;
4490 this->exps = new Expressions();
4491
4492 this->exps->reserve(tup->objects->dim);
4493 for (size_t i = 0; i < tup->objects->dim; i++)
4494 { RootObject *o = (*tup->objects)[i];
4495 if (Dsymbol *s = getDsymbol(o))
4496 {
4497 /* If tuple element represents a symbol, translate to DsymbolExp
4498 * to supply implicit 'this' if needed later.
4499 */
4500 Expression *e = new DsymbolExp(loc, s);
4501 this->exps->push(e);
4502 }
4503 else if (o->dyncast() == DYNCAST_EXPRESSION)
4504 {
4505 Expression *e = ((Expression *)o)->copy();
4506 e->loc = loc; // Bugzilla 15669
4507 this->exps->push(e);
4508 }
4509 else if (o->dyncast() == DYNCAST_TYPE)
4510 {
4511 Type *t = (Type *)o;
4512 Expression *e = new TypeExp(loc, t);
4513 this->exps->push(e);
4514 }
4515 else
4516 {
4517 error("%s is not an expression", o->toChars());
4518 }
4519 }
4520 }
4521
equals(RootObject * o)4522 bool TupleExp::equals(RootObject *o)
4523 {
4524 if (this == o)
4525 return true;
4526 if (((Expression *)o)->op == TOKtuple)
4527 {
4528 TupleExp *te = (TupleExp *)o;
4529 if (exps->dim != te->exps->dim)
4530 return false;
4531 if ((e0 && !e0->equals(te->e0)) || (!e0 && te->e0))
4532 return false;
4533 for (size_t i = 0; i < exps->dim; i++)
4534 {
4535 Expression *e1 = (*exps)[i];
4536 Expression *e2 = (*te->exps)[i];
4537 if (!e1->equals(e2))
4538 return false;
4539 }
4540 return true;
4541 }
4542 return false;
4543 }
4544
syntaxCopy()4545 Expression *TupleExp::syntaxCopy()
4546 {
4547 return new TupleExp(loc, e0 ? e0->syntaxCopy() : NULL, arraySyntaxCopy(exps));
4548 }
4549
toTupleExp()4550 TupleExp *TupleExp::toTupleExp()
4551 {
4552 return this;
4553 }
4554
4555 /******************************** FuncExp *********************************/
4556
FuncExp(Loc loc,Dsymbol * s)4557 FuncExp::FuncExp(Loc loc, Dsymbol *s)
4558 : Expression(loc, TOKfunction, sizeof(FuncExp))
4559 {
4560 this->td = s->isTemplateDeclaration();
4561 this->fd = s->isFuncLiteralDeclaration();
4562 if (td)
4563 {
4564 assert(td->literal);
4565 assert(td->members && td->members->dim == 1);
4566 fd = (*td->members)[0]->isFuncLiteralDeclaration();
4567 }
4568 tok = fd->tok; // save original kind of function/delegate/(infer)
4569 assert(fd->fbody);
4570 }
4571
equals(RootObject * o)4572 bool FuncExp::equals(RootObject *o)
4573 {
4574 if (this == o)
4575 return true;
4576 if (o->dyncast() != DYNCAST_EXPRESSION)
4577 return false;
4578 if (((Expression *)o)->op == TOKfunction)
4579 {
4580 FuncExp *fe = (FuncExp *)o;
4581 return fd == fe->fd;
4582 }
4583 return false;
4584 }
4585
genIdent(Scope * sc)4586 void FuncExp::genIdent(Scope *sc)
4587 {
4588 if (fd->ident == Id::empty)
4589 {
4590 const char *s;
4591 if (fd->fes) s = "__foreachbody";
4592 else if (fd->tok == TOKreserved) s = "__lambda";
4593 else if (fd->tok == TOKdelegate) s = "__dgliteral";
4594 else s = "__funcliteral";
4595
4596 DsymbolTable *symtab;
4597 if (FuncDeclaration *func = sc->parent->isFuncDeclaration())
4598 {
4599 if (func->localsymtab == NULL)
4600 {
4601 // Inside template constraint, symtab is not set yet.
4602 // Initialize it lazily.
4603 func->localsymtab = new DsymbolTable();
4604 }
4605 symtab = func->localsymtab;
4606 }
4607 else
4608 {
4609 ScopeDsymbol *sds = sc->parent->isScopeDsymbol();
4610 if (!sds->symtab)
4611 {
4612 // Inside template constraint, symtab may not be set yet.
4613 // Initialize it lazily.
4614 assert(sds->isTemplateInstance());
4615 sds->symtab = new DsymbolTable();
4616 }
4617 symtab = sds->symtab;
4618 }
4619 assert(symtab);
4620 int num = (int)dmd_aaLen(symtab->tab) + 1;
4621 Identifier *id = Identifier::generateId(s, num);
4622 fd->ident = id;
4623 if (td) td->ident = id;
4624 symtab->insert(td ? (Dsymbol *)td : (Dsymbol *)fd);
4625 }
4626 }
4627
syntaxCopy()4628 Expression *FuncExp::syntaxCopy()
4629 {
4630 if (td)
4631 return new FuncExp(loc, td->syntaxCopy(NULL));
4632 else if (fd->semanticRun == PASSinit)
4633 return new FuncExp(loc, fd->syntaxCopy(NULL));
4634 else // Bugzilla 13481: Prevent multiple semantic analysis of lambda body.
4635 return new FuncExp(loc, fd);
4636 }
4637
matchType(Type * to,Scope * sc,FuncExp ** presult,int flag)4638 MATCH FuncExp::matchType(Type *to, Scope *sc, FuncExp **presult, int flag)
4639 {
4640 //printf("FuncExp::matchType('%s'), to=%s\n", type ? type->toChars() : "null", to->toChars());
4641 if (presult)
4642 *presult = NULL;
4643
4644 TypeFunction *tof = NULL;
4645 if (to->ty == Tdelegate)
4646 {
4647 if (tok == TOKfunction)
4648 {
4649 if (!flag)
4650 error("cannot match function literal to delegate type '%s'", to->toChars());
4651 return MATCHnomatch;
4652 }
4653 tof = (TypeFunction *)to->nextOf();
4654 }
4655 else if (to->ty == Tpointer && to->nextOf()->ty == Tfunction)
4656 {
4657 if (tok == TOKdelegate)
4658 {
4659 if (!flag)
4660 error("cannot match delegate literal to function pointer type '%s'", to->toChars());
4661 return MATCHnomatch;
4662 }
4663 tof = (TypeFunction *)to->nextOf();
4664 }
4665
4666 if (td)
4667 {
4668 if (!tof)
4669 {
4670 L1:
4671 if (!flag)
4672 error("cannot infer parameter types from %s", to->toChars());
4673 return MATCHnomatch;
4674 }
4675
4676 // Parameter types inference from 'tof'
4677 assert(td->_scope);
4678 TypeFunction *tf = (TypeFunction *)fd->type;
4679 //printf("\ttof = %s\n", tof->toChars());
4680 //printf("\ttf = %s\n", tf->toChars());
4681 size_t dim = Parameter::dim(tf->parameters);
4682
4683 if (Parameter::dim(tof->parameters) != dim ||
4684 tof->varargs != tf->varargs)
4685 goto L1;
4686
4687 Objects *tiargs = new Objects();
4688 tiargs->reserve(td->parameters->dim);
4689
4690 for (size_t i = 0; i < td->parameters->dim; i++)
4691 {
4692 TemplateParameter *tp = (*td->parameters)[i];
4693 size_t u = 0;
4694 for (; u < dim; u++)
4695 {
4696 Parameter *p = Parameter::getNth(tf->parameters, u);
4697 if (p->type->ty == Tident &&
4698 ((TypeIdentifier *)p->type)->ident == tp->ident)
4699 {
4700 break;
4701 }
4702 }
4703 assert(u < dim);
4704 Parameter *pto = Parameter::getNth(tof->parameters, u);
4705 Type *t = pto->type;
4706 if (t->ty == Terror)
4707 goto L1;
4708 tiargs->push(t);
4709 }
4710
4711 // Set target of return type inference
4712 if (!tf->next && tof->next)
4713 fd->treq = to;
4714
4715 TemplateInstance *ti = new TemplateInstance(loc, td, tiargs);
4716 Expression *ex = new ScopeExp(loc, ti);
4717 ex = ::semantic(ex, td->_scope);
4718
4719 // Reset inference target for the later re-semantic
4720 fd->treq = NULL;
4721
4722 if (ex->op == TOKerror)
4723 return MATCHnomatch;
4724 if (ex->op != TOKfunction)
4725 goto L1;
4726 return ((FuncExp *)ex)->matchType(to, sc, presult, flag);
4727 }
4728
4729 if (!tof || !tof->next)
4730 return MATCHnomatch;
4731
4732 assert(type && type != Type::tvoid);
4733 TypeFunction *tfx = (TypeFunction *)fd->type;
4734 bool convertMatch = (type->ty != to->ty);
4735
4736 if (fd->inferRetType && tfx->next->implicitConvTo(tof->next) == MATCHconvert)
4737 {
4738 /* If return type is inferred and covariant return,
4739 * tweak return statements to required return type.
4740 *
4741 * interface I {}
4742 * class C : Object, I{}
4743 *
4744 * I delegate() dg = delegate() { return new class C(); }
4745 */
4746 convertMatch = true;
4747
4748 TypeFunction *tfy = new TypeFunction(tfx->parameters, tof->next, tfx->varargs, tfx->linkage, STCundefined);
4749 tfy->mod = tfx->mod;
4750 tfy->isnothrow = tfx->isnothrow;
4751 tfy->isnogc = tfx->isnogc;
4752 tfy->purity = tfx->purity;
4753 tfy->isproperty = tfx->isproperty;
4754 tfy->isref = tfx->isref;
4755 tfy->iswild = tfx->iswild;
4756 tfy->deco = tfy->merge()->deco;
4757
4758 tfx = tfy;
4759 }
4760
4761 Type *tx;
4762 if (tok == TOKdelegate ||
4763 (tok == TOKreserved && (type->ty == Tdelegate ||
4764 (type->ty == Tpointer && to->ty == Tdelegate))))
4765 {
4766 // Allow conversion from implicit function pointer to delegate
4767 tx = new TypeDelegate(tfx);
4768 tx->deco = tx->merge()->deco;
4769 }
4770 else
4771 {
4772 assert(tok == TOKfunction ||
4773 (tok == TOKreserved && type->ty == Tpointer));
4774 tx = tfx->pointerTo();
4775 }
4776 //printf("\ttx = %s, to = %s\n", tx->toChars(), to->toChars());
4777
4778 MATCH m = tx->implicitConvTo(to);
4779 if (m > MATCHnomatch)
4780 {
4781 // MATCHexact: exact type match
4782 // MATCHconst: covairiant type match (eg. attributes difference)
4783 // MATCHconvert: context conversion
4784 m = convertMatch ? MATCHconvert : tx->equals(to) ? MATCHexact : MATCHconst;
4785
4786 if (presult)
4787 {
4788 (*presult) = (FuncExp *)copy();
4789 (*presult)->type = to;
4790
4791 // Bugzilla 12508: Tweak function body for covariant returns.
4792 (*presult)->fd->modifyReturns(sc, tof->next);
4793 }
4794 }
4795 else if (!flag)
4796 {
4797 error("cannot implicitly convert expression (%s) of type %s to %s",
4798 toChars(), tx->toChars(), to->toChars());
4799 }
4800 return m;
4801 }
4802
toChars()4803 const char *FuncExp::toChars()
4804 {
4805 return fd->toChars();
4806 }
4807
checkType()4808 bool FuncExp::checkType()
4809 {
4810 if (td)
4811 {
4812 error("template lambda has no type");
4813 return true;
4814 }
4815 return false;
4816 }
4817
checkValue()4818 bool FuncExp::checkValue()
4819 {
4820 if (td)
4821 {
4822 error("template lambda has no value");
4823 return true;
4824 }
4825 return false;
4826 }
4827
4828 /******************************** DeclarationExp **************************/
4829
DeclarationExp(Loc loc,Dsymbol * declaration)4830 DeclarationExp::DeclarationExp(Loc loc, Dsymbol *declaration)
4831 : Expression(loc, TOKdeclaration, sizeof(DeclarationExp))
4832 {
4833 this->declaration = declaration;
4834 }
4835
syntaxCopy()4836 Expression *DeclarationExp::syntaxCopy()
4837 {
4838 return new DeclarationExp(loc, declaration->syntaxCopy(NULL));
4839 }
4840
hasCode()4841 bool DeclarationExp::hasCode()
4842 {
4843 if (VarDeclaration *vd = declaration->isVarDeclaration())
4844 {
4845 return !(vd->storage_class & (STCmanifest | STCstatic));
4846 }
4847 return false;
4848 }
4849
4850 /************************ TypeidExp ************************************/
4851
4852 /*
4853 * typeid(int)
4854 */
4855
TypeidExp(Loc loc,RootObject * o)4856 TypeidExp::TypeidExp(Loc loc, RootObject *o)
4857 : Expression(loc, TOKtypeid, sizeof(TypeidExp))
4858 {
4859 this->obj = o;
4860 }
4861
syntaxCopy()4862 Expression *TypeidExp::syntaxCopy()
4863 {
4864 return new TypeidExp(loc, objectSyntaxCopy(obj));
4865 }
4866
4867 /************************ TraitsExp ************************************/
4868 /*
4869 * __traits(identifier, args...)
4870 */
4871
TraitsExp(Loc loc,Identifier * ident,Objects * args)4872 TraitsExp::TraitsExp(Loc loc, Identifier *ident, Objects *args)
4873 : Expression(loc, TOKtraits, sizeof(TraitsExp))
4874 {
4875 this->ident = ident;
4876 this->args = args;
4877 }
4878
syntaxCopy()4879 Expression *TraitsExp::syntaxCopy()
4880 {
4881 return new TraitsExp(loc, ident, TemplateInstance::arraySyntaxCopy(args));
4882 }
4883
4884 /************************************************************/
4885
HaltExp(Loc loc)4886 HaltExp::HaltExp(Loc loc)
4887 : Expression(loc, TOKhalt, sizeof(HaltExp))
4888 {
4889 }
4890
4891 /************************************************************/
4892
IsExp(Loc loc,Type * targ,Identifier * id,TOK tok,Type * tspec,TOK tok2,TemplateParameters * parameters)4893 IsExp::IsExp(Loc loc, Type *targ, Identifier *id, TOK tok,
4894 Type *tspec, TOK tok2, TemplateParameters *parameters)
4895 : Expression(loc, TOKis, sizeof(IsExp))
4896 {
4897 this->targ = targ;
4898 this->id = id;
4899 this->tok = tok;
4900 this->tspec = tspec;
4901 this->tok2 = tok2;
4902 this->parameters = parameters;
4903 }
4904
syntaxCopy()4905 Expression *IsExp::syntaxCopy()
4906 {
4907 // This section is identical to that in TemplateDeclaration::syntaxCopy()
4908 TemplateParameters *p = NULL;
4909 if (parameters)
4910 {
4911 p = new TemplateParameters();
4912 p->setDim(parameters->dim);
4913 for (size_t i = 0; i < p->dim; i++)
4914 (*p)[i] = (*parameters)[i]->syntaxCopy();
4915 }
4916 return new IsExp(loc,
4917 targ->syntaxCopy(),
4918 id,
4919 tok,
4920 tspec ? tspec->syntaxCopy() : NULL,
4921 tok2,
4922 p);
4923 }
4924
4925 void unSpeculative(Scope *sc, RootObject *o);
4926
4927 /************************************************************/
4928
UnaExp(Loc loc,TOK op,int size,Expression * e1)4929 UnaExp::UnaExp(Loc loc, TOK op, int size, Expression *e1)
4930 : Expression(loc, op, size)
4931 {
4932 this->e1 = e1;
4933 this->att1 = NULL;
4934 }
4935
syntaxCopy()4936 Expression *UnaExp::syntaxCopy()
4937 {
4938 UnaExp *e = (UnaExp *)copy();
4939 e->type = NULL;
4940 e->e1 = e->e1->syntaxCopy();
4941 return e;
4942 }
4943
4944 /********************************
4945 * The type for a unary expression is incompatible.
4946 * Print error message.
4947 * Returns:
4948 * ErrorExp
4949 */
incompatibleTypes()4950 Expression *UnaExp::incompatibleTypes()
4951 {
4952 if (e1->type->toBasetype() == Type::terror)
4953 return e1;
4954
4955 if (e1->op == TOKtype)
4956 {
4957 error("incompatible type for (%s(%s)): cannot use '%s' with types",
4958 Token::toChars(op), e1->toChars(), Token::toChars(op));
4959 }
4960 else
4961 {
4962 error("incompatible type for (%s(%s)): '%s'",
4963 Token::toChars(op), e1->toChars(), e1->type->toChars());
4964 }
4965 return new ErrorExp();
4966 }
4967
resolveLoc(Loc loc,Scope * sc)4968 Expression *UnaExp::resolveLoc(Loc loc, Scope *sc)
4969 {
4970 e1 = e1->resolveLoc(loc, sc);
4971 return this;
4972 }
4973
4974 /************************************************************/
4975
BinExp(Loc loc,TOK op,int size,Expression * e1,Expression * e2)4976 BinExp::BinExp(Loc loc, TOK op, int size, Expression *e1, Expression *e2)
4977 : Expression(loc, op, size)
4978 {
4979 this->e1 = e1;
4980 this->e2 = e2;
4981
4982 this->att1 = NULL;
4983 this->att2 = NULL;
4984 }
4985
syntaxCopy()4986 Expression *BinExp::syntaxCopy()
4987 {
4988 BinExp *e = (BinExp *)copy();
4989 e->type = NULL;
4990 e->e1 = e->e1->syntaxCopy();
4991 e->e2 = e->e2->syntaxCopy();
4992 return e;
4993 }
4994
checkOpAssignTypes(Scope * sc)4995 Expression *BinExp::checkOpAssignTypes(Scope *sc)
4996 {
4997 // At that point t1 and t2 are the merged types. type is the original type of the lhs.
4998 Type *t1 = e1->type;
4999 Type *t2 = e2->type;
5000
5001 // T opAssign floating yields a floating. Prevent truncating conversions (float to int).
5002 // See issue 3841.
5003 // Should we also prevent double to float (type->isfloating() && type->size() < t2 ->size()) ?
5004 if (op == TOKaddass || op == TOKminass ||
5005 op == TOKmulass || op == TOKdivass || op == TOKmodass ||
5006 op == TOKpowass)
5007 {
5008 if ((type->isintegral() && t2->isfloating()))
5009 {
5010 warning("%s %s %s is performing truncating conversion",
5011 type->toChars(), Token::toChars(op), t2->toChars());
5012 }
5013 }
5014
5015 // generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary
5016 if (op == TOKmulass || op == TOKdivass || op == TOKmodass)
5017 {
5018 // Any multiplication by an imaginary or complex number yields a complex result.
5019 // r *= c, i*=c, r*=i, i*=i are all forbidden operations.
5020 const char *opstr = Token::toChars(op);
5021 if (t1->isreal() && t2->iscomplex())
5022 {
5023 error("%s %s %s is undefined. Did you mean %s %s %s.re ?",
5024 t1->toChars(), opstr, t2->toChars(),
5025 t1->toChars(), opstr, t2->toChars());
5026 return new ErrorExp();
5027 }
5028 else if (t1->isimaginary() && t2->iscomplex())
5029 {
5030 error("%s %s %s is undefined. Did you mean %s %s %s.im ?",
5031 t1->toChars(), opstr, t2->toChars(),
5032 t1->toChars(), opstr, t2->toChars());
5033 return new ErrorExp();
5034 }
5035 else if ((t1->isreal() || t1->isimaginary()) &&
5036 t2->isimaginary())
5037 {
5038 error("%s %s %s is an undefined operation", t1->toChars(), opstr, t2->toChars());
5039 return new ErrorExp();
5040 }
5041 }
5042
5043 // generate an error if this is a nonsensical += or -=, eg real += imaginary
5044 if (op == TOKaddass || op == TOKminass)
5045 {
5046 // Addition or subtraction of a real and an imaginary is a complex result.
5047 // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
5048 if ((t1->isreal() && (t2->isimaginary() || t2->iscomplex())) ||
5049 (t1->isimaginary() && (t2->isreal() || t2->iscomplex())))
5050 {
5051 error("%s %s %s is undefined (result is complex)",
5052 t1->toChars(), Token::toChars(op), t2->toChars());
5053 return new ErrorExp();
5054 }
5055 if (type->isreal() || type->isimaginary())
5056 {
5057 assert(global.errors || t2->isfloating());
5058 e2 = e2->castTo(sc, t1);
5059 }
5060 }
5061
5062 if (op == TOKmulass)
5063 {
5064 if (t2->isfloating())
5065 {
5066 if (t1->isreal())
5067 {
5068 if (t2->isimaginary() || t2->iscomplex())
5069 {
5070 e2 = e2->castTo(sc, t1);
5071 }
5072 }
5073 else if (t1->isimaginary())
5074 {
5075 if (t2->isimaginary() || t2->iscomplex())
5076 {
5077 switch (t1->ty)
5078 {
5079 case Timaginary32: t2 = Type::tfloat32; break;
5080 case Timaginary64: t2 = Type::tfloat64; break;
5081 case Timaginary80: t2 = Type::tfloat80; break;
5082 default:
5083 assert(0);
5084 }
5085 e2 = e2->castTo(sc, t2);
5086 }
5087 }
5088 }
5089 }
5090 else if (op == TOKdivass)
5091 {
5092 if (t2->isimaginary())
5093 {
5094 if (t1->isreal())
5095 {
5096 // x/iv = i(-x/v)
5097 // Therefore, the result is 0
5098 e2 = new CommaExp(loc, e2, new RealExp(loc, CTFloat::zero, t1));
5099 e2->type = t1;
5100 Expression *e = new AssignExp(loc, e1, e2);
5101 e->type = t1;
5102 return e;
5103 }
5104 else if (t1->isimaginary())
5105 {
5106 Type *t3;
5107 switch (t1->ty)
5108 {
5109 case Timaginary32: t3 = Type::tfloat32; break;
5110 case Timaginary64: t3 = Type::tfloat64; break;
5111 case Timaginary80: t3 = Type::tfloat80; break;
5112 default:
5113 assert(0);
5114 }
5115 e2 = e2->castTo(sc, t3);
5116 Expression *e = new AssignExp(loc, e1, e2);
5117 e->type = t1;
5118 return e;
5119 }
5120 }
5121 }
5122 else if (op == TOKmodass)
5123 {
5124 if (t2->iscomplex())
5125 {
5126 error("cannot perform modulo complex arithmetic");
5127 return new ErrorExp();
5128 }
5129 }
5130 return this;
5131 }
5132
5133 /********************************
5134 * The types for a binary expression are incompatible.
5135 * Print error message.
5136 * Returns:
5137 * ErrorExp
5138 */
incompatibleTypes()5139 Expression *BinExp::incompatibleTypes()
5140 {
5141 if (e1->type->toBasetype() == Type::terror)
5142 return e1;
5143 if (e2->type->toBasetype() == Type::terror)
5144 return e2;
5145
5146 // CondExp uses 'a ? b : c' but we're comparing 'b : c'
5147 TOK thisOp = (op == TOKquestion) ? TOKcolon : op;
5148 if (e1->op == TOKtype || e2->op == TOKtype)
5149 {
5150 error("incompatible types for ((%s) %s (%s)): cannot use '%s' with types",
5151 e1->toChars(), Token::toChars(thisOp), e2->toChars(), Token::toChars(op));
5152 }
5153 else
5154 {
5155 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'",
5156 e1->toChars(), Token::toChars(thisOp), e2->toChars(),
5157 e1->type->toChars(), e2->type->toChars());
5158 }
5159 return new ErrorExp();
5160 }
5161
checkIntegralBin()5162 bool BinExp::checkIntegralBin()
5163 {
5164 bool r1 = e1->checkIntegral();
5165 bool r2 = e2->checkIntegral();
5166 return (r1 || r2);
5167 }
5168
checkArithmeticBin()5169 bool BinExp::checkArithmeticBin()
5170 {
5171 bool r1 = e1->checkArithmetic();
5172 bool r2 = e2->checkArithmetic();
5173 return (r1 || r2);
5174 }
5175
5176 /********************** BinAssignExp **************************************/
5177
BinAssignExp(Loc loc,TOK op,int size,Expression * e1,Expression * e2)5178 BinAssignExp::BinAssignExp(Loc loc, TOK op, int size, Expression *e1, Expression *e2)
5179 : BinExp(loc, op, size, e1, e2)
5180 {
5181 }
5182
isLvalue()5183 bool BinAssignExp::isLvalue()
5184 {
5185 return true;
5186 }
5187
toLvalue(Scope *,Expression *)5188 Expression *BinAssignExp::toLvalue(Scope *, Expression *)
5189 {
5190 // Lvalue-ness will be handled in glue layer.
5191 return this;
5192 }
5193
modifiableLvalue(Scope * sc,Expression *)5194 Expression *BinAssignExp::modifiableLvalue(Scope *sc, Expression *)
5195 {
5196 // should check e1->checkModifiable() ?
5197 return toLvalue(sc, this);
5198 }
5199
5200 /************************************************************/
5201
CompileExp(Loc loc,Expression * e)5202 CompileExp::CompileExp(Loc loc, Expression *e)
5203 : UnaExp(loc, TOKmixin, sizeof(CompileExp), e)
5204 {
5205 }
5206
5207 /************************************************************/
5208
ImportExp(Loc loc,Expression * e)5209 ImportExp::ImportExp(Loc loc, Expression *e)
5210 : UnaExp(loc, TOKimport, sizeof(ImportExp), e)
5211 {
5212 }
5213
5214 /************************************************************/
5215
AssertExp(Loc loc,Expression * e,Expression * msg)5216 AssertExp::AssertExp(Loc loc, Expression *e, Expression *msg)
5217 : UnaExp(loc, TOKassert, sizeof(AssertExp), e)
5218 {
5219 this->msg = msg;
5220 }
5221
syntaxCopy()5222 Expression *AssertExp::syntaxCopy()
5223 {
5224 return new AssertExp(loc, e1->syntaxCopy(), msg ? msg->syntaxCopy() : NULL);
5225 }
5226
5227 /************************************************************/
5228
DotIdExp(Loc loc,Expression * e,Identifier * ident)5229 DotIdExp::DotIdExp(Loc loc, Expression *e, Identifier *ident)
5230 : UnaExp(loc, TOKdotid, sizeof(DotIdExp), e)
5231 {
5232 this->ident = ident;
5233 this->wantsym = false;
5234 this->noderef = false;
5235 }
5236
create(Loc loc,Expression * e,Identifier * ident)5237 DotIdExp *DotIdExp::create(Loc loc, Expression *e, Identifier *ident)
5238 {
5239 return new DotIdExp(loc, e, ident);
5240 }
5241
5242 /********************** DotTemplateExp ***********************************/
5243
5244 // Mainly just a placeholder
5245
DotTemplateExp(Loc loc,Expression * e,TemplateDeclaration * td)5246 DotTemplateExp::DotTemplateExp(Loc loc, Expression *e, TemplateDeclaration *td)
5247 : UnaExp(loc, TOKdottd, sizeof(DotTemplateExp), e)
5248
5249 {
5250 this->td = td;
5251 }
5252
5253 /************************************************************/
5254
DotVarExp(Loc loc,Expression * e,Declaration * var,bool hasOverloads)5255 DotVarExp::DotVarExp(Loc loc, Expression *e, Declaration *var, bool hasOverloads)
5256 : UnaExp(loc, TOKdotvar, sizeof(DotVarExp), e)
5257 {
5258 //printf("DotVarExp()\n");
5259 this->var = var;
5260 this->hasOverloads = var->isVarDeclaration() ? false : hasOverloads;
5261 }
5262
isLvalue()5263 bool DotVarExp::isLvalue()
5264 {
5265 return true;
5266 }
5267
toLvalue(Scope *,Expression *)5268 Expression *DotVarExp::toLvalue(Scope *, Expression *)
5269 {
5270 //printf("DotVarExp::toLvalue(%s)\n", toChars());
5271 return this;
5272 }
5273
5274 /***********************************************
5275 * Mark variable v as modified if it is inside a constructor that var
5276 * is a field in.
5277 */
modifyFieldVar(Loc loc,Scope * sc,VarDeclaration * var,Expression * e1)5278 int modifyFieldVar(Loc loc, Scope *sc, VarDeclaration *var, Expression *e1)
5279 {
5280 //printf("modifyFieldVar(var = %s)\n", var->toChars());
5281 Dsymbol *s = sc->func;
5282 while (1)
5283 {
5284 FuncDeclaration *fd = NULL;
5285 if (s)
5286 fd = s->isFuncDeclaration();
5287 if (fd &&
5288 ((fd->isCtorDeclaration() && var->isField()) ||
5289 (fd->isStaticCtorDeclaration() && !var->isField())) &&
5290 fd->toParent2() == var->toParent2() &&
5291 (!e1 || e1->op == TOKthis)
5292 )
5293 {
5294 bool result = true;
5295
5296 var->ctorinit = true;
5297 //printf("setting ctorinit\n");
5298
5299 if (var->isField() && sc->fieldinit && !sc->intypeof)
5300 {
5301 assert(e1);
5302 bool mustInit = ((var->storage_class & STCnodefaultctor) != 0 ||
5303 var->type->needsNested());
5304
5305 size_t dim = sc->fieldinit_dim;
5306 AggregateDeclaration *ad = fd->isMember2();
5307 assert(ad);
5308 size_t i;
5309 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ?
5310 {
5311 if (ad->fields[i] == var)
5312 break;
5313 }
5314 assert(i < dim);
5315 unsigned fi = sc->fieldinit[i];
5316
5317 if (fi & CSXthis_ctor)
5318 {
5319 if (var->type->isMutable() && e1->type->isMutable())
5320 result = false;
5321 else
5322 {
5323 const char *modStr = !var->type->isMutable() ? MODtoChars(var->type->mod) : MODtoChars(e1->type->mod);
5324 ::error(loc, "%s field '%s' initialized multiple times", modStr, var->toChars());
5325 }
5326 }
5327 else if (sc->noctor || (fi & CSXlabel))
5328 {
5329 if (!mustInit && var->type->isMutable() && e1->type->isMutable())
5330 result = false;
5331 else
5332 {
5333 const char *modStr = !var->type->isMutable() ? MODtoChars(var->type->mod) : MODtoChars(e1->type->mod);
5334 ::error(loc, "%s field '%s' initialization is not allowed in loops or after labels", modStr, var->toChars());
5335 }
5336 }
5337 sc->fieldinit[i] |= CSXthis_ctor;
5338 if (var->overlapped) // Bugzilla 15258
5339 {
5340 for (size_t j = 0; j < ad->fields.dim; j++)
5341 {
5342 VarDeclaration *v = ad->fields[j];
5343 if (v == var || !var->isOverlappedWith(v))
5344 continue;
5345 v->ctorinit = true;
5346 sc->fieldinit[j] = CSXthis_ctor;
5347 }
5348 }
5349 }
5350 else if (fd != sc->func)
5351 {
5352 if (var->type->isMutable())
5353 result = false;
5354 else if (sc->func->fes)
5355 {
5356 const char *p = var->isField() ? "field" : var->kind();
5357 ::error(loc, "%s %s '%s' initialization is not allowed in foreach loop",
5358 MODtoChars(var->type->mod), p, var->toChars());
5359 }
5360 else
5361 {
5362 const char *p = var->isField() ? "field" : var->kind();
5363 ::error(loc, "%s %s '%s' initialization is not allowed in nested function '%s'",
5364 MODtoChars(var->type->mod), p, var->toChars(), sc->func->toChars());
5365 }
5366 }
5367 return result;
5368 }
5369 else
5370 {
5371 if (s)
5372 {
5373 s = s->toParent2();
5374 continue;
5375 }
5376 }
5377 break;
5378 }
5379 return false;
5380 }
5381
checkModifiable(Scope * sc,int flag)5382 int DotVarExp::checkModifiable(Scope *sc, int flag)
5383 {
5384 //printf("DotVarExp::checkModifiable %s %s\n", toChars(), type->toChars());
5385 if (checkUnsafeAccess(sc, this, false, !flag))
5386 return 2;
5387
5388 if (e1->op == TOKthis)
5389 return var->checkModify(loc, sc, type, e1, flag);
5390
5391 //printf("\te1 = %s\n", e1->toChars());
5392 return e1->checkModifiable(sc, flag);
5393 }
5394
modifiableLvalue(Scope * sc,Expression * e)5395 Expression *DotVarExp::modifiableLvalue(Scope *sc, Expression *e)
5396 {
5397 return Expression::modifiableLvalue(sc, e);
5398 }
5399
5400 /************************************************************/
5401
5402 /* Things like:
5403 * foo.bar!(args)
5404 */
5405
DotTemplateInstanceExp(Loc loc,Expression * e,Identifier * name,Objects * tiargs)5406 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, Identifier *name, Objects *tiargs)
5407 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e)
5408 {
5409 //printf("DotTemplateInstanceExp()\n");
5410 this->ti = new TemplateInstance(loc, name);
5411 this->ti->tiargs = tiargs;
5412 }
5413
DotTemplateInstanceExp(Loc loc,Expression * e,TemplateInstance * ti)5414 DotTemplateInstanceExp::DotTemplateInstanceExp(Loc loc, Expression *e, TemplateInstance *ti)
5415 : UnaExp(loc, TOKdotti, sizeof(DotTemplateInstanceExp), e)
5416 {
5417 this->ti = ti;
5418 }
5419
syntaxCopy()5420 Expression *DotTemplateInstanceExp::syntaxCopy()
5421 {
5422 return new DotTemplateInstanceExp(loc,
5423 e1->syntaxCopy(),
5424 ti->name,
5425 TemplateInstance::arraySyntaxCopy(ti->tiargs));
5426 }
5427
findTempDecl(Scope * sc)5428 bool DotTemplateInstanceExp::findTempDecl(Scope *sc)
5429 {
5430 if (ti->tempdecl)
5431 return true;
5432
5433 Expression *e = new DotIdExp(loc, e1, ti->name);
5434 e = semantic(e, sc);
5435 if (e->op == TOKdot)
5436 e = ((DotExp *)e)->e2;
5437
5438 Dsymbol *s = NULL;
5439 switch (e->op)
5440 {
5441 case TOKoverloadset: s = ((OverExp *)e)->vars; break;
5442 case TOKdottd: s = ((DotTemplateExp *)e)->td; break;
5443 case TOKscope: s = ((ScopeExp *)e)->sds; break;
5444 case TOKdotvar: s = ((DotVarExp *)e)->var; break;
5445 case TOKvar: s = ((VarExp *)e)->var; break;
5446 default: return false;
5447 }
5448 return ti->updateTempDecl(sc, s);
5449 }
5450
5451 /************************************************************/
5452
DelegateExp(Loc loc,Expression * e,FuncDeclaration * f,bool hasOverloads)5453 DelegateExp::DelegateExp(Loc loc, Expression *e, FuncDeclaration *f, bool hasOverloads)
5454 : UnaExp(loc, TOKdelegate, sizeof(DelegateExp), e)
5455 {
5456 this->func = f;
5457 this->hasOverloads = hasOverloads;
5458 }
5459
5460 /************************************************************/
5461
DotTypeExp(Loc loc,Expression * e,Dsymbol * s)5462 DotTypeExp::DotTypeExp(Loc loc, Expression *e, Dsymbol *s)
5463 : UnaExp(loc, TOKdottype, sizeof(DotTypeExp), e)
5464 {
5465 this->sym = s;
5466 this->type = NULL;
5467 }
5468
5469 /************************************************************/
5470
CallExp(Loc loc,Expression * e,Expressions * exps)5471 CallExp::CallExp(Loc loc, Expression *e, Expressions *exps)
5472 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5473 {
5474 this->arguments = exps;
5475 this->f = NULL;
5476 this->directcall = false;
5477 }
5478
CallExp(Loc loc,Expression * e)5479 CallExp::CallExp(Loc loc, Expression *e)
5480 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5481 {
5482 this->arguments = NULL;
5483 this->f = NULL;
5484 this->directcall = false;
5485 }
5486
CallExp(Loc loc,Expression * e,Expression * earg1)5487 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1)
5488 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5489 {
5490 Expressions *arguments = new Expressions();
5491 if (earg1)
5492 {
5493 arguments->setDim(1);
5494 (*arguments)[0] = earg1;
5495 }
5496 this->arguments = arguments;
5497 this->f = NULL;
5498 this->directcall = false;
5499 }
5500
CallExp(Loc loc,Expression * e,Expression * earg1,Expression * earg2)5501 CallExp::CallExp(Loc loc, Expression *e, Expression *earg1, Expression *earg2)
5502 : UnaExp(loc, TOKcall, sizeof(CallExp), e)
5503 {
5504 Expressions *arguments = new Expressions();
5505 arguments->setDim(2);
5506 (*arguments)[0] = earg1;
5507 (*arguments)[1] = earg2;
5508
5509 this->arguments = arguments;
5510 this->f = NULL;
5511 this->directcall = false;
5512 }
5513
create(Loc loc,Expression * e,Expressions * exps)5514 CallExp *CallExp::create(Loc loc, Expression *e, Expressions *exps)
5515 {
5516 return new CallExp(loc, e, exps);
5517 }
5518
create(Loc loc,Expression * e)5519 CallExp *CallExp::create(Loc loc, Expression *e)
5520 {
5521 return new CallExp(loc, e);
5522 }
5523
create(Loc loc,Expression * e,Expression * earg1)5524 CallExp *CallExp::create(Loc loc, Expression *e, Expression *earg1)
5525 {
5526 return new CallExp(loc, e, earg1);
5527 }
5528
syntaxCopy()5529 Expression *CallExp::syntaxCopy()
5530 {
5531 return new CallExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
5532 }
5533
isLvalue()5534 bool CallExp::isLvalue()
5535 {
5536 Type *tb = e1->type->toBasetype();
5537 if (tb->ty == Tdelegate || tb->ty == Tpointer)
5538 tb = tb->nextOf();
5539 if (tb->ty == Tfunction && ((TypeFunction *)tb)->isref)
5540 {
5541 if (e1->op == TOKdotvar)
5542 if (((DotVarExp *)e1)->var->isCtorDeclaration())
5543 return false;
5544 return true; // function returns a reference
5545 }
5546 return false;
5547 }
5548
toLvalue(Scope * sc,Expression * e)5549 Expression *CallExp::toLvalue(Scope *sc, Expression *e)
5550 {
5551 if (isLvalue())
5552 return this;
5553 return Expression::toLvalue(sc, e);
5554 }
5555
addDtorHook(Scope * sc)5556 Expression *CallExp::addDtorHook(Scope *sc)
5557 {
5558 /* Only need to add dtor hook if it's a type that needs destruction.
5559 * Use same logic as VarDeclaration::callScopeDtor()
5560 */
5561
5562 if (e1->type && e1->type->ty == Tfunction)
5563 {
5564 TypeFunction *tf = (TypeFunction *)e1->type;
5565 if (tf->isref)
5566 return this;
5567 }
5568
5569 Type *tv = type->baseElemOf();
5570 if (tv->ty == Tstruct)
5571 {
5572 TypeStruct *ts = (TypeStruct *)tv;
5573 StructDeclaration *sd = ts->sym;
5574 if (sd->dtor)
5575 {
5576 /* Type needs destruction, so declare a tmp
5577 * which the back end will recognize and call dtor on
5578 */
5579 VarDeclaration *tmp = copyToTemp(0, "__tmpfordtor", this);
5580 DeclarationExp *de = new DeclarationExp(loc, tmp);
5581 VarExp *ve = new VarExp(loc, tmp);
5582 Expression *e = new CommaExp(loc, de, ve);
5583 e = semantic(e, sc);
5584 return e;
5585 }
5586 }
5587 return this;
5588 }
5589
5590 FuncDeclaration *isFuncAddress(Expression *e, bool *hasOverloads = NULL)
5591 {
5592 if (e->op == TOKaddress)
5593 {
5594 Expression *ae1 = ((AddrExp *)e)->e1;
5595 if (ae1->op == TOKvar)
5596 {
5597 VarExp *ve = (VarExp *)ae1;
5598 if (hasOverloads)
5599 *hasOverloads = ve->hasOverloads;
5600 return ve->var->isFuncDeclaration();
5601 }
5602 if (ae1->op == TOKdotvar)
5603 {
5604 DotVarExp *dve = (DotVarExp *)ae1;
5605 if (hasOverloads)
5606 *hasOverloads = dve->hasOverloads;
5607 return dve->var->isFuncDeclaration();
5608 }
5609 }
5610 else
5611 {
5612 if (e->op == TOKsymoff)
5613 {
5614 SymOffExp *soe = (SymOffExp *)e;
5615 if (hasOverloads)
5616 *hasOverloads = soe->hasOverloads;
5617 return soe->var->isFuncDeclaration();
5618 }
5619 if (e->op == TOKdelegate)
5620 {
5621 DelegateExp *dge = (DelegateExp *)e;
5622 if (hasOverloads)
5623 *hasOverloads = dge->hasOverloads;
5624 return dge->func->isFuncDeclaration();
5625 }
5626 }
5627 return NULL;
5628 }
5629
5630 /************************************************************/
5631
AddrExp(Loc loc,Expression * e)5632 AddrExp::AddrExp(Loc loc, Expression *e)
5633 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e)
5634 {
5635 }
5636
AddrExp(Loc loc,Expression * e,Type * t)5637 AddrExp::AddrExp(Loc loc, Expression *e, Type *t)
5638 : UnaExp(loc, TOKaddress, sizeof(AddrExp), e)
5639 {
5640 type = t;
5641 }
5642
5643 /************************************************************/
5644
PtrExp(Loc loc,Expression * e)5645 PtrExp::PtrExp(Loc loc, Expression *e)
5646 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
5647 {
5648 // if (e->type)
5649 // type = ((TypePointer *)e->type)->next;
5650 }
5651
PtrExp(Loc loc,Expression * e,Type * t)5652 PtrExp::PtrExp(Loc loc, Expression *e, Type *t)
5653 : UnaExp(loc, TOKstar, sizeof(PtrExp), e)
5654 {
5655 type = t;
5656 }
5657
isLvalue()5658 bool PtrExp::isLvalue()
5659 {
5660 return true;
5661 }
5662
toLvalue(Scope *,Expression *)5663 Expression *PtrExp::toLvalue(Scope *, Expression *)
5664 {
5665 return this;
5666 }
5667
checkModifiable(Scope * sc,int flag)5668 int PtrExp::checkModifiable(Scope *sc, int flag)
5669 {
5670 if (e1->op == TOKsymoff)
5671 { SymOffExp *se = (SymOffExp *)e1;
5672 return se->var->checkModify(loc, sc, type, NULL, flag);
5673 }
5674 else if (e1->op == TOKaddress)
5675 {
5676 AddrExp *ae = (AddrExp *)e1;
5677 return ae->e1->checkModifiable(sc, flag);
5678 }
5679 return 1;
5680 }
5681
modifiableLvalue(Scope * sc,Expression * e)5682 Expression *PtrExp::modifiableLvalue(Scope *sc, Expression *e)
5683 {
5684 //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
5685 return Expression::modifiableLvalue(sc, e);
5686 }
5687
5688 /************************************************************/
5689
NegExp(Loc loc,Expression * e)5690 NegExp::NegExp(Loc loc, Expression *e)
5691 : UnaExp(loc, TOKneg, sizeof(NegExp), e)
5692 {
5693 }
5694
5695 /************************************************************/
5696
UAddExp(Loc loc,Expression * e)5697 UAddExp::UAddExp(Loc loc, Expression *e)
5698 : UnaExp(loc, TOKuadd, sizeof(UAddExp), e)
5699 {
5700 }
5701
5702 /************************************************************/
5703
ComExp(Loc loc,Expression * e)5704 ComExp::ComExp(Loc loc, Expression *e)
5705 : UnaExp(loc, TOKtilde, sizeof(ComExp), e)
5706 {
5707 }
5708
5709 /************************************************************/
5710
NotExp(Loc loc,Expression * e)5711 NotExp::NotExp(Loc loc, Expression *e)
5712 : UnaExp(loc, TOKnot, sizeof(NotExp), e)
5713 {
5714 }
5715
5716 /************************************************************/
5717
DeleteExp(Loc loc,Expression * e,bool isRAII)5718 DeleteExp::DeleteExp(Loc loc, Expression *e, bool isRAII)
5719 : UnaExp(loc, TOKdelete, sizeof(DeleteExp), e)
5720 {
5721 this->isRAII = isRAII;
5722 }
5723
toBoolean(Scope *)5724 Expression *DeleteExp::toBoolean(Scope *)
5725 {
5726 error("delete does not give a boolean result");
5727 return new ErrorExp();
5728 }
5729
5730 /************************************************************/
5731
CastExp(Loc loc,Expression * e,Type * t)5732 CastExp::CastExp(Loc loc, Expression *e, Type *t)
5733 : UnaExp(loc, TOKcast, sizeof(CastExp), e)
5734 {
5735 this->to = t;
5736 this->mod = (unsigned char)~0;
5737 }
5738
5739 /* For cast(const) and cast(immutable)
5740 */
CastExp(Loc loc,Expression * e,unsigned char mod)5741 CastExp::CastExp(Loc loc, Expression *e, unsigned char mod)
5742 : UnaExp(loc, TOKcast, sizeof(CastExp), e)
5743 {
5744 this->to = NULL;
5745 this->mod = mod;
5746 }
5747
syntaxCopy()5748 Expression *CastExp::syntaxCopy()
5749 {
5750 return to ? new CastExp(loc, e1->syntaxCopy(), to->syntaxCopy())
5751 : new CastExp(loc, e1->syntaxCopy(), mod);
5752 }
5753
5754 /************************************************************/
5755
VectorExp(Loc loc,Expression * e,Type * t)5756 VectorExp::VectorExp(Loc loc, Expression *e, Type *t)
5757 : UnaExp(loc, TOKvector, sizeof(VectorExp), e)
5758 {
5759 assert(t->ty == Tvector);
5760 to = (TypeVector *)t;
5761 dim = ~0;
5762 ownedByCtfe = OWNEDcode;
5763 }
5764
create(Loc loc,Expression * e,Type * t)5765 VectorExp *VectorExp::create(Loc loc, Expression *e, Type *t)
5766 {
5767 return new VectorExp(loc, e, t);
5768 }
5769
syntaxCopy()5770 Expression *VectorExp::syntaxCopy()
5771 {
5772 return new VectorExp(loc, e1->syntaxCopy(), to->syntaxCopy());
5773 }
5774
5775 /************************************************************/
5776
VectorArrayExp(Loc loc,Expression * e1)5777 VectorArrayExp::VectorArrayExp(Loc loc, Expression *e1)
5778 : UnaExp(loc, TOKvectorarray, sizeof(VectorArrayExp), e1)
5779 {
5780 }
5781
isLvalue()5782 bool VectorArrayExp::isLvalue()
5783 {
5784 return e1->isLvalue();
5785 }
5786
toLvalue(Scope * sc,Expression * e)5787 Expression *VectorArrayExp::toLvalue(Scope *sc, Expression *e)
5788 {
5789 e1 = e1->toLvalue(sc, e);
5790 return this;
5791 }
5792
5793 /************************************************************/
5794
SliceExp(Loc loc,Expression * e1,IntervalExp * ie)5795 SliceExp::SliceExp(Loc loc, Expression *e1, IntervalExp *ie)
5796 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1)
5797 {
5798 this->upr = ie ? ie->upr : NULL;
5799 this->lwr = ie ? ie->lwr : NULL;
5800 lengthVar = NULL;
5801 upperIsInBounds = false;
5802 lowerIsLessThanUpper = false;
5803 arrayop = false;
5804 }
5805
SliceExp(Loc loc,Expression * e1,Expression * lwr,Expression * upr)5806 SliceExp::SliceExp(Loc loc, Expression *e1, Expression *lwr, Expression *upr)
5807 : UnaExp(loc, TOKslice, sizeof(SliceExp), e1)
5808 {
5809 this->upr = upr;
5810 this->lwr = lwr;
5811 lengthVar = NULL;
5812 upperIsInBounds = false;
5813 lowerIsLessThanUpper = false;
5814 arrayop = false;
5815 }
5816
syntaxCopy()5817 Expression *SliceExp::syntaxCopy()
5818 {
5819 SliceExp *se = new SliceExp(loc, e1->syntaxCopy(),
5820 lwr ? lwr->syntaxCopy() : NULL,
5821 upr ? upr->syntaxCopy() : NULL);
5822 se->lengthVar = this->lengthVar; // bug7871
5823 return se;
5824 }
5825
checkModifiable(Scope * sc,int flag)5826 int SliceExp::checkModifiable(Scope *sc, int flag)
5827 {
5828 //printf("SliceExp::checkModifiable %s\n", toChars());
5829 if (e1->type->ty == Tsarray ||
5830 (e1->op == TOKindex && e1->type->ty != Tarray) ||
5831 e1->op == TOKslice)
5832 {
5833 return e1->checkModifiable(sc, flag);
5834 }
5835 return 1;
5836 }
5837
isLvalue()5838 bool SliceExp::isLvalue()
5839 {
5840 /* slice expression is rvalue in default, but
5841 * conversion to reference of static array is only allowed.
5842 */
5843 return (type && type->toBasetype()->ty == Tsarray);
5844 }
5845
toLvalue(Scope * sc,Expression * e)5846 Expression *SliceExp::toLvalue(Scope *sc, Expression *e)
5847 {
5848 //printf("SliceExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL);
5849 return (type && type->toBasetype()->ty == Tsarray)
5850 ? this : Expression::toLvalue(sc, e);
5851 }
5852
modifiableLvalue(Scope *,Expression *)5853 Expression *SliceExp::modifiableLvalue(Scope *, Expression *)
5854 {
5855 error("slice expression %s is not a modifiable lvalue", toChars());
5856 return this;
5857 }
5858
isBool(bool result)5859 bool SliceExp::isBool(bool result)
5860 {
5861 return e1->isBool(result);
5862 }
5863
5864 /********************** ArrayLength **************************************/
5865
ArrayLengthExp(Loc loc,Expression * e1)5866 ArrayLengthExp::ArrayLengthExp(Loc loc, Expression *e1)
5867 : UnaExp(loc, TOKarraylength, sizeof(ArrayLengthExp), e1)
5868 {
5869 }
5870
opAssignToOp(Loc loc,TOK op,Expression * e1,Expression * e2)5871 Expression *opAssignToOp(Loc loc, TOK op, Expression *e1, Expression *e2)
5872 { Expression *e;
5873
5874 switch (op)
5875 {
5876 case TOKaddass: e = new AddExp(loc, e1, e2); break;
5877 case TOKminass: e = new MinExp(loc, e1, e2); break;
5878 case TOKmulass: e = new MulExp(loc, e1, e2); break;
5879 case TOKdivass: e = new DivExp(loc, e1, e2); break;
5880 case TOKmodass: e = new ModExp(loc, e1, e2); break;
5881 case TOKandass: e = new AndExp(loc, e1, e2); break;
5882 case TOKorass: e = new OrExp (loc, e1, e2); break;
5883 case TOKxorass: e = new XorExp(loc, e1, e2); break;
5884 case TOKshlass: e = new ShlExp(loc, e1, e2); break;
5885 case TOKshrass: e = new ShrExp(loc, e1, e2); break;
5886 case TOKushrass: e = new UshrExp(loc, e1, e2); break;
5887 default: assert(0);
5888 }
5889 return e;
5890 }
5891
5892 /*********************
5893 * Rewrite:
5894 * array.length op= e2
5895 * as:
5896 * array.length = array.length op e2
5897 * or:
5898 * auto tmp = &array;
5899 * (*tmp).length = (*tmp).length op e2
5900 */
5901
rewriteOpAssign(BinExp * exp)5902 Expression *ArrayLengthExp::rewriteOpAssign(BinExp *exp)
5903 {
5904 Expression *e;
5905
5906 assert(exp->e1->op == TOKarraylength);
5907 ArrayLengthExp *ale = (ArrayLengthExp *)exp->e1;
5908 if (ale->e1->op == TOKvar)
5909 {
5910 e = opAssignToOp(exp->loc, exp->op, ale, exp->e2);
5911 e = new AssignExp(exp->loc, ale->syntaxCopy(), e);
5912 }
5913 else
5914 {
5915 /* auto tmp = &array;
5916 * (*tmp).length = (*tmp).length op e2
5917 */
5918 VarDeclaration *tmp = copyToTemp(0, "__arraylength", new AddrExp(ale->loc, ale->e1));
5919
5920 Expression *e1 = new ArrayLengthExp(ale->loc, new PtrExp(ale->loc, new VarExp(ale->loc, tmp)));
5921 Expression *elvalue = e1->syntaxCopy();
5922 e = opAssignToOp(exp->loc, exp->op, e1, exp->e2);
5923 e = new AssignExp(exp->loc, elvalue, e);
5924 e = new CommaExp(exp->loc, new DeclarationExp(ale->loc, tmp), e);
5925 }
5926 return e;
5927 }
5928
5929 /*********************** IntervalExp ********************************/
5930
5931 // Mainly just a placeholder
5932
IntervalExp(Loc loc,Expression * lwr,Expression * upr)5933 IntervalExp::IntervalExp(Loc loc, Expression *lwr, Expression *upr)
5934 : Expression(loc, TOKinterval, sizeof(IntervalExp))
5935 {
5936 this->lwr = lwr;
5937 this->upr = upr;
5938 }
5939
syntaxCopy()5940 Expression *IntervalExp::syntaxCopy()
5941 {
5942 return new IntervalExp(loc, lwr->syntaxCopy(), upr->syntaxCopy());
5943 }
5944
5945 /********************** DelegatePtrExp **************************************/
5946
DelegatePtrExp(Loc loc,Expression * e1)5947 DelegatePtrExp::DelegatePtrExp(Loc loc, Expression *e1)
5948 : UnaExp(loc, TOKdelegateptr, sizeof(DelegatePtrExp), e1)
5949 {
5950 }
5951
isLvalue()5952 bool DelegatePtrExp::isLvalue()
5953 {
5954 return e1->isLvalue();
5955 }
5956
toLvalue(Scope * sc,Expression * e)5957 Expression *DelegatePtrExp::toLvalue(Scope *sc, Expression *e)
5958 {
5959 e1 = e1->toLvalue(sc, e);
5960 return this;
5961 }
5962
modifiableLvalue(Scope * sc,Expression * e)5963 Expression *DelegatePtrExp::modifiableLvalue(Scope *sc, Expression *e)
5964 {
5965 if (sc->func->setUnsafe())
5966 {
5967 error("cannot modify delegate pointer in @safe code %s", toChars());
5968 return new ErrorExp();
5969 }
5970 return Expression::modifiableLvalue(sc, e);
5971 }
5972
5973 /********************** DelegateFuncptrExp **************************************/
5974
DelegateFuncptrExp(Loc loc,Expression * e1)5975 DelegateFuncptrExp::DelegateFuncptrExp(Loc loc, Expression *e1)
5976 : UnaExp(loc, TOKdelegatefuncptr, sizeof(DelegateFuncptrExp), e1)
5977 {
5978 }
5979
isLvalue()5980 bool DelegateFuncptrExp::isLvalue()
5981 {
5982 return e1->isLvalue();
5983 }
5984
toLvalue(Scope * sc,Expression * e)5985 Expression *DelegateFuncptrExp::toLvalue(Scope *sc, Expression *e)
5986 {
5987 e1 = e1->toLvalue(sc, e);
5988 return this;
5989 }
5990
modifiableLvalue(Scope * sc,Expression * e)5991 Expression *DelegateFuncptrExp::modifiableLvalue(Scope *sc, Expression *e)
5992 {
5993 if (sc->func->setUnsafe())
5994 {
5995 error("cannot modify delegate function pointer in @safe code %s", toChars());
5996 return new ErrorExp();
5997 }
5998 return Expression::modifiableLvalue(sc, e);
5999 }
6000
6001 /*********************** ArrayExp *************************************/
6002
6003 // e1 [ i1, i2, i3, ... ]
6004
ArrayExp(Loc loc,Expression * e1,Expression * index)6005 ArrayExp::ArrayExp(Loc loc, Expression *e1, Expression *index)
6006 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1)
6007 {
6008 arguments = new Expressions();
6009 if (index)
6010 arguments->push(index);
6011 lengthVar = NULL;
6012 currentDimension = 0;
6013 }
6014
ArrayExp(Loc loc,Expression * e1,Expressions * args)6015 ArrayExp::ArrayExp(Loc loc, Expression *e1, Expressions *args)
6016 : UnaExp(loc, TOKarray, sizeof(ArrayExp), e1)
6017 {
6018 arguments = args;
6019 lengthVar = NULL;
6020 currentDimension = 0;
6021 }
6022
syntaxCopy()6023 Expression *ArrayExp::syntaxCopy()
6024 {
6025 ArrayExp *ae = new ArrayExp(loc, e1->syntaxCopy(), arraySyntaxCopy(arguments));
6026 ae->lengthVar = this->lengthVar; // bug7871
6027 return ae;
6028 }
6029
isLvalue()6030 bool ArrayExp::isLvalue()
6031 {
6032 if (type && type->toBasetype()->ty == Tvoid)
6033 return false;
6034 return true;
6035 }
6036
toLvalue(Scope *,Expression *)6037 Expression *ArrayExp::toLvalue(Scope *, Expression *)
6038 {
6039 if (type && type->toBasetype()->ty == Tvoid)
6040 error("voids have no value");
6041 return this;
6042 }
6043
6044 /************************* DotExp ***********************************/
6045
DotExp(Loc loc,Expression * e1,Expression * e2)6046 DotExp::DotExp(Loc loc, Expression *e1, Expression *e2)
6047 : BinExp(loc, TOKdot, sizeof(DotExp), e1, e2)
6048 {
6049 }
6050
6051 /************************* CommaExp ***********************************/
6052
CommaExp(Loc loc,Expression * e1,Expression * e2,bool generated)6053 CommaExp::CommaExp(Loc loc, Expression *e1, Expression *e2, bool generated)
6054 : BinExp(loc, TOKcomma, sizeof(CommaExp), e1, e2)
6055 {
6056 isGenerated = generated;
6057 allowCommaExp = generated;
6058 }
6059
isLvalue()6060 bool CommaExp::isLvalue()
6061 {
6062 return e2->isLvalue();
6063 }
6064
toLvalue(Scope * sc,Expression *)6065 Expression *CommaExp::toLvalue(Scope *sc, Expression *)
6066 {
6067 e2 = e2->toLvalue(sc, NULL);
6068 return this;
6069 }
6070
checkModifiable(Scope * sc,int flag)6071 int CommaExp::checkModifiable(Scope *sc, int flag)
6072 {
6073 return e2->checkModifiable(sc, flag);
6074 }
6075
modifiableLvalue(Scope * sc,Expression * e)6076 Expression *CommaExp::modifiableLvalue(Scope *sc, Expression *e)
6077 {
6078 e2 = e2->modifiableLvalue(sc, e);
6079 return this;
6080 }
6081
isBool(bool result)6082 bool CommaExp::isBool(bool result)
6083 {
6084 return e2->isBool(result);
6085 }
6086
toBoolean(Scope * sc)6087 Expression *CommaExp::toBoolean(Scope *sc)
6088 {
6089 Expression *ex2 = e2->toBoolean(sc);
6090 if (ex2->op == TOKerror)
6091 return ex2;
6092 e2 = ex2;
6093 type = e2->type;
6094 return this;
6095 }
6096
addDtorHook(Scope * sc)6097 Expression *CommaExp::addDtorHook(Scope *sc)
6098 {
6099 e2 = e2->addDtorHook(sc);
6100 return this;
6101 }
6102
6103 /************************** IndexExp **********************************/
6104
6105 // e1 [ e2 ]
6106
IndexExp(Loc loc,Expression * e1,Expression * e2)6107 IndexExp::IndexExp(Loc loc, Expression *e1, Expression *e2)
6108 : BinExp(loc, TOKindex, sizeof(IndexExp), e1, e2)
6109 {
6110 //printf("IndexExp::IndexExp('%s')\n", toChars());
6111 lengthVar = NULL;
6112 modifiable = false; // assume it is an rvalue
6113 indexIsInBounds = false;
6114 }
6115
syntaxCopy()6116 Expression *IndexExp::syntaxCopy()
6117 {
6118 IndexExp *ie = new IndexExp(loc, e1->syntaxCopy(), e2->syntaxCopy());
6119 ie->lengthVar = this->lengthVar; // bug7871
6120 return ie;
6121 }
6122
isLvalue()6123 bool IndexExp::isLvalue()
6124 {
6125 return true;
6126 }
6127
toLvalue(Scope *,Expression *)6128 Expression *IndexExp::toLvalue(Scope *, Expression *)
6129 {
6130 return this;
6131 }
6132
checkModifiable(Scope * sc,int flag)6133 int IndexExp::checkModifiable(Scope *sc, int flag)
6134 {
6135 if (e1->type->ty == Tsarray ||
6136 e1->type->ty == Taarray ||
6137 (e1->op == TOKindex && e1->type->ty != Tarray) ||
6138 e1->op == TOKslice)
6139 {
6140 return e1->checkModifiable(sc, flag);
6141 }
6142 return 1;
6143 }
6144
modifiableLvalue(Scope * sc,Expression * e)6145 Expression *IndexExp::modifiableLvalue(Scope *sc, Expression *e)
6146 {
6147 //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
6148 Expression *ex = markSettingAAElem();
6149 if (ex->op == TOKerror)
6150 return ex;
6151
6152 return Expression::modifiableLvalue(sc, e);
6153 }
6154
markSettingAAElem()6155 Expression *IndexExp::markSettingAAElem()
6156 {
6157 if (e1->type->toBasetype()->ty == Taarray)
6158 {
6159 Type *t2b = e2->type->toBasetype();
6160 if (t2b->ty == Tarray && t2b->nextOf()->isMutable())
6161 {
6162 error("associative arrays can only be assigned values with immutable keys, not %s", e2->type->toChars());
6163 return new ErrorExp();
6164 }
6165 modifiable = true;
6166
6167 if (e1->op == TOKindex)
6168 {
6169 Expression *ex = ((IndexExp *)e1)->markSettingAAElem();
6170 if (ex->op == TOKerror)
6171 return ex;
6172 assert(ex == e1);
6173 }
6174 }
6175 return this;
6176 }
6177
6178 /************************* PostExp ***********************************/
6179
PostExp(TOK op,Loc loc,Expression * e)6180 PostExp::PostExp(TOK op, Loc loc, Expression *e)
6181 : BinExp(loc, op, sizeof(PostExp), e,
6182 new IntegerExp(loc, 1, Type::tint32))
6183 {
6184 }
6185
6186 /************************* PreExp ***********************************/
6187
PreExp(TOK op,Loc loc,Expression * e)6188 PreExp::PreExp(TOK op, Loc loc, Expression *e)
6189 : UnaExp(loc, op, sizeof(PreExp), e)
6190 {
6191 }
6192
6193 /************************************************************/
6194
6195 /* op can be TOKassign, TOKconstruct, or TOKblit */
6196
AssignExp(Loc loc,Expression * e1,Expression * e2)6197 AssignExp::AssignExp(Loc loc, Expression *e1, Expression *e2)
6198 : BinExp(loc, TOKassign, sizeof(AssignExp), e1, e2)
6199 {
6200 memset = 0;
6201 }
6202
isLvalue()6203 bool AssignExp::isLvalue()
6204 {
6205 // Array-op 'x[] = y[]' should make an rvalue.
6206 // Setting array length 'x.length = v' should make an rvalue.
6207 if (e1->op == TOKslice ||
6208 e1->op == TOKarraylength)
6209 {
6210 return false;
6211 }
6212 return true;
6213 }
6214
toLvalue(Scope * sc,Expression * ex)6215 Expression *AssignExp::toLvalue(Scope *sc, Expression *ex)
6216 {
6217 if (e1->op == TOKslice ||
6218 e1->op == TOKarraylength)
6219 {
6220 return Expression::toLvalue(sc, ex);
6221 }
6222
6223 /* In front-end level, AssignExp should make an lvalue of e1.
6224 * Taking the address of e1 will be handled in low level layer,
6225 * so this function does nothing.
6226 */
6227 return this;
6228 }
6229
toBoolean(Scope *)6230 Expression *AssignExp::toBoolean(Scope *)
6231 {
6232 // Things like:
6233 // if (a = b) ...
6234 // are usually mistakes.
6235
6236 error("assignment cannot be used as a condition, perhaps == was meant?");
6237 return new ErrorExp();
6238 }
6239
6240 /************************************************************/
6241
ConstructExp(Loc loc,Expression * e1,Expression * e2)6242 ConstructExp::ConstructExp(Loc loc, Expression *e1, Expression *e2)
6243 : AssignExp(loc, e1, e2)
6244 {
6245 op = TOKconstruct;
6246 }
6247
ConstructExp(Loc loc,VarDeclaration * v,Expression * e2)6248 ConstructExp::ConstructExp(Loc loc, VarDeclaration *v, Expression *e2)
6249 : AssignExp(loc, new VarExp(loc, v), e2)
6250 {
6251 assert(v->type && e1->type);
6252 op = TOKconstruct;
6253
6254 if (v->storage_class & (STCref | STCout))
6255 memset |= referenceInit;
6256 }
6257
6258 /************************************************************/
6259
BlitExp(Loc loc,Expression * e1,Expression * e2)6260 BlitExp::BlitExp(Loc loc, Expression *e1, Expression *e2)
6261 : AssignExp(loc, e1, e2)
6262 {
6263 op = TOKblit;
6264 }
6265
BlitExp(Loc loc,VarDeclaration * v,Expression * e2)6266 BlitExp::BlitExp(Loc loc, VarDeclaration *v, Expression *e2)
6267 : AssignExp(loc, new VarExp(loc, v), e2)
6268 {
6269 assert(v->type && e1->type);
6270 op = TOKblit;
6271
6272 if (v->storage_class & (STCref | STCout))
6273 memset |= referenceInit;
6274 }
6275
6276 /************************************************************/
6277
AddAssignExp(Loc loc,Expression * e1,Expression * e2)6278 AddAssignExp::AddAssignExp(Loc loc, Expression *e1, Expression *e2)
6279 : BinAssignExp(loc, TOKaddass, sizeof(AddAssignExp), e1, e2)
6280 {
6281 }
6282
6283 /************************************************************/
6284
MinAssignExp(Loc loc,Expression * e1,Expression * e2)6285 MinAssignExp::MinAssignExp(Loc loc, Expression *e1, Expression *e2)
6286 : BinAssignExp(loc, TOKminass, sizeof(MinAssignExp), e1, e2)
6287 {
6288 }
6289
6290 /************************************************************/
6291
CatAssignExp(Loc loc,Expression * e1,Expression * e2)6292 CatAssignExp::CatAssignExp(Loc loc, Expression *e1, Expression *e2)
6293 : BinAssignExp(loc, TOKcatass, sizeof(CatAssignExp), e1, e2)
6294 {
6295 }
6296
6297 /************************************************************/
6298
MulAssignExp(Loc loc,Expression * e1,Expression * e2)6299 MulAssignExp::MulAssignExp(Loc loc, Expression *e1, Expression *e2)
6300 : BinAssignExp(loc, TOKmulass, sizeof(MulAssignExp), e1, e2)
6301 {
6302 }
6303
6304 /************************************************************/
6305
DivAssignExp(Loc loc,Expression * e1,Expression * e2)6306 DivAssignExp::DivAssignExp(Loc loc, Expression *e1, Expression *e2)
6307 : BinAssignExp(loc, TOKdivass, sizeof(DivAssignExp), e1, e2)
6308 {
6309 }
6310
6311 /************************************************************/
6312
ModAssignExp(Loc loc,Expression * e1,Expression * e2)6313 ModAssignExp::ModAssignExp(Loc loc, Expression *e1, Expression *e2)
6314 : BinAssignExp(loc, TOKmodass, sizeof(ModAssignExp), e1, e2)
6315 {
6316 }
6317
6318 /************************************************************/
6319
ShlAssignExp(Loc loc,Expression * e1,Expression * e2)6320 ShlAssignExp::ShlAssignExp(Loc loc, Expression *e1, Expression *e2)
6321 : BinAssignExp(loc, TOKshlass, sizeof(ShlAssignExp), e1, e2)
6322 {
6323 }
6324
6325 /************************************************************/
6326
ShrAssignExp(Loc loc,Expression * e1,Expression * e2)6327 ShrAssignExp::ShrAssignExp(Loc loc, Expression *e1, Expression *e2)
6328 : BinAssignExp(loc, TOKshrass, sizeof(ShrAssignExp), e1, e2)
6329 {
6330 }
6331
6332 /************************************************************/
6333
UshrAssignExp(Loc loc,Expression * e1,Expression * e2)6334 UshrAssignExp::UshrAssignExp(Loc loc, Expression *e1, Expression *e2)
6335 : BinAssignExp(loc, TOKushrass, sizeof(UshrAssignExp), e1, e2)
6336 {
6337 }
6338
6339 /************************************************************/
6340
AndAssignExp(Loc loc,Expression * e1,Expression * e2)6341 AndAssignExp::AndAssignExp(Loc loc, Expression *e1, Expression *e2)
6342 : BinAssignExp(loc, TOKandass, sizeof(AndAssignExp), e1, e2)
6343 {
6344 }
6345
6346 /************************************************************/
6347
OrAssignExp(Loc loc,Expression * e1,Expression * e2)6348 OrAssignExp::OrAssignExp(Loc loc, Expression *e1, Expression *e2)
6349 : BinAssignExp(loc, TOKorass, sizeof(OrAssignExp), e1, e2)
6350 {
6351 }
6352
6353 /************************************************************/
6354
XorAssignExp(Loc loc,Expression * e1,Expression * e2)6355 XorAssignExp::XorAssignExp(Loc loc, Expression *e1, Expression *e2)
6356 : BinAssignExp(loc, TOKxorass, sizeof(XorAssignExp), e1, e2)
6357 {
6358 }
6359
6360 /***************** PowAssignExp *******************************************/
6361
PowAssignExp(Loc loc,Expression * e1,Expression * e2)6362 PowAssignExp::PowAssignExp(Loc loc, Expression *e1, Expression *e2)
6363 : BinAssignExp(loc, TOKpowass, sizeof(PowAssignExp), e1, e2)
6364 {
6365 }
6366
6367 /************************* AddExp *****************************/
6368
AddExp(Loc loc,Expression * e1,Expression * e2)6369 AddExp::AddExp(Loc loc, Expression *e1, Expression *e2)
6370 : BinExp(loc, TOKadd, sizeof(AddExp), e1, e2)
6371 {
6372 }
6373
6374 /************************************************************/
6375
MinExp(Loc loc,Expression * e1,Expression * e2)6376 MinExp::MinExp(Loc loc, Expression *e1, Expression *e2)
6377 : BinExp(loc, TOKmin, sizeof(MinExp), e1, e2)
6378 {
6379 }
6380
6381 /************************* CatExp *****************************/
6382
CatExp(Loc loc,Expression * e1,Expression * e2)6383 CatExp::CatExp(Loc loc, Expression *e1, Expression *e2)
6384 : BinExp(loc, TOKcat, sizeof(CatExp), e1, e2)
6385 {
6386 }
6387
6388 /************************************************************/
6389
MulExp(Loc loc,Expression * e1,Expression * e2)6390 MulExp::MulExp(Loc loc, Expression *e1, Expression *e2)
6391 : BinExp(loc, TOKmul, sizeof(MulExp), e1, e2)
6392 {
6393 }
6394
6395 /************************************************************/
6396
DivExp(Loc loc,Expression * e1,Expression * e2)6397 DivExp::DivExp(Loc loc, Expression *e1, Expression *e2)
6398 : BinExp(loc, TOKdiv, sizeof(DivExp), e1, e2)
6399 {
6400 }
6401
6402 /************************************************************/
6403
ModExp(Loc loc,Expression * e1,Expression * e2)6404 ModExp::ModExp(Loc loc, Expression *e1, Expression *e2)
6405 : BinExp(loc, TOKmod, sizeof(ModExp), e1, e2)
6406 {
6407 }
6408
6409 /************************************************************/
6410
PowExp(Loc loc,Expression * e1,Expression * e2)6411 PowExp::PowExp(Loc loc, Expression *e1, Expression *e2)
6412 : BinExp(loc, TOKpow, sizeof(PowExp), e1, e2)
6413 {
6414 }
6415
6416 /************************************************************/
6417
ShlExp(Loc loc,Expression * e1,Expression * e2)6418 ShlExp::ShlExp(Loc loc, Expression *e1, Expression *e2)
6419 : BinExp(loc, TOKshl, sizeof(ShlExp), e1, e2)
6420 {
6421 }
6422
6423 /************************************************************/
6424
ShrExp(Loc loc,Expression * e1,Expression * e2)6425 ShrExp::ShrExp(Loc loc, Expression *e1, Expression *e2)
6426 : BinExp(loc, TOKshr, sizeof(ShrExp), e1, e2)
6427 {
6428 }
6429
6430 /************************************************************/
6431
UshrExp(Loc loc,Expression * e1,Expression * e2)6432 UshrExp::UshrExp(Loc loc, Expression *e1, Expression *e2)
6433 : BinExp(loc, TOKushr, sizeof(UshrExp), e1, e2)
6434 {
6435 }
6436
6437 /************************************************************/
6438
AndExp(Loc loc,Expression * e1,Expression * e2)6439 AndExp::AndExp(Loc loc, Expression *e1, Expression *e2)
6440 : BinExp(loc, TOKand, sizeof(AndExp), e1, e2)
6441 {
6442 }
6443
6444 /************************************************************/
6445
OrExp(Loc loc,Expression * e1,Expression * e2)6446 OrExp::OrExp(Loc loc, Expression *e1, Expression *e2)
6447 : BinExp(loc, TOKor, sizeof(OrExp), e1, e2)
6448 {
6449 }
6450
6451 /************************************************************/
6452
XorExp(Loc loc,Expression * e1,Expression * e2)6453 XorExp::XorExp(Loc loc, Expression *e1, Expression *e2)
6454 : BinExp(loc, TOKxor, sizeof(XorExp), e1, e2)
6455 {
6456 }
6457
6458 /************************************************************/
6459
OrOrExp(Loc loc,Expression * e1,Expression * e2)6460 OrOrExp::OrOrExp(Loc loc, Expression *e1, Expression *e2)
6461 : BinExp(loc, TOKoror, sizeof(OrOrExp), e1, e2)
6462 {
6463 }
6464
toBoolean(Scope * sc)6465 Expression *OrOrExp::toBoolean(Scope *sc)
6466 {
6467 Expression *ex2 = e2->toBoolean(sc);
6468 if (ex2->op == TOKerror)
6469 return ex2;
6470 e2 = ex2;
6471 return this;
6472 }
6473
6474 /************************************************************/
6475
AndAndExp(Loc loc,Expression * e1,Expression * e2)6476 AndAndExp::AndAndExp(Loc loc, Expression *e1, Expression *e2)
6477 : BinExp(loc, TOKandand, sizeof(AndAndExp), e1, e2)
6478 {
6479 }
6480
toBoolean(Scope * sc)6481 Expression *AndAndExp::toBoolean(Scope *sc)
6482 {
6483 Expression *ex2 = e2->toBoolean(sc);
6484 if (ex2->op == TOKerror)
6485 return ex2;
6486 e2 = ex2;
6487 return this;
6488 }
6489
6490 /************************************************************/
6491
InExp(Loc loc,Expression * e1,Expression * e2)6492 InExp::InExp(Loc loc, Expression *e1, Expression *e2)
6493 : BinExp(loc, TOKin, sizeof(InExp), e1, e2)
6494 {
6495 }
6496
6497 /************************************************************/
6498
6499 /* This deletes the key e1 from the associative array e2
6500 */
6501
RemoveExp(Loc loc,Expression * e1,Expression * e2)6502 RemoveExp::RemoveExp(Loc loc, Expression *e1, Expression *e2)
6503 : BinExp(loc, TOKremove, sizeof(RemoveExp), e1, e2)
6504 {
6505 type = Type::tbool;
6506 }
6507
6508 /************************************************************/
6509
CmpExp(TOK op,Loc loc,Expression * e1,Expression * e2)6510 CmpExp::CmpExp(TOK op, Loc loc, Expression *e1, Expression *e2)
6511 : BinExp(loc, op, sizeof(CmpExp), e1, e2)
6512 {
6513 }
6514
6515 /************************************************************/
6516
EqualExp(TOK op,Loc loc,Expression * e1,Expression * e2)6517 EqualExp::EqualExp(TOK op, Loc loc, Expression *e1, Expression *e2)
6518 : BinExp(loc, op, sizeof(EqualExp), e1, e2)
6519 {
6520 assert(op == TOKequal || op == TOKnotequal);
6521 }
6522
6523 /************************************************************/
6524
IdentityExp(TOK op,Loc loc,Expression * e1,Expression * e2)6525 IdentityExp::IdentityExp(TOK op, Loc loc, Expression *e1, Expression *e2)
6526 : BinExp(loc, op, sizeof(IdentityExp), e1, e2)
6527 {
6528 }
6529
6530 /****************************************************************/
6531
CondExp(Loc loc,Expression * econd,Expression * e1,Expression * e2)6532 CondExp::CondExp(Loc loc, Expression *econd, Expression *e1, Expression *e2)
6533 : BinExp(loc, TOKquestion, sizeof(CondExp), e1, e2)
6534 {
6535 this->econd = econd;
6536 }
6537
syntaxCopy()6538 Expression *CondExp::syntaxCopy()
6539 {
6540 return new CondExp(loc, econd->syntaxCopy(), e1->syntaxCopy(), e2->syntaxCopy());
6541 }
6542
hookDtors(Scope * sc)6543 void CondExp::hookDtors(Scope *sc)
6544 {
6545 class DtorVisitor : public StoppableVisitor
6546 {
6547 public:
6548 Scope *sc;
6549 CondExp *ce;
6550 VarDeclaration *vcond;
6551 bool isThen;
6552
6553 DtorVisitor(Scope *sc, CondExp *ce)
6554 {
6555 this->sc = sc;
6556 this->ce = ce;
6557 this->vcond = NULL;
6558 }
6559
6560 void visit(Expression *)
6561 {
6562 //printf("(e = %s)\n", e->toChars());
6563 }
6564
6565 void visit(DeclarationExp *e)
6566 {
6567 VarDeclaration *v = e->declaration->isVarDeclaration();
6568 if (v && !v->isDataseg())
6569 {
6570 if (v->_init)
6571 {
6572 ExpInitializer *ei = v->_init->isExpInitializer();
6573 if (ei)
6574 ei->exp->accept(this);
6575 }
6576
6577 if (v->needsScopeDtor())
6578 {
6579 if (!vcond)
6580 {
6581 vcond = copyToTemp(STCvolatile, "__cond", ce->econd);
6582 vcond->semantic(sc);
6583
6584 Expression *de = new DeclarationExp(ce->econd->loc, vcond);
6585 de = semantic(de, sc);
6586
6587 Expression *ve = new VarExp(ce->econd->loc, vcond);
6588 ce->econd = Expression::combine(de, ve);
6589 }
6590
6591 //printf("\t++v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
6592 Expression *ve = new VarExp(vcond->loc, vcond);
6593 if (isThen)
6594 v->edtor = new AndAndExp(v->edtor->loc, ve, v->edtor);
6595 else
6596 v->edtor = new OrOrExp(v->edtor->loc, ve, v->edtor);
6597 v->edtor = semantic(v->edtor, sc);
6598 //printf("\t--v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
6599 }
6600 }
6601 }
6602 };
6603
6604 DtorVisitor v(sc, this);
6605 //printf("+%s\n", toChars());
6606 v.isThen = true; walkPostorder(e1, &v);
6607 v.isThen = false; walkPostorder(e2, &v);
6608 //printf("-%s\n", toChars());
6609 }
6610
isLvalue()6611 bool CondExp::isLvalue()
6612 {
6613 return e1->isLvalue() && e2->isLvalue();
6614 }
6615
6616
toLvalue(Scope * sc,Expression *)6617 Expression *CondExp::toLvalue(Scope *sc, Expression *)
6618 {
6619 // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
6620 CondExp *e = (CondExp *)copy();
6621 e->e1 = e1->toLvalue(sc, NULL)->addressOf();
6622 e->e2 = e2->toLvalue(sc, NULL)->addressOf();
6623 e->type = type->pointerTo();
6624 return new PtrExp(loc, e, type);
6625 }
6626
checkModifiable(Scope * sc,int flag)6627 int CondExp::checkModifiable(Scope *sc, int flag)
6628 {
6629 return e1->checkModifiable(sc, flag) && e2->checkModifiable(sc, flag);
6630 }
6631
modifiableLvalue(Scope * sc,Expression *)6632 Expression *CondExp::modifiableLvalue(Scope *sc, Expression *)
6633 {
6634 //error("conditional expression %s is not a modifiable lvalue", toChars());
6635 e1 = e1->modifiableLvalue(sc, e1);
6636 e2 = e2->modifiableLvalue(sc, e2);
6637 return toLvalue(sc, this);
6638 }
6639
toBoolean(Scope * sc)6640 Expression *CondExp::toBoolean(Scope *sc)
6641 {
6642 Expression *ex1 = e1->toBoolean(sc);
6643 Expression *ex2 = e2->toBoolean(sc);
6644 if (ex1->op == TOKerror)
6645 return ex1;
6646 if (ex2->op == TOKerror)
6647 return ex2;
6648 e1 = ex1;
6649 e2 = ex2;
6650 return this;
6651 }
6652
6653 /****************************************************************/
6654
DefaultInitExp(Loc loc,TOK subop,int size)6655 DefaultInitExp::DefaultInitExp(Loc loc, TOK subop, int size)
6656 : Expression(loc, TOKdefault, size)
6657 {
6658 this->subop = subop;
6659 }
6660
6661 /****************************************************************/
6662
FileInitExp(Loc loc,TOK tok)6663 FileInitExp::FileInitExp(Loc loc, TOK tok)
6664 : DefaultInitExp(loc, tok, sizeof(FileInitExp))
6665 {
6666 }
6667
resolveLoc(Loc loc,Scope * sc)6668 Expression *FileInitExp::resolveLoc(Loc loc, Scope *sc)
6669 {
6670 //printf("FileInitExp::resolve() %s\n", toChars());
6671 const char *s = loc.filename ? loc.filename : sc->_module->ident->toChars();
6672 if (subop == TOKfilefullpath)
6673 s = FileName::combine(sc->_module->srcfilePath, s);
6674 Expression *e = new StringExp(loc, const_cast<char *>(s));
6675 e = semantic(e, sc);
6676 e = e->castTo(sc, type);
6677 return e;
6678 }
6679
6680 /****************************************************************/
6681
LineInitExp(Loc loc)6682 LineInitExp::LineInitExp(Loc loc)
6683 : DefaultInitExp(loc, TOKline, sizeof(LineInitExp))
6684 {
6685 }
6686
resolveLoc(Loc loc,Scope * sc)6687 Expression *LineInitExp::resolveLoc(Loc loc, Scope *sc)
6688 {
6689 Expression *e = new IntegerExp(loc, loc.linnum, Type::tint32);
6690 e = e->castTo(sc, type);
6691 return e;
6692 }
6693
6694 /****************************************************************/
6695
ModuleInitExp(Loc loc)6696 ModuleInitExp::ModuleInitExp(Loc loc)
6697 : DefaultInitExp(loc, TOKmodulestring, sizeof(ModuleInitExp))
6698 {
6699 }
6700
resolveLoc(Loc loc,Scope * sc)6701 Expression *ModuleInitExp::resolveLoc(Loc loc, Scope *sc)
6702 {
6703 const char *s;
6704 if (sc->callsc)
6705 s = sc->callsc->_module->toPrettyChars();
6706 else
6707 s = sc->_module->toPrettyChars();
6708 Expression *e = new StringExp(loc, const_cast<char *>(s));
6709 e = semantic(e, sc);
6710 e = e->castTo(sc, type);
6711 return e;
6712 }
6713
6714 /****************************************************************/
6715
FuncInitExp(Loc loc)6716 FuncInitExp::FuncInitExp(Loc loc)
6717 : DefaultInitExp(loc, TOKfuncstring, sizeof(FuncInitExp))
6718 {
6719 }
6720
resolveLoc(Loc loc,Scope * sc)6721 Expression *FuncInitExp::resolveLoc(Loc loc, Scope *sc)
6722 {
6723 const char *s;
6724 if (sc->callsc && sc->callsc->func)
6725 s = sc->callsc->func->Dsymbol::toPrettyChars();
6726 else if (sc->func)
6727 s = sc->func->Dsymbol::toPrettyChars();
6728 else
6729 s = "";
6730 Expression *e = new StringExp(loc, const_cast<char *>(s));
6731 e = semantic(e, sc);
6732 e = e->castTo(sc, type);
6733 return e;
6734 }
6735
6736 /****************************************************************/
6737
PrettyFuncInitExp(Loc loc)6738 PrettyFuncInitExp::PrettyFuncInitExp(Loc loc)
6739 : DefaultInitExp(loc, TOKprettyfunc, sizeof(PrettyFuncInitExp))
6740 {
6741 }
6742
resolveLoc(Loc loc,Scope * sc)6743 Expression *PrettyFuncInitExp::resolveLoc(Loc loc, Scope *sc)
6744 {
6745 FuncDeclaration *fd;
6746 if (sc->callsc && sc->callsc->func)
6747 fd = sc->callsc->func;
6748 else
6749 fd = sc->func;
6750
6751 const char *s;
6752 if (fd)
6753 {
6754 const char *funcStr = fd->Dsymbol::toPrettyChars();
6755 OutBuffer buf;
6756 functionToBufferWithIdent((TypeFunction *)fd->type, &buf, funcStr);
6757 s = buf.extractString();
6758 }
6759 else
6760 {
6761 s = "";
6762 }
6763
6764 Expression *e = new StringExp(loc, const_cast<char *>(s));
6765 e = semantic(e, sc);
6766 e = e->castTo(sc, type);
6767 return e;
6768 }
6769
6770 /****************************************************************/
6771
extractOpDollarSideEffect(Scope * sc,UnaExp * ue)6772 Expression *extractOpDollarSideEffect(Scope *sc, UnaExp *ue)
6773 {
6774 Expression *e0;
6775 Expression *e1 = Expression::extractLast(ue->e1, &e0);
6776 // Bugzilla 12585: Extract the side effect part if ue->e1 is comma.
6777
6778 if (!isTrivialExp(e1))
6779 {
6780 /* Even if opDollar is needed, 'e1' should be evaluate only once. So
6781 * Rewrite:
6782 * e1.opIndex( ... use of $ ... )
6783 * e1.opSlice( ... use of $ ... )
6784 * as:
6785 * (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
6786 * (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
6787 */
6788 e1 = extractSideEffect(sc, "__dop", &e0, e1, false);
6789 assert(e1->op == TOKvar);
6790 VarExp *ve = (VarExp *)e1;
6791 ve->var->storage_class |= STCexptemp; // lifetime limited to expression
6792 }
6793 ue->e1 = e1;
6794 return e0;
6795 }
6796
6797 /**************************************
6798 * Runs semantic on ae->arguments. Declares temporary variables
6799 * if '$' was used.
6800 */
resolveOpDollar(Scope * sc,ArrayExp * ae,Expression ** pe0)6801 Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, Expression **pe0)
6802 {
6803 assert(!ae->lengthVar);
6804
6805 *pe0 = NULL;
6806
6807 AggregateDeclaration *ad = isAggregate(ae->e1->type);
6808 Dsymbol *slice = search_function(ad, Id::slice);
6809 //printf("slice = %s %s\n", slice->kind(), slice->toChars());
6810
6811 for (size_t i = 0; i < ae->arguments->dim; i++)
6812 {
6813 if (i == 0)
6814 *pe0 = extractOpDollarSideEffect(sc, ae);
6815
6816 Expression *e = (*ae->arguments)[i];
6817 if (e->op == TOKinterval && !(slice && slice->isTemplateDeclaration()))
6818 {
6819 Lfallback:
6820 if (ae->arguments->dim == 1)
6821 return NULL;
6822 ae->error("multi-dimensional slicing requires template opSlice");
6823 return new ErrorExp();
6824 }
6825 //printf("[%d] e = %s\n", i, e->toChars());
6826
6827 // Create scope for '$' variable for this dimension
6828 ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae);
6829 sym->loc = ae->loc;
6830 sym->parent = sc->scopesym;
6831 sc = sc->push(sym);
6832 ae->lengthVar = NULL; // Create it only if required
6833 ae->currentDimension = i; // Dimension for $, if required
6834
6835 e = semantic(e, sc);
6836 e = resolveProperties(sc, e);
6837
6838 if (ae->lengthVar && sc->func)
6839 {
6840 // If $ was used, declare it now
6841 Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
6842 de = semantic(de, sc);
6843 *pe0 = Expression::combine(*pe0, de);
6844 }
6845 sc = sc->pop();
6846
6847 if (e->op == TOKinterval)
6848 {
6849 IntervalExp *ie = (IntervalExp *)e;
6850
6851 Objects *tiargs = new Objects();
6852 Expression *edim = new IntegerExp(ae->loc, i, Type::tsize_t);
6853 edim = semantic(edim, sc);
6854 tiargs->push(edim);
6855
6856 Expressions *fargs = new Expressions();
6857 fargs->push(ie->lwr);
6858 fargs->push(ie->upr);
6859
6860 unsigned xerrors = global.startGagging();
6861 sc = sc->push();
6862 FuncDeclaration *fslice = resolveFuncCall(ae->loc, sc, slice, tiargs, ae->e1->type, fargs, 1);
6863 sc = sc->pop();
6864 global.endGagging(xerrors);
6865 if (!fslice)
6866 goto Lfallback;
6867
6868 e = new DotTemplateInstanceExp(ae->loc, ae->e1, slice->ident, tiargs);
6869 e = new CallExp(ae->loc, e, fargs);
6870 e = semantic(e, sc);
6871 }
6872
6873 if (!e->type)
6874 {
6875 ae->error("%s has no value", e->toChars());
6876 e = new ErrorExp();
6877 }
6878 if (e->op == TOKerror)
6879 return e;
6880
6881 (*ae->arguments)[i] = e;
6882 }
6883
6884 return ae;
6885 }
6886
6887 /***********************************************************
6888 * Resolve `exp` as a compile-time known string.
6889 * Params:
6890 * sc = scope
6891 * exp = Expression which expected as a string
6892 * s = What the string is expected for, will be used in error diagnostic.
6893 * Returns:
6894 * String literal, or `null` if error happens.
6895 */
semanticString(Scope * sc,Expression * exp,const char * s)6896 StringExp *semanticString(Scope *sc, Expression *exp, const char *s)
6897 {
6898 sc = sc->startCTFE();
6899 exp = semantic(exp, sc);
6900 exp = resolveProperties(sc, exp);
6901 sc = sc->endCTFE();
6902
6903 if (exp->op == TOKerror)
6904 return NULL;
6905
6906 Expression *e = exp;
6907 if (exp->type->isString())
6908 {
6909 e = e->ctfeInterpret();
6910 if (e->op == TOKerror)
6911 return NULL;
6912 }
6913
6914 StringExp *se = e->toStringExp();
6915 if (!se)
6916 {
6917 exp->error("string expected for %s, not (%s) of type %s",
6918 s, exp->toChars(), exp->type->toChars());
6919 return NULL;
6920 }
6921 return se;
6922 }
6923
6924 /**************************************
6925 * Runs semantic on se->lwr and se->upr. Declares a temporary variable
6926 * if '$' was used.
6927 */
resolveOpDollar(Scope * sc,ArrayExp * ae,IntervalExp * ie,Expression ** pe0)6928 Expression *resolveOpDollar(Scope *sc, ArrayExp *ae, IntervalExp *ie, Expression **pe0)
6929 {
6930 //assert(!ae->lengthVar);
6931 if (!ie)
6932 return ae;
6933
6934 VarDeclaration *lengthVar = ae->lengthVar;
6935
6936 // create scope for '$'
6937 ArrayScopeSymbol *sym = new ArrayScopeSymbol(sc, ae);
6938 sym->loc = ae->loc;
6939 sym->parent = sc->scopesym;
6940 sc = sc->push(sym);
6941
6942 for (size_t i = 0; i < 2; ++i)
6943 {
6944 Expression *e = i == 0 ? ie->lwr : ie->upr;
6945 e = semantic(e, sc);
6946 e = resolveProperties(sc, e);
6947 if (!e->type)
6948 {
6949 ae->error("%s has no value", e->toChars());
6950 return new ErrorExp();
6951 }
6952 (i == 0 ? ie->lwr : ie->upr) = e;
6953 }
6954
6955 if (lengthVar != ae->lengthVar && sc->func)
6956 {
6957 // If $ was used, declare it now
6958 Expression *de = new DeclarationExp(ae->loc, ae->lengthVar);
6959 de = semantic(de, sc);
6960 *pe0 = Expression::combine(*pe0, de);
6961 }
6962 sc = sc->pop();
6963
6964 return ae;
6965 }
6966
reorderSettingAAElem(Scope * sc)6967 Expression *BinExp::reorderSettingAAElem(Scope *sc)
6968 {
6969 BinExp *be = this;
6970
6971 if (be->e1->op != TOKindex)
6972 return be;
6973 IndexExp *ie = (IndexExp *)be->e1;
6974 if (ie->e1->type->toBasetype()->ty != Taarray)
6975 return be;
6976
6977 /* Fix evaluation order of setting AA element. (Bugzilla 3825)
6978 * Rewrite:
6979 * aa[k1][k2][k3] op= val;
6980 * as:
6981 * auto ref __aatmp = aa;
6982 * auto ref __aakey3 = k1, __aakey2 = k2, __aakey1 = k3;
6983 * auto ref __aaval = val;
6984 * __aatmp[__aakey3][__aakey2][__aakey1] op= __aaval; // assignment
6985 */
6986
6987 Expression *e0 = NULL;
6988 while (1)
6989 {
6990 Expression *de = NULL;
6991 ie->e2 = extractSideEffect(sc, "__aakey", &de, ie->e2);
6992 e0 = Expression::combine(de, e0);
6993
6994 Expression *ie1 = ie->e1;
6995 if (ie1->op != TOKindex ||
6996 ((IndexExp *)ie1)->e1->type->toBasetype()->ty != Taarray)
6997 {
6998 break;
6999 }
7000 ie = (IndexExp *)ie1;
7001 }
7002 assert(ie->e1->type->toBasetype()->ty == Taarray);
7003
7004 Expression *de = NULL;
7005 ie->e1 = extractSideEffect(sc, "__aatmp", &de, ie->e1);
7006 e0 = Expression::combine(de, e0);
7007
7008 be->e2 = extractSideEffect(sc, "__aaval", &e0, be->e2, true);
7009
7010 //printf("-e0 = %s, be = %s\n", e0->toChars(), be->toChars());
7011 return Expression::combine(e0, be);
7012 }
7013