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