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