1 /**
2  * Compiler implementation of the
3  * $(LINK2 http://www.dlang.org, D programming language).
4  *
5  * Copyright:   Copyright (c) 1999-2016 by Digital Mars, All Rights Reserved
6  * Authors:     $(LINK2 http://www.digitalmars.com, Walter Bright)
7  * License:     $(LINK2 http://www.boost.org/LICENSE_1_0.txt, Boost License 1.0)
8  * Source:      $(DMDSRC _expression.d)
9  */
10 
11 module ddmd.expression;
12 
13 import core.stdc.stdarg;
14 import core.stdc.stdio;
15 import core.stdc..string;
16 
17 import ddmd.access;
18 import ddmd.aggregate;
19 import ddmd.aliasthis;
20 import ddmd.apply;
21 import ddmd.argtypes;
22 import ddmd.arrayop;
23 import ddmd.arraytypes;
24 import ddmd.attrib;
25 import ddmd.gluelayer;
26 import ddmd.canthrow;
27 import ddmd.complex;
28 import ddmd.constfold;
29 import ddmd.ctfeexpr;
30 import ddmd.dcast;
31 import ddmd.dclass;
32 import ddmd.declaration;
33 import ddmd.delegatize;
34 import ddmd.denum;
35 import ddmd.dimport;
36 import ddmd.dinterpret;
37 import ddmd.dmangle;
38 import ddmd.dmodule;
39 import ddmd.dscope;
40 import ddmd.dstruct;
41 import ddmd.dsymbol;
42 import ddmd.dtemplate;
43 import ddmd.errors;
44 import ddmd.func;
45 import ddmd.globals;
46 import ddmd.hdrgen;
47 import ddmd.id;
48 import ddmd.identifier;
49 import ddmd.imphint;
50 import ddmd.inline;
51 import ddmd.intrange;
52 import ddmd.mtype;
53 import ddmd.nspace;
54 import ddmd.opover;
55 import ddmd.optimize;
56 import ddmd.parse;
57 import ddmd.root.ctfloat;
58 import ddmd.root.file;
59 import ddmd.root.filename;
60 import ddmd.root.outbuffer;
61 import ddmd.root.rmem;
62 import ddmd.root.rootobject;
63 import ddmd.safe;
64 import ddmd.sideeffect;
65 import ddmd.target;
66 import ddmd.tokens;
67 import ddmd.traits;
68 import ddmd.typinf;
69 import ddmd.utf;
70 import ddmd.utils;
71 import ddmd.visitor;
72 
73 enum LOGSEMANTIC = false;
74 void emplaceExp(T : Expression, Args...)(void* p, Args args)
75 {
76     scope tmp = new T(args);
77     memcpy(p, cast(void*)tmp, __traits(classInstanceSize, T));
78 }
79 
80 void emplaceExp(T : UnionExp)(T* p, Expression e)
81 {
82     memcpy(p, cast(void*)e, e.size);
83 }
84 
85 /*************************************************************
86  * Given var, we need to get the
87  * right 'this' pointer if var is in an outer class, but our
88  * existing 'this' pointer is in an inner class.
89  * Input:
90  *      e1      existing 'this'
91  *      ad      struct or class we need the correct 'this' for
92  *      var     the specific member of ad we're accessing
93  */
94 extern (C++) Expression getRightThis(Loc loc, Scope* sc, AggregateDeclaration ad, Expression e1, Declaration var, int flag = 0)
95 {
96     //printf("\ngetRightThis(e1 = %s, ad = %s, var = %s)\n", e1->toChars(), ad->toChars(), var->toChars());
97 L1:
98     Type t = e1.type.toBasetype();
99     //printf("e1->type = %s, var->type = %s\n", e1->type->toChars(), var->type->toChars());
100 
101     /* If e1 is not the 'this' pointer for ad
102      */
103     if (ad && !(t.ty == Tpointer && t.nextOf().ty == Tstruct && (cast(TypeStruct)t.nextOf()).sym == ad) && !(t.ty == Tstruct && (cast(TypeStruct)t).sym == ad))
104     {
105         ClassDeclaration cd = ad.isClassDeclaration();
106         ClassDeclaration tcd = t.isClassHandle();
107 
108         /* e1 is the right this if ad is a base class of e1
109          */
110         if (!cd || !tcd || !(tcd == cd || cd.isBaseOf(tcd, null)))
111         {
112             /* Only classes can be inner classes with an 'outer'
113              * member pointing to the enclosing class instance
114              */
115             if (tcd && tcd.isNested())
116             {
117                 /* e1 is the 'this' pointer for an inner class: tcd.
118                  * Rewrite it as the 'this' pointer for the outer class.
119                  */
120                 e1 = new DotVarExp(loc, e1, tcd.vthis);
121                 e1.type = tcd.vthis.type;
122                 e1.type = e1.type.addMod(t.mod);
123                 // Do not call checkNestedRef()
124                 //e1 = e1->semantic(sc);
125 
126                 // Skip up over nested functions, and get the enclosing
127                 // class type.
128                 int n = 0;
129                 Dsymbol s;
130                 for (s = tcd.toParent(); s && s.isFuncDeclaration(); s = s.toParent())
131                 {
132                     FuncDeclaration f = s.isFuncDeclaration();
133                     if (f.vthis)
134                     {
135                         //printf("rewriting e1 to %s's this\n", f->toChars());
136                         n++;
137                         e1 = new VarExp(loc, f.vthis);
138                     }
139                     else
140                     {
141                         e1.error("need 'this' of type %s to access member %s from static function %s", ad.toChars(), var.toChars(), f.toChars());
142                         e1 = new ErrorExp();
143                         return e1;
144                     }
145                 }
146                 if (s && s.isClassDeclaration())
147                 {
148                     e1.type = s.isClassDeclaration().type;
149                     e1.type = e1.type.addMod(t.mod);
150                     if (n > 1)
151                         e1 = e1.semantic(sc);
152                 }
153                 else
154                     e1 = e1.semantic(sc);
155                 goto L1;
156             }
157 
158             /* Can't find a path from e1 to ad
159              */
160             if (flag)
161                 return null;
162             e1.error("this for %s needs to be type %s not type %s", var.toChars(), ad.toChars(), t.toChars());
163             return new ErrorExp();
164         }
165     }
166     return e1;
167 }
168 
169 /*****************************************
170  * Determine if 'this' is available.
171  * If it is, return the FuncDeclaration that has it.
172  */
173 extern (C++) FuncDeclaration hasThis(Scope* sc)
174 {
175     //printf("hasThis()\n");
176     Dsymbol p = sc.parent;
177     while (p && p.isTemplateMixin())
178         p = p.parent;
179     FuncDeclaration fdthis = p ? p.isFuncDeclaration() : null;
180     //printf("fdthis = %p, '%s'\n", fdthis, fdthis ? fdthis->toChars() : "");
181 
182     // Go upwards until we find the enclosing member function
183     FuncDeclaration fd = fdthis;
184     while (1)
185     {
186         if (!fd)
187         {
188             goto Lno;
189         }
190         if (!fd.isNested())
191             break;
192 
193         Dsymbol parent = fd.parent;
194         while (1)
195         {
196             if (!parent)
197                 goto Lno;
198             TemplateInstance ti = parent.isTemplateInstance();
199             if (ti)
200                 parent = ti.parent;
201             else
202                 break;
203         }
204         fd = parent.isFuncDeclaration();
205     }
206 
207     if (!fd.isThis())
208     {
209         //printf("test '%s'\n", fd->toChars());
210         goto Lno;
211     }
212 
213     assert(fd.vthis);
214     return fd;
215 
216 Lno:
217     return null; // don't have 'this' available
218 }
219 
220 extern (C++) bool isNeedThisScope(Scope* sc, Declaration d)
221 {
222     if (sc.intypeof == 1)
223         return false;
224 
225     AggregateDeclaration ad = d.isThis();
226     if (!ad)
227         return false;
228     //printf("d = %s, ad = %s\n", d.toChars(), ad.toChars());
229 
230     for (Dsymbol s = sc.parent; s; s = s.toParent2())
231     {
232         //printf("\ts = %s %s, toParent2() = %p\n", s.kind(), s.toChars(), s.toParent2());
233         if (AggregateDeclaration ad2 = s.isAggregateDeclaration())
234         {
235             if (ad2 == ad)
236                 return false;
237             else if (ad2.isNested())
238                 continue;
239             else
240                 return true;
241         }
242         if (FuncDeclaration f = s.isFuncDeclaration())
243         {
244             if (f.isMember2())
245                 break;
246         }
247     }
248     return true;
249 }
250 
251 /***************************************
252  * Pull out any properties.
253  */
254 extern (C++) Expression resolvePropertiesX(Scope* sc, Expression e1, Expression e2 = null)
255 {
256     //printf("resolvePropertiesX, e1 = %s %s, e2 = %s\n", Token.toChars(e1.op), e1.toChars(), e2 ? e2.toChars() : null);
257     Loc loc = e1.loc;
258 
259     OverloadSet os;
260     Dsymbol s;
261     Objects* tiargs;
262     Type tthis;
263     if (e1.op == TOKdot)
264     {
265         DotExp de = cast(DotExp)e1;
266         if (de.e2.op == TOKoverloadset)
267         {
268             tiargs = null;
269             tthis = de.e1.type;
270             os = (cast(OverExp)de.e2).vars;
271             goto Los;
272         }
273     }
274     else if (e1.op == TOKoverloadset)
275     {
276         tiargs = null;
277         tthis = null;
278         os = (cast(OverExp)e1).vars;
279     Los:
280         assert(os);
281         FuncDeclaration fd = null;
282         if (e2)
283         {
284             e2 = e2.semantic(sc);
285             if (e2.op == TOKerror)
286                 return new ErrorExp();
287             e2 = resolveProperties(sc, e2);
288 
289             Expressions a;
290             a.push(e2);
291 
292             for (size_t i = 0; i < os.a.dim; i++)
293             {
294                 FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, &a, 1);
295                 if (f)
296                 {
297                     if (f.errors)
298                         return new ErrorExp();
299                     fd = f;
300                     assert(fd.type.ty == Tfunction);
301                     TypeFunction tf = cast(TypeFunction)fd.type;
302                 }
303             }
304             if (fd)
305             {
306                 Expression e = new CallExp(loc, e1, e2);
307                 return e.semantic(sc);
308             }
309         }
310         {
311             for (size_t i = 0; i < os.a.dim; i++)
312             {
313                 FuncDeclaration f = resolveFuncCall(loc, sc, os.a[i], tiargs, tthis, null, 1);
314                 if (f)
315                 {
316                     if (f.errors)
317                         return new ErrorExp();
318                     fd = f;
319                     assert(fd.type.ty == Tfunction);
320                     TypeFunction tf = cast(TypeFunction)fd.type;
321                     if (!tf.isref && e2)
322                         goto Leproplvalue;
323                 }
324             }
325             if (fd)
326             {
327                 Expression e = new CallExp(loc, e1);
328                 if (e2)
329                     e = new AssignExp(loc, e, e2);
330                 return e.semantic(sc);
331             }
332         }
333         if (e2)
334             goto Leprop;
335     }
336     else if (e1.op == TOKdotti)
337     {
338         DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)e1;
339         if (!dti.findTempDecl(sc))
340             goto Leprop;
341         if (!dti.ti.semanticTiargs(sc))
342             goto Leprop;
343         tiargs = dti.ti.tiargs;
344         tthis = dti.e1.type;
345         if ((os = dti.ti.tempdecl.isOverloadSet()) !is null)
346             goto Los;
347         if ((s = dti.ti.tempdecl) !is null)
348             goto Lfd;
349     }
350     else if (e1.op == TOKdottd)
351     {
352         DotTemplateExp dte = cast(DotTemplateExp)e1;
353         s = dte.td;
354         tiargs = null;
355         tthis = dte.e1.type;
356         goto Lfd;
357     }
358     else if (e1.op == TOKscope)
359     {
360         s = (cast(ScopeExp)e1).sds;
361         TemplateInstance ti = s.isTemplateInstance();
362         if (ti && !ti.semanticRun && ti.tempdecl)
363         {
364             //assert(ti.needsTypeInference(sc));
365             if (!ti.semanticTiargs(sc))
366                 goto Leprop;
367             tiargs = ti.tiargs;
368             tthis = null;
369             if ((os = ti.tempdecl.isOverloadSet()) !is null)
370                 goto Los;
371             if ((s = ti.tempdecl) !is null)
372                 goto Lfd;
373         }
374     }
375     else if (e1.op == TOKtemplate)
376     {
377         s = (cast(TemplateExp)e1).td;
378         tiargs = null;
379         tthis = null;
380         goto Lfd;
381     }
382     else if (e1.op == TOKdotvar && e1.type && e1.type.toBasetype().ty == Tfunction)
383     {
384         DotVarExp dve = cast(DotVarExp)e1;
385         s = dve.var.isFuncDeclaration();
386         tiargs = null;
387         tthis = dve.e1.type;
388         goto Lfd;
389     }
390     else if (e1.op == TOKvar && e1.type && e1.type.toBasetype().ty == Tfunction)
391     {
392         s = (cast(VarExp)e1).var.isFuncDeclaration();
393         tiargs = null;
394         tthis = null;
395     Lfd:
396         assert(s);
397         if (e2)
398         {
399             e2 = e2.semantic(sc);
400             if (e2.op == TOKerror)
401                 return new ErrorExp();
402             e2 = resolveProperties(sc, e2);
403 
404             Expressions a;
405             a.push(e2);
406 
407             FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, &a, 1);
408             if (fd && fd.type)
409             {
410                 if (fd.errors)
411                     return new ErrorExp();
412                 assert(fd.type.ty == Tfunction);
413                 TypeFunction tf = cast(TypeFunction)fd.type;
414                 Expression e = new CallExp(loc, e1, e2);
415                 return e.semantic(sc);
416             }
417         }
418         {
419             FuncDeclaration fd = resolveFuncCall(loc, sc, s, tiargs, tthis, null, 1);
420             if (fd && fd.type)
421             {
422                 if (fd.errors)
423                     return new ErrorExp();
424                 assert(fd.type.ty == Tfunction);
425                 TypeFunction tf = cast(TypeFunction)fd.type;
426                 if (!e2 || tf.isref)
427                 {
428                     Expression e = new CallExp(loc, e1);
429                     if (e2)
430                         e = new AssignExp(loc, e, e2);
431                     return e.semantic(sc);
432                 }
433             }
434         }
435         if (FuncDeclaration fd = s.isFuncDeclaration())
436         {
437             // Keep better diagnostic message for invalid property usage of functions
438             assert(fd.type.ty == Tfunction);
439             TypeFunction tf = cast(TypeFunction)fd.type;
440             Expression e = new CallExp(loc, e1, e2);
441             return e.semantic(sc);
442         }
443         if (e2)
444             goto Leprop;
445     }
446     if (e1.op == TOKvar)
447     {
448         VarExp ve = cast(VarExp)e1;
449         VarDeclaration v = ve.var.isVarDeclaration();
450         if (v && ve.checkPurity(sc, v))
451             return new ErrorExp();
452     }
453     if (e2)
454         return null;
455 
456     if (e1.type && e1.op != TOKtype) // function type is not a property
457     {
458         /* Look for e1 being a lazy parameter; rewrite as delegate call
459          */
460         if (e1.op == TOKvar)
461         {
462             VarExp ve = cast(VarExp)e1;
463             if (ve.var.storage_class & STClazy)
464             {
465                 Expression e = new CallExp(loc, e1);
466                 return e.semantic(sc);
467             }
468         }
469         else if (e1.op == TOKdotvar)
470         {
471             // Check for reading overlapped pointer field in @safe code.
472             if (checkUnsafeAccess(sc, e1, true, true))
473                 return new ErrorExp();
474         }
475         else if (e1.op == TOKdot)
476         {
477             e1.error("expression has no value");
478             return new ErrorExp();
479         }
480         else if (e1.op == TOKcall)
481         {
482             CallExp ce = cast(CallExp)e1;
483             // Check for reading overlapped pointer field in @safe code.
484             if (checkUnsafeAccess(sc, ce.e1, true, true))
485                 return new ErrorExp();
486         }
487     }
488 
489     if (!e1.type)
490     {
491         error(loc, "cannot resolve type for %s", e1.toChars());
492         e1 = new ErrorExp();
493     }
494     return e1;
495 
496 Leprop:
497     error(loc, "not a property %s", e1.toChars());
498     return new ErrorExp();
499 
500 Leproplvalue:
501     error(loc, "%s is not an lvalue", e1.toChars());
502     return new ErrorExp();
503 }
504 
505 extern (C++) Expression resolveProperties(Scope* sc, Expression e)
506 {
507     //printf("resolveProperties(%s)\n", e->toChars());
508     e = resolvePropertiesX(sc, e);
509     if (e.checkRightThis(sc))
510         return new ErrorExp();
511     return e;
512 }
513 
514 /******************************
515  * Check the tail CallExp is really property function call.
516  */
517 extern (C++) bool checkPropertyCall(Expression e, Expression emsg)
518 {
519     while (e.op == TOKcomma)
520         e = (cast(CommaExp)e).e2;
521 
522     if (e.op == TOKcall)
523     {
524         CallExp ce = cast(CallExp)e;
525         TypeFunction tf;
526         if (ce.f)
527         {
528             tf = cast(TypeFunction)ce.f.type;
529             /* If a forward reference to ce->f, try to resolve it
530              */
531             if (!tf.deco && ce.f._scope)
532             {
533                 ce.f.semantic(ce.f._scope);
534                 tf = cast(TypeFunction)ce.f.type;
535             }
536         }
537         else if (ce.e1.type.ty == Tfunction)
538             tf = cast(TypeFunction)ce.e1.type;
539         else if (ce.e1.type.ty == Tdelegate)
540             tf = cast(TypeFunction)ce.e1.type.nextOf();
541         else if (ce.e1.type.ty == Tpointer && ce.e1.type.nextOf().ty == Tfunction)
542             tf = cast(TypeFunction)ce.e1.type.nextOf();
543         else
544             assert(0);
545     }
546     return false;
547 }
548 
549 /******************************
550  * If e1 is a property function (template), resolve it.
551  */
552 extern (C++) Expression resolvePropertiesOnly(Scope* sc, Expression e1)
553 {
554     //printf("e1 = %s %s\n", Token::toChars(e1->op), e1->toChars());
555     OverloadSet os;
556     FuncDeclaration fd;
557     TemplateDeclaration td;
558 
559     if (e1.op == TOKdot)
560     {
561         DotExp de = cast(DotExp)e1;
562         if (de.e2.op == TOKoverloadset)
563         {
564             os = (cast(OverExp)de.e2).vars;
565             goto Los;
566         }
567     }
568     else if (e1.op == TOKoverloadset)
569     {
570         os = (cast(OverExp)e1).vars;
571     Los:
572         assert(os);
573         for (size_t i = 0; i < os.a.dim; i++)
574         {
575             Dsymbol s = os.a[i];
576             fd = s.isFuncDeclaration();
577             td = s.isTemplateDeclaration();
578             if (fd)
579             {
580                 if ((cast(TypeFunction)fd.type).isproperty)
581                     return resolveProperties(sc, e1);
582             }
583             else if (td && td.onemember && (fd = td.onemember.isFuncDeclaration()) !is null)
584             {
585                 if ((cast(TypeFunction)fd.type).isproperty || (fd.storage_class2 & STCproperty) || (td._scope.stc & STCproperty))
586                 {
587                     return resolveProperties(sc, e1);
588                 }
589             }
590         }
591     }
592     else if (e1.op == TOKdotti)
593     {
594         DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)e1;
595         if (dti.ti.tempdecl && (td = dti.ti.tempdecl.isTemplateDeclaration()) !is null)
596             goto Ltd;
597     }
598     else if (e1.op == TOKdottd)
599     {
600         td = (cast(DotTemplateExp)e1).td;
601         goto Ltd;
602     }
603     else if (e1.op == TOKscope)
604     {
605         Dsymbol s = (cast(ScopeExp)e1).sds;
606         TemplateInstance ti = s.isTemplateInstance();
607         if (ti && !ti.semanticRun && ti.tempdecl)
608         {
609             if ((td = ti.tempdecl.isTemplateDeclaration()) !is null)
610                 goto Ltd;
611         }
612     }
613     else if (e1.op == TOKtemplate)
614     {
615         td = (cast(TemplateExp)e1).td;
616     Ltd:
617         assert(td);
618         if (td.onemember && (fd = td.onemember.isFuncDeclaration()) !is null)
619         {
620             if ((cast(TypeFunction)fd.type).isproperty || (fd.storage_class2 & STCproperty) || (td._scope.stc & STCproperty))
621             {
622                 return resolveProperties(sc, e1);
623             }
624         }
625     }
626     else if (e1.op == TOKdotvar && e1.type.ty == Tfunction)
627     {
628         DotVarExp dve = cast(DotVarExp)e1;
629         fd = dve.var.isFuncDeclaration();
630         goto Lfd;
631     }
632     else if (e1.op == TOKvar && e1.type.ty == Tfunction && (sc.intypeof || !(cast(VarExp)e1).var.needThis()))
633     {
634         fd = (cast(VarExp)e1).var.isFuncDeclaration();
635     Lfd:
636         assert(fd);
637         if ((cast(TypeFunction)fd.type).isproperty)
638             return resolveProperties(sc, e1);
639     }
640     return e1;
641 }
642 
643 /******************************
644  * Find symbol in accordance with the UFCS name look up rule
645  */
646 extern (C++) Expression searchUFCS(Scope* sc, UnaExp ue, Identifier ident)
647 {
648     //printf("searchUFCS(ident = %s)\n", ident.toChars());
649     Loc loc = ue.loc;
650 
651     // TODO: merge with Scope.search.searchScopes()
652     Dsymbol searchScopes(int flags)
653     {
654         Dsymbol s = null;
655         for (Scope* scx = sc; scx; scx = scx.enclosing)
656         {
657             if (!scx.scopesym)
658                 continue;
659             if (scx.scopesym.isModule())
660                 flags |= SearchUnqualifiedModule;    // tell Module.search() that SearchLocalsOnly is to be obeyed
661             s = scx.scopesym.search(loc, ident, flags);
662             if (s)
663             {
664                 // overload set contains only module scope symbols.
665                 if (s.isOverloadSet())
666                     break;
667                 // selective/renamed imports also be picked up
668                 if (AliasDeclaration ad = s.isAliasDeclaration())
669                 {
670                     if (ad._import)
671                         break;
672                 }
673                 // See only module scope symbols for UFCS target.
674                 Dsymbol p = s.toParent2();
675                 if (p && p.isModule())
676                     break;
677             }
678             s = null;
679 
680             // Stop when we hit a module, but keep going if that is not just under the global scope
681             if (scx.scopesym.isModule() && !(scx.enclosing && !scx.enclosing.enclosing))
682                 break;
683         }
684         return s;
685     }
686 
687     int flags = 0;
688     Dsymbol s;
689 
690     Dsymbol sold = void;
691     if (global.params.bug10378 || global.params.check10378)
692     {
693         sold = searchScopes(flags | IgnoreSymbolVisibility);
694         if (!global.params.check10378)
695         {
696             s = sold;
697             goto Lsearchdone;
698         }
699     }
700 
701     // First look in local scopes
702     s = searchScopes(flags | SearchLocalsOnly);
703     if (!s)
704     {
705         // Second look in imported modules
706         s = searchScopes(flags | SearchImportsOnly);
707 
708         /** Still find private symbols, so that symbols that weren't access
709          * checked by the compiler remain usable.  Once the deprecation is over,
710          * this should be moved to search_correct instead.
711          */
712         if (!s)
713         {
714             s = searchScopes(flags | SearchLocalsOnly | IgnoreSymbolVisibility);
715             if (!s)
716                 s = searchScopes(flags | SearchImportsOnly | IgnoreSymbolVisibility);
717 
718             if (s)
719                 .deprecation(loc, "%s is not visible from module %s", s.toPrettyChars(), sc._module.toChars());
720         }
721     }
722     if (global.params.check10378)
723     {
724         alias snew = s;
725         if (sold !is snew)
726             Scope.deprecation10378(loc, sold, snew);
727         if (global.params.bug10378)
728             s = sold;
729     }
730 Lsearchdone:
731 
732     if (!s)
733         return ue.e1.type.Type.getProperty(loc, ident, 0);
734 
735     FuncDeclaration f = s.isFuncDeclaration();
736     if (f)
737     {
738         TemplateDeclaration td = getFuncTemplateDecl(f);
739         if (td)
740         {
741             if (td.overroot)
742                 td = td.overroot;
743             s = td;
744         }
745     }
746 
747     if (ue.op == TOKdotti)
748     {
749         DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)ue;
750         auto ti = new TemplateInstance(loc, s.ident, dti.ti.tiargs);
751         if (!ti.updateTempDecl(sc, s))
752             return new ErrorExp();
753         return new ScopeExp(loc, ti);
754     }
755     else
756     {
757         //printf("-searchUFCS() %s\n", s.toChars());
758         return new DsymbolExp(loc, s);
759     }
760 }
761 
762 /******************************
763  * check e is exp.opDispatch!(tiargs) or not
764  * It's used to switch to UFCS the semantic analysis path
765  */
766 extern (C++) bool isDotOpDispatch(Expression e)
767 {
768     return e.op == TOKdotti && (cast(DotTemplateInstanceExp)e).ti.name == Id.opDispatch;
769 }
770 
771 /******************************
772  * Pull out callable entity with UFCS.
773  */
774 extern (C++) Expression resolveUFCS(Scope* sc, CallExp ce)
775 {
776     Loc loc = ce.loc;
777     Expression eleft;
778     Expression e;
779 
780     if (ce.e1.op == TOKdotid)
781     {
782         DotIdExp die = cast(DotIdExp)ce.e1;
783         Identifier ident = die.ident;
784 
785         Expression ex = die.semanticX(sc);
786         if (ex != die)
787         {
788             ce.e1 = ex;
789             return null;
790         }
791         eleft = die.e1;
792 
793         Type t = eleft.type.toBasetype();
794         if (t.ty == Tarray || t.ty == Tsarray || t.ty == Tnull || (t.isTypeBasic() && t.ty != Tvoid))
795         {
796             /* Built-in types and arrays have no callable properties, so do shortcut.
797              * It is necessary in: e.init()
798              */
799         }
800         else if (t.ty == Taarray)
801         {
802             if (ident == Id.remove)
803             {
804                 /* Transform:
805                  *  aa.remove(arg) into delete aa[arg]
806                  */
807                 if (!ce.arguments || ce.arguments.dim != 1)
808                 {
809                     ce.error("expected key as argument to aa.remove()");
810                     return new ErrorExp();
811                 }
812                 if (!eleft.type.isMutable())
813                 {
814                     ce.error("cannot remove key from %s associative array %s", MODtoChars(t.mod), eleft.toChars());
815                     return new ErrorExp();
816                 }
817                 Expression key = (*ce.arguments)[0];
818                 key = key.semantic(sc);
819                 key = resolveProperties(sc, key);
820 
821                 TypeAArray taa = cast(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 = die.semanticY(sc, 1))
835             {
836                 if (ey.op == TOKerror)
837                     return ey;
838                 ce.e1 = ey;
839                 if (isDotOpDispatch(ey))
840                 {
841                     uint errors = global.startGagging();
842                     e = ce.syntaxCopy().semantic(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 = cast(DotTemplateInstanceExp)ce.e1;
856         if (Expression ey = dti.semanticY(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 extern (C++) Expression resolveUFCSProperties(Scope* sc, Expression e1, Expression e2 = null)
880 {
881     Loc loc = e1.loc;
882     Expression eleft;
883     Expression e;
884 
885     if (e1.op == TOKdotid)
886     {
887         DotIdExp die = cast(DotIdExp)e1;
888         eleft = die.e1;
889         e = searchUFCS(sc, die, die.ident);
890     }
891     else if (e1.op == TOKdotti)
892     {
893         DotTemplateInstanceExp dti;
894         dti = cast(DotTemplateInstanceExp)e1;
895         eleft = dti.e1;
896         e = searchUFCS(sc, dti, dti.ti.name);
897     }
898     else
899         return null;
900 
901     // Rewrite
902     if (e2)
903     {
904         // run semantic without gagging
905         e2 = e2.semantic(sc);
906 
907         /* f(e1) = e2
908          */
909         Expression ex = e.copy();
910         auto a1 = new Expressions();
911         a1.setDim(1);
912         (*a1)[0] = eleft;
913         ex = new CallExp(loc, ex, a1);
914         ex = ex.trySemantic(sc);
915 
916         /* f(e1, e2)
917          */
918         auto a2 = new Expressions();
919         a2.setDim(2);
920         (*a2)[0] = eleft;
921         (*a2)[1] = e2;
922         e = new CallExp(loc, e, a2);
923         if (ex)
924         {
925             // if fallback setter exists, gag errors
926             e = e.trySemantic(sc);
927             if (!e)
928             {
929                 checkPropertyCall(ex, e1);
930                 ex = new AssignExp(loc, ex, e2);
931                 return ex.semantic(sc);
932             }
933         }
934         else
935         {
936             // strict setter prints errors if fails
937             e = e.semantic(sc);
938         }
939         checkPropertyCall(e, e1);
940         return e;
941     }
942     else
943     {
944         /* f(e1)
945          */
946         auto arguments = new Expressions();
947         arguments.setDim(1);
948         (*arguments)[0] = eleft;
949         e = new CallExp(loc, e, arguments);
950         e = e.semantic(sc);
951         checkPropertyCall(e, e1);
952         return e.semantic(sc);
953     }
954 }
955 
956 /******************************
957  * Perform semantic() on an array of Expressions.
958  */
959 extern (C++) bool arrayExpressionSemantic(Expressions* exps, Scope* sc, bool preserveErrors = false)
960 {
961     bool err = false;
962     if (exps)
963     {
964         for (size_t i = 0; i < exps.dim; i++)
965         {
966             Expression e = (*exps)[i];
967             if (e)
968             {
969                 e = e.semantic(sc);
970                 if (e.op == TOKerror)
971                     err = true;
972                 if (preserveErrors || e.op != TOKerror)
973                     (*exps)[i] = e;
974             }
975         }
976     }
977     return err;
978 }
979 
980 /****************************************
981  * Expand tuples.
982  * Input:
983  *      exps    aray of Expressions
984  * Output:
985  *      exps    rewritten in place
986  */
987 extern (C++) void expandTuples(Expressions* exps)
988 {
989     //printf("expandTuples()\n");
990     if (exps)
991     {
992         for (size_t i = 0; i < exps.dim; i++)
993         {
994             Expression arg = (*exps)[i];
995             if (!arg)
996                 continue;
997 
998             // Look for tuple with 0 members
999             if (arg.op == TOKtype)
1000             {
1001                 TypeExp e = cast(TypeExp)arg;
1002                 if (e.type.toBasetype().ty == Ttuple)
1003                 {
1004                     TypeTuple tt = cast(TypeTuple)e.type.toBasetype();
1005                     if (!tt.arguments || tt.arguments.dim == 0)
1006                     {
1007                         exps.remove(i);
1008                         if (i == exps.dim)
1009                             return;
1010                         i--;
1011                         continue;
1012                     }
1013                 }
1014             }
1015 
1016             // Inline expand all the tuples
1017             while (arg.op == TOKtuple)
1018             {
1019                 TupleExp te = cast(TupleExp)arg;
1020                 exps.remove(i); // remove arg
1021                 exps.insert(i, te.exps); // replace with tuple contents
1022                 if (i == exps.dim)
1023                     return; // empty tuple, no more arguments
1024                 (*exps)[i] = Expression.combine(te.e0, (*exps)[i]);
1025                 arg = (*exps)[i];
1026             }
1027         }
1028     }
1029 }
1030 
1031 /****************************************
1032  * Expand alias this tuples.
1033  */
1034 extern (C++) TupleDeclaration isAliasThisTuple(Expression e)
1035 {
1036     if (!e.type)
1037         return null;
1038 
1039     Type t = e.type.toBasetype();
1040 Lagain:
1041     if (Dsymbol s = t.toDsymbol(null))
1042     {
1043         AggregateDeclaration ad = s.isAggregateDeclaration();
1044         if (ad)
1045         {
1046             s = ad.aliasthis;
1047             if (s && s.isVarDeclaration())
1048             {
1049                 TupleDeclaration td = s.isVarDeclaration().toAlias().isTupleDeclaration();
1050                 if (td && td.isexp)
1051                     return td;
1052             }
1053             if (Type att = t.aliasthisOf())
1054             {
1055                 t = att;
1056                 goto Lagain;
1057             }
1058         }
1059     }
1060     return null;
1061 }
1062 
1063 extern (C++) int expandAliasThisTuples(Expressions* exps, size_t starti = 0)
1064 {
1065     if (!exps || exps.dim == 0)
1066         return -1;
1067 
1068     for (size_t u = starti; u < exps.dim; u++)
1069     {
1070         Expression exp = (*exps)[u];
1071         TupleDeclaration td = isAliasThisTuple(exp);
1072         if (td)
1073         {
1074             exps.remove(u);
1075             for (size_t i = 0; i < td.objects.dim; ++i)
1076             {
1077                 Expression e = isExpression((*td.objects)[i]);
1078                 assert(e);
1079                 assert(e.op == TOKdsymbol);
1080                 DsymbolExp se = cast(DsymbolExp)e;
1081                 Declaration d = se.s.isDeclaration();
1082                 assert(d);
1083                 e = new DotVarExp(exp.loc, exp, d);
1084                 assert(d.type);
1085                 e.type = d.type;
1086                 exps.insert(u + i, e);
1087             }
1088             version (none)
1089             {
1090                 printf("expansion ->\n");
1091                 for (size_t i = 0; i < exps.dim; ++i)
1092                 {
1093                     Expression e = (*exps)[i];
1094                     printf("\texps[%d] e = %s %s\n", i, Token.tochars[e.op], e.toChars());
1095                 }
1096             }
1097             return cast(int)u;
1098         }
1099     }
1100     return -1;
1101 }
1102 
1103 /****************************************
1104  * The common type is determined by applying ?: to each pair.
1105  * Output:
1106  *      exps[]  properties resolved, implicitly cast to common type, rewritten in place
1107  *      *pt     if pt is not NULL, set to the common type
1108  * Returns:
1109  *      true    a semantic error was detected
1110  */
1111 extern (C++) bool arrayExpressionToCommonType(Scope* sc, Expressions* exps, Type* pt)
1112 {
1113     /* Still have a problem with:
1114      *  ubyte[][] = [ cast(ubyte[])"hello", [1]];
1115      * which works if the array literal is initialized top down with the ubyte[][]
1116      * type, but fails with this function doing bottom up typing.
1117      */
1118 
1119     //printf("arrayExpressionToCommonType()\n");
1120     scope IntegerExp integerexp = new IntegerExp(0);
1121     scope CondExp condexp = new CondExp(Loc(), integerexp, null, null);
1122 
1123     Type t0 = null;
1124     Expression e0 = null;
1125     size_t j0 = ~0;
1126 
1127     for (size_t i = 0; i < exps.dim; i++)
1128     {
1129         Expression e = (*exps)[i];
1130         if (!e)
1131             continue;
1132 
1133         e = resolveProperties(sc, e);
1134         if (!e.type)
1135         {
1136             e.error("%s has no value", e.toChars());
1137             t0 = Type.terror;
1138             continue;
1139         }
1140         if (e.op == TOKtype)
1141         {
1142             e.checkValue(); // report an error "type T has no value"
1143             t0 = Type.terror;
1144             continue;
1145         }
1146         if (checkNonAssignmentArrayOp(e))
1147         {
1148             t0 = Type.terror;
1149             continue;
1150         }
1151 
1152         e = doCopyOrMove(sc, e);
1153 
1154         if (t0 && !t0.equals(e.type))
1155         {
1156             /* This applies ?: to merge the types. It's backwards;
1157              * ?: should call this function to merge types.
1158              */
1159             condexp.type = null;
1160             condexp.e1 = e0;
1161             condexp.e2 = e;
1162             condexp.loc = e.loc;
1163             Expression ex = condexp.semantic(sc);
1164             if (ex.op == TOKerror)
1165                 e = ex;
1166             else
1167             {
1168                 (*exps)[j0] = condexp.e1;
1169                 e = condexp.e2;
1170             }
1171         }
1172         j0 = i;
1173         e0 = e;
1174         t0 = e.type;
1175         if (e.op != TOKerror)
1176             (*exps)[i] = e;
1177     }
1178 
1179     if (!t0)
1180         t0 = Type.tvoid; // [] is typed as void[]
1181     else if (t0.ty != Terror)
1182     {
1183         for (size_t i = 0; i < exps.dim; i++)
1184         {
1185             Expression e = (*exps)[i];
1186             if (!e)
1187                 continue;
1188 
1189             e = e.implicitCastTo(sc, t0);
1190             //assert(e->op != TOKerror);
1191             if (e.op == TOKerror)
1192             {
1193                 /* Bugzilla 13024: a workaround for the bug in typeMerge -
1194                  * it should paint e1 and e2 by deduced common type,
1195                  * but doesn't in this particular case.
1196                  */
1197                 t0 = Type.terror;
1198                 break;
1199             }
1200             (*exps)[i] = e;
1201         }
1202     }
1203     if (pt)
1204         *pt = t0;
1205 
1206     return (t0 == Type.terror);
1207 }
1208 
1209 /****************************************
1210  * Get TemplateDeclaration enclosing FuncDeclaration.
1211  */
1212 extern (C++) TemplateDeclaration getFuncTemplateDecl(Dsymbol s)
1213 {
1214     FuncDeclaration f = s.isFuncDeclaration();
1215     if (f && f.parent)
1216     {
1217         TemplateInstance ti = f.parent.isTemplateInstance();
1218         if (ti && !ti.isTemplateMixin() && ti.tempdecl && (cast(TemplateDeclaration)ti.tempdecl).onemember && ti.tempdecl.ident == f.ident)
1219         {
1220             return cast(TemplateDeclaration)ti.tempdecl;
1221         }
1222     }
1223     return null;
1224 }
1225 
1226 /****************************************
1227  * Preprocess arguments to function.
1228  * Output:
1229  *      exps[]  tuples expanded, properties resolved, rewritten in place
1230  * Returns:
1231  *      true    a semantic error occurred
1232  */
1233 extern (C++) bool preFunctionParameters(Loc loc, Scope* sc, Expressions* exps)
1234 {
1235     bool err = false;
1236     if (exps)
1237     {
1238         expandTuples(exps);
1239 
1240         for (size_t i = 0; i < exps.dim; i++)
1241         {
1242             Expression arg = (*exps)[i];
1243             arg = resolveProperties(sc, arg);
1244             if (arg.op == TOKtype)
1245             {
1246                 arg.error("cannot pass type %s as a function argument", arg.toChars());
1247                 arg = new ErrorExp();
1248                 err = true;
1249             }
1250             else if (checkNonAssignmentArrayOp(arg))
1251             {
1252                 arg = new ErrorExp();
1253                 err = true;
1254             }
1255             (*exps)[i] = arg;
1256         }
1257     }
1258     return err;
1259 }
1260 
1261 /************************************************
1262  * If we want the value of this expression, but do not want to call
1263  * the destructor on it.
1264  */
1265 extern (C++) Expression valueNoDtor(Expression e)
1266 {
1267     if (e.op == TOKcall)
1268     {
1269         /* The struct value returned from the function is transferred
1270          * so do not call the destructor on it.
1271          * Recognize:
1272          *       ((S _ctmp = S.init), _ctmp).this(...)
1273          * and make sure the destructor is not called on _ctmp
1274          * BUG: if e is a CommaExp, we should go down the right side.
1275          */
1276         CallExp ce = cast(CallExp)e;
1277         if (ce.e1.op == TOKdotvar)
1278         {
1279             DotVarExp dve = cast(DotVarExp)ce.e1;
1280             if (dve.var.isCtorDeclaration())
1281             {
1282                 // It's a constructor call
1283                 if (dve.e1.op == TOKcomma)
1284                 {
1285                     CommaExp comma = cast(CommaExp)dve.e1;
1286                     if (comma.e2.op == TOKvar)
1287                     {
1288                         VarExp ve = cast(VarExp)comma.e2;
1289                         VarDeclaration ctmp = ve.var.isVarDeclaration();
1290                         if (ctmp)
1291                         {
1292                             ctmp.storage_class |= STCnodtor;
1293                             assert(!ce.isLvalue());
1294                         }
1295                     }
1296                 }
1297             }
1298         }
1299     }
1300     else if (e.op == TOKvar)
1301     {
1302         auto vtmp = (cast(VarExp)e).var.isVarDeclaration();
1303         if (vtmp && (vtmp.storage_class & STCrvalue))
1304         {
1305             vtmp.storage_class |= STCnodtor;
1306         }
1307     }
1308     return e;
1309 }
1310 
1311 /********************************************
1312  * Issue an error if default construction is disabled for type t.
1313  * Default construction is required for arrays and 'out' parameters.
1314  * Returns:
1315  *      true    an error was issued
1316  */
1317 extern (C++) bool checkDefCtor(Loc loc, Type t)
1318 {
1319     t = t.baseElemOf();
1320     if (t.ty == Tstruct)
1321     {
1322         StructDeclaration sd = (cast(TypeStruct)t).sym;
1323         if (sd.noDefaultCtor)
1324         {
1325             sd.error(loc, "default construction is disabled");
1326             return true;
1327         }
1328     }
1329     return false;
1330 }
1331 
1332 /*********************************************
1333  * If e is an instance of a struct, and that struct has a copy constructor,
1334  * rewrite e as:
1335  *    (tmp = e),tmp
1336  * Input:
1337  *      sc      just used to specify the scope of created temporary variable
1338  */
1339 extern (C++) Expression callCpCtor(Scope* sc, Expression e)
1340 {
1341     Type tv = e.type.baseElemOf();
1342     if (tv.ty == Tstruct)
1343     {
1344         StructDeclaration sd = (cast(TypeStruct)tv).sym;
1345         if (sd.postblit)
1346         {
1347             /* Create a variable tmp, and replace the argument e with:
1348              *      (tmp = e),tmp
1349              * and let AssignExp() handle the construction.
1350              * This is not the most efficent, ideally tmp would be constructed
1351              * directly onto the stack.
1352              */
1353             auto tmp = copyToTemp(STCrvalue, "__copytmp", e);
1354             tmp.storage_class |= STCnodtor;
1355             tmp.semantic(sc);
1356             Expression de = new DeclarationExp(e.loc, tmp);
1357             Expression ve = new VarExp(e.loc, tmp);
1358             de.type = Type.tvoid;
1359             ve.type = e.type;
1360             e = Expression.combine(de, ve);
1361         }
1362     }
1363     return e;
1364 }
1365 
1366 /************************************************
1367  * Handle the postblit call on lvalue, or the move of rvalue.
1368  */
1369 extern (C++) Expression doCopyOrMove(Scope *sc, Expression e)
1370 {
1371     if (e.op == TOKquestion)
1372     {
1373         auto ce = cast(CondExp)e;
1374         ce.e1 = doCopyOrMove(sc, ce.e1);
1375         ce.e2 = doCopyOrMove(sc, ce.e2);
1376     }
1377     else
1378     {
1379         e = e.isLvalue() ? callCpCtor(sc, e) : valueNoDtor(e);
1380     }
1381     return e;
1382 }
1383 
1384 /****************************************
1385  * Now that we know the exact type of the function we're calling,
1386  * the arguments[] need to be adjusted:
1387  *      1. implicitly convert argument to the corresponding parameter type
1388  *      2. add default arguments for any missing arguments
1389  *      3. do default promotions on arguments corresponding to ...
1390  *      4. add hidden _arguments[] argument
1391  *      5. call copy constructor for struct value arguments
1392  * Input:
1393  *      tf      type of the function
1394  *      fd      the function being called, NULL if called indirectly
1395  * Output:
1396  *      *prettype return type of function
1397  *      *peprefix expression to execute before arguments[] are evaluated, NULL if none
1398  * Returns:
1399  *      true    errors happened
1400  */
1401 extern (C++) bool functionParameters(Loc loc, Scope* sc, TypeFunction tf, Type tthis, Expressions* arguments, FuncDeclaration fd, Type* prettype, Expression* peprefix)
1402 {
1403     //printf("functionParameters()\n");
1404     assert(arguments);
1405     assert(fd || tf.next);
1406     size_t nargs = arguments ? arguments.dim : 0;
1407     size_t nparams = Parameter.dim(tf.parameters);
1408     uint olderrors = global.errors;
1409     bool err = false;
1410     *prettype = Type.terror;
1411     Expression eprefix = null;
1412     *peprefix = null;
1413 
1414     if (nargs > nparams && tf.varargs == 0)
1415     {
1416         error(loc, "expected %llu arguments, not %llu for non-variadic function type %s", cast(ulong)nparams, cast(ulong)nargs, tf.toChars());
1417         return true;
1418     }
1419 
1420     // If inferring return type, and semantic3() needs to be run if not already run
1421     if (!tf.next && fd.inferRetType)
1422     {
1423         fd.functionSemantic();
1424     }
1425     else if (fd && fd.parent)
1426     {
1427         TemplateInstance ti = fd.parent.isTemplateInstance();
1428         if (ti && ti.tempdecl)
1429         {
1430             fd.functionSemantic3();
1431         }
1432     }
1433     bool isCtorCall = fd && fd.needThis() && fd.isCtorDeclaration();
1434 
1435     size_t n = (nargs > nparams) ? nargs : nparams; // n = max(nargs, nparams)
1436 
1437     /* If the function return type has wildcards in it, we'll need to figure out the actual type
1438      * based on the actual argument types.
1439      */
1440     MOD wildmatch = 0;
1441     if (tthis && tf.isWild() && !isCtorCall)
1442     {
1443         Type t = tthis;
1444         if (t.isImmutable())
1445             wildmatch = MODimmutable;
1446         else if (t.isWildConst())
1447             wildmatch = MODwildconst;
1448         else if (t.isWild())
1449             wildmatch = MODwild;
1450         else if (t.isConst())
1451             wildmatch = MODconst;
1452         else
1453             wildmatch = MODmutable;
1454     }
1455 
1456     int done = 0;
1457     for (size_t i = 0; i < n; i++)
1458     {
1459         Expression arg;
1460 
1461         if (i < nargs)
1462             arg = (*arguments)[i];
1463         else
1464             arg = null;
1465 
1466         if (i < nparams)
1467         {
1468             Parameter p = Parameter.getNth(tf.parameters, i);
1469 
1470             if (!arg)
1471             {
1472                 if (!p.defaultArg)
1473                 {
1474                     if (tf.varargs == 2 && i + 1 == nparams)
1475                         goto L2;
1476                     error(loc, "expected %llu function arguments, not %llu", cast(ulong)nparams, cast(ulong)nargs);
1477                     return true;
1478                 }
1479                 arg = p.defaultArg;
1480                 arg = inlineCopy(arg, sc);
1481                 // __FILE__, __LINE__, __MODULE__, __FUNCTION__, and __PRETTY_FUNCTION__
1482                 arg = arg.resolveLoc(loc, sc);
1483                 arguments.push(arg);
1484                 nargs++;
1485             }
1486 
1487             if (tf.varargs == 2 && i + 1 == nparams)
1488             {
1489                 //printf("\t\tvarargs == 2, p->type = '%s'\n", p->type->toChars());
1490                 {
1491                     MATCH m;
1492                     if ((m = arg.implicitConvTo(p.type)) > MATCHnomatch)
1493                     {
1494                         if (p.type.nextOf() && arg.implicitConvTo(p.type.nextOf()) >= m)
1495                             goto L2;
1496                         else if (nargs != nparams)
1497                         {
1498                             error(loc, "expected %llu function arguments, not %llu", cast(ulong)nparams, cast(ulong)nargs);
1499                             return true;
1500                         }
1501                         goto L1;
1502                     }
1503                 }
1504             L2:
1505                 Type tb = p.type.toBasetype();
1506                 Type tret = p.isLazyArray();
1507                 switch (tb.ty)
1508                 {
1509                 case Tsarray:
1510                 case Tarray:
1511                     {
1512                         /* Create a static array variable v of type arg->type:
1513                          *  T[dim] __arrayArg = [ arguments[i], ..., arguments[nargs-1] ];
1514                          *
1515                          * The array literal in the initializer of the hidden variable
1516                          * is now optimized. See Bugzilla 2356.
1517                          */
1518                         Type tbn = (cast(TypeArray)tb).next;
1519                         Type tsa = tbn.sarrayOf(nargs - i);
1520 
1521                         auto elements = new Expressions();
1522                         elements.setDim(nargs - i);
1523                         for (size_t u = 0; u < elements.dim; u++)
1524                         {
1525                             Expression a = (*arguments)[i + u];
1526                             if (tret && a.implicitConvTo(tret))
1527                             {
1528                                 a = a.implicitCastTo(sc, tret);
1529                                 a = a.optimize(WANTvalue);
1530                                 a = toDelegate(a, a.type, sc);
1531                             }
1532                             else
1533                                 a = a.implicitCastTo(sc, tbn);
1534                             (*elements)[u] = a;
1535                         }
1536                         // Bugzilla 14395: Convert to a static array literal, or its slice.
1537                         arg = new ArrayLiteralExp(loc, elements);
1538                         arg.type = tsa;
1539                         if (tb.ty == Tarray)
1540                         {
1541                             arg = new SliceExp(loc, arg, null, null);
1542                             arg.type = p.type;
1543                         }
1544                         break;
1545                     }
1546                 case Tclass:
1547                     {
1548                         /* Set arg to be:
1549                          *      new Tclass(arg0, arg1, ..., argn)
1550                          */
1551                         auto args = new Expressions();
1552                         args.setDim(nargs - i);
1553                         for (size_t u = i; u < nargs; u++)
1554                             (*args)[u - i] = (*arguments)[u];
1555                         arg = new NewExp(loc, null, null, p.type, args);
1556                         break;
1557                     }
1558                 default:
1559                     if (!arg)
1560                     {
1561                         error(loc, "not enough arguments");
1562                         return true;
1563                     }
1564                     break;
1565                 }
1566                 arg = arg.semantic(sc);
1567                 //printf("\targ = '%s'\n", arg->toChars());
1568                 arguments.setDim(i + 1);
1569                 (*arguments)[i] = arg;
1570                 nargs = i + 1;
1571                 done = 1;
1572             }
1573 
1574         L1:
1575             if (!(p.storageClass & STClazy && p.type.ty == Tvoid))
1576             {
1577                 bool isRef = (p.storageClass & (STCref | STCout)) != 0;
1578                 if (ubyte wm = arg.type.deduceWild(p.type, isRef))
1579                 {
1580                     if (wildmatch)
1581                         wildmatch = MODmerge(wildmatch, wm);
1582                     else
1583                         wildmatch = wm;
1584                     //printf("[%d] p = %s, a = %s, wm = %d, wildmatch = %d\n", i, p->type->toChars(), arg->type->toChars(), wm, wildmatch);
1585                 }
1586             }
1587         }
1588         if (done)
1589             break;
1590     }
1591     if ((wildmatch == MODmutable || wildmatch == MODimmutable) && tf.next.hasWild() && (tf.isref || !tf.next.implicitConvTo(tf.next.immutableOf())))
1592     {
1593         if (fd)
1594         {
1595             /* If the called function may return the reference to
1596              * outer inout data, it should be rejected.
1597              *
1598              * void foo(ref inout(int) x) {
1599              *   ref inout(int) bar(inout(int)) { return x; }
1600              *   struct S { ref inout(int) bar() inout { return x; } }
1601              *   bar(int.init) = 1;  // bad!
1602              *   S().bar() = 1;      // bad!
1603              * }
1604              */
1605             Dsymbol s = null;
1606             if (fd.isThis() || fd.isNested())
1607                 s = fd.toParent2();
1608             for (; s; s = s.toParent2())
1609             {
1610                 if (auto ad = s.isAggregateDeclaration())
1611                 {
1612                     if (ad.isNested())
1613                         continue;
1614                     break;
1615                 }
1616                 if (auto ff = s.isFuncDeclaration())
1617                 {
1618                     if ((cast(TypeFunction)ff.type).iswild)
1619                         goto Linouterr;
1620 
1621                     if (ff.isNested() || ff.isThis())
1622                         continue;
1623                 }
1624                 break;
1625             }
1626         }
1627         else if (tf.isWild())
1628         {
1629         Linouterr:
1630             const(char)* s = wildmatch == MODmutable ? "mutable" : MODtoChars(wildmatch);
1631             error(loc, "modify inout to %s is not allowed inside inout function", s);
1632             return true;
1633         }
1634     }
1635 
1636     assert(nargs >= nparams);
1637     for (size_t i = 0; i < nargs; i++)
1638     {
1639         Expression arg = (*arguments)[i];
1640         assert(arg);
1641         if (i < nparams)
1642         {
1643             Parameter p = Parameter.getNth(tf.parameters, i);
1644             if (!(p.storageClass & STClazy && p.type.ty == Tvoid))
1645             {
1646                 Type tprm = p.type;
1647                 if (p.type.hasWild())
1648                     tprm = p.type.substWildTo(wildmatch);
1649                 if (!tprm.equals(arg.type))
1650                 {
1651                     //printf("arg->type = %s, p->type = %s\n", arg->type->toChars(), p->type->toChars());
1652                     arg = arg.implicitCastTo(sc, tprm);
1653                     arg = arg.optimize(WANTvalue, (p.storageClass & (STCref | STCout)) != 0);
1654                 }
1655             }
1656             if (p.storageClass & STCref)
1657             {
1658                 arg = arg.toLvalue(sc, arg);
1659 
1660                 // Look for mutable misaligned pointer, etc., in @safe mode
1661                 err |= checkUnsafeAccess(sc, arg, false, true);
1662             }
1663             else if (p.storageClass & STCout)
1664             {
1665                 Type t = arg.type;
1666                 if (!t.isMutable() || !t.isAssignable()) // check blit assignable
1667                 {
1668                     arg.error("cannot modify struct %s with immutable members", arg.toChars());
1669                     err = true;
1670                 }
1671                 else
1672                 {
1673                     // Look for misaligned pointer, etc., in @safe mode
1674                     err |= checkUnsafeAccess(sc, arg, false, true);
1675                     err |= checkDefCtor(arg.loc, t); // t must be default constructible
1676                 }
1677                 arg = arg.toLvalue(sc, arg);
1678             }
1679             else if (p.storageClass & STClazy)
1680             {
1681                 // Convert lazy argument to a delegate
1682                 if (p.type.ty == Tvoid)
1683                     arg = toDelegate(arg, p.type, sc);
1684                 else
1685                     arg = toDelegate(arg, arg.type, sc);
1686             }
1687             //printf("arg: %s\n", arg->toChars());
1688             //printf("type: %s\n", arg->type->toChars());
1689 
1690             /* Look for arguments that cannot 'escape' from the called
1691              * function.
1692              */
1693             if (!tf.parameterEscapes(p))
1694             {
1695                 Expression a = arg;
1696                 if (a.op == TOKcast)
1697                     a = (cast(CastExp)a).e1;
1698                 if (a.op == TOKfunction)
1699                 {
1700                     /* Function literals can only appear once, so if this
1701                      * appearance was scoped, there cannot be any others.
1702                      */
1703                     FuncExp fe = cast(FuncExp)a;
1704                     fe.fd.tookAddressOf = 0;
1705                 }
1706                 else if (a.op == TOKdelegate)
1707                 {
1708                     /* For passing a delegate to a scoped parameter,
1709                      * this doesn't count as taking the address of it.
1710                      * We only worry about 'escaping' references to the function.
1711                      */
1712                     DelegateExp de = cast(DelegateExp)a;
1713                     if (de.e1.op == TOKvar)
1714                     {
1715                         VarExp ve = cast(VarExp)de.e1;
1716                         FuncDeclaration f = ve.var.isFuncDeclaration();
1717                         if (f)
1718                         {
1719                             f.tookAddressOf--;
1720                             //printf("--tookAddressOf = %d\n", f.tookAddressOf);
1721                         }
1722                     }
1723                 }
1724             }
1725             arg = arg.optimize(WANTvalue, (p.storageClass & (STCref | STCout)) != 0);
1726         }
1727         else
1728         {
1729             // These will be the trailing ... arguments
1730             // If not D linkage, do promotions
1731             if (tf.linkage != LINKd)
1732             {
1733                 // Promote bytes, words, etc., to ints
1734                 arg = integralPromotions(arg, sc);
1735 
1736                 // Promote floats to doubles
1737                 switch (arg.type.ty)
1738                 {
1739                 case Tfloat32:
1740                     arg = arg.castTo(sc, Type.tfloat64);
1741                     break;
1742 
1743                 case Timaginary32:
1744                     arg = arg.castTo(sc, Type.timaginary64);
1745                     break;
1746 
1747                 default:
1748                     break;
1749                 }
1750                 if (tf.varargs == 1)
1751                 {
1752                     const(char)* p = tf.linkage == LINKc ? "extern(C)" : "extern(C++)";
1753                     if (arg.type.ty == Tarray)
1754                     {
1755                         arg.error("cannot pass dynamic arrays to %s vararg functions", p);
1756                         err = true;
1757                     }
1758                     if (arg.type.ty == Tsarray)
1759                     {
1760                         arg.error("cannot pass static arrays to %s vararg functions", p);
1761                         err = true;
1762                     }
1763                 }
1764             }
1765 
1766             // Do not allow types that need destructors
1767             if (arg.type.needsDestruction())
1768             {
1769                 arg.error("cannot pass types that need destruction as variadic arguments");
1770                 err = true;
1771             }
1772 
1773             // Convert static arrays to dynamic arrays
1774             // BUG: I don't think this is right for D2
1775             Type tb = arg.type.toBasetype();
1776             if (tb.ty == Tsarray)
1777             {
1778                 TypeSArray ts = cast(TypeSArray)tb;
1779                 Type ta = ts.next.arrayOf();
1780                 if (ts.size(arg.loc) == 0)
1781                     arg = new NullExp(arg.loc, ta);
1782                 else
1783                     arg = arg.castTo(sc, ta);
1784             }
1785             if (tb.ty == Tstruct)
1786             {
1787                 //arg = callCpCtor(sc, arg);
1788             }
1789             // Give error for overloaded function addresses
1790             if (arg.op == TOKsymoff)
1791             {
1792                 SymOffExp se = cast(SymOffExp)arg;
1793                 if (se.hasOverloads && !se.var.isFuncDeclaration().isUnique())
1794                 {
1795                     arg.error("function %s is overloaded", arg.toChars());
1796                     err = true;
1797                 }
1798             }
1799             if (arg.checkValue())
1800                 err = true;
1801             arg = arg.optimize(WANTvalue);
1802         }
1803         (*arguments)[i] = arg;
1804     }
1805 
1806     /* Remaining problems:
1807      * 1. order of evaluation - some function push L-to-R, others R-to-L. Until we resolve what array assignment does (which is
1808      *    implemented by calling a function) we'll defer this for now.
1809      * 2. value structs (or static arrays of them) that need to be copy constructed
1810      * 3. value structs (or static arrays of them) that have destructors, and subsequent arguments that may throw before the
1811      *    function gets called (functions normally destroy their parameters)
1812      * 2 and 3 are handled by doing the argument construction in 'eprefix' so that if a later argument throws, they are cleaned
1813      * up properly. Pushing arguments on the stack then cannot fail.
1814      */
1815     if (1)
1816     {
1817         /* TODO: tackle problem 1)
1818          */
1819         const bool leftToRight = true; // TODO: something like !fd.isArrayOp
1820         if (!leftToRight)
1821             assert(nargs == nparams); // no variadics for RTL order, as they would probably be evaluated LTR and so add complexity
1822 
1823         const ptrdiff_t start = (leftToRight ? 0 : cast(ptrdiff_t)nargs - 1);
1824         const ptrdiff_t end = (leftToRight ? cast(ptrdiff_t)nargs : -1);
1825         const ptrdiff_t step = (leftToRight ? 1 : -1);
1826 
1827         /* Compute indices of last throwing argument and first arg needing destruction.
1828          * Used to not set up destructors unless an arg needs destruction on a throw
1829          * in a later argument.
1830          */
1831         ptrdiff_t lastthrow = -1;
1832         ptrdiff_t firstdtor = -1;
1833         for (ptrdiff_t i = start; i != end; i += step)
1834         {
1835             Expression arg = (*arguments)[i];
1836             if (canThrow(arg, sc.func, false))
1837                 lastthrow = i;
1838             if (firstdtor == -1 && arg.type.needsDestruction())
1839             {
1840                 Parameter p = (i >= nparams ? null : Parameter.getNth(tf.parameters, i));
1841                 if (!(p && (p.storageClass & (STClazy | STCref | STCout))))
1842                     firstdtor = i;
1843             }
1844         }
1845 
1846         /* Does problem 3) apply to this call?
1847          */
1848         const bool needsPrefix = (firstdtor >= 0 && lastthrow >= 0
1849             && (lastthrow - firstdtor) * step > 0);
1850 
1851         /* If so, initialize 'eprefix' by declaring the gate
1852          */
1853         VarDeclaration gate = null;
1854         if (needsPrefix)
1855         {
1856             // eprefix => bool __gate [= false]
1857             Identifier idtmp = Identifier.generateId("__gate");
1858             gate = new VarDeclaration(loc, Type.tbool, idtmp, null);
1859             gate.storage_class |= STCtemp | STCctfe | STCvolatile;
1860             gate.semantic(sc);
1861 
1862             auto ae = new DeclarationExp(loc, gate);
1863             eprefix = ae.semantic(sc);
1864         }
1865 
1866         for (ptrdiff_t i = start; i != end; i += step)
1867         {
1868             Expression arg = (*arguments)[i];
1869 
1870             Parameter parameter = (i >= nparams ? null : Parameter.getNth(tf.parameters, i));
1871             const bool isRef = (parameter && (parameter.storageClass & (STCref | STCout)));
1872             const bool isLazy = (parameter && (parameter.storageClass & STClazy));
1873 
1874             /* Skip lazy parameters
1875              */
1876             if (isLazy)
1877                 continue;
1878 
1879             /* Do we have a gate? Then we have a prefix and we're not yet past the last throwing arg.
1880              * Declare a temporary variable for this arg and append that declaration to 'eprefix',
1881              * which will implicitly take care of potential problem 2) for this arg.
1882              * 'eprefix' will therefore finally contain all args up to and including the last
1883              * potentially throwing arg, excluding all lazy parameters.
1884              */
1885             if (gate)
1886             {
1887                 const bool needsDtor = (!isRef && arg.type.needsDestruction() && i != lastthrow);
1888 
1889                 /* Declare temporary 'auto __pfx = arg' (needsDtor) or 'auto __pfy = arg' (!needsDtor)
1890                  */
1891                 auto tmp = copyToTemp(0,
1892                     needsDtor ? "__pfx" : "__pfy",
1893                     !isRef ? arg : arg.addressOf());
1894                 tmp.semantic(sc);
1895 
1896                 /* Modify the destructor so it only runs if gate==false, i.e.,
1897                  * only if there was a throw while constructing the args
1898                  */
1899                 if (!needsDtor)
1900                 {
1901                     if (tmp.edtor)
1902                     {
1903                         assert(i == lastthrow);
1904                         tmp.edtor = null;
1905                     }
1906                 }
1907                 else
1908                 {
1909                     // edtor => (__gate || edtor)
1910                     assert(tmp.edtor);
1911                     Expression e = tmp.edtor;
1912                     e = new OrOrExp(e.loc, new VarExp(e.loc, gate), e);
1913                     tmp.edtor = e.semantic(sc);
1914                     //printf("edtor: %s\n", tmp.edtor.toChars());
1915                 }
1916 
1917                 // eprefix => (eprefix, auto __pfx/y = arg)
1918                 auto ae = new DeclarationExp(loc, tmp);
1919                 eprefix = Expression.combine(eprefix, ae.semantic(sc));
1920 
1921                 // arg => __pfx/y
1922                 arg = new VarExp(loc, tmp);
1923                 arg = arg.semantic(sc);
1924                 if (isRef)
1925                 {
1926                     arg = new PtrExp(loc, arg);
1927                     arg = arg.semantic(sc);
1928                 }
1929 
1930                 /* Last throwing arg? Then finalize eprefix => (eprefix, gate = true),
1931                  * i.e., disable the dtors right after constructing the last throwing arg.
1932                  * From now on, the callee will take care of destructing the args because
1933                  * the args are implicitly moved into function parameters.
1934                  *
1935                  * Set gate to null to let the next iterations know they don't need to
1936                  * append to eprefix anymore.
1937                  */
1938                 if (i == lastthrow)
1939                 {
1940                     auto e = new AssignExp(gate.loc, new VarExp(gate.loc, gate), new IntegerExp(gate.loc, 1, Type.tbool));
1941                     eprefix = Expression.combine(eprefix, e.semantic(sc));
1942                     gate = null;
1943                 }
1944             }
1945             else
1946             {
1947                 /* No gate, no prefix to append to.
1948                  * Handle problem 2) by calling the copy constructor for value structs
1949                  * (or static arrays of them) if appropriate.
1950                  */
1951                 Type tv = arg.type.baseElemOf();
1952                 if (!isRef && tv.ty == Tstruct)
1953                     arg = doCopyOrMove(sc, arg);
1954             }
1955 
1956             (*arguments)[i] = arg;
1957         }
1958     }
1959     //if (eprefix) printf("eprefix: %s\n", eprefix->toChars());
1960 
1961     // If D linkage and variadic, add _arguments[] as first argument
1962     if (tf.linkage == LINKd && tf.varargs == 1)
1963     {
1964         assert(arguments.dim >= nparams);
1965 
1966         auto args = new Parameters();
1967         args.setDim(arguments.dim - nparams);
1968         for (size_t i = 0; i < arguments.dim - nparams; i++)
1969         {
1970             auto arg = new Parameter(STCin, (*arguments)[nparams + i].type, null, null);
1971             (*args)[i] = arg;
1972         }
1973         auto tup = new TypeTuple(args);
1974         Expression e = new TypeidExp(loc, tup);
1975         e = e.semantic(sc);
1976         arguments.insert(0, e);
1977     }
1978 
1979     Type tret = tf.next;
1980     if (isCtorCall)
1981     {
1982         //printf("[%s] fd = %s %s, %d %d %d\n", loc.toChars(), fd->toChars(), fd->type->toChars(),
1983         //    wildmatch, tf->isWild(), fd->isolateReturn());
1984         if (!tthis)
1985         {
1986             assert(sc.intypeof || global.errors);
1987             tthis = fd.isThis().type.addMod(fd.type.mod);
1988         }
1989         if (tf.isWild() && !fd.isolateReturn())
1990         {
1991             if (wildmatch)
1992                 tret = tret.substWildTo(wildmatch);
1993             int offset;
1994             if (!tret.implicitConvTo(tthis) && !(MODimplicitConv(tret.mod, tthis.mod) && tret.isBaseOf(tthis, &offset) && offset == 0))
1995             {
1996                 const(char)* s1 = tret.isNaked() ? " mutable" : tret.modToChars();
1997                 const(char)* s2 = tthis.isNaked() ? " mutable" : tthis.modToChars();
1998                 .error(loc, "inout constructor %s creates%s object, not%s", fd.toPrettyChars(), s1, s2);
1999                 err = true;
2000             }
2001         }
2002         tret = tthis;
2003     }
2004     else if (wildmatch && tret)
2005     {
2006         /* Adjust function return type based on wildmatch
2007          */
2008         //printf("wildmatch = x%x, tret = %s\n", wildmatch, tret.toChars());
2009         tret = tret.substWildTo(wildmatch);
2010     }
2011     *prettype = tret;
2012     *peprefix = eprefix;
2013     return (err || olderrors != global.errors);
2014 }
2015 
2016 /****************************************************************/
2017 /* A type meant as a union of all the Expression types,
2018  * to serve essentially as a Variant that will sit on the stack
2019  * during CTFE to reduce memory consumption.
2020  */
2021 struct UnionExp
2022 {
2023     // yes, default constructor does nothing
2024     extern (D) this(Expression e)
2025     {
2026         memcpy(&this, cast(void*)e, e.size);
2027     }
2028 
2029     /* Extract pointer to Expression
2030      */
2031     extern (C++) Expression exp()
2032     {
2033         return cast(Expression)&u;
2034     }
2035 
2036     /* Convert to an allocated Expression
2037      */
2038     extern (C++) Expression copy()
2039     {
2040         Expression e = exp();
2041         //if (e->size > sizeof(u)) printf("%s\n", Token::toChars(e->op));
2042         assert(e.size <= u.sizeof);
2043         if (e.op == TOKcantexp)
2044             return CTFEExp.cantexp;
2045         if (e.op == TOKvoidexp)
2046             return CTFEExp.voidexp;
2047         if (e.op == TOKbreak)
2048             return CTFEExp.breakexp;
2049         if (e.op == TOKcontinue)
2050             return CTFEExp.continueexp;
2051         if (e.op == TOKgoto)
2052             return CTFEExp.gotoexp;
2053         return e.copy();
2054     }
2055 
2056 private:
2057     union __AnonStruct__u
2058     {
2059         char[__traits(classInstanceSize, Expression)] exp;
2060         char[__traits(classInstanceSize, IntegerExp)] integerexp;
2061         char[__traits(classInstanceSize, ErrorExp)] errorexp;
2062         char[__traits(classInstanceSize, RealExp)] realexp;
2063         char[__traits(classInstanceSize, ComplexExp)] complexexp;
2064         char[__traits(classInstanceSize, SymOffExp)] symoffexp;
2065         char[__traits(classInstanceSize, StringExp)] stringexp;
2066         char[__traits(classInstanceSize, ArrayLiteralExp)] arrayliteralexp;
2067         char[__traits(classInstanceSize, AssocArrayLiteralExp)] assocarrayliteralexp;
2068         char[__traits(classInstanceSize, StructLiteralExp)] structliteralexp;
2069         char[__traits(classInstanceSize, NullExp)] nullexp;
2070         char[__traits(classInstanceSize, DotVarExp)] dotvarexp;
2071         char[__traits(classInstanceSize, AddrExp)] addrexp;
2072         char[__traits(classInstanceSize, IndexExp)] indexexp;
2073         char[__traits(classInstanceSize, SliceExp)] sliceexp;
2074         // Ensure that the union is suitably aligned.
2075         real_t for_alignment_only;
2076     }
2077 
2078     __AnonStruct__u u;
2079 }
2080 
2081 /********************************
2082  * Test to see if two reals are the same.
2083  * Regard NaN's as equivalent.
2084  * Regard +0 and -0 as different.
2085  */
2086 extern (C++) int RealEquals(real_t x1, real_t x2)
2087 {
2088     return (CTFloat.isNaN(x1) && CTFloat.isNaN(x2)) || CTFloat.isIdentical(x1, x2);
2089 }
2090 
2091 /************************ TypeDotIdExp ************************************/
2092 /* Things like:
2093  *      int.size
2094  *      foo.size
2095  *      (foo).size
2096  *      cast(foo).size
2097  */
2098 extern (C++) DotIdExp typeDotIdExp(Loc loc, Type type, Identifier ident)
2099 {
2100     return new DotIdExp(loc, new TypeExp(loc, type), ident);
2101 }
2102 
2103 /***********************************************
2104  * Mark variable v as modified if it is inside a constructor that var
2105  * is a field in.
2106  */
2107 extern (C++) int modifyFieldVar(Loc loc, Scope* sc, VarDeclaration var, Expression e1)
2108 {
2109     //printf("modifyFieldVar(var = %s)\n", var->toChars());
2110     Dsymbol s = sc.func;
2111     while (1)
2112     {
2113         FuncDeclaration fd = null;
2114         if (s)
2115             fd = s.isFuncDeclaration();
2116         if (fd &&
2117             ((fd.isCtorDeclaration() && var.isField()) ||
2118              (fd.isStaticCtorDeclaration() && !var.isField())) &&
2119             fd.toParent2() == var.toParent2() &&
2120             (!e1 || e1.op == TOKthis))
2121         {
2122             bool result = true;
2123 
2124             var.ctorinit = true;
2125             //printf("setting ctorinit\n");
2126 
2127             if (var.isField() && sc.fieldinit && !sc.intypeof)
2128             {
2129                 assert(e1);
2130                 auto mustInit = ((var.storage_class & STCnodefaultctor) != 0 ||
2131                                  var.type.needsNested());
2132 
2133                 auto dim = sc.fieldinit_dim;
2134                 auto ad = fd.isMember2();
2135                 assert(ad);
2136                 size_t i;
2137                 for (i = 0; i < dim; i++) // same as findFieldIndexByName in ctfeexp.c ?
2138                 {
2139                     if (ad.fields[i] == var)
2140                         break;
2141                 }
2142                 assert(i < dim);
2143                 uint fi = sc.fieldinit[i];
2144 
2145                 if (fi & CSXthis_ctor)
2146                 {
2147                     if (var.type.isMutable() && e1.type.isMutable())
2148                         result = false;
2149                     else
2150                     {
2151                         const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
2152                         .error(loc, "%s field '%s' initialized multiple times", modStr, var.toChars());
2153                     }
2154                 }
2155                 else if (sc.noctor || (fi & CSXlabel))
2156                 {
2157                     if (!mustInit && var.type.isMutable() && e1.type.isMutable())
2158                         result = false;
2159                     else
2160                     {
2161                         const(char)* modStr = !var.type.isMutable() ? MODtoChars(var.type.mod) : MODtoChars(e1.type.mod);
2162                         .error(loc, "%s field '%s' initialization is not allowed in loops or after labels", modStr, var.toChars());
2163                     }
2164                 }
2165 
2166                 sc.fieldinit[i] |= CSXthis_ctor;
2167                 if (var.overlapped) // Bugzilla 15258
2168                 {
2169                     foreach (j, v; ad.fields)
2170                     {
2171                         if (v is var || !var.isOverlappedWith(v))
2172                             continue;
2173                         v.ctorinit = true;
2174                         sc.fieldinit[j] = CSXthis_ctor;
2175                     }
2176                 }
2177             }
2178             else if (fd != sc.func)
2179             {
2180                 if (var.type.isMutable())
2181                     result = false;
2182                 else if (sc.func.fes)
2183                 {
2184                     const(char)* p = var.isField() ? "field" : var.kind();
2185                     .error(loc, "%s %s '%s' initialization is not allowed in foreach loop",
2186                         MODtoChars(var.type.mod), p, var.toChars());
2187                 }
2188                 else
2189                 {
2190                     const(char)* p = var.isField() ? "field" : var.kind();
2191                     .error(loc, "%s %s '%s' initialization is not allowed in nested function '%s'",
2192                         MODtoChars(var.type.mod), p, var.toChars(), sc.func.toChars());
2193                 }
2194             }
2195             return result;
2196         }
2197         else
2198         {
2199             if (s)
2200             {
2201                 s = s.toParent2();
2202                 continue;
2203             }
2204         }
2205         break;
2206     }
2207     return false;
2208 }
2209 
2210 extern (C++) Expression opAssignToOp(Loc loc, TOK op, Expression e1, Expression e2)
2211 {
2212     Expression e;
2213     switch (op)
2214     {
2215     case TOKaddass:
2216         e = new AddExp(loc, e1, e2);
2217         break;
2218 
2219     case TOKminass:
2220         e = new MinExp(loc, e1, e2);
2221         break;
2222 
2223     case TOKmulass:
2224         e = new MulExp(loc, e1, e2);
2225         break;
2226 
2227     case TOKdivass:
2228         e = new DivExp(loc, e1, e2);
2229         break;
2230 
2231     case TOKmodass:
2232         e = new ModExp(loc, e1, e2);
2233         break;
2234 
2235     case TOKandass:
2236         e = new AndExp(loc, e1, e2);
2237         break;
2238 
2239     case TOKorass:
2240         e = new OrExp(loc, e1, e2);
2241         break;
2242 
2243     case TOKxorass:
2244         e = new XorExp(loc, e1, e2);
2245         break;
2246 
2247     case TOKshlass:
2248         e = new ShlExp(loc, e1, e2);
2249         break;
2250 
2251     case TOKshrass:
2252         e = new ShrExp(loc, e1, e2);
2253         break;
2254 
2255     case TOKushrass:
2256         e = new UshrExp(loc, e1, e2);
2257         break;
2258 
2259     default:
2260         assert(0);
2261     }
2262     return e;
2263 }
2264 
2265 /****************************************************************/
2266 
2267 extern (C++) Expression extractOpDollarSideEffect(Scope* sc, UnaExp ue)
2268 {
2269     Expression e0;
2270     Expression e1 = Expression.extractLast(ue.e1, &e0);
2271     // Bugzilla 12585: Extract the side effect part if ue->e1 is comma.
2272 
2273     if (!isTrivialExp(e1))
2274     {
2275         /* Even if opDollar is needed, 'e1' should be evaluate only once. So
2276          * Rewrite:
2277          *      e1.opIndex( ... use of $ ... )
2278          *      e1.opSlice( ... use of $ ... )
2279          * as:
2280          *      (ref __dop = e1, __dop).opIndex( ... __dop.opDollar ...)
2281          *      (ref __dop = e1, __dop).opSlice( ... __dop.opDollar ...)
2282          */
2283         e1 = extractSideEffect(sc, "__dop", e0, e1, false);
2284         assert(e1.op == TOKvar);
2285         VarExp ve = cast(VarExp)e1;
2286         ve.var.storage_class |= STCexptemp;     // lifetime limited to expression
2287     }
2288     ue.e1 = e1;
2289     return e0;
2290 }
2291 
2292 /**************************************
2293  * Runs semantic on ae->arguments. Declares temporary variables
2294  * if '$' was used.
2295  */
2296 extern (C++) Expression resolveOpDollar(Scope* sc, ArrayExp ae, Expression* pe0)
2297 {
2298     assert(!ae.lengthVar);
2299     *pe0 = null;
2300     AggregateDeclaration ad = isAggregate(ae.e1.type);
2301     Dsymbol slice = search_function(ad, Id.slice);
2302     //printf("slice = %s %s\n", slice->kind(), slice->toChars());
2303     for (size_t i = 0; i < ae.arguments.dim; i++)
2304     {
2305         if (i == 0)
2306             *pe0 = extractOpDollarSideEffect(sc, ae);
2307 
2308         Expression e = (*ae.arguments)[i];
2309         if (e.op == TOKinterval && !(slice && slice.isTemplateDeclaration()))
2310         {
2311         Lfallback:
2312             if (ae.arguments.dim == 1)
2313                 return null;
2314             ae.error("multi-dimensional slicing requires template opSlice");
2315             return new ErrorExp();
2316         }
2317         //printf("[%d] e = %s\n", i, e->toChars());
2318 
2319         // Create scope for '$' variable for this dimension
2320         auto sym = new ArrayScopeSymbol(sc, ae);
2321         sym.loc = ae.loc;
2322         sym.parent = sc.scopesym;
2323         sc = sc.push(sym);
2324         ae.lengthVar = null; // Create it only if required
2325         ae.currentDimension = i; // Dimension for $, if required
2326 
2327         e = e.semantic(sc);
2328         e = resolveProperties(sc, e);
2329 
2330         if (ae.lengthVar && sc.func)
2331         {
2332             // If $ was used, declare it now
2333             Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
2334             de = de.semantic(sc);
2335             *pe0 = Expression.combine(*pe0, de);
2336         }
2337         sc = sc.pop();
2338 
2339         if (e.op == TOKinterval)
2340         {
2341             IntervalExp ie = cast(IntervalExp)e;
2342 
2343             auto tiargs = new Objects();
2344             Expression edim = new IntegerExp(ae.loc, i, Type.tsize_t);
2345             edim = edim.semantic(sc);
2346             tiargs.push(edim);
2347 
2348             auto fargs = new Expressions();
2349             fargs.push(ie.lwr);
2350             fargs.push(ie.upr);
2351 
2352             uint xerrors = global.startGagging();
2353             sc = sc.push();
2354             FuncDeclaration fslice = resolveFuncCall(ae.loc, sc, slice, tiargs, ae.e1.type, fargs, 1);
2355             sc = sc.pop();
2356             global.endGagging(xerrors);
2357             if (!fslice)
2358                 goto Lfallback;
2359 
2360             e = new DotTemplateInstanceExp(ae.loc, ae.e1, slice.ident, tiargs);
2361             e = new CallExp(ae.loc, e, fargs);
2362             e = e.semantic(sc);
2363         }
2364 
2365         if (!e.type)
2366         {
2367             ae.error("%s has no value", e.toChars());
2368             e = new ErrorExp();
2369         }
2370         if (e.op == TOKerror)
2371             return e;
2372 
2373         (*ae.arguments)[i] = e;
2374     }
2375     return ae;
2376 }
2377 
2378 /**************************************
2379  * Runs semantic on se->lwr and se->upr. Declares a temporary variable
2380  * if '$' was used.
2381  */
2382 extern (C++) Expression resolveOpDollar(Scope* sc, ArrayExp ae, IntervalExp ie, Expression* pe0)
2383 {
2384     //assert(!ae->lengthVar);
2385     if (!ie)
2386         return ae;
2387 
2388     VarDeclaration lengthVar = ae.lengthVar;
2389 
2390     // create scope for '$'
2391     auto sym = new ArrayScopeSymbol(sc, ae);
2392     sym.loc = ae.loc;
2393     sym.parent = sc.scopesym;
2394     sc = sc.push(sym);
2395 
2396     for (size_t i = 0; i < 2; ++i)
2397     {
2398         Expression e = i == 0 ? ie.lwr : ie.upr;
2399         e = e.semantic(sc);
2400         e = resolveProperties(sc, e);
2401         if (!e.type)
2402         {
2403             ae.error("%s has no value", e.toChars());
2404             return new ErrorExp();
2405         }
2406         (i == 0 ? ie.lwr : ie.upr) = e;
2407     }
2408 
2409     if (lengthVar != ae.lengthVar && sc.func)
2410     {
2411         // If $ was used, declare it now
2412         Expression de = new DeclarationExp(ae.loc, ae.lengthVar);
2413         de = de.semantic(sc);
2414         *pe0 = Expression.combine(*pe0, de);
2415     }
2416 
2417     sc = sc.pop();
2418 
2419     return ae;
2420 }
2421 
2422 /***********************************************************
2423  * Resolve `exp` as a compile-time known string.
2424  * Params:
2425  *  sc  = scope
2426  *  exp = Expression which expected as a string
2427  *  s   = What the string is expected for, will be used in error diagnostic.
2428  * Returns:
2429  *  String literal, or `null` if error happens.
2430  */
2431 StringExp semanticString(Scope *sc, Expression exp, const char* s)
2432 {
2433     sc = sc.startCTFE();
2434     exp = exp.semantic(sc);
2435     exp = resolveProperties(sc, exp);
2436     sc = sc.endCTFE();
2437 
2438     if (exp.op == TOKerror)
2439         return null;
2440 
2441     auto e = exp;
2442     if (exp.type.isString())
2443     {
2444         e = e.ctfeInterpret();
2445         if (e.op == TOKerror)
2446             return null;
2447     }
2448 
2449     auto se = e.toStringExp();
2450     if (!se)
2451     {
2452         exp.error("string expected for %s, not (%s) of type %s",
2453             s, exp.toChars(), exp.type.toChars());
2454         return null;
2455     }
2456     return se;
2457 }
2458 
2459 enum OwnedBy : int
2460 {
2461     OWNEDcode,          // normal code expression in AST
2462     OWNEDctfe,          // value expression for CTFE
2463     OWNEDcache,         // constant value cached for CTFE
2464 }
2465 
2466 alias OWNEDcode = OwnedBy.OWNEDcode;
2467 alias OWNEDctfe = OwnedBy.OWNEDctfe;
2468 alias OWNEDcache = OwnedBy.OWNEDcache;
2469 
2470 enum WANTvalue  = 0;    // default
2471 enum WANTexpand = 1;    // expand const/immutable variables if possible
2472 
2473 /***********************************************************
2474  */
2475 extern (C++) abstract class Expression : RootObject
2476 {
2477     Loc loc;        // file location
2478     Type type;      // !=null means that semantic() has been run
2479     TOK op;         // to minimize use of dynamic_cast
2480     ubyte size;     // # of bytes in Expression so we can copy() it
2481     ubyte parens;   // if this is a parenthesized expression
2482 
2483     final extern (D) this(Loc loc, TOK op, int size)
2484     {
2485         //printf("Expression::Expression(op = %d) this = %p\n", op, this);
2486         this.loc = loc;
2487         this.op = op;
2488         this.size = cast(ubyte)size;
2489     }
2490 
2491     static void _init()
2492     {
2493         CTFEExp.cantexp = new CTFEExp(TOKcantexp);
2494         CTFEExp.voidexp = new CTFEExp(TOKvoidexp);
2495         CTFEExp.breakexp = new CTFEExp(TOKbreak);
2496         CTFEExp.continueexp = new CTFEExp(TOKcontinue);
2497         CTFEExp.gotoexp = new CTFEExp(TOKgoto);
2498     }
2499 
2500     /*********************************
2501      * Does *not* do a deep copy.
2502      */
2503     final Expression copy()
2504     {
2505         Expression e;
2506         if (!size)
2507         {
2508             debug
2509             {
2510                 fprintf(stderr, "No expression copy for: %s\n", toChars());
2511                 printf("op = %d\n", op);
2512                 print();
2513             }
2514             assert(0);
2515         }
2516         e = cast(Expression)mem.xmalloc(size);
2517         //printf("Expression::copy(op = %d) e = %p\n", op, e);
2518         return cast(Expression)memcpy(cast(void*)e, cast(void*)this, size);
2519     }
2520 
2521     Expression syntaxCopy()
2522     {
2523         //printf("Expression::syntaxCopy()\n");
2524         //print();
2525         return copy();
2526     }
2527 
2528     /**************************
2529      * Semantically analyze Expression.
2530      * Determine types, fold constants, etc.
2531      */
2532     Expression semantic(Scope* sc)
2533     {
2534         static if (LOGSEMANTIC)
2535         {
2536             printf("Expression::semantic() %s\n", toChars());
2537         }
2538         if (type)
2539             type = type.semantic(loc, sc);
2540         else
2541             type = Type.tvoid;
2542         return this;
2543     }
2544 
2545     /**********************************
2546      * Try to run semantic routines.
2547      * If they fail, return NULL.
2548      */
2549     final Expression trySemantic(Scope* sc)
2550     {
2551         //printf("+trySemantic(%s)\n", toChars());
2552         uint errors = global.startGagging();
2553         Expression e = semantic(sc);
2554         if (global.endGagging(errors))
2555         {
2556             e = null;
2557         }
2558         //printf("-trySemantic(%s)\n", toChars());
2559         return e;
2560     }
2561 
2562     // kludge for template.isExpression()
2563     override final int dyncast()
2564     {
2565         return DYNCAST_EXPRESSION;
2566     }
2567 
2568     override final void print()
2569     {
2570         fprintf(stderr, "%s\n", toChars());
2571         fflush(stderr);
2572     }
2573 
2574     override const(char)* toChars()
2575     {
2576         OutBuffer buf;
2577         HdrGenState hgs;
2578         toCBuffer(this, &buf, &hgs);
2579         return buf.extractString();
2580     }
2581 
2582     /********************
2583      * Print AST data structure in a nice format.
2584      * Params:
2585      *  indent = indentation level
2586      */
2587     void printAST(int indent = 0)
2588     {
2589         foreach (i; 0 .. indent)
2590             printf(" ");
2591         printf("%s %s\n", Token.toChars(op), type ? type.toChars() : "");
2592     }
2593 
2594     final void error(const(char)* format, ...) const
2595     {
2596         if (type != Type.terror)
2597         {
2598             va_list ap;
2599             va_start(ap, format);
2600             .verror(loc, format, ap);
2601             va_end(ap);
2602         }
2603     }
2604 
2605     final void warning(const(char)* format, ...) const
2606     {
2607         if (type != Type.terror)
2608         {
2609             va_list ap;
2610             va_start(ap, format);
2611             .vwarning(loc, format, ap);
2612             va_end(ap);
2613         }
2614     }
2615 
2616     final void deprecation(const(char)* format, ...) const
2617     {
2618         if (type != Type.terror)
2619         {
2620             va_list ap;
2621             va_start(ap, format);
2622             .vdeprecation(loc, format, ap);
2623             va_end(ap);
2624         }
2625     }
2626 
2627     /**********************************
2628      * Combine e1 and e2 by CommaExp if both are not NULL.
2629      */
2630     static Expression combine(Expression e1, Expression e2)
2631     {
2632         if (e1)
2633         {
2634             if (e2)
2635             {
2636                 e1 = new CommaExp(e1.loc, e1, e2);
2637                 e1.type = e2.type;
2638             }
2639         }
2640         else
2641             e1 = e2;
2642         return e1;
2643     }
2644 
2645     /**********************************
2646      * If 'e' is a tree of commas, returns the leftmost expression
2647      * by stripping off it from the tree. The remained part of the tree
2648      * is returned via *pe0.
2649      * Otherwise 'e' is directly returned and *pe0 is set to NULL.
2650      */
2651     static Expression extractLast(Expression e, Expression* pe0)
2652     {
2653         if (e.op != TOKcomma)
2654         {
2655             *pe0 = null;
2656             return e;
2657         }
2658 
2659         CommaExp ce = cast(CommaExp)e;
2660         if (ce.e2.op != TOKcomma)
2661         {
2662             *pe0 = ce.e1;
2663             return ce.e2;
2664         }
2665         else
2666         {
2667             *pe0 = e;
2668 
2669             Expression* pce = &ce.e2;
2670             while ((cast(CommaExp)(*pce)).e2.op == TOKcomma)
2671             {
2672                 pce = &(cast(CommaExp)(*pce)).e2;
2673             }
2674             assert((*pce).op == TOKcomma);
2675             ce = cast(CommaExp)(*pce);
2676             *pce = ce.e1;
2677 
2678             return ce.e2;
2679         }
2680     }
2681 
2682     static Expressions* arraySyntaxCopy(Expressions* exps)
2683     {
2684         Expressions* a = null;
2685         if (exps)
2686         {
2687             a = new Expressions();
2688             a.setDim(exps.dim);
2689             for (size_t i = 0; i < a.dim; i++)
2690             {
2691                 Expression e = (*exps)[i];
2692                 (*a)[i] = e ? e.syntaxCopy() : null;
2693             }
2694         }
2695         return a;
2696     }
2697 
2698     dinteger_t toInteger()
2699     {
2700         //printf("Expression %s\n", Token::toChars(op));
2701         error("integer constant expression expected instead of %s", toChars());
2702         return 0;
2703     }
2704 
2705     uinteger_t toUInteger()
2706     {
2707         //printf("Expression %s\n", Token::toChars(op));
2708         return cast(uinteger_t)toInteger();
2709     }
2710 
2711     real_t toReal()
2712     {
2713         error("floating point constant expression expected instead of %s", toChars());
2714         return CTFloat.zero;
2715     }
2716 
2717     real_t toImaginary()
2718     {
2719         error("floating point constant expression expected instead of %s", toChars());
2720         return CTFloat.zero;
2721     }
2722 
2723     complex_t toComplex()
2724     {
2725         error("floating point constant expression expected instead of %s", toChars());
2726         return complex_t(CTFloat.zero);
2727     }
2728 
2729     StringExp toStringExp()
2730     {
2731         return null;
2732     }
2733 
2734     /***************************************
2735      * Return !=0 if expression is an lvalue.
2736      */
2737     bool isLvalue()
2738     {
2739         return false;
2740     }
2741 
2742     /*******************************
2743      * Give error if we're not an lvalue.
2744      * If we can, convert expression to be an lvalue.
2745      */
2746     Expression toLvalue(Scope* sc, Expression e)
2747     {
2748         if (!e)
2749             e = this;
2750         else if (!loc.filename)
2751             loc = e.loc;
2752 
2753         if (e.op == TOKtype)
2754             error("%s '%s' is a type, not an lvalue", e.type.kind(), e.type.toChars());
2755         else
2756             error("%s is not an lvalue", e.toChars());
2757 
2758         return new ErrorExp();
2759     }
2760 
2761     Expression modifiableLvalue(Scope* sc, Expression e)
2762     {
2763         //printf("Expression::modifiableLvalue() %s, type = %s\n", toChars(), type->toChars());
2764         // See if this expression is a modifiable lvalue (i.e. not const)
2765         if (checkModifiable(sc) == 1)
2766         {
2767             assert(type);
2768             if (!type.isMutable())
2769             {
2770                 error("cannot modify %s expression %s", MODtoChars(type.mod), toChars());
2771                 return new ErrorExp();
2772             }
2773             else if (!type.isAssignable())
2774             {
2775                 error("cannot modify struct %s %s with immutable members", toChars(), type.toChars());
2776                 return new ErrorExp();
2777             }
2778         }
2779         return toLvalue(sc, e);
2780     }
2781 
2782     final Expression implicitCastTo(Scope* sc, Type t)
2783     {
2784         return .implicitCastTo(this, sc, t);
2785     }
2786 
2787     final MATCH implicitConvTo(Type t)
2788     {
2789         return .implicitConvTo(this, t);
2790     }
2791 
2792     final Expression castTo(Scope* sc, Type t)
2793     {
2794         return .castTo(this, sc, t);
2795     }
2796 
2797     /****************************************
2798      * Resolve __FILE__, __LINE__, __MODULE__, __FUNCTION__, __PRETTY_FUNCTION__ to loc.
2799      */
2800     Expression resolveLoc(Loc loc, Scope* sc)
2801     {
2802         return this;
2803     }
2804 
2805     /****************************************
2806      * Check that the expression has a valid type.
2807      * If not, generates an error "... has no type".
2808      * Returns:
2809      *      true if the expression is not valid.
2810      * Note:
2811      *      When this function returns true, `checkValue()` should also return true.
2812      */
2813     bool checkType()
2814     {
2815         return false;
2816     }
2817 
2818     /****************************************
2819      * Check that the expression has a valid value.
2820      * If not, generates an error "... has no value".
2821      * Returns:
2822      *      true if the expression is not valid or has void type.
2823      */
2824     bool checkValue()
2825     {
2826         if (type && type.toBasetype().ty == Tvoid)
2827         {
2828             error("expression %s is void and has no value", toChars());
2829             //print(); assert(0);
2830             if (!global.gag)
2831                 type = Type.terror;
2832             return true;
2833         }
2834         return false;
2835     }
2836 
2837     final bool checkScalar()
2838     {
2839         if (op == TOKerror)
2840             return true;
2841         if (type.toBasetype().ty == Terror)
2842             return true;
2843         if (!type.isscalar())
2844         {
2845             error("'%s' is not a scalar, it is a %s", toChars(), type.toChars());
2846             return true;
2847         }
2848         return checkValue();
2849     }
2850 
2851     final bool checkNoBool()
2852     {
2853         if (op == TOKerror)
2854             return true;
2855         if (type.toBasetype().ty == Terror)
2856             return true;
2857         if (type.toBasetype().ty == Tbool)
2858         {
2859             error("operation not allowed on bool '%s'", toChars());
2860             return true;
2861         }
2862         return false;
2863     }
2864 
2865     final bool checkIntegral()
2866     {
2867         if (op == TOKerror)
2868             return true;
2869         if (type.toBasetype().ty == Terror)
2870             return true;
2871         if (!type.isintegral())
2872         {
2873             error("'%s' is not of integral type, it is a %s", toChars(), type.toChars());
2874             return true;
2875         }
2876         return checkValue();
2877     }
2878 
2879     final bool checkArithmetic()
2880     {
2881         if (op == TOKerror)
2882             return true;
2883         if (type.toBasetype().ty == Terror)
2884             return true;
2885         if (!type.isintegral() && !type.isfloating())
2886         {
2887             error("'%s' is not of arithmetic type, it is a %s", toChars(), type.toChars());
2888             return true;
2889         }
2890         return checkValue();
2891     }
2892 
2893     final void checkDeprecated(Scope* sc, Dsymbol s)
2894     {
2895         s.checkDeprecated(loc, sc);
2896     }
2897 
2898     /*********************************************
2899      * Calling function f.
2900      * Check the purity, i.e. if we're in a pure function
2901      * we can only call other pure functions.
2902      * Returns true if error occurs.
2903      */
2904     final bool checkPurity(Scope* sc, FuncDeclaration f)
2905     {
2906         if (!sc.func)
2907             return false;
2908         if (sc.func == f)
2909             return false;
2910         if (sc.intypeof == 1)
2911             return false;
2912         if (sc.flags & (SCOPEctfe | SCOPEdebug))
2913             return false;
2914 
2915         /* Given:
2916          * void f() {
2917          *   pure void g() {
2918          *     /+pure+/ void h() {
2919          *       /+pure+/ void i() { }
2920          *     }
2921          *   }
2922          * }
2923          * g() can call h() but not f()
2924          * i() can call h() and g() but not f()
2925          */
2926 
2927         // Find the closest pure parent of the calling function
2928         FuncDeclaration outerfunc = sc.func;
2929         FuncDeclaration calledparent = f;
2930 
2931         if (outerfunc.isInstantiated())
2932         {
2933             // The attributes of outerfunc should be inferred from the call of f.
2934         }
2935         else if (f.isInstantiated())
2936         {
2937             // The attributes of f are inferred from its body.
2938         }
2939         else if (f.isFuncLiteralDeclaration())
2940         {
2941             // The attributes of f are always inferred in its declared place.
2942         }
2943         else
2944         {
2945             /* Today, static local functions are impure by default, but they cannot
2946              * violate purity of enclosing functions.
2947              *
2948              *  auto foo() pure {      // non instantiated funciton
2949              *    static auto bar() {  // static, without pure attribute
2950              *      impureFunc();      // impure call
2951              *      // Although impureFunc is called inside bar, f(= impureFunc)
2952              *      // is not callable inside pure outerfunc(= foo <- bar).
2953              *    }
2954              *
2955              *    bar();
2956              *    // Although bar is called inside foo, f(= bar) is callable
2957              *    // bacause calledparent(= foo) is same with outerfunc(= foo).
2958              *  }
2959              */
2960 
2961             while (outerfunc.toParent2() && outerfunc.isPureBypassingInference() == PUREimpure && outerfunc.toParent2().isFuncDeclaration())
2962             {
2963                 outerfunc = outerfunc.toParent2().isFuncDeclaration();
2964                 if (outerfunc.type.ty == Terror)
2965                     return true;
2966             }
2967             while (calledparent.toParent2() && calledparent.isPureBypassingInference() == PUREimpure && calledparent.toParent2().isFuncDeclaration())
2968             {
2969                 calledparent = calledparent.toParent2().isFuncDeclaration();
2970                 if (calledparent.type.ty == Terror)
2971                     return true;
2972             }
2973         }
2974 
2975         // If the caller has a pure parent, then either the called func must be pure,
2976         // OR, they must have the same pure parent.
2977         if (!f.isPure() && calledparent != outerfunc)
2978         {
2979             FuncDeclaration ff = outerfunc;
2980             if (sc.flags & SCOPEcompile ? ff.isPureBypassingInference() >= PUREweak : ff.setImpure())
2981             {
2982                 error("pure %s '%s' cannot call impure %s '%s'",
2983                     ff.kind(), ff.toPrettyChars(), f.kind(), f.toPrettyChars());
2984                 return true;
2985             }
2986         }
2987         return false;
2988     }
2989 
2990     /*******************************************
2991      * Accessing variable v.
2992      * Check for purity and safety violations.
2993      * Returns true if error occurs.
2994      */
2995     final bool checkPurity(Scope* sc, VarDeclaration v)
2996     {
2997         //printf("v = %s %s\n", v->type->toChars(), v->toChars());
2998         /* Look for purity and safety violations when accessing variable v
2999          * from current function.
3000          */
3001         if (!sc.func)
3002             return false;
3003         if (sc.intypeof == 1)
3004             return false; // allow violations inside typeof(expression)
3005         if (sc.flags & (SCOPEctfe | SCOPEdebug))
3006             return false; // allow violations inside compile-time evaluated expressions and debug conditionals
3007         if (v.ident == Id.ctfe)
3008             return false; // magic variable never violates pure and safe
3009         if (v.isImmutable())
3010             return false; // always safe and pure to access immutables...
3011         if (v.isConst() && !v.isRef() && (v.isDataseg() || v.isParameter()) && v.type.implicitConvTo(v.type.immutableOf()))
3012             return false; // or const global/parameter values which have no mutable indirections
3013         if (v.storage_class & STCmanifest)
3014             return false; // ...or manifest constants
3015 
3016         bool err = false;
3017         if (v.isDataseg())
3018         {
3019             // Bugzilla 7533: Accessing implicit generated __gate is pure.
3020             if (v.ident == Id.gate)
3021                 return false;
3022 
3023             /* Accessing global mutable state.
3024              * Therefore, this function and all its immediately enclosing
3025              * functions must be pure.
3026              */
3027             /* Today, static local functions are impure by default, but they cannot
3028              * violate purity of enclosing functions.
3029              *
3030              *  auto foo() pure {      // non instantiated funciton
3031              *    static auto bar() {  // static, without pure attribute
3032              *      globalData++;      // impure access
3033              *      // Although globalData is accessed inside bar,
3034              *      // it is not accessible inside pure foo.
3035              *    }
3036              *  }
3037              */
3038             for (Dsymbol s = sc.func; s; s = s.toParent2())
3039             {
3040                 FuncDeclaration ff = s.isFuncDeclaration();
3041                 if (!ff)
3042                     break;
3043                 if (sc.flags & SCOPEcompile ? ff.isPureBypassingInference() >= PUREweak : ff.setImpure())
3044                 {
3045                     error("pure %s '%s' cannot access mutable static data '%s'",
3046                         ff.kind(), ff.toPrettyChars(), v.toChars());
3047                     err = true;
3048                     break;
3049                 }
3050 
3051                 /* If the enclosing is an instantiated function or a lambda, its
3052                  * attribute inference result is preferred.
3053                  */
3054                 if (ff.isInstantiated())
3055                     break;
3056                 if (ff.isFuncLiteralDeclaration())
3057                     break;
3058             }
3059         }
3060         else
3061         {
3062             /* Given:
3063              * void f() {
3064              *   int fx;
3065              *   pure void g() {
3066              *     int gx;
3067              *     /+pure+/ void h() {
3068              *       int hx;
3069              *       /+pure+/ void i() { }
3070              *     }
3071              *   }
3072              * }
3073              * i() can modify hx and gx but not fx
3074              */
3075 
3076             Dsymbol vparent = v.toParent2();
3077             for (Dsymbol s = sc.func; !err && s; s = s.toParent2())
3078             {
3079                 if (s == vparent)
3080                     break;
3081 
3082                 if (AggregateDeclaration ad = s.isAggregateDeclaration())
3083                 {
3084                     if (ad.isNested())
3085                         continue;
3086                     break;
3087                 }
3088                 FuncDeclaration ff = s.isFuncDeclaration();
3089                 if (!ff)
3090                     break;
3091                 if (ff.isNested() || ff.isThis())
3092                 {
3093                     if (ff.type.isImmutable() ||
3094                         ff.type.isShared() && !MODimplicitConv(ff.type.mod, v.type.mod))
3095                     {
3096                         OutBuffer ffbuf;
3097                         OutBuffer vbuf;
3098                         MODMatchToBuffer(&ffbuf, ff.type.mod, v.type.mod);
3099                         MODMatchToBuffer(&vbuf, v.type.mod, ff.type.mod);
3100                         error("%s%s '%s' cannot access %sdata '%s'",
3101                             ffbuf.peekString(), ff.kind(), ff.toPrettyChars(), vbuf.peekString(), v.toChars());
3102                         err = true;
3103                         break;
3104                     }
3105                     continue;
3106                 }
3107                 break;
3108             }
3109         }
3110 
3111         /* Do not allow safe functions to access __gshared data
3112          */
3113         if (v.storage_class & STCgshared)
3114         {
3115             if (sc.func.setUnsafe())
3116             {
3117                 error("safe %s '%s' cannot access __gshared data '%s'",
3118                     sc.func.kind(), sc.func.toChars(), v.toChars());
3119                 err = true;
3120             }
3121         }
3122 
3123         return err;
3124     }
3125 
3126     /*********************************************
3127      * Calling function f.
3128      * Check the safety, i.e. if we're in a @safe function
3129      * we can only call @safe or @trusted functions.
3130      * Returns true if error occurs.
3131      */
3132     final bool checkSafety(Scope* sc, FuncDeclaration f)
3133     {
3134         if (!sc.func)
3135             return false;
3136         if (sc.func == f)
3137             return false;
3138         if (sc.intypeof == 1)
3139             return false;
3140         if (sc.flags & SCOPEctfe)
3141             return false;
3142 
3143         if (!f.isSafe() && !f.isTrusted())
3144         {
3145             if (sc.flags & SCOPEcompile ? sc.func.isSafeBypassingInference() : sc.func.setUnsafe())
3146             {
3147                 if (loc.linnum == 0) // e.g. implicitly generated dtor
3148                     loc = sc.func.loc;
3149                 error("@safe %s '%s' cannot call @system %s '%s'",
3150                     sc.func.kind(), sc.func.toPrettyChars(), f.kind(), f.toPrettyChars());
3151                 return true;
3152             }
3153         }
3154         return false;
3155     }
3156 
3157     /*********************************************
3158      * Calling function f.
3159      * Check the @nogc-ness, i.e. if we're in a @nogc function
3160      * we can only call other @nogc functions.
3161      * Returns true if error occurs.
3162      */
3163     final bool checkNogc(Scope* sc, FuncDeclaration f)
3164     {
3165         if (!sc.func)
3166             return false;
3167         if (sc.func == f)
3168             return false;
3169         if (sc.intypeof == 1)
3170             return false;
3171         if (sc.flags & SCOPEctfe)
3172             return false;
3173 
3174         if (!f.isNogc())
3175         {
3176             if (sc.flags & SCOPEcompile ? sc.func.isNogcBypassingInference() : sc.func.setGC())
3177             {
3178                 if (loc.linnum == 0) // e.g. implicitly generated dtor
3179                     loc = sc.func.loc;
3180                 error("@nogc %s '%s' cannot call non-@nogc %s '%s'",
3181                     sc.func.kind(), sc.func.toPrettyChars(), f.kind(), f.toPrettyChars());
3182                 return true;
3183             }
3184         }
3185         return false;
3186     }
3187 
3188     /********************************************
3189      * Check that the postblit is callable if t is an array of structs.
3190      * Returns true if error happens.
3191      */
3192     final bool checkPostblit(Scope* sc, Type t)
3193     {
3194         t = t.baseElemOf();
3195         if (t.ty == Tstruct)
3196         {
3197             // Bugzilla 11395: Require TypeInfo generation for array concatenation
3198             semanticTypeInfo(sc, t);
3199 
3200             StructDeclaration sd = (cast(TypeStruct)t).sym;
3201             if (sd.postblit)
3202             {
3203                 if (sd.postblit.storage_class & STCdisable)
3204                 {
3205                     sd.error(loc, "is not copyable because it is annotated with @disable");
3206                     return true;
3207                 }
3208                 //checkDeprecated(sc, sd->postblit);        // necessary?
3209                 checkPurity(sc, sd.postblit);
3210                 checkSafety(sc, sd.postblit);
3211                 checkNogc(sc, sd.postblit);
3212                 //checkAccess(sd, loc, sc, sd->postblit);   // necessary?
3213                 return false;
3214             }
3215         }
3216         return false;
3217     }
3218 
3219     final bool checkRightThis(Scope* sc)
3220     {
3221         if (op == TOKerror)
3222             return true;
3223         if (op == TOKvar && type.ty != Terror)
3224         {
3225             VarExp ve = cast(VarExp)this;
3226             if (isNeedThisScope(sc, ve.var))
3227             {
3228                 //printf("checkRightThis sc->intypeof = %d, ad = %p, func = %p, fdthis = %p\n",
3229                 //        sc->intypeof, sc->getStructClassScope(), func, fdthis);
3230                 error("need 'this' for '%s' of type '%s'", ve.var.toChars(), ve.var.type.toChars());
3231                 return true;
3232             }
3233         }
3234         return false;
3235     }
3236 
3237     /*******************************
3238      * Check whether the expression allows RMW operations, error with rmw operator diagnostic if not.
3239      * ex is the RHS expression, or NULL if ++/-- is used (for diagnostics)
3240      * Returns true if error occurs.
3241      */
3242     final bool checkReadModifyWrite(TOK rmwOp, Expression ex = null)
3243     {
3244         //printf("Expression::checkReadModifyWrite() %s %s", toChars(), ex ? ex->toChars() : "");
3245         if (!type || !type.isShared())
3246             return false;
3247 
3248         // atomicOp uses opAssign (+=/-=) rather than opOp (++/--) for the CT string literal.
3249         switch (rmwOp)
3250         {
3251         case TOKplusplus:
3252         case TOKpreplusplus:
3253             rmwOp = TOKaddass;
3254             break;
3255         case TOKminusminus:
3256         case TOKpreminusminus:
3257             rmwOp = TOKminass;
3258             break;
3259         default:
3260             break;
3261         }
3262 
3263         deprecation("read-modify-write operations are not allowed for shared variables. Use core.atomic.atomicOp!\"%s\"(%s, %s) instead.", Token.toChars(rmwOp), toChars(), ex ? ex.toChars() : "1");
3264         return false;
3265 
3266         // note: enable when deprecation becomes an error.
3267         // return true;
3268     }
3269 
3270     /***************************************
3271      * Parameters:
3272      *      sc:     scope
3273      *      flag:   1: do not issue error message for invalid modification
3274      * Returns:
3275      *      0:      is not modifiable
3276      *      1:      is modifiable in default == being related to type->isMutable()
3277      *      2:      is modifiable, because this is a part of initializing.
3278      */
3279     int checkModifiable(Scope* sc, int flag = 0)
3280     {
3281         return type ? 1 : 0; // default modifiable
3282     }
3283 
3284     /*****************************
3285      * If expression can be tested for true or false,
3286      * returns the modified expression.
3287      * Otherwise returns ErrorExp.
3288      */
3289     Expression toBoolean(Scope* sc)
3290     {
3291         // Default is 'yes' - do nothing
3292         debug
3293         {
3294             if (!type)
3295                 print();
3296             assert(type);
3297         }
3298         Expression e = this;
3299         Type t = type;
3300         Type tb = type.toBasetype();
3301         Type att = null;
3302     Lagain:
3303         // Structs can be converted to bool using opCast(bool)()
3304         if (tb.ty == Tstruct)
3305         {
3306             AggregateDeclaration ad = (cast(TypeStruct)tb).sym;
3307             /* Don't really need to check for opCast first, but by doing so we
3308              * get better error messages if it isn't there.
3309              */
3310             Dsymbol fd = search_function(ad, Id._cast);
3311             if (fd)
3312             {
3313                 e = new CastExp(loc, e, Type.tbool);
3314                 e = e.semantic(sc);
3315                 return e;
3316             }
3317 
3318             // Forward to aliasthis.
3319             if (ad.aliasthis && tb != att)
3320             {
3321                 if (!att && tb.checkAliasThisRec())
3322                     att = tb;
3323                 e = resolveAliasThis(sc, e);
3324                 t = e.type;
3325                 tb = e.type.toBasetype();
3326                 goto Lagain;
3327             }
3328         }
3329 
3330         if (!t.isBoolean())
3331         {
3332             if (tb != Type.terror)
3333                 error("expression %s of type %s does not have a boolean value", toChars(), t.toChars());
3334             return new ErrorExp();
3335         }
3336         return e;
3337     }
3338 
3339     /************************************************
3340      * Destructors are attached to VarDeclarations.
3341      * Hence, if expression returns a temp that needs a destructor,
3342      * make sure and create a VarDeclaration for that temp.
3343      */
3344     Expression addDtorHook(Scope* sc)
3345     {
3346         return this;
3347     }
3348 
3349     /******************************
3350      * Take address of expression.
3351      */
3352     final Expression addressOf()
3353     {
3354         //printf("Expression::addressOf()\n");
3355         debug
3356         {
3357             assert(op == TOKerror || isLvalue());
3358         }
3359         Expression e = new AddrExp(loc, this);
3360         e.type = type.pointerTo();
3361         return e;
3362     }
3363 
3364     /******************************
3365      * If this is a reference, dereference it.
3366      */
3367     final Expression deref()
3368     {
3369         //printf("Expression::deref()\n");
3370         // type could be null if forward referencing an 'auto' variable
3371         if (type && type.ty == Treference)
3372         {
3373             Expression e = new PtrExp(loc, this);
3374             e.type = (cast(TypeReference)type).next;
3375             return e;
3376         }
3377         return this;
3378     }
3379 
3380     final Expression optimize(int result, bool keepLvalue = false)
3381     {
3382         return Expression_optimize(this, result, keepLvalue);
3383     }
3384 
3385     // Entry point for CTFE.
3386     // A compile-time result is required. Give an error if not possible
3387     final Expression ctfeInterpret()
3388     {
3389         return .ctfeInterpret(this);
3390     }
3391 
3392     final int isConst()
3393     {
3394         return .isConst(this);
3395     }
3396 
3397     /********************************
3398      * Does this expression statically evaluate to a boolean 'result' (true or false)?
3399      */
3400     bool isBool(bool result)
3401     {
3402         return false;
3403     }
3404 
3405     final Expression op_overload(Scope* sc)
3406     {
3407         return .op_overload(this, sc);
3408     }
3409 
3410     void accept(Visitor v)
3411     {
3412         v.visit(this);
3413     }
3414 }
3415 
3416 /***********************************************************
3417  */
3418 extern (C++) final class IntegerExp : Expression
3419 {
3420     dinteger_t value;
3421 
3422     extern (D) this(Loc loc, dinteger_t value, Type type)
3423     {
3424         super(loc, TOKint64, __traits(classInstanceSize, IntegerExp));
3425         //printf("IntegerExp(value = %lld, type = '%s')\n", value, type ? type->toChars() : "");
3426         assert(type);
3427         if (!type.isscalar())
3428         {
3429             //printf("%s, loc = %d\n", toChars(), loc.linnum);
3430             if (type.ty != Terror)
3431                 error("integral constant must be scalar type, not %s", type.toChars());
3432             type = Type.terror;
3433         }
3434         this.type = type;
3435         setInteger(value);
3436     }
3437 
3438     extern (D) this(dinteger_t value)
3439     {
3440         super(Loc(), TOKint64, __traits(classInstanceSize, IntegerExp));
3441         this.type = Type.tint32;
3442         this.value = cast(d_int32)value;
3443     }
3444 
3445     override bool equals(RootObject o)
3446     {
3447         if (this == o)
3448             return true;
3449         if ((cast(Expression)o).op == TOKint64)
3450         {
3451             IntegerExp ne = cast(IntegerExp)o;
3452             if (type.toHeadMutable().equals(ne.type.toHeadMutable()) && value == ne.value)
3453             {
3454                 return true;
3455             }
3456         }
3457         return false;
3458     }
3459 
3460     override Expression semantic(Scope* sc)
3461     {
3462         assert(type);
3463         if (type.ty == Terror)
3464             return new ErrorExp();
3465         assert(type.deco);
3466         normalize();
3467         return this;
3468     }
3469 
3470     override dinteger_t toInteger()
3471     {
3472         normalize(); // necessary until we fix all the paints of 'type'
3473         return value;
3474     }
3475 
3476     override real_t toReal()
3477     {
3478         normalize(); // necessary until we fix all the paints of 'type'
3479         Type t = type.toBasetype();
3480         if (t.ty == Tuns64)
3481             return real_t(cast(d_uns64)value);
3482         else
3483             return real_t(cast(d_int64)value);
3484     }
3485 
3486     override real_t toImaginary()
3487     {
3488         return CTFloat.zero;
3489     }
3490 
3491     override complex_t toComplex()
3492     {
3493         return complex_t(toReal());
3494     }
3495 
3496     override bool isBool(bool result)
3497     {
3498         bool r = toInteger() != 0;
3499         return result ? r : !r;
3500     }
3501 
3502     override Expression toLvalue(Scope* sc, Expression e)
3503     {
3504         if (!e)
3505             e = this;
3506         else if (!loc.filename)
3507             loc = e.loc;
3508         e.error("constant %s is not an lvalue", e.toChars());
3509         return new ErrorExp();
3510     }
3511 
3512     override void accept(Visitor v)
3513     {
3514         v.visit(this);
3515     }
3516 
3517     dinteger_t getInteger()
3518     {
3519         return value;
3520     }
3521 
3522     void setInteger(dinteger_t value)
3523     {
3524         this.value = value;
3525         normalize();
3526     }
3527 
3528 private:
3529     void normalize()
3530     {
3531         /* 'Normalize' the value of the integer to be in range of the type
3532          */
3533         switch (type.toBasetype().ty)
3534         {
3535         case Tbool:
3536             value = (value != 0);
3537             break;
3538 
3539         case Tint8:
3540             value = cast(d_int8)value;
3541             break;
3542 
3543         case Tchar:
3544         case Tuns8:
3545             value = cast(d_uns8)value;
3546             break;
3547 
3548         case Tint16:
3549             value = cast(d_int16)value;
3550             break;
3551 
3552         case Twchar:
3553         case Tuns16:
3554             value = cast(d_uns16)value;
3555             break;
3556 
3557         case Tint32:
3558             value = cast(d_int32)value;
3559             break;
3560 
3561         case Tdchar:
3562         case Tuns32:
3563             value = cast(d_uns32)value;
3564             break;
3565 
3566         case Tint64:
3567             value = cast(d_int64)value;
3568             break;
3569 
3570         case Tuns64:
3571             value = cast(d_uns64)value;
3572             break;
3573 
3574         case Tpointer:
3575             if (Target.ptrsize == 4)
3576                 value = cast(d_uns32)value;
3577             else if (Target.ptrsize == 8)
3578                 value = cast(d_uns64)value;
3579             else
3580                 assert(0);
3581             break;
3582 
3583         default:
3584             break;
3585         }
3586     }
3587 }
3588 
3589 /***********************************************************
3590  * Use this expression for error recovery.
3591  * It should behave as a 'sink' to prevent further cascaded error messages.
3592  */
3593 extern (C++) final class ErrorExp : Expression
3594 {
3595     extern (D) this()
3596     {
3597         super(Loc(), TOKerror, __traits(classInstanceSize, ErrorExp));
3598         type = Type.terror;
3599     }
3600 
3601     override Expression toLvalue(Scope* sc, Expression e)
3602     {
3603         return this;
3604     }
3605 
3606     override void accept(Visitor v)
3607     {
3608         v.visit(this);
3609     }
3610 
3611     extern (C++) static __gshared ErrorExp errorexp; // handy shared value
3612 }
3613 
3614 /***********************************************************
3615  */
3616 extern (C++) final class RealExp : Expression
3617 {
3618     real_t value;
3619 
3620     extern (D) this(Loc loc, real_t value, Type type)
3621     {
3622         super(loc, TOKfloat64, __traits(classInstanceSize, RealExp));
3623         //printf("RealExp::RealExp(%Lg)\n", value);
3624         this.value = value;
3625         this.type = type;
3626     }
3627 
3628     override bool equals(RootObject o)
3629     {
3630         if (this == o)
3631             return true;
3632         if ((cast(Expression)o).op == TOKfloat64)
3633         {
3634             RealExp ne = cast(RealExp)o;
3635             if (type.toHeadMutable().equals(ne.type.toHeadMutable()) && RealEquals(value, ne.value))
3636             {
3637                 return true;
3638             }
3639         }
3640         return false;
3641     }
3642 
3643     override Expression semantic(Scope* sc)
3644     {
3645         if (!type)
3646             type = Type.tfloat64;
3647         else
3648             type = type.semantic(loc, sc);
3649         return this;
3650     }
3651 
3652     override dinteger_t toInteger()
3653     {
3654         return cast(sinteger_t)toReal();
3655     }
3656 
3657     override uinteger_t toUInteger()
3658     {
3659         return cast(uinteger_t)toReal();
3660     }
3661 
3662     override real_t toReal()
3663     {
3664         return type.isreal() ? value : CTFloat.zero;
3665     }
3666 
3667     override real_t toImaginary()
3668     {
3669         return type.isreal() ? CTFloat.zero : value;
3670     }
3671 
3672     override complex_t toComplex()
3673     {
3674         return complex_t(toReal(), toImaginary());
3675     }
3676 
3677     override bool isBool(bool result)
3678     {
3679         return result ? cast(bool)value : !cast(bool)value;
3680     }
3681 
3682     override void accept(Visitor v)
3683     {
3684         v.visit(this);
3685     }
3686 }
3687 
3688 /***********************************************************
3689  */
3690 extern (C++) final class ComplexExp : Expression
3691 {
3692     complex_t value;
3693 
3694     extern (D) this(Loc loc, complex_t value, Type type)
3695     {
3696         super(loc, TOKcomplex80, __traits(classInstanceSize, ComplexExp));
3697         this.value = value;
3698         this.type = type;
3699         //printf("ComplexExp::ComplexExp(%s)\n", toChars());
3700     }
3701 
3702     override bool equals(RootObject o)
3703     {
3704         if (this == o)
3705             return true;
3706         if ((cast(Expression)o).op == TOKcomplex80)
3707         {
3708             ComplexExp ne = cast(ComplexExp)o;
3709             if (type.toHeadMutable().equals(ne.type.toHeadMutable()) && RealEquals(creall(value), creall(ne.value)) && RealEquals(cimagl(value), cimagl(ne.value)))
3710             {
3711                 return true;
3712             }
3713         }
3714         return false;
3715     }
3716 
3717     override Expression semantic(Scope* sc)
3718     {
3719         if (!type)
3720             type = Type.tcomplex80;
3721         else
3722             type = type.semantic(loc, sc);
3723         return this;
3724     }
3725 
3726     override dinteger_t toInteger()
3727     {
3728         return cast(sinteger_t)toReal();
3729     }
3730 
3731     override uinteger_t toUInteger()
3732     {
3733         return cast(uinteger_t)toReal();
3734     }
3735 
3736     override real_t toReal()
3737     {
3738         return creall(value);
3739     }
3740 
3741     override real_t toImaginary()
3742     {
3743         return cimagl(value);
3744     }
3745 
3746     override complex_t toComplex()
3747     {
3748         return value;
3749     }
3750 
3751     override bool isBool(bool result)
3752     {
3753         if (result)
3754             return cast(bool)value;
3755         else
3756             return !value;
3757     }
3758 
3759     override void accept(Visitor v)
3760     {
3761         v.visit(this);
3762     }
3763 }
3764 
3765 /***********************************************************
3766  */
3767 extern (C++) class IdentifierExp : Expression
3768 {
3769     Identifier ident;
3770 
3771     final extern (D) this(Loc loc, Identifier ident)
3772     {
3773         super(loc, TOKidentifier, __traits(classInstanceSize, IdentifierExp));
3774         this.ident = ident;
3775     }
3776 
3777     static IdentifierExp create(Loc loc, Identifier ident)
3778     {
3779         return new IdentifierExp(loc, ident);
3780     }
3781 
3782     override final Expression semantic(Scope* sc)
3783     {
3784         static if (LOGSEMANTIC)
3785         {
3786             printf("IdentifierExp::semantic('%s')\n", ident.toChars());
3787         }
3788         if (type) // This is used as the dummy expression
3789             return this;
3790 
3791         Dsymbol scopesym;
3792         Dsymbol s = sc.search(loc, ident, &scopesym);
3793         if (s)
3794         {
3795             if (s.errors)
3796                 return new ErrorExp();
3797 
3798             Expression e;
3799 
3800             /* See if the symbol was a member of an enclosing 'with'
3801              */
3802             WithScopeSymbol withsym = scopesym.isWithScopeSymbol();
3803             if (withsym && withsym.withstate.wthis)
3804             {
3805                 /* Disallow shadowing
3806                  */
3807                 // First find the scope of the with
3808                 Scope* scwith = sc;
3809                 while (scwith.scopesym != scopesym)
3810                 {
3811                     scwith = scwith.enclosing;
3812                     assert(scwith);
3813                 }
3814                 // Look at enclosing scopes for symbols with the same name,
3815                 // in the same function
3816                 for (Scope* scx = scwith; scx && scx.func == scwith.func; scx = scx.enclosing)
3817                 {
3818                     Dsymbol s2;
3819                     if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
3820                     {
3821                         error("with symbol %s is shadowing local symbol %s", s.toPrettyChars(), s2.toPrettyChars());
3822                         return new ErrorExp();
3823                     }
3824                 }
3825                 s = s.toAlias();
3826 
3827                 // Same as wthis.ident
3828                 //  TODO: DotIdExp.semantic will find 'ident' from 'wthis' again.
3829                 //  The redudancy should be removed.
3830                 e = new VarExp(loc, withsym.withstate.wthis);
3831                 e = new DotIdExp(loc, e, ident);
3832                 e = e.semantic(sc);
3833             }
3834             else
3835             {
3836                 if (withsym)
3837                 {
3838                     Declaration d = s.isDeclaration();
3839                     if (d)
3840                         checkAccess(loc, sc, null, d);
3841                 }
3842 
3843                 /* If f is really a function template,
3844                  * then replace f with the function template declaration.
3845                  */
3846                 FuncDeclaration f = s.isFuncDeclaration();
3847                 if (f)
3848                 {
3849                     TemplateDeclaration td = getFuncTemplateDecl(f);
3850                     if (td)
3851                     {
3852                         if (td.overroot) // if not start of overloaded list of TemplateDeclaration's
3853                             td = td.overroot; // then get the start
3854                         e = new TemplateExp(loc, td, f);
3855                         e = e.semantic(sc);
3856                         return e;
3857                     }
3858                 }
3859                 // Haven't done overload resolution yet, so pass 1
3860                 e = DsymbolExp.resolve(loc, sc, s, true);
3861             }
3862             return e;
3863         }
3864 
3865         if (hasThis(sc))
3866         {
3867             AggregateDeclaration ad = sc.getStructClassScope();
3868             if (ad && ad.aliasthis)
3869             {
3870                 Expression e;
3871                 e = new IdentifierExp(loc, Id.This);
3872                 e = new DotIdExp(loc, e, ad.aliasthis.ident);
3873                 e = new DotIdExp(loc, e, ident);
3874                 e = e.trySemantic(sc);
3875                 if (e)
3876                     return e;
3877             }
3878         }
3879 
3880         if (ident == Id.ctfe)
3881         {
3882             if (sc.flags & SCOPEctfe)
3883             {
3884                 error("variable __ctfe cannot be read at compile time");
3885                 return new ErrorExp();
3886             }
3887 
3888             // Create the magic __ctfe bool variable
3889             auto vd = new VarDeclaration(loc, Type.tbool, Id.ctfe, null);
3890             vd.storage_class |= STCtemp;
3891             Expression e = new VarExp(loc, vd);
3892             e = e.semantic(sc);
3893             return e;
3894         }
3895 
3896         const(char)* n = importHint(ident.toChars());
3897         if (n)
3898             error("'%s' is not defined, perhaps you need to import %s; ?", ident.toChars(), n);
3899         else
3900         {
3901             s = sc.search_correct(ident);
3902             if (s)
3903                 error("undefined identifier '%s', did you mean %s '%s'?", ident.toChars(), s.kind(), s.toChars());
3904             else
3905                 error("undefined identifier '%s'", ident.toChars());
3906         }
3907         return new ErrorExp();
3908     }
3909 
3910     override final bool isLvalue()
3911     {
3912         return true;
3913     }
3914 
3915     override final Expression toLvalue(Scope* sc, Expression e)
3916     {
3917         return this;
3918     }
3919 
3920     override void accept(Visitor v)
3921     {
3922         v.visit(this);
3923     }
3924 }
3925 
3926 /***********************************************************
3927  */
3928 extern (C++) final class DollarExp : IdentifierExp
3929 {
3930     extern (D) this(Loc loc)
3931     {
3932         super(loc, Id.dollar);
3933     }
3934 
3935     override void accept(Visitor v)
3936     {
3937         v.visit(this);
3938     }
3939 }
3940 
3941 /***********************************************************
3942  * Won't be generated by parser.
3943  * A placeholder expression to call DsymbolExp.resolve on specific symbol.
3944  */
3945 extern (C++) final class DsymbolExp : Expression
3946 {
3947     Dsymbol s;
3948     bool hasOverloads;
3949 
3950     extern (D) this(Loc loc, Dsymbol s, bool hasOverloads = true)
3951     {
3952         super(loc, TOKdsymbol, __traits(classInstanceSize, DsymbolExp));
3953         this.s = s;
3954         this.hasOverloads = hasOverloads;
3955     }
3956 
3957     override Expression semantic(Scope* sc)
3958     {
3959         return resolve(loc ,sc, s, hasOverloads);
3960     }
3961 
3962     /****************************************
3963      * Resolve a symbol `s` and wraps it in an expression object.
3964      * Params:
3965      *      hasOverloads = works if the aliased symbol is a function.
3966      *          true:  it's overloaded and will be resolved later.
3967      *          false: it's exact function symbol.
3968      */
3969     static Expression resolve(Loc loc, Scope *sc, Dsymbol s, bool hasOverloads)
3970     {
3971         static if (LOGSEMANTIC)
3972         {
3973             printf("DsymbolExp::resolve(%s %s)\n", s.kind(), s.toChars());
3974         }
3975 
3976     Lagain:
3977         Expression e;
3978 
3979         //printf("DsymbolExp:: %p '%s' is a symbol\n", this, toChars());
3980         //printf("s = '%s', s.kind = '%s'\n", s.toChars(), s.kind());
3981         Dsymbol olds = s;
3982         Declaration d = s.isDeclaration();
3983         if (d && (d.storage_class & STCtemplateparameter))
3984         {
3985             s = s.toAlias();
3986         }
3987         else
3988         {
3989             if (!s.isFuncDeclaration()) // functions are checked after overloading
3990                 s.checkDeprecated(loc, sc);
3991 
3992             // Bugzilla 12023: if 's' is a tuple variable, the tuple is returned.
3993             s = s.toAlias();
3994 
3995             //printf("s = '%s', s.kind = '%s', s.needThis() = %p\n", s.toChars(), s.kind(), s.needThis());
3996             if (s != olds && !s.isFuncDeclaration())
3997                 s.checkDeprecated(loc, sc);
3998         }
3999 
4000         if (auto em = s.isEnumMember())
4001         {
4002             return em.getVarExp(loc, sc);
4003         }
4004         if (auto v = s.isVarDeclaration())
4005         {
4006             //printf("Identifier '%s' is a variable, type '%s'\n", s.toChars(), v.type.toChars());
4007             if (!v.type ||                  // during variable type inference
4008                 !v.type.deco && v.inuse)    // during variable type semantic
4009             {
4010                 if (v.inuse)    // variable type depends on the variable itself
4011                     .error(loc, "circular reference to %s '%s'", v.kind(), v.toPrettyChars());
4012                 else            // variable type cannot be determined
4013                     .error(loc, "forward reference to %s '%s'", v.kind(), v.toPrettyChars());
4014                 return new ErrorExp();
4015             }
4016             if (v.type.ty == Terror)
4017                 return new ErrorExp();
4018 
4019             if ((v.storage_class & STCmanifest) && v._init)
4020             {
4021                 if (v.inuse)
4022                 {
4023                     .error(loc, "circular initialization of %s '%s'", v.kind(), v.toPrettyChars());
4024                     return new ErrorExp();
4025                 }
4026                 e = v.expandInitializer(loc);
4027                 v.inuse++;
4028                 e = e.semantic(sc);
4029                 v.inuse--;
4030                 return e;
4031             }
4032 
4033             // Change the ancestor lambdas to delegate before hasThis(sc) call.
4034             if (v.checkNestedReference(sc, loc))
4035                 return new ErrorExp();
4036 
4037             if (v.needThis() && hasThis(sc))
4038                 e = new DotVarExp(loc, new ThisExp(loc), v);
4039             else
4040                 e = new VarExp(loc, v);
4041             e = e.semantic(sc);
4042             return e;
4043         }
4044         if (auto fld = s.isFuncLiteralDeclaration())
4045         {
4046             //printf("'%s' is a function literal\n", fld.toChars());
4047             e = new FuncExp(loc, fld);
4048             return e.semantic(sc);
4049         }
4050         if (auto f = s.isFuncDeclaration())
4051         {
4052             f = f.toAliasFunc();
4053             if (!f.functionSemantic())
4054                 return new ErrorExp();
4055 
4056             if (!hasOverloads && f.checkForwardRef(loc))
4057                 return new ErrorExp();
4058 
4059             auto fd = s.isFuncDeclaration();
4060             fd.type = f.type;
4061             return new VarExp(loc, fd, hasOverloads);
4062         }
4063         if (OverDeclaration od = s.isOverDeclaration())
4064         {
4065             e = new VarExp(loc, od, true);
4066             e.type = Type.tvoid;
4067             return e;
4068         }
4069         if (OverloadSet o = s.isOverloadSet())
4070         {
4071             //printf("'%s' is an overload set\n", o.toChars());
4072             return new OverExp(loc, o);
4073         }
4074 
4075         if (Import imp = s.isImport())
4076         {
4077             if (!imp.pkg)
4078             {
4079                 .error(loc, "forward reference of import %s", imp.toChars());
4080                 return new ErrorExp();
4081             }
4082             auto ie = new ScopeExp(loc, imp.pkg);
4083             return ie.semantic(sc);
4084         }
4085         if (Package pkg = s.isPackage())
4086         {
4087             auto ie = new ScopeExp(loc, pkg);
4088             return ie.semantic(sc);
4089         }
4090         if (Module mod = s.isModule())
4091         {
4092             auto ie = new ScopeExp(loc, mod);
4093             return ie.semantic(sc);
4094         }
4095         if (Nspace ns = s.isNspace())
4096         {
4097             auto ie = new ScopeExp(loc, ns);
4098             return ie.semantic(sc);
4099         }
4100 
4101         if (Type t = s.getType())
4102         {
4103             return (new TypeExp(loc, t)).semantic(sc);
4104         }
4105 
4106         if (TupleDeclaration tup = s.isTupleDeclaration())
4107         {
4108             if (tup.needThis() && hasThis(sc))
4109                 e = new DotVarExp(loc, new ThisExp(loc), tup);
4110             else
4111                 e = new TupleExp(loc, tup);
4112             e = e.semantic(sc);
4113             return e;
4114         }
4115 
4116         if (TemplateInstance ti = s.isTemplateInstance())
4117         {
4118             ti.semantic(sc);
4119             if (!ti.inst || ti.errors)
4120                 return new ErrorExp();
4121             s = ti.toAlias();
4122             if (!s.isTemplateInstance())
4123                 goto Lagain;
4124             e = new ScopeExp(loc, ti);
4125             e = e.semantic(sc);
4126             return e;
4127         }
4128         if (TemplateDeclaration td = s.isTemplateDeclaration())
4129         {
4130             Dsymbol p = td.toParent2();
4131             FuncDeclaration fdthis = hasThis(sc);
4132             AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
4133             if (fdthis && ad && isAggregate(fdthis.vthis.type) == ad && (td._scope.stc & STCstatic) == 0)
4134             {
4135                 e = new DotTemplateExp(loc, new ThisExp(loc), td);
4136             }
4137             else
4138                 e = new TemplateExp(loc, td);
4139             e = e.semantic(sc);
4140             return e;
4141         }
4142 
4143         .error(loc, "%s '%s' is not a variable", s.kind(), s.toChars());
4144         return new ErrorExp();
4145     }
4146 
4147     override bool isLvalue()
4148     {
4149         return true;
4150     }
4151 
4152     override Expression toLvalue(Scope* sc, Expression e)
4153     {
4154         return this;
4155     }
4156 
4157     override void accept(Visitor v)
4158     {
4159         v.visit(this);
4160     }
4161 }
4162 
4163 /***********************************************************
4164  */
4165 extern (C++) class ThisExp : Expression
4166 {
4167     VarDeclaration var;
4168 
4169     final extern (D) this(Loc loc)
4170     {
4171         super(loc, TOKthis, __traits(classInstanceSize, ThisExp));
4172         //printf("ThisExp::ThisExp() loc = %d\n", loc.linnum);
4173     }
4174 
4175     override Expression semantic(Scope* sc)
4176     {
4177         static if (LOGSEMANTIC)
4178         {
4179             printf("ThisExp::semantic()\n");
4180         }
4181         if (type)
4182             return this;
4183 
4184         FuncDeclaration fd = hasThis(sc); // fd is the uplevel function with the 'this' variable
4185 
4186         /* Special case for typeof(this) and typeof(super) since both
4187          * should work even if they are not inside a non-static member function
4188          */
4189         if (!fd && sc.intypeof == 1)
4190         {
4191             // Find enclosing struct or class
4192             for (Dsymbol s = sc.getStructClassScope(); 1; s = s.parent)
4193             {
4194                 if (!s)
4195                 {
4196                     error("%s is not in a class or struct scope", toChars());
4197                     goto Lerr;
4198                 }
4199                 ClassDeclaration cd = s.isClassDeclaration();
4200                 if (cd)
4201                 {
4202                     type = cd.type;
4203                     return this;
4204                 }
4205                 StructDeclaration sd = s.isStructDeclaration();
4206                 if (sd)
4207                 {
4208                     type = sd.type;
4209                     return this;
4210                 }
4211             }
4212         }
4213         if (!fd)
4214             goto Lerr;
4215 
4216         assert(fd.vthis);
4217         var = fd.vthis;
4218         assert(var.parent);
4219         type = var.type;
4220         if (var.checkNestedReference(sc, loc))
4221             return new ErrorExp();
4222         if (!sc.intypeof)
4223             sc.callSuper |= CSXthis;
4224         return this;
4225 
4226     Lerr:
4227         error("'this' is only defined in non-static member functions, not %s", sc.parent.toChars());
4228         return new ErrorExp();
4229     }
4230 
4231     override final bool isBool(bool result)
4232     {
4233         return result ? true : false;
4234     }
4235 
4236     override final bool isLvalue()
4237     {
4238         // Class `this` should be an rvalue; struct `this` should be an lvalue.
4239         return type.toBasetype().ty != Tclass;
4240     }
4241 
4242     override final Expression toLvalue(Scope* sc, Expression e)
4243     {
4244         if (type.toBasetype().ty == Tclass)
4245         {
4246             // Class `this` is an rvalue; struct `this` is an lvalue.
4247             return Expression.toLvalue(sc, e);
4248         }
4249         return this;
4250     }
4251 
4252     override void accept(Visitor v)
4253     {
4254         v.visit(this);
4255     }
4256 }
4257 
4258 /***********************************************************
4259  */
4260 extern (C++) final class SuperExp : ThisExp
4261 {
4262     extern (D) this(Loc loc)
4263     {
4264         super(loc);
4265         op = TOKsuper;
4266     }
4267 
4268     override Expression semantic(Scope* sc)
4269     {
4270         static if (LOGSEMANTIC)
4271         {
4272             printf("SuperExp::semantic('%s')\n", toChars());
4273         }
4274         if (type)
4275             return this;
4276 
4277         FuncDeclaration fd = hasThis(sc);
4278         ClassDeclaration cd;
4279         Dsymbol s;
4280 
4281         /* Special case for typeof(this) and typeof(super) since both
4282          * should work even if they are not inside a non-static member function
4283          */
4284         if (!fd && sc.intypeof == 1)
4285         {
4286             // Find enclosing class
4287             for (s = sc.getStructClassScope(); 1; s = s.parent)
4288             {
4289                 if (!s)
4290                 {
4291                     error("%s is not in a class scope", toChars());
4292                     goto Lerr;
4293                 }
4294                 cd = s.isClassDeclaration();
4295                 if (cd)
4296                 {
4297                     cd = cd.baseClass;
4298                     if (!cd)
4299                     {
4300                         error("class %s has no 'super'", s.toChars());
4301                         goto Lerr;
4302                     }
4303                     type = cd.type;
4304                     return this;
4305                 }
4306             }
4307         }
4308         if (!fd)
4309             goto Lerr;
4310 
4311         var = fd.vthis;
4312         assert(var && var.parent);
4313 
4314         s = fd.toParent();
4315         while (s && s.isTemplateInstance())
4316             s = s.toParent();
4317         if (s.isTemplateDeclaration()) // allow inside template constraint
4318             s = s.toParent();
4319         assert(s);
4320         cd = s.isClassDeclaration();
4321         //printf("parent is %s %s\n", fd->toParent()->kind(), fd->toParent()->toChars());
4322         if (!cd)
4323             goto Lerr;
4324         if (!cd.baseClass)
4325         {
4326             error("no base class for %s", cd.toChars());
4327             type = var.type;
4328         }
4329         else
4330         {
4331             type = cd.baseClass.type;
4332             type = type.castMod(var.type.mod);
4333         }
4334 
4335         if (var.checkNestedReference(sc, loc))
4336             return new ErrorExp();
4337 
4338         if (!sc.intypeof)
4339             sc.callSuper |= CSXsuper;
4340         return this;
4341 
4342     Lerr:
4343         error("'super' is only allowed in non-static class member functions");
4344         return new ErrorExp();
4345     }
4346 
4347     override void accept(Visitor v)
4348     {
4349         v.visit(this);
4350     }
4351 }
4352 
4353 /***********************************************************
4354  */
4355 extern (C++) final class NullExp : Expression
4356 {
4357     ubyte committed;    // !=0 if type is committed
4358 
4359     extern (D) this(Loc loc, Type type = null)
4360     {
4361         super(loc, TOKnull, __traits(classInstanceSize, NullExp));
4362         this.type = type;
4363     }
4364 
4365     override bool equals(RootObject o)
4366     {
4367         if (o && o.dyncast() == DYNCAST_EXPRESSION)
4368         {
4369             Expression e = cast(Expression)o;
4370             if (e.op == TOKnull && type.equals(e.type))
4371             {
4372                 return true;
4373             }
4374         }
4375         return false;
4376     }
4377 
4378     override Expression semantic(Scope* sc)
4379     {
4380         static if (LOGSEMANTIC)
4381         {
4382             printf("NullExp::semantic('%s')\n", toChars());
4383         }
4384         // NULL is the same as (void *)0
4385         if (type)
4386             return this;
4387         type = Type.tnull;
4388         return this;
4389     }
4390 
4391     override bool isBool(bool result)
4392     {
4393         return result ? false : true;
4394     }
4395 
4396     override StringExp toStringExp()
4397     {
4398         if (implicitConvTo(Type.tstring))
4399         {
4400             auto se = new StringExp(loc, cast(char*)mem.xcalloc(1, 1), 0);
4401             se.type = Type.tstring;
4402             return se;
4403         }
4404         return null;
4405     }
4406 
4407     override void accept(Visitor v)
4408     {
4409         v.visit(this);
4410     }
4411 }
4412 
4413 /***********************************************************
4414  */
4415 extern (C++) final class StringExp : Expression
4416 {
4417     union
4418     {
4419         char* string;   // if sz == 1
4420         wchar* wstring; // if sz == 2
4421         dchar* dstring; // if sz == 4
4422     }                   // (const if ownedByCtfe == OWNEDcode)
4423     size_t len;         // number of code units
4424     ubyte sz = 1;       // 1: char, 2: wchar, 4: dchar
4425     ubyte committed;    // !=0 if type is committed
4426     char postfix = 0;   // 'c', 'w', 'd'
4427     OwnedBy ownedByCtfe = OWNEDcode;
4428 
4429     extern (D) this(Loc loc, char* string)
4430     {
4431         super(loc, TOKstring, __traits(classInstanceSize, StringExp));
4432         this.string = string;
4433         this.len = strlen(string);
4434         this.sz = 1;                    // work around LDC bug #1286
4435     }
4436 
4437     extern (D) this(Loc loc, void* string, size_t len)
4438     {
4439         super(loc, TOKstring, __traits(classInstanceSize, StringExp));
4440         this.string = cast(char*)string;
4441         this.len = len;
4442         this.sz = 1;                    // work around LDC bug #1286
4443     }
4444 
4445     extern (D) this(Loc loc, void* string, size_t len, char postfix)
4446     {
4447         super(loc, TOKstring, __traits(classInstanceSize, StringExp));
4448         this.string = cast(char*)string;
4449         this.len = len;
4450         this.postfix = postfix;
4451         this.sz = 1;                    // work around LDC bug #1286
4452     }
4453 
4454     static StringExp create(Loc loc, char* s)
4455     {
4456         return new StringExp(loc, s);
4457     }
4458 
4459     override bool equals(RootObject o)
4460     {
4461         //printf("StringExp::equals('%s') %s\n", o->toChars(), toChars());
4462         if (o && o.dyncast() == DYNCAST_EXPRESSION)
4463         {
4464             Expression e = cast(Expression)o;
4465             if (e.op == TOKstring)
4466             {
4467                 return compare(o) == 0;
4468             }
4469         }
4470         return false;
4471     }
4472 
4473     override Expression semantic(Scope* sc)
4474     {
4475         static if (LOGSEMANTIC)
4476         {
4477             printf("StringExp::semantic() %s\n", toChars());
4478         }
4479         if (type)
4480             return this;
4481 
4482         OutBuffer buffer;
4483         size_t newlen = 0;
4484         const(char)* p;
4485         size_t u;
4486         dchar c;
4487 
4488         switch (postfix)
4489         {
4490         case 'd':
4491             for (u = 0; u < len;)
4492             {
4493                 p = utf_decodeChar(string, len, u, c);
4494                 if (p)
4495                 {
4496                     error("%s", p);
4497                     return new ErrorExp();
4498                 }
4499                 else
4500                 {
4501                     buffer.write4(c);
4502                     newlen++;
4503                 }
4504             }
4505             buffer.write4(0);
4506             dstring = cast(dchar*)buffer.extractData();
4507             len = newlen;
4508             sz = 4;
4509             type = new TypeDArray(Type.tdchar.immutableOf());
4510             committed = 1;
4511             break;
4512 
4513         case 'w':
4514             for (u = 0; u < len;)
4515             {
4516                 p = utf_decodeChar(string, len, u, c);
4517                 if (p)
4518                 {
4519                     error("%s", p);
4520                     return new ErrorExp();
4521                 }
4522                 else
4523                 {
4524                     buffer.writeUTF16(c);
4525                     newlen++;
4526                     if (c >= 0x10000)
4527                         newlen++;
4528                 }
4529             }
4530             buffer.writeUTF16(0);
4531             wstring = cast(wchar*)buffer.extractData();
4532             len = newlen;
4533             sz = 2;
4534             type = new TypeDArray(Type.twchar.immutableOf());
4535             committed = 1;
4536             break;
4537 
4538         case 'c':
4539             committed = 1;
4540             goto default;
4541 
4542         default:
4543             type = new TypeDArray(Type.tchar.immutableOf());
4544             break;
4545         }
4546         type = type.semantic(loc, sc);
4547         //type = type->immutableOf();
4548         //printf("type = %s\n", type->toChars());
4549 
4550         return this;
4551     }
4552 
4553     /**********************************
4554      * Return the number of code units the string would be if it were re-encoded
4555      * as tynto.
4556      * Params:
4557      *      tynto = code unit type of the target encoding
4558      * Returns:
4559      *      number of code units
4560      */
4561     final size_t numberOfCodeUnits(int tynto = 0) const
4562     {
4563         int encSize;
4564         switch (tynto)
4565         {
4566             case 0:      return len;
4567             case Tchar:  encSize = 1; break;
4568             case Twchar: encSize = 2; break;
4569             case Tdchar: encSize = 4; break;
4570             default:
4571                 assert(0);
4572         }
4573         if (sz == encSize)
4574             return len;
4575 
4576         size_t result = 0;
4577         dchar c;
4578 
4579         switch (sz)
4580         {
4581         case 1:
4582             for (size_t u = 0; u < len;)
4583             {
4584                 if (const p = utf_decodeChar(string, len, u, c))
4585                 {
4586                     error("%s", p);
4587                     return 0;
4588                 }
4589                 result += utf_codeLength(encSize, c);
4590             }
4591             break;
4592 
4593         case 2:
4594             for (size_t u = 0; u < len;)
4595             {
4596                 if (const p = utf_decodeWchar(wstring, len, u, c))
4597                 {
4598                     error("%s", p);
4599                     return 0;
4600                 }
4601                 result += utf_codeLength(encSize, c);
4602             }
4603             break;
4604 
4605         case 4:
4606             foreach (u; 0 .. len)
4607             {
4608                 result += utf_codeLength(encSize, dstring[u]);
4609             }
4610             break;
4611 
4612         default:
4613             assert(0);
4614         }
4615         return result;
4616     }
4617 
4618     /**********************************************
4619      * Write the contents of the string to dest.
4620      * Use numberOfCodeUnits() to determine size of result.
4621      * Params:
4622      *  dest = destination
4623      *  tyto = encoding type of the result
4624      *  zero = add terminating 0
4625      */
4626     void writeTo(void* dest, bool zero, int tyto = 0) const
4627     {
4628         int encSize;
4629         switch (tyto)
4630         {
4631             case 0:      encSize = sz; break;
4632             case Tchar:  encSize = 1; break;
4633             case Twchar: encSize = 2; break;
4634             case Tdchar: encSize = 4; break;
4635             default:
4636                 assert(0);
4637         }
4638         if (sz == encSize)
4639         {
4640             memcpy(dest, string, len * sz);
4641             if (zero)
4642                 memset(dest + len * sz, 0, sz);
4643         }
4644         else
4645             assert(0);
4646     }
4647 
4648     /*********************************************
4649      * Get the code unit at index i
4650      * Params:
4651      *  i = index
4652      * Returns:
4653      *  code unit at index i
4654      */
4655     final dchar getCodeUnit(size_t i) const pure
4656     {
4657         assert(i < len);
4658         final switch (sz)
4659         {
4660         case 1:
4661             return string[i];
4662         case 2:
4663             return wstring[i];
4664         case 4:
4665             return dstring[i];
4666         }
4667     }
4668 
4669     /*********************************************
4670      * Set the code unit at index i to c
4671      * Params:
4672      *  i = index
4673      *  c = code unit to set it to
4674      */
4675     final void setCodeUnit(size_t i, dchar c)
4676     {
4677         assert(i < len);
4678         final switch (sz)
4679         {
4680         case 1:
4681             string[i] = cast(char)c;
4682             break;
4683         case 2:
4684             wstring[i] = cast(wchar)c;
4685             break;
4686         case 4:
4687             dstring[i] = c;
4688             break;
4689         }
4690     }
4691 
4692     /**************************************************
4693      * If the string data is UTF-8 and can be accessed directly,
4694      * return a pointer to it.
4695      * Do not assume a terminating 0.
4696      * Returns:
4697      *  pointer to string data if possible, null if not
4698      */
4699     char* toPtr()
4700     {
4701         return (sz == 1) ? string : null;
4702     }
4703 
4704     override StringExp toStringExp()
4705     {
4706         return this;
4707     }
4708 
4709     /****************************************
4710      * Convert string to char[].
4711      */
4712     StringExp toUTF8(Scope* sc)
4713     {
4714         if (sz != 1)
4715         {
4716             // Convert to UTF-8 string
4717             committed = 0;
4718             Expression e = castTo(sc, Type.tchar.arrayOf());
4719             e = e.optimize(WANTvalue);
4720             assert(e.op == TOKstring);
4721             StringExp se = cast(StringExp)e;
4722             assert(se.sz == 1);
4723             return se;
4724         }
4725         return this;
4726     }
4727 
4728     override int compare(RootObject obj)
4729     {
4730         //printf("StringExp::compare()\n");
4731         // Used to sort case statement expressions so we can do an efficient lookup
4732         StringExp se2 = cast(StringExp)obj;
4733 
4734         // This is a kludge so isExpression() in template.c will return 5
4735         // for StringExp's.
4736         if (!se2)
4737             return 5;
4738 
4739         assert(se2.op == TOKstring);
4740 
4741         size_t len1 = len;
4742         size_t len2 = se2.len;
4743 
4744         //printf("sz = %d, len1 = %d, len2 = %d\n", sz, (int)len1, (int)len2);
4745         if (len1 == len2)
4746         {
4747             switch (sz)
4748             {
4749             case 1:
4750                 return memcmp(string, se2..string, len1);
4751 
4752             case 2:
4753                 {
4754                     wchar* s1 = cast(wchar*)string;
4755                     wchar* s2 = cast(wchar*)se2..string;
4756                     for (size_t u = 0; u < len; u++)
4757                     {
4758                         if (s1[u] != s2[u])
4759                             return s1[u] - s2[u];
4760                     }
4761                 }
4762                 break;
4763             case 4:
4764                 {
4765                     dchar* s1 = cast(dchar*)string;
4766                     dchar* s2 = cast(dchar*)se2..string;
4767                     for (size_t u = 0; u < len; u++)
4768                     {
4769                         if (s1[u] != s2[u])
4770                             return s1[u] - s2[u];
4771                     }
4772                 }
4773                 break;
4774             default:
4775                 assert(0);
4776             }
4777         }
4778         return cast(int)(len1 - len2);
4779     }
4780 
4781     override bool isBool(bool result)
4782     {
4783         return result ? true : false;
4784     }
4785 
4786     override bool isLvalue()
4787     {
4788         /* string literal is rvalue in default, but
4789          * conversion to reference of static array is only allowed.
4790          */
4791         return (type && type.toBasetype().ty == Tsarray);
4792     }
4793 
4794     override Expression toLvalue(Scope* sc, Expression e)
4795     {
4796         //printf("StringExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL);
4797         return (type && type.toBasetype().ty == Tsarray) ? this : Expression.toLvalue(sc, e);
4798     }
4799 
4800     override Expression modifiableLvalue(Scope* sc, Expression e)
4801     {
4802         error("cannot modify string literal %s", toChars());
4803         return new ErrorExp();
4804     }
4805 
4806     uint charAt(uinteger_t i) const
4807     {
4808         uint value;
4809         switch (sz)
4810         {
4811         case 1:
4812             value = (cast(char*)string)[cast(size_t)i];
4813             break;
4814 
4815         case 2:
4816             value = (cast(ushort*)string)[cast(size_t)i];
4817             break;
4818 
4819         case 4:
4820             value = (cast(uint*)string)[cast(size_t)i];
4821             break;
4822 
4823         default:
4824             assert(0);
4825         }
4826         return value;
4827     }
4828 
4829     /********************************
4830      * Convert string contents to a 0 terminated string,
4831      * allocated by mem.xmalloc().
4832      */
4833     extern (D) final const(char)[] toStringz() const
4834     {
4835         auto nbytes = len * sz;
4836         char* s = cast(char*)mem.xmalloc(nbytes + sz);
4837         writeTo(s, true);
4838         return s[0 .. nbytes];
4839     }
4840 
4841     extern (D) const(char)[] peekSlice() const
4842     {
4843         assert(sz == 1);
4844         return this.string[0 .. len];
4845     }
4846 
4847     override void accept(Visitor v)
4848     {
4849         v.visit(this);
4850     }
4851 }
4852 
4853 /***********************************************************
4854  */
4855 extern (C++) final class TupleExp : Expression
4856 {
4857     /* Tuple-field access may need to take out its side effect part.
4858      * For example:
4859      *      foo().tupleof
4860      * is rewritten as:
4861      *      (ref __tup = foo(); tuple(__tup.field0, __tup.field1, ...))
4862      * The declaration of temporary variable __tup will be stored in TupleExp.e0.
4863      */
4864     Expression e0;
4865 
4866     Expressions* exps;
4867 
4868     extern (D) this(Loc loc, Expression e0, Expressions* exps)
4869     {
4870         super(loc, TOKtuple, __traits(classInstanceSize, TupleExp));
4871         //printf("TupleExp(this = %p)\n", this);
4872         this.e0 = e0;
4873         this.exps = exps;
4874     }
4875 
4876     extern (D) this(Loc loc, Expressions* exps)
4877     {
4878         super(loc, TOKtuple, __traits(classInstanceSize, TupleExp));
4879         //printf("TupleExp(this = %p)\n", this);
4880         this.exps = exps;
4881     }
4882 
4883     extern (D) this(Loc loc, TupleDeclaration tup)
4884     {
4885         super(loc, TOKtuple, __traits(classInstanceSize, TupleExp));
4886         this.exps = new Expressions();
4887 
4888         this.exps.reserve(tup.objects.dim);
4889         for (size_t i = 0; i < tup.objects.dim; i++)
4890         {
4891             RootObject o = (*tup.objects)[i];
4892             if (Dsymbol s = getDsymbol(o))
4893             {
4894                 /* If tuple element represents a symbol, translate to DsymbolExp
4895                  * to supply implicit 'this' if needed later.
4896                  */
4897                 Expression e = new DsymbolExp(loc, s);
4898                 this.exps.push(e);
4899             }
4900             else if (o.dyncast() == DYNCAST_EXPRESSION)
4901             {
4902                 auto e = (cast(Expression)o).copy();
4903                 e.loc = loc;    // Bugzilla 15669
4904                 this.exps.push(e);
4905             }
4906             else if (o.dyncast() == DYNCAST_TYPE)
4907             {
4908                 Type t = cast(Type)o;
4909                 Expression e = new TypeExp(loc, t);
4910                 this.exps.push(e);
4911             }
4912             else
4913             {
4914                 error("%s is not an expression", o.toChars());
4915             }
4916         }
4917     }
4918 
4919     override Expression syntaxCopy()
4920     {
4921         return new TupleExp(loc, e0 ? e0.syntaxCopy() : null, arraySyntaxCopy(exps));
4922     }
4923 
4924     override bool equals(RootObject o)
4925     {
4926         if (this == o)
4927             return true;
4928         if ((cast(Expression)o).op == TOKtuple)
4929         {
4930             TupleExp te = cast(TupleExp)o;
4931             if (exps.dim != te.exps.dim)
4932                 return false;
4933             if (e0 && !e0.equals(te.e0) || !e0 && te.e0)
4934                 return false;
4935             for (size_t i = 0; i < exps.dim; i++)
4936             {
4937                 Expression e1 = (*exps)[i];
4938                 Expression e2 = (*te.exps)[i];
4939                 if (!e1.equals(e2))
4940                     return false;
4941             }
4942             return true;
4943         }
4944         return false;
4945     }
4946 
4947     override Expression semantic(Scope* sc)
4948     {
4949         static if (LOGSEMANTIC)
4950         {
4951             printf("+TupleExp::semantic(%s)\n", toChars());
4952         }
4953         if (type)
4954             return this;
4955 
4956         if (e0)
4957             e0 = e0.semantic(sc);
4958 
4959         // Run semantic() on each argument
4960         bool err = false;
4961         for (size_t i = 0; i < exps.dim; i++)
4962         {
4963             Expression e = (*exps)[i];
4964             e = e.semantic(sc);
4965             if (!e.type)
4966             {
4967                 error("%s has no value", e.toChars());
4968                 err = true;
4969             }
4970             else if (e.op == TOKerror)
4971                 err = true;
4972             else
4973                 (*exps)[i] = e;
4974         }
4975         if (err)
4976             return new ErrorExp();
4977 
4978         expandTuples(exps);
4979 
4980         type = new TypeTuple(exps);
4981         type = type.semantic(loc, sc);
4982         //printf("-TupleExp::semantic(%s)\n", toChars());
4983         return this;
4984     }
4985 
4986     override void accept(Visitor v)
4987     {
4988         v.visit(this);
4989     }
4990 }
4991 
4992 /***********************************************************
4993  * [ e1, e2, e3, ... ]
4994  */
4995 extern (C++) final class ArrayLiteralExp : Expression
4996 {
4997     /** If !is null, elements[] can be sparse and basis is used for the
4998      * "default" element value. In other words, non-null elements[i] overrides
4999      * this 'basis' value.
5000      */
5001     Expression basis;
5002 
5003     Expressions* elements;
5004     OwnedBy ownedByCtfe = OWNEDcode;
5005 
5006     extern (D) this(Loc loc, Expressions* elements)
5007     {
5008         super(loc, TOKarrayliteral, __traits(classInstanceSize, ArrayLiteralExp));
5009         this.elements = elements;
5010     }
5011 
5012     extern (D) this(Loc loc, Expression e)
5013     {
5014         super(loc, TOKarrayliteral, __traits(classInstanceSize, ArrayLiteralExp));
5015         elements = new Expressions();
5016         elements.push(e);
5017     }
5018 
5019     extern (D) this(Loc loc, Expression basis, Expressions* elements)
5020     {
5021         super(loc, TOKarrayliteral, __traits(classInstanceSize, ArrayLiteralExp));
5022         this.basis = basis;
5023         this.elements = elements;
5024     }
5025 
5026     override Expression syntaxCopy()
5027     {
5028         return new ArrayLiteralExp(loc,
5029             basis ? basis.syntaxCopy() : null,
5030             arraySyntaxCopy(elements));
5031     }
5032 
5033     override bool equals(RootObject o)
5034     {
5035         if (this == o)
5036             return true;
5037         if (o && o.dyncast() == DYNCAST_EXPRESSION && (cast(Expression)o).op == TOKarrayliteral)
5038         {
5039             ArrayLiteralExp ae = cast(ArrayLiteralExp)o;
5040             if (elements.dim != ae.elements.dim)
5041                 return false;
5042             if (elements.dim == 0 && !type.equals(ae.type))
5043             {
5044                 return false;
5045             }
5046             for (size_t i = 0; i < elements.dim; i++)
5047             {
5048                 Expression e1 = (*elements)[i];
5049                 Expression e2 = (*ae.elements)[i];
5050                 if (!e1)
5051                     e1 = basis;
5052                 if (!e2)
5053                     e2 = ae.basis;
5054                 if (e1 != e2 && (!e1 || !e2 || !e1.equals(e2)))
5055                     return false;
5056             }
5057             return true;
5058         }
5059         return false;
5060     }
5061 
5062     final Expression getElement(size_t i)
5063     {
5064         auto el = (*elements)[i];
5065         if (!el)
5066             el = basis;
5067         return el;
5068     }
5069 
5070     /** Copy element `Expressions` in the parameters when they're `ArrayLiteralExp`s.
5071      * Params:
5072      *      e1  = If it's ArrayLiteralExp, its `elements` will be copied.
5073      *            Otherwise, `e1` itself will be pushed into the new `Expressions`.
5074      *      e2  = If it's not `null`, it will be pushed/appended to the new
5075      *            `Expressions` by the same way with `e1`.
5076      * Returns:
5077      *      Newly allocated `Expresions. Note that it points the original
5078      *      `Expression` values in e1 and e2.
5079      */
5080     static Expressions* copyElements(Expression e1, Expression e2 = null)
5081     {
5082         auto elems = new Expressions();
5083 
5084         void append(ArrayLiteralExp ale)
5085         {
5086             if (!ale.elements)
5087                 return;
5088             auto d = elems.dim;
5089             elems.append(ale.elements);
5090             foreach (ref el; (*elems)[][d .. elems.dim])
5091             {
5092                 if (!el)
5093                     el = ale.basis;
5094             }
5095         }
5096 
5097         if (e1.op == TOKarrayliteral)
5098             append(cast(ArrayLiteralExp)e1);
5099         else
5100             elems.push(e1);
5101 
5102         if (e2)
5103         {
5104             if (e2.op == TOKarrayliteral)
5105                 append(cast(ArrayLiteralExp)e2);
5106             else
5107                 elems.push(e2);
5108         }
5109 
5110         return elems;
5111     }
5112 
5113     override Expression semantic(Scope* sc)
5114     {
5115         static if (LOGSEMANTIC)
5116         {
5117             printf("ArrayLiteralExp::semantic('%s')\n", toChars());
5118         }
5119         if (type)
5120             return this;
5121 
5122         /* Perhaps an empty array literal [ ] should be rewritten as null?
5123          */
5124 
5125         if (basis)
5126             basis = basis.semantic(sc);
5127         if (arrayExpressionSemantic(elements, sc) || (basis && basis.op == TOKerror))
5128             return new ErrorExp();
5129 
5130         expandTuples(elements);
5131 
5132         Type t0;
5133         if (basis)
5134             elements.push(basis);
5135         bool err = arrayExpressionToCommonType(sc, elements, &t0);
5136         if (basis)
5137             basis = elements.pop();
5138         if (err)
5139             return new ErrorExp();
5140 
5141         type = t0.arrayOf();
5142         type = type.semantic(loc, sc);
5143 
5144         /* Disallow array literals of type void being used.
5145          */
5146         if (elements.dim > 0 && t0.ty == Tvoid)
5147         {
5148             error("%s of type %s has no value", toChars(), type.toChars());
5149             return new ErrorExp();
5150         }
5151 
5152         semanticTypeInfo(sc, type);
5153 
5154         return this;
5155     }
5156 
5157     override bool isBool(bool result)
5158     {
5159         size_t dim = elements ? elements.dim : 0;
5160         return result ? (dim != 0) : (dim == 0);
5161     }
5162 
5163     override StringExp toStringExp()
5164     {
5165         TY telem = type.nextOf().toBasetype().ty;
5166         if (telem == Tchar || telem == Twchar || telem == Tdchar || (telem == Tvoid && (!elements || elements.dim == 0)))
5167         {
5168             ubyte sz = 1;
5169             if (telem == Twchar)
5170                 sz = 2;
5171             else if (telem == Tdchar)
5172                 sz = 4;
5173 
5174             OutBuffer buf;
5175             if (elements)
5176             {
5177                 for (size_t i = 0; i < elements.dim; ++i)
5178                 {
5179                     auto ch = getElement(i);
5180                     if (ch.op != TOKint64)
5181                         return null;
5182                     if (sz == 1)
5183                         buf.writeByte(cast(uint)ch.toInteger());
5184                     else if (sz == 2)
5185                         buf.writeword(cast(uint)ch.toInteger());
5186                     else
5187                         buf.write4(cast(uint)ch.toInteger());
5188                 }
5189             }
5190             char prefix;
5191             if (sz == 1)
5192             {
5193                 prefix = 'c';
5194                 buf.writeByte(0);
5195             }
5196             else if (sz == 2)
5197             {
5198                 prefix = 'w';
5199                 buf.writeword(0);
5200             }
5201             else
5202             {
5203                 prefix = 'd';
5204                 buf.write4(0);
5205             }
5206 
5207             const(size_t) len = buf.offset / sz - 1;
5208             auto se = new StringExp(loc, buf.extractData(), len, prefix);
5209             se.sz = sz;
5210             se.type = type;
5211             return se;
5212         }
5213         return null;
5214     }
5215 
5216     override void accept(Visitor v)
5217     {
5218         v.visit(this);
5219     }
5220 }
5221 
5222 /***********************************************************
5223  * [ key0 : value0, key1 : value1, ... ]
5224  */
5225 extern (C++) final class AssocArrayLiteralExp : Expression
5226 {
5227     Expressions* keys;
5228     Expressions* values;
5229     OwnedBy ownedByCtfe = OWNEDcode;
5230 
5231     extern (D) this(Loc loc, Expressions* keys, Expressions* values)
5232     {
5233         super(loc, TOKassocarrayliteral, __traits(classInstanceSize, AssocArrayLiteralExp));
5234         assert(keys.dim == values.dim);
5235         this.keys = keys;
5236         this.values = values;
5237     }
5238 
5239     override bool equals(RootObject o)
5240     {
5241         if (this == o)
5242             return true;
5243         if (o && o.dyncast() == DYNCAST_EXPRESSION && (cast(Expression)o).op == TOKassocarrayliteral)
5244         {
5245             AssocArrayLiteralExp ae = cast(AssocArrayLiteralExp)o;
5246             if (keys.dim != ae.keys.dim)
5247                 return false;
5248             size_t count = 0;
5249             for (size_t i = 0; i < keys.dim; i++)
5250             {
5251                 for (size_t j = 0; j < ae.keys.dim; j++)
5252                 {
5253                     if ((*keys)[i].equals((*ae.keys)[j]))
5254                     {
5255                         if (!(*values)[i].equals((*ae.values)[j]))
5256                             return false;
5257                         ++count;
5258                     }
5259                 }
5260             }
5261             return count == keys.dim;
5262         }
5263         return false;
5264     }
5265 
5266     override Expression syntaxCopy()
5267     {
5268         return new AssocArrayLiteralExp(loc, arraySyntaxCopy(keys), arraySyntaxCopy(values));
5269     }
5270 
5271     override Expression semantic(Scope* sc)
5272     {
5273         static if (LOGSEMANTIC)
5274         {
5275             printf("AssocArrayLiteralExp::semantic('%s')\n", toChars());
5276         }
5277         if (type)
5278             return this;
5279 
5280         // Run semantic() on each element
5281         bool err_keys = arrayExpressionSemantic(keys, sc);
5282         bool err_vals = arrayExpressionSemantic(values, sc);
5283         if (err_keys || err_vals)
5284             return new ErrorExp();
5285 
5286         expandTuples(keys);
5287         expandTuples(values);
5288         if (keys.dim != values.dim)
5289         {
5290             error("number of keys is %u, must match number of values %u", keys.dim, values.dim);
5291             return new ErrorExp();
5292         }
5293 
5294         Type tkey = null;
5295         Type tvalue = null;
5296         err_keys = arrayExpressionToCommonType(sc, keys, &tkey);
5297         err_vals = arrayExpressionToCommonType(sc, values, &tvalue);
5298         if (err_keys || err_vals)
5299             return new ErrorExp();
5300 
5301         if (tkey == Type.terror || tvalue == Type.terror)
5302             return new ErrorExp();
5303 
5304         type = new TypeAArray(tvalue, tkey);
5305         type = type.semantic(loc, sc);
5306 
5307         semanticTypeInfo(sc, type);
5308 
5309         return this;
5310     }
5311 
5312     override bool isBool(bool result)
5313     {
5314         size_t dim = keys.dim;
5315         return result ? (dim != 0) : (dim == 0);
5316     }
5317 
5318     override void accept(Visitor v)
5319     {
5320         v.visit(this);
5321     }
5322 }
5323 
5324 enum stageScrub             = 0x1;  /// scrubReturnValue is running
5325 enum stageSearchPointers    = 0x2;  /// hasNonConstPointers is running
5326 enum stageOptimize          = 0x4;  /// optimize is running
5327 enum stageApply             = 0x8;  /// apply is running
5328 enum stageInlineScan        = 0x10; /// inlineScan is running
5329 enum stageToCBuffer         = 0x20; /// toCBuffer is running
5330 
5331 /***********************************************************
5332  * sd( e1, e2, e3, ... )
5333  */
5334 extern (C++) final class StructLiteralExp : Expression
5335 {
5336     StructDeclaration sd;   /// which aggregate this is for
5337     Expressions* elements;  /// parallels sd.fields[] with null entries for fields to skip
5338     Type stype;             /// final type of result (can be different from sd's type)
5339 
5340     bool useStaticInit;     /// if this is true, use the StructDeclaration's init symbol
5341     Symbol* sym;            /// back end symbol to initialize with literal
5342 
5343     OwnedBy ownedByCtfe = OWNEDcode;
5344 
5345     /** pointer to the origin instance of the expression.
5346      * once a new expression is created, origin is set to 'this'.
5347      * anytime when an expression copy is created, 'origin' pointer is set to
5348      * 'origin' pointer value of the original expression.
5349      */
5350     StructLiteralExp origin;
5351 
5352     /// those fields need to prevent a infinite recursion when one field of struct initialized with 'this' pointer.
5353     StructLiteralExp inlinecopy;
5354 
5355     /** anytime when recursive function is calling, 'stageflags' marks with bit flag of
5356      * current stage and unmarks before return from this function.
5357      * 'inlinecopy' uses similar 'stageflags' and from multiple evaluation 'doInline'
5358      * (with infinite recursion) of this expression.
5359      */
5360     int stageflags;
5361 
5362     extern (D) this(Loc loc, StructDeclaration sd, Expressions* elements, Type stype = null)
5363     {
5364         super(loc, TOKstructliteral, __traits(classInstanceSize, StructLiteralExp));
5365         this.sd = sd;
5366         if (!elements)
5367             elements = new Expressions();
5368         this.elements = elements;
5369         this.stype = stype;
5370         this.origin = this;
5371         //printf("StructLiteralExp::StructLiteralExp(%s)\n", toChars());
5372     }
5373 
5374     static StructLiteralExp create(Loc loc, StructDeclaration sd, void* elements, Type stype = null)
5375     {
5376         return new StructLiteralExp(loc, sd, cast(Expressions*)elements, stype);
5377     }
5378 
5379     override bool equals(RootObject o)
5380     {
5381         if (this == o)
5382             return true;
5383         if (o && o.dyncast() == DYNCAST_EXPRESSION && (cast(Expression)o).op == TOKstructliteral)
5384         {
5385             StructLiteralExp se = cast(StructLiteralExp)o;
5386             if (!type.equals(se.type))
5387                 return false;
5388             if (elements.dim != se.elements.dim)
5389                 return false;
5390             for (size_t i = 0; i < elements.dim; i++)
5391             {
5392                 Expression e1 = (*elements)[i];
5393                 Expression e2 = (*se.elements)[i];
5394                 if (e1 != e2 && (!e1 || !e2 || !e1.equals(e2)))
5395                     return false;
5396             }
5397             return true;
5398         }
5399         return false;
5400     }
5401 
5402     override Expression syntaxCopy()
5403     {
5404         auto exp = new StructLiteralExp(loc, sd, arraySyntaxCopy(elements), type ? type : stype);
5405         exp.origin = this;
5406         return exp;
5407     }
5408 
5409     override Expression semantic(Scope* sc)
5410     {
5411         static if (LOGSEMANTIC)
5412         {
5413             printf("StructLiteralExp::semantic('%s')\n", toChars());
5414         }
5415         if (type)
5416             return this;
5417 
5418         sd.size(loc);
5419         if (sd.sizeok != SIZEOKdone)
5420             return new ErrorExp();
5421 
5422         if (arrayExpressionSemantic(elements, sc)) // run semantic() on each element
5423             return new ErrorExp();
5424 
5425         expandTuples(elements);
5426 
5427         /* Fit elements[] to the corresponding type of field[].
5428          */
5429         if (!sd.fit(loc, sc, elements, stype))
5430             return new ErrorExp();
5431 
5432         /* Fill out remainder of elements[] with default initializers for fields[]
5433          */
5434         if (!sd.fill(loc, elements, false))
5435         {
5436             /* An error in the initializer needs to be recorded as an error
5437              * in the enclosing function or template, since the initializer
5438              * will be part of the stuct declaration.
5439              */
5440             global.increaseErrorCount();
5441             return new ErrorExp();
5442         }
5443 
5444         if (checkFrameAccess(loc, sc, sd, elements.dim))
5445             return new ErrorExp();
5446 
5447         type = stype ? stype : sd.type;
5448         return this;
5449     }
5450 
5451     /**************************************
5452      * Gets expression at offset of type.
5453      * Returns NULL if not found.
5454      */
5455     Expression getField(Type type, uint offset)
5456     {
5457         //printf("StructLiteralExp::getField(this = %s, type = %s, offset = %u)\n",
5458         //  /*toChars()*/"", type->toChars(), offset);
5459         Expression e = null;
5460         int i = getFieldIndex(type, offset);
5461 
5462         if (i != -1)
5463         {
5464             //printf("\ti = %d\n", i);
5465             if (i == sd.fields.dim - 1 && sd.isNested())
5466                 return null;
5467 
5468             assert(i < elements.dim);
5469             e = (*elements)[i];
5470             if (e)
5471             {
5472                 //printf("e = %s, e->type = %s\n", e->toChars(), e->type->toChars());
5473 
5474                 /* If type is a static array, and e is an initializer for that array,
5475                  * then the field initializer should be an array literal of e.
5476                  */
5477                 if (e.type.castMod(0) != type.castMod(0) && type.ty == Tsarray)
5478                 {
5479                     TypeSArray tsa = cast(TypeSArray)type;
5480                     size_t length = cast(size_t)tsa.dim.toInteger();
5481                     auto z = new Expressions();
5482                     z.setDim(length);
5483                     for (size_t q = 0; q < length; ++q)
5484                         (*z)[q] = e.copy();
5485                     e = new ArrayLiteralExp(loc, z);
5486                     e.type = type;
5487                 }
5488                 else
5489                 {
5490                     e = e.copy();
5491                     e.type = type;
5492                 }
5493                 if (useStaticInit && e.op == TOKstructliteral && e.type.needsNested())
5494                 {
5495                     StructLiteralExp se = cast(StructLiteralExp)e;
5496                     se.useStaticInit = true;
5497                 }
5498             }
5499         }
5500         return e;
5501     }
5502 
5503     /************************************
5504      * Get index of field.
5505      * Returns -1 if not found.
5506      */
5507     int getFieldIndex(Type type, uint offset)
5508     {
5509         /* Find which field offset is by looking at the field offsets
5510          */
5511         if (elements.dim)
5512         {
5513             for (size_t i = 0; i < sd.fields.dim; i++)
5514             {
5515                 VarDeclaration v = sd.fields[i];
5516                 if (offset == v.offset && type.size() == v.type.size())
5517                 {
5518                     /* context field might not be filled. */
5519                     if (i == sd.fields.dim - 1 && sd.isNested())
5520                         return cast(int)i;
5521                     Expression e = (*elements)[i];
5522                     if (e)
5523                     {
5524                         return cast(int)i;
5525                     }
5526                     break;
5527                 }
5528             }
5529         }
5530         return -1;
5531     }
5532 
5533     override Expression addDtorHook(Scope* sc)
5534     {
5535         /* If struct requires a destructor, rewrite as:
5536          *    (S tmp = S()),tmp
5537          * so that the destructor can be hung on tmp.
5538          */
5539         if (sd.dtor && sc.func)
5540         {
5541             /* Make an identifier for the temporary of the form:
5542              *   __sl%s%d, where %s is the struct name
5543              */
5544             const(size_t) len = 10;
5545             char[len + 1] buf;
5546             buf[len] = 0;
5547             strcpy(buf.ptr, "__sl");
5548             strncat(buf.ptr, sd.ident.toChars(), len - 4 - 1);
5549             assert(buf[len] == 0);
5550 
5551             auto tmp = copyToTemp(0, buf.ptr, this);
5552             Expression ae = new DeclarationExp(loc, tmp);
5553             Expression e = new CommaExp(loc, ae, new VarExp(loc, tmp));
5554             e = e.semantic(sc);
5555             return e;
5556         }
5557         return this;
5558     }
5559 
5560     override void accept(Visitor v)
5561     {
5562         v.visit(this);
5563     }
5564 }
5565 
5566 /***********************************************************
5567  * Mainly just a placeholder
5568  */
5569 extern (C++) final class TypeExp : Expression
5570 {
5571     extern (D) this(Loc loc, Type type)
5572     {
5573         super(loc, TOKtype, __traits(classInstanceSize, TypeExp));
5574         //printf("TypeExp::TypeExp(%s)\n", type->toChars());
5575         this.type = type;
5576     }
5577 
5578     override Expression syntaxCopy()
5579     {
5580         return new TypeExp(loc, type.syntaxCopy());
5581     }
5582 
5583     override Expression semantic(Scope* sc)
5584     {
5585         if (type.ty == Terror)
5586             return new ErrorExp();
5587 
5588         //printf("TypeExp::semantic(%s)\n", type->toChars());
5589         Expression e;
5590         Type t;
5591         Dsymbol s;
5592 
5593         type.resolve(loc, sc, &e, &t, &s, true);
5594         if (e)
5595         {
5596             //printf("e = %s %s\n", Token::toChars(e->op), e->toChars());
5597             e = e.semantic(sc);
5598         }
5599         else if (t)
5600         {
5601             //printf("t = %d %s\n", t->ty, t->toChars());
5602             type = t.semantic(loc, sc);
5603             e = this;
5604         }
5605         else if (s)
5606         {
5607             //printf("s = %s %s\n", s->kind(), s->toChars());
5608             e = DsymbolExp.resolve(loc, sc, s, true);
5609         }
5610         else
5611             assert(0);
5612 
5613         if (global.params.vcomplex)
5614             type.checkComplexTransition(loc);
5615 
5616         return e;
5617     }
5618 
5619     override bool checkType()
5620     {
5621         error("type %s is not an expression", toChars());
5622         return true;
5623     }
5624 
5625     override bool checkValue()
5626     {
5627         error("type %s has no value", toChars());
5628         return true;
5629     }
5630 
5631     override void accept(Visitor v)
5632     {
5633         v.visit(this);
5634     }
5635 }
5636 
5637 /***********************************************************
5638  * Mainly just a placeholder of
5639  *  Package, Module, Nspace, and TemplateInstance (including TemplateMixin)
5640  *
5641  * A template instance that requires IFTI:
5642  *      foo!tiargs(fargs)       // foo!tiargs
5643  * is left until CallExp::semantic() or resolveProperties()
5644  */
5645 extern (C++) final class ScopeExp : Expression
5646 {
5647     ScopeDsymbol sds;
5648 
5649     extern (D) this(Loc loc, ScopeDsymbol sds)
5650     {
5651         super(loc, TOKscope, __traits(classInstanceSize, ScopeExp));
5652         //printf("ScopeExp::ScopeExp(sds = '%s')\n", sds.toChars());
5653         //static int count; if (++count == 38) *(char*)0=0;
5654         this.sds = sds;
5655         assert(!sds.isTemplateDeclaration());   // instead, you should use TemplateExp
5656     }
5657 
5658     override Expression syntaxCopy()
5659     {
5660         return new ScopeExp(loc, cast(ScopeDsymbol)sds.syntaxCopy(null));
5661     }
5662 
5663     override Expression semantic(Scope* sc)
5664     {
5665         static if (LOGSEMANTIC)
5666         {
5667             printf("+ScopeExp::semantic(%p '%s')\n", this, toChars());
5668         }
5669         if (type)
5670             return this;
5671 
5672         ScopeDsymbol sds2 = sds;
5673         TemplateInstance ti = sds2.isTemplateInstance();
5674         while (ti)
5675         {
5676             WithScopeSymbol withsym;
5677             if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
5678             {
5679                 return new ErrorExp();
5680             }
5681             if (withsym && withsym.withstate.wthis)
5682             {
5683                 Expression e = new VarExp(loc, withsym.withstate.wthis);
5684                 e = new DotTemplateInstanceExp(loc, e, ti);
5685                 return e.semantic(sc);
5686             }
5687             if (ti.needsTypeInference(sc))
5688             {
5689                 if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
5690                 {
5691                     Dsymbol p = td.toParent2();
5692                     FuncDeclaration fdthis = hasThis(sc);
5693                     AggregateDeclaration ad = p ? p.isAggregateDeclaration() : null;
5694                     if (fdthis && ad && isAggregate(fdthis.vthis.type) == ad && (td._scope.stc & STCstatic) == 0)
5695                     {
5696                         Expression e = new DotTemplateInstanceExp(loc, new ThisExp(loc), ti.name, ti.tiargs);
5697                         return e.semantic(sc);
5698                     }
5699                 }
5700                 else if (OverloadSet os = ti.tempdecl.isOverloadSet())
5701                 {
5702                     FuncDeclaration fdthis = hasThis(sc);
5703                     AggregateDeclaration ad = os.parent.isAggregateDeclaration();
5704                     if (fdthis && ad && isAggregate(fdthis.vthis.type) == ad)
5705                     {
5706                         Expression e = new DotTemplateInstanceExp(loc, new ThisExp(loc), ti.name, ti.tiargs);
5707                         return e.semantic(sc);
5708                     }
5709                 }
5710                 // ti is an instance which requires IFTI.
5711                 sds = ti;
5712                 type = Type.tvoid;
5713                 return this;
5714             }
5715             ti.semantic(sc);
5716             if (!ti.inst || ti.errors)
5717                 return new ErrorExp();
5718 
5719             Dsymbol s = ti.toAlias();
5720             if (s == ti)
5721             {
5722                 sds = ti;
5723                 type = Type.tvoid;
5724                 return this;
5725             }
5726             sds2 = s.isScopeDsymbol();
5727             if (sds2)
5728             {
5729                 ti = sds2.isTemplateInstance();
5730                 //printf("+ sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
5731                 continue;
5732             }
5733 
5734             if (auto v = s.isVarDeclaration())
5735             {
5736                 if (!v.type)
5737                 {
5738                     error("forward reference of %s %s", v.kind(), v.toChars());
5739                     return new ErrorExp();
5740                 }
5741                 if ((v.storage_class & STCmanifest) && v._init)
5742                 {
5743                     /* When an instance that will be converted to a constant exists,
5744                      * the instance representation "foo!tiargs" is treated like a
5745                      * variable name, and its recursive appearance check (note that
5746                      * it's equivalent with a recursive instantiation of foo) is done
5747                      * separately from the circular initialization check for the
5748                      * eponymous enum variable declaration.
5749                      *
5750                      *  template foo(T) {
5751                      *    enum bool foo = foo;    // recursive definition check (v.inuse)
5752                      *  }
5753                      *  template bar(T) {
5754                      *    enum bool bar = bar!T;  // recursive instantiation check (ti.inuse)
5755                      *  }
5756                      */
5757                     if (ti.inuse)
5758                     {
5759                         error("recursive expansion of %s '%s'", ti.kind(), ti.toPrettyChars());
5760                         return new ErrorExp();
5761                     }
5762                     auto e = v.expandInitializer(loc);
5763                     ti.inuse++;
5764                     e = e.semantic(sc);
5765                     ti.inuse--;
5766                     return e;
5767                 }
5768             }
5769 
5770             //printf("s = %s, '%s'\n", s.kind(), s.toChars());
5771             auto e = DsymbolExp.resolve(loc, sc, s, true);
5772             //printf("-1ScopeExp::semantic()\n");
5773             return e;
5774         }
5775 
5776         //printf("sds2 = %s, '%s'\n", sds2.kind(), sds2.toChars());
5777         //printf("\tparent = '%s'\n", sds2.parent.toChars());
5778         sds2.semantic(sc);
5779 
5780         if (auto t = sds2.getType())    // (Aggregate|Enum)Declaration
5781             return (new TypeExp(loc, t)).semantic(sc);
5782 
5783         if (auto td = sds2.isTemplateDeclaration())
5784             return (new TemplateExp(loc, td)).semantic(sc);
5785 
5786         sds = sds2;
5787         type = Type.tvoid;
5788         //printf("-2ScopeExp::semantic() %s\n", toChars());
5789         return this;
5790     }
5791 
5792     override bool checkType()
5793     {
5794         if (sds.isPackage())
5795         {
5796             error("%s %s has no type", sds.kind(), sds.toChars());
5797             return true;
5798         }
5799         if (auto ti = sds.isTemplateInstance())
5800         {
5801             //assert(ti.needsTypeInference(sc));
5802             if (ti.tempdecl &&
5803                 ti.semantictiargsdone &&
5804                 ti.semanticRun == PASSinit)
5805             {
5806                 error("partial %s %s has no type", sds.kind(), toChars());
5807                 return true;
5808             }
5809         }
5810         return false;
5811     }
5812 
5813     override bool checkValue()
5814     {
5815         error("%s %s has no value", sds.kind(), sds.toChars());
5816         return true;
5817     }
5818 
5819     override void accept(Visitor v)
5820     {
5821         v.visit(this);
5822     }
5823 }
5824 
5825 /***********************************************************
5826  * Mainly just a placeholder
5827  */
5828 extern (C++) final class TemplateExp : Expression
5829 {
5830     TemplateDeclaration td;
5831     FuncDeclaration fd;
5832 
5833     extern (D) this(Loc loc, TemplateDeclaration td, FuncDeclaration fd = null)
5834     {
5835         super(loc, TOKtemplate, __traits(classInstanceSize, TemplateExp));
5836         //printf("TemplateExp(): %s\n", td->toChars());
5837         this.td = td;
5838         this.fd = fd;
5839     }
5840 
5841     override bool isLvalue()
5842     {
5843         return fd !is null;
5844     }
5845 
5846     override Expression toLvalue(Scope* sc, Expression e)
5847     {
5848         if (!fd)
5849             return Expression.toLvalue(sc, e);
5850 
5851         assert(sc);
5852         return DsymbolExp.resolve(loc, sc, fd, true);
5853     }
5854 
5855     override bool checkType()
5856     {
5857         error("%s %s has no type", td.kind(), toChars());
5858         return true;
5859     }
5860 
5861     override bool checkValue()
5862     {
5863         error("%s %s has no value", td.kind(), toChars());
5864         return true;
5865     }
5866 
5867     override void accept(Visitor v)
5868     {
5869         v.visit(this);
5870     }
5871 }
5872 
5873 /***********************************************************
5874  * thisexp.new(newargs) newtype(arguments)
5875  */
5876 extern (C++) final class NewExp : Expression
5877 {
5878     Expression thisexp;         // if !=null, 'this' for class being allocated
5879     Expressions* newargs;       // Array of Expression's to call new operator
5880     Type newtype;
5881     Expressions* arguments;     // Array of Expression's
5882     Expression argprefix;       // expression to be evaluated just before arguments[]
5883     CtorDeclaration member;     // constructor function
5884     NewDeclaration allocator;   // allocator function
5885     int onstack;                // allocate on stack
5886 
5887     extern (D) this(Loc loc, Expression thisexp, Expressions* newargs, Type newtype, Expressions* arguments)
5888     {
5889         super(loc, TOKnew, __traits(classInstanceSize, NewExp));
5890         this.thisexp = thisexp;
5891         this.newargs = newargs;
5892         this.newtype = newtype;
5893         this.arguments = arguments;
5894     }
5895 
5896     override Expression syntaxCopy()
5897     {
5898         return new NewExp(loc,
5899             thisexp ? thisexp.syntaxCopy() : null,
5900             arraySyntaxCopy(newargs),
5901             newtype.syntaxCopy(),
5902             arraySyntaxCopy(arguments));
5903     }
5904 
5905     override Expression semantic(Scope* sc)
5906     {
5907         static if (LOGSEMANTIC)
5908         {
5909             printf("NewExp::semantic() %s\n", toChars());
5910             if (thisexp)
5911                 printf("\tthisexp = %s\n", thisexp.toChars());
5912             printf("\tnewtype: %s\n", newtype.toChars());
5913         }
5914         if (type) // if semantic() already run
5915             return this;
5916 
5917         // Bugzilla 11581: With the syntax `new T[edim]` or `thisexp.new T[edim]`,
5918         // T should be analyzed first and edim should go into arguments iff it's
5919         // not a tuple.
5920         Expression edim = null;
5921         if (!arguments && newtype.ty == Tsarray)
5922         {
5923             edim = (cast(TypeSArray)newtype).dim;
5924             newtype = (cast(TypeNext)newtype).next;
5925         }
5926 
5927         ClassDeclaration cdthis = null;
5928         if (thisexp)
5929         {
5930             thisexp = thisexp.semantic(sc);
5931             if (thisexp.op == TOKerror)
5932                 return new ErrorExp();
5933             cdthis = thisexp.type.isClassHandle();
5934             if (!cdthis)
5935             {
5936                 error("'this' for nested class must be a class type, not %s", thisexp.type.toChars());
5937                 return new ErrorExp();
5938             }
5939 
5940             sc = sc.push(cdthis);
5941             type = newtype.semantic(loc, sc);
5942             sc = sc.pop();
5943         }
5944         else
5945         {
5946             type = newtype.semantic(loc, sc);
5947         }
5948         if (type.ty == Terror)
5949             return new ErrorExp();
5950 
5951         if (edim)
5952         {
5953             if (type.toBasetype().ty == Ttuple)
5954             {
5955                 // --> new T[edim]
5956                 type = new TypeSArray(type, edim);
5957                 type = type.semantic(loc, sc);
5958                 if (type.ty == Terror)
5959                     return new ErrorExp();
5960             }
5961             else
5962             {
5963                 // --> new T[](edim)
5964                 arguments = new Expressions();
5965                 arguments.push(edim);
5966                 type = type.arrayOf();
5967             }
5968         }
5969 
5970         newtype = type; // in case type gets cast to something else
5971         Type tb = type.toBasetype();
5972         //printf("tb: %s, deco = %s\n", tb.toChars(), tb.deco);
5973 
5974         if (arrayExpressionSemantic(newargs, sc) ||
5975             preFunctionParameters(loc, sc, newargs))
5976         {
5977             return new ErrorExp();
5978         }
5979         if (arrayExpressionSemantic(arguments, sc) ||
5980             preFunctionParameters(loc, sc, arguments))
5981         {
5982             return new ErrorExp();
5983         }
5984 
5985         if (thisexp && tb.ty != Tclass)
5986         {
5987             error("e.new is only for allocating nested classes, not %s", tb.toChars());
5988             return new ErrorExp();
5989         }
5990 
5991         size_t nargs = arguments ? arguments.dim : 0;
5992         Expression newprefix = null;
5993 
5994         if (tb.ty == Tclass)
5995         {
5996             auto cd = (cast(TypeClass)tb).sym;
5997             cd.size(loc);
5998             if (cd.sizeok != SIZEOKdone)
5999                 return new ErrorExp();
6000             if (!cd.ctor)
6001                 cd.ctor = cd.searchCtor();
6002             if (cd.noDefaultCtor && !nargs && !cd.defaultCtor)
6003             {
6004                 error("default construction is disabled for type %s", cd.type.toChars());
6005                 return new ErrorExp();
6006             }
6007 
6008             if (cd.isInterfaceDeclaration())
6009             {
6010                 error("cannot create instance of interface %s", cd.toChars());
6011                 return new ErrorExp();
6012             }
6013             if (cd.isAbstract())
6014             {
6015                 error("cannot create instance of abstract class %s", cd.toChars());
6016                 for (size_t i = 0; i < cd.vtbl.dim; i++)
6017                 {
6018                     FuncDeclaration fd = cd.vtbl[i].isFuncDeclaration();
6019                     if (fd && fd.isAbstract())
6020                     {
6021                         errorSupplemental(loc, "function '%s' is not implemented",
6022                             fd.toFullSignature());
6023                     }
6024                 }
6025                 return new ErrorExp();
6026             }
6027             // checkDeprecated() is already done in newtype->semantic().
6028 
6029             if (cd.isNested())
6030             {
6031                 /* We need a 'this' pointer for the nested class.
6032                  * Ensure we have the right one.
6033                  */
6034                 Dsymbol s = cd.toParent2();
6035 
6036                 //printf("cd isNested, parent = %s '%s'\n", s.kind(), s.toPrettyChars());
6037                 if (auto cdn = s.isClassDeclaration())
6038                 {
6039                     if (!cdthis)
6040                     {
6041                         // Supply an implicit 'this' and try again
6042                         thisexp = new ThisExp(loc);
6043                         for (Dsymbol sp = sc.parent; 1; sp = sp.parent)
6044                         {
6045                             if (!sp)
6046                             {
6047                                 error("outer class %s 'this' needed to 'new' nested class %s",
6048                                     cdn.toChars(), cd.toChars());
6049                                 return new ErrorExp();
6050                             }
6051                             ClassDeclaration cdp = sp.isClassDeclaration();
6052                             if (!cdp)
6053                                 continue;
6054                             if (cdp == cdn || cdn.isBaseOf(cdp, null))
6055                                 break;
6056                             // Add a '.outer' and try again
6057                             thisexp = new DotIdExp(loc, thisexp, Id.outer);
6058                         }
6059 
6060                         thisexp = thisexp.semantic(sc);
6061                         if (thisexp.op == TOKerror)
6062                             return new ErrorExp();
6063                         cdthis = thisexp.type.isClassHandle();
6064                     }
6065                     if (cdthis != cdn && !cdn.isBaseOf(cdthis, null))
6066                     {
6067                         //printf("cdthis = %s\n", cdthis.toChars());
6068                         error("'this' for nested class must be of type %s, not %s",
6069                             cdn.toChars(), thisexp.type.toChars());
6070                         return new ErrorExp();
6071                     }
6072                     if (!MODimplicitConv(thisexp.type.mod, newtype.mod))
6073                     {
6074                         error("nested type %s should have the same or weaker constancy as enclosing type %s",
6075                             newtype.toChars(), thisexp.type.toChars());
6076                         return new ErrorExp();
6077                     }
6078                 }
6079                 else if (thisexp)
6080                 {
6081                     error("e.new is only for allocating nested classes");
6082                     return new ErrorExp();
6083                 }
6084                 else if (auto fdn = s.isFuncDeclaration())
6085                 {
6086                     // make sure the parent context fdn of cd is reachable from sc
6087                     if (checkNestedRef(sc.parent, fdn))
6088                     {
6089                         error("outer function context of %s is needed to 'new' nested class %s",
6090                             fdn.toPrettyChars(), cd.toPrettyChars());
6091                         return new ErrorExp();
6092                     }
6093                 }
6094                 else
6095                     assert(0);
6096             }
6097             else if (thisexp)
6098             {
6099                 error("e.new is only for allocating nested classes");
6100                 return new ErrorExp();
6101             }
6102 
6103             if (cd.aggNew)
6104             {
6105                 // Prepend the size argument to newargs[]
6106                 Expression e = new IntegerExp(loc, cd.size(loc), Type.tsize_t);
6107                 if (!newargs)
6108                     newargs = new Expressions();
6109                 newargs.shift(e);
6110 
6111                 FuncDeclaration f = resolveFuncCall(loc, sc, cd.aggNew, null, tb, newargs);
6112                 if (!f || f.errors)
6113                     return new ErrorExp();
6114                 checkDeprecated(sc, f);
6115                 checkPurity(sc, f);
6116                 checkSafety(sc, f);
6117                 checkNogc(sc, f);
6118                 checkAccess(cd, loc, sc, f);
6119 
6120                 TypeFunction tf = cast(TypeFunction)f.type;
6121                 Type rettype;
6122                 if (functionParameters(loc, sc, tf, null, newargs, f, &rettype, &newprefix))
6123                     return new ErrorExp();
6124 
6125                 allocator = f.isNewDeclaration();
6126                 assert(allocator);
6127             }
6128             else
6129             {
6130                 if (newargs && newargs.dim)
6131                 {
6132                     error("no allocator for %s", cd.toChars());
6133                     return new ErrorExp();
6134                 }
6135             }
6136 
6137             if (cd.ctor)
6138             {
6139                 FuncDeclaration f = resolveFuncCall(loc, sc, cd.ctor, null, tb, arguments, 0);
6140                 if (!f || f.errors)
6141                     return new ErrorExp();
6142                 checkDeprecated(sc, f);
6143                 checkPurity(sc, f);
6144                 checkSafety(sc, f);
6145                 checkNogc(sc, f);
6146                 checkAccess(cd, loc, sc, f);
6147 
6148                 TypeFunction tf = cast(TypeFunction)f.type;
6149                 if (!arguments)
6150                     arguments = new Expressions();
6151                 if (functionParameters(loc, sc, tf, type, arguments, f, &type, &argprefix))
6152                     return new ErrorExp();
6153 
6154                 member = f.isCtorDeclaration();
6155                 assert(member);
6156             }
6157             else
6158             {
6159                 if (nargs)
6160                 {
6161                     error("no constructor for %s", cd.toChars());
6162                     return new ErrorExp();
6163                 }
6164             }
6165         }
6166         else if (tb.ty == Tstruct)
6167         {
6168             auto sd = (cast(TypeStruct)tb).sym;
6169             sd.size(loc);
6170             if (sd.sizeok != SIZEOKdone)
6171                 return new ErrorExp();
6172             if (!sd.ctor)
6173                 sd.ctor = sd.searchCtor();
6174             if (sd.noDefaultCtor && !nargs)
6175             {
6176                 error("default construction is disabled for type %s", sd.type.toChars());
6177                 return new ErrorExp();
6178             }
6179             // checkDeprecated() is already done in newtype->semantic().
6180 
6181             if (sd.aggNew)
6182             {
6183                 // Prepend the uint size argument to newargs[]
6184                 Expression e = new IntegerExp(loc, sd.size(loc), Type.tsize_t);
6185                 if (!newargs)
6186                     newargs = new Expressions();
6187                 newargs.shift(e);
6188 
6189                 FuncDeclaration f = resolveFuncCall(loc, sc, sd.aggNew, null, tb, newargs);
6190                 if (!f || f.errors)
6191                     return new ErrorExp();
6192                 checkDeprecated(sc, f);
6193                 checkPurity(sc, f);
6194                 checkSafety(sc, f);
6195                 checkNogc(sc, f);
6196                 checkAccess(sd, loc, sc, f);
6197 
6198                 TypeFunction tf = cast(TypeFunction)f.type;
6199                 Type rettype;
6200                 if (functionParameters(loc, sc, tf, null, newargs, f, &rettype, &newprefix))
6201                     return new ErrorExp();
6202 
6203                 allocator = f.isNewDeclaration();
6204                 assert(allocator);
6205             }
6206             else
6207             {
6208                 if (newargs && newargs.dim)
6209                 {
6210                     error("no allocator for %s", sd.toChars());
6211                     return new ErrorExp();
6212                 }
6213             }
6214 
6215             if (sd.ctor && nargs)
6216             {
6217                 FuncDeclaration f = resolveFuncCall(loc, sc, sd.ctor, null, tb, arguments, 0);
6218                 if (!f || f.errors)
6219                     return new ErrorExp();
6220                 checkDeprecated(sc, f);
6221                 checkPurity(sc, f);
6222                 checkSafety(sc, f);
6223                 checkNogc(sc, f);
6224                 checkAccess(sd, loc, sc, f);
6225 
6226                 TypeFunction tf = cast(TypeFunction)f.type;
6227                 if (!arguments)
6228                     arguments = new Expressions();
6229                 if (functionParameters(loc, sc, tf, type, arguments, f, &type, &argprefix))
6230                     return new ErrorExp();
6231 
6232                 member = f.isCtorDeclaration();
6233                 assert(member);
6234 
6235                 if (checkFrameAccess(loc, sc, sd, sd.fields.dim))
6236                     return new ErrorExp();
6237             }
6238             else
6239             {
6240                 if (!arguments)
6241                     arguments = new Expressions();
6242 
6243                 if (!sd.fit(loc, sc, arguments, tb))
6244                     return new ErrorExp();
6245 
6246                 if (!sd.fill(loc, arguments, false))
6247                     return new ErrorExp();
6248 
6249                 if (checkFrameAccess(loc, sc, sd, arguments ? arguments.dim : 0))
6250                     return new ErrorExp();
6251             }
6252 
6253             type = type.pointerTo();
6254         }
6255         else if (tb.ty == Tarray && nargs)
6256         {
6257             Type tn = tb.nextOf().baseElemOf();
6258             Dsymbol s = tn.toDsymbol(sc);
6259             AggregateDeclaration ad = s ? s.isAggregateDeclaration() : null;
6260             if (ad && ad.noDefaultCtor)
6261             {
6262                 error("default construction is disabled for type %s", tb.nextOf().toChars());
6263                 return new ErrorExp();
6264             }
6265             for (size_t i = 0; i < nargs; i++)
6266             {
6267                 if (tb.ty != Tarray)
6268                 {
6269                     error("too many arguments for array");
6270                     return new ErrorExp();
6271                 }
6272 
6273                 Expression arg = (*arguments)[i];
6274                 arg = resolveProperties(sc, arg);
6275                 arg = arg.implicitCastTo(sc, Type.tsize_t);
6276                 arg = arg.optimize(WANTvalue);
6277                 if (arg.op == TOKint64 && cast(sinteger_t)arg.toInteger() < 0)
6278                 {
6279                     error("negative array index %s", arg.toChars());
6280                     return new ErrorExp();
6281                 }
6282                 (*arguments)[i] = arg;
6283                 tb = (cast(TypeDArray)tb).next.toBasetype();
6284             }
6285         }
6286         else if (tb.isscalar())
6287         {
6288             if (!nargs)
6289             {
6290             }
6291             else if (nargs == 1)
6292             {
6293                 Expression e = (*arguments)[0];
6294                 e = e.implicitCastTo(sc, tb);
6295                 (*arguments)[0] = e;
6296             }
6297             else
6298             {
6299                 error("more than one argument for construction of %s", type.toChars());
6300                 return new ErrorExp();
6301             }
6302 
6303             type = type.pointerTo();
6304         }
6305         else
6306         {
6307             error("new can only create structs, dynamic arrays or class objects, not %s's", type.toChars());
6308             return new ErrorExp();
6309         }
6310 
6311         //printf("NewExp: '%s'\n", toChars());
6312         //printf("NewExp:type '%s'\n", type->toChars());
6313         semanticTypeInfo(sc, type);
6314 
6315         if (newprefix)
6316             return combine(newprefix, this);
6317         return this;
6318     }
6319 
6320     override void accept(Visitor v)
6321     {
6322         v.visit(this);
6323     }
6324 }
6325 
6326 /***********************************************************
6327  * thisexp.new(newargs) class baseclasses { } (arguments)
6328  */
6329 extern (C++) final class NewAnonClassExp : Expression
6330 {
6331     Expression thisexp;     // if !=null, 'this' for class being allocated
6332     Expressions* newargs;   // Array of Expression's to call new operator
6333     ClassDeclaration cd;    // class being instantiated
6334     Expressions* arguments; // Array of Expression's to call class constructor
6335 
6336     extern (D) this(Loc loc, Expression thisexp, Expressions* newargs, ClassDeclaration cd, Expressions* arguments)
6337     {
6338         super(loc, TOKnewanonclass, __traits(classInstanceSize, NewAnonClassExp));
6339         this.thisexp = thisexp;
6340         this.newargs = newargs;
6341         this.cd = cd;
6342         this.arguments = arguments;
6343     }
6344 
6345     override Expression syntaxCopy()
6346     {
6347         return new NewAnonClassExp(loc, thisexp ? thisexp.syntaxCopy() : null, arraySyntaxCopy(newargs), cast(ClassDeclaration)cd.syntaxCopy(null), arraySyntaxCopy(arguments));
6348     }
6349 
6350     override Expression semantic(Scope* sc)
6351     {
6352         static if (LOGSEMANTIC)
6353         {
6354             printf("NewAnonClassExp::semantic() %s\n", toChars());
6355             //printf("thisexp = %p\n", thisexp);
6356             //printf("type: %s\n", type->toChars());
6357         }
6358 
6359         Expression d = new DeclarationExp(loc, cd);
6360         sc = sc.push(); // just create new scope
6361         sc.flags &= ~SCOPEctfe; // temporary stop CTFE
6362         d = d.semantic(sc);
6363         sc = sc.pop();
6364 
6365         if (!cd.errors && sc.intypeof && !sc.parent.inNonRoot())
6366         {
6367             ScopeDsymbol sds = sc.tinst ? cast(ScopeDsymbol)sc.tinst : sc._module;
6368             sds.members.push(cd);
6369         }
6370 
6371         Expression n = new NewExp(loc, thisexp, newargs, cd.type, arguments);
6372 
6373         Expression c = new CommaExp(loc, d, n);
6374         return c.semantic(sc);
6375     }
6376 
6377     override void accept(Visitor v)
6378     {
6379         v.visit(this);
6380     }
6381 }
6382 
6383 /***********************************************************
6384  */
6385 extern (C++) class SymbolExp : Expression
6386 {
6387     Declaration var;
6388     bool hasOverloads;
6389 
6390     final extern (D) this(Loc loc, TOK op, int size, Declaration var, bool hasOverloads)
6391     {
6392         super(loc, op, size);
6393         assert(var);
6394         this.var = var;
6395         this.hasOverloads = hasOverloads;
6396     }
6397 
6398     override void accept(Visitor v)
6399     {
6400         v.visit(this);
6401     }
6402 
6403     override void printAST(int indent)
6404     {
6405         Expression.printAST(indent);
6406         foreach (i; 0 .. indent + 2)
6407             printf(" ");
6408         printf(".var: %s\n", var ? var.toChars() : "");
6409     }
6410 }
6411 
6412 /***********************************************************
6413  * Offset from symbol
6414  */
6415 extern (C++) final class SymOffExp : SymbolExp
6416 {
6417     dinteger_t offset;
6418 
6419     extern (D) this(Loc loc, Declaration var, dinteger_t offset, bool hasOverloads = true)
6420     {
6421         if (auto v = var.isVarDeclaration())
6422         {
6423             // FIXME: This error report will never be handled anyone.
6424             // It should be done before the SymOffExp construction.
6425             if (v.needThis())
6426                 .error(loc, "need 'this' for address of %s", v.toChars());
6427             hasOverloads = false;
6428         }
6429         super(loc, TOKsymoff, __traits(classInstanceSize, SymOffExp), var, hasOverloads);
6430         this.offset = offset;
6431     }
6432 
6433     override Expression semantic(Scope* sc)
6434     {
6435         static if (LOGSEMANTIC)
6436         {
6437             printf("SymOffExp::semantic('%s')\n", toChars());
6438         }
6439         //var->semantic(sc);
6440         if (!type)
6441             type = var.type.pointerTo();
6442 
6443         if (auto v = var.isVarDeclaration())
6444         {
6445             if (v.checkNestedReference(sc, loc))
6446                 return new ErrorExp();
6447         }
6448         else if (auto f = var.isFuncDeclaration())
6449         {
6450             if (f.checkNestedReference(sc, loc))
6451                 return new ErrorExp();
6452         }
6453 
6454         return this;
6455     }
6456 
6457     override bool isBool(bool result)
6458     {
6459         return result ? true : false;
6460     }
6461 
6462     override void accept(Visitor v)
6463     {
6464         v.visit(this);
6465     }
6466 }
6467 
6468 /***********************************************************
6469  * Variable
6470  */
6471 extern (C++) final class VarExp : SymbolExp
6472 {
6473     extern (D) this(Loc loc, Declaration var, bool hasOverloads = true)
6474     {
6475         if (var.isVarDeclaration())
6476             hasOverloads = false;
6477 
6478         super(loc, TOKvar, __traits(classInstanceSize, VarExp), var, hasOverloads);
6479         //printf("VarExp(this = %p, '%s', loc = %s)\n", this, var->toChars(), loc.toChars());
6480         //if (strcmp(var->ident->toChars(), "func") == 0) assert(0);
6481         this.type = var.type;
6482     }
6483 
6484     static VarExp create(Loc loc, Declaration var, bool hasOverloads = true)
6485     {
6486         return new VarExp(loc, var, hasOverloads);
6487     }
6488 
6489     override bool equals(RootObject o)
6490     {
6491         if (this == o)
6492             return true;
6493         if ((cast(Expression)o).op == TOKvar)
6494         {
6495             VarExp ne = cast(VarExp)o;
6496             if (type.toHeadMutable().equals(ne.type.toHeadMutable()) && var == ne.var)
6497             {
6498                 return true;
6499             }
6500         }
6501         return false;
6502     }
6503 
6504     override Expression semantic(Scope* sc)
6505     {
6506         static if (LOGSEMANTIC)
6507         {
6508             printf("VarExp::semantic(%s)\n", toChars());
6509         }
6510         if (auto fd = var.isFuncDeclaration())
6511         {
6512             //printf("L%d fd = %s\n", __LINE__, f->toChars());
6513             if (!fd.functionSemantic())
6514                 return new ErrorExp();
6515         }
6516 
6517         if (!type)
6518             type = var.type;
6519         if (type && !type.deco)
6520             type = type.semantic(loc, sc);
6521 
6522         /* Fix for 1161 doesn't work because it causes protection
6523          * problems when instantiating imported templates passing private
6524          * variables as alias template parameters.
6525          */
6526         //checkAccess(loc, sc, NULL, var);
6527 
6528         if (auto vd = var.isVarDeclaration())
6529         {
6530             if (vd.checkNestedReference(sc, loc))
6531                 return new ErrorExp();
6532 
6533             // Bugzilla 12025: If the variable is not actually used in runtime code,
6534             // the purity violation error is redundant.
6535             //checkPurity(sc, vd);
6536         }
6537         else if (auto fd = var.isFuncDeclaration())
6538         {
6539             // TODO: If fd isn't yet resolved its overload, the checkNestedReference
6540             // call would cause incorrect validation.
6541             // Maybe here should be moved in CallExp, or AddrExp for functions.
6542             if (fd.checkNestedReference(sc, loc))
6543                 return new ErrorExp();
6544         }
6545         else if (auto od = var.isOverDeclaration())
6546         {
6547             type = Type.tvoid; // ambiguous type?
6548         }
6549 
6550         return this;
6551     }
6552 
6553     override int checkModifiable(Scope* sc, int flag)
6554     {
6555         //printf("VarExp::checkModifiable %s", toChars());
6556         assert(type);
6557         return var.checkModify(loc, sc, type, null, flag);
6558     }
6559 
6560     bool checkReadModifyWrite();
6561 
6562     override bool isLvalue()
6563     {
6564         if (var.storage_class & (STClazy | STCrvalue | STCmanifest))
6565             return false;
6566         return true;
6567     }
6568 
6569     override Expression toLvalue(Scope* sc, Expression e)
6570     {
6571         if (var.storage_class & STCmanifest)
6572         {
6573             error("manifest constant '%s' is not lvalue", var.toChars());
6574             return new ErrorExp();
6575         }
6576         if (var.storage_class & STClazy)
6577         {
6578             error("lazy variables cannot be lvalues");
6579             return new ErrorExp();
6580         }
6581         if (var.ident == Id.ctfe)
6582         {
6583             error("compiler-generated variable __ctfe is not an lvalue");
6584             return new ErrorExp();
6585         }
6586         if (var.ident == Id.dollar) // Bugzilla 13574
6587         {
6588             error("'$' is not an lvalue");
6589             return new ErrorExp();
6590         }
6591         return this;
6592     }
6593 
6594     override Expression modifiableLvalue(Scope* sc, Expression e)
6595     {
6596         //printf("VarExp::modifiableLvalue('%s')\n", var->toChars());
6597         if (var.storage_class & STCmanifest)
6598         {
6599             error("cannot modify manifest constant '%s'", toChars());
6600             return new ErrorExp();
6601         }
6602         // See if this expression is a modifiable lvalue (i.e. not const)
6603         return Expression.modifiableLvalue(sc, e);
6604     }
6605 
6606     override void accept(Visitor v)
6607     {
6608         v.visit(this);
6609     }
6610 }
6611 
6612 /***********************************************************
6613  * Overload Set
6614  */
6615 extern (C++) final class OverExp : Expression
6616 {
6617     OverloadSet vars;
6618 
6619     extern (D) this(Loc loc, OverloadSet s)
6620     {
6621         super(loc, TOKoverloadset, __traits(classInstanceSize, OverExp));
6622         //printf("OverExp(this = %p, '%s')\n", this, var->toChars());
6623         vars = s;
6624         type = Type.tvoid;
6625     }
6626 
6627     override bool isLvalue()
6628     {
6629         return true;
6630     }
6631 
6632     override Expression toLvalue(Scope* sc, Expression e)
6633     {
6634         return this;
6635     }
6636 
6637     override void accept(Visitor v)
6638     {
6639         v.visit(this);
6640     }
6641 }
6642 
6643 /***********************************************************
6644  * Function/Delegate literal
6645  */
6646 extern (C++) final class FuncExp : Expression
6647 {
6648     FuncLiteralDeclaration fd;
6649     TemplateDeclaration td;
6650     TOK tok;
6651 
6652     extern (D) this(Loc loc, Dsymbol s)
6653     {
6654         super(loc, TOKfunction, __traits(classInstanceSize, FuncExp));
6655         this.td = s.isTemplateDeclaration();
6656         this.fd = s.isFuncLiteralDeclaration();
6657         if (td)
6658         {
6659             assert(td.literal);
6660             assert(td.members && td.members.dim == 1);
6661             fd = (*td.members)[0].isFuncLiteralDeclaration();
6662         }
6663         tok = fd.tok; // save original kind of function/delegate/(infer)
6664         assert(fd.fbody);
6665     }
6666 
6667     override bool equals(RootObject o)
6668     {
6669         if (this == o)
6670             return true;
6671         if (o.dyncast() != DYNCAST_EXPRESSION)
6672             return false;
6673         if ((cast(Expression)o).op == TOKfunction)
6674         {
6675             FuncExp fe = cast(FuncExp)o;
6676             return fd == fe.fd;
6677         }
6678         return false;
6679     }
6680 
6681     void genIdent(Scope* sc)
6682     {
6683         if (fd.ident == Id.empty)
6684         {
6685             const(char)* s;
6686             if (fd.fes)
6687                 s = "__foreachbody";
6688             else if (fd.tok == TOKreserved)
6689                 s = "__lambda";
6690             else if (fd.tok == TOKdelegate)
6691                 s = "__dgliteral";
6692             else
6693                 s = "__funcliteral";
6694 
6695             DsymbolTable symtab;
6696             if (FuncDeclaration func = sc.parent.isFuncDeclaration())
6697             {
6698                 if (func.localsymtab is null)
6699                 {
6700                     // Inside template constraint, symtab is not set yet.
6701                     // Initialize it lazily.
6702                     func.localsymtab = new DsymbolTable();
6703                 }
6704                 symtab = func.localsymtab;
6705             }
6706             else
6707             {
6708                 ScopeDsymbol sds = sc.parent.isScopeDsymbol();
6709                 if (!sds.symtab)
6710                 {
6711                     // Inside template constraint, symtab may not be set yet.
6712                     // Initialize it lazily.
6713                     assert(sds.isTemplateInstance());
6714                     sds.symtab = new DsymbolTable();
6715                 }
6716                 symtab = sds.symtab;
6717             }
6718             assert(symtab);
6719             Identifier id = Identifier.generateId(s, symtab.len() + 1);
6720             fd.ident = id;
6721             if (td)
6722                 td.ident = id;
6723             symtab.insert(td ? cast(Dsymbol)td : cast(Dsymbol)fd);
6724         }
6725     }
6726 
6727     override Expression syntaxCopy()
6728     {
6729         if (td)
6730             return new FuncExp(loc, td.syntaxCopy(null));
6731         else if (fd.semanticRun == PASSinit)
6732             return new FuncExp(loc, fd.syntaxCopy(null));
6733         else // Bugzilla 13481: Prevent multiple semantic analysis of lambda body.
6734             return new FuncExp(loc, fd);
6735     }
6736 
6737     override Expression semantic(Scope* sc)
6738     {
6739         static if (LOGSEMANTIC)
6740         {
6741             printf("FuncExp::semantic(%s)\n", toChars());
6742             if (fd.treq)
6743                 printf("  treq = %s\n", fd.treq.toChars());
6744         }
6745         Expression e = this;
6746 
6747         sc = sc.push(); // just create new scope
6748         sc.flags &= ~SCOPEctfe; // temporary stop CTFE
6749         sc.protection = Prot(PROTpublic); // Bugzilla 12506
6750 
6751         if (!type || type == Type.tvoid)
6752         {
6753             /* fd->treq might be incomplete type,
6754              * so should not semantic it.
6755              * void foo(T)(T delegate(int) dg){}
6756              * foo(a=>a); // in IFTI, treq == T delegate(int)
6757              */
6758             //if (fd->treq)
6759             //    fd->treq = fd->treq->semantic(loc, sc);
6760 
6761             genIdent(sc);
6762 
6763             // Set target of return type inference
6764             if (fd.treq && !fd.type.nextOf())
6765             {
6766                 TypeFunction tfv = null;
6767                 if (fd.treq.ty == Tdelegate || (fd.treq.ty == Tpointer && fd.treq.nextOf().ty == Tfunction))
6768                     tfv = cast(TypeFunction)fd.treq.nextOf();
6769                 if (tfv)
6770                 {
6771                     TypeFunction tfl = cast(TypeFunction)fd.type;
6772                     tfl.next = tfv.nextOf();
6773                 }
6774             }
6775 
6776             //printf("td = %p, treq = %p\n", td, fd->treq);
6777             if (td)
6778             {
6779                 assert(td.parameters && td.parameters.dim);
6780                 td.semantic(sc);
6781                 type = Type.tvoid; // temporary type
6782 
6783                 if (fd.treq) // defer type determination
6784                 {
6785                     FuncExp fe;
6786                     if (matchType(fd.treq, sc, &fe) > MATCHnomatch)
6787                         e = fe;
6788                     else
6789                         e = new ErrorExp();
6790                 }
6791                 goto Ldone;
6792             }
6793 
6794             uint olderrors = global.errors;
6795             fd.semantic(sc);
6796             if (olderrors == global.errors)
6797             {
6798                 fd.semantic2(sc);
6799                 if (olderrors == global.errors)
6800                     fd.semantic3(sc);
6801             }
6802             if (olderrors != global.errors)
6803             {
6804                 if (fd.type && fd.type.ty == Tfunction && !fd.type.nextOf())
6805                     (cast(TypeFunction)fd.type).next = Type.terror;
6806                 e = new ErrorExp();
6807                 goto Ldone;
6808             }
6809 
6810             // Type is a "delegate to" or "pointer to" the function literal
6811             if ((fd.isNested() && fd.tok == TOKdelegate) || (tok == TOKreserved && fd.treq && fd.treq.ty == Tdelegate))
6812             {
6813                 type = new TypeDelegate(fd.type);
6814                 type = type.semantic(loc, sc);
6815 
6816                 fd.tok = TOKdelegate;
6817             }
6818             else
6819             {
6820                 type = new TypePointer(fd.type);
6821                 type = type.semantic(loc, sc);
6822                 //type = fd->type->pointerTo();
6823 
6824                 /* A lambda expression deduced to function pointer might become
6825                  * to a delegate literal implicitly.
6826                  *
6827                  *   auto foo(void function() fp) { return 1; }
6828                  *   assert(foo({}) == 1);
6829                  *
6830                  * So, should keep fd->tok == TOKreserve if fd->treq == NULL.
6831                  */
6832                 if (fd.treq && fd.treq.ty == Tpointer)
6833                 {
6834                     // change to non-nested
6835                     fd.tok = TOKfunction;
6836                     fd.vthis = null;
6837                 }
6838             }
6839             fd.tookAddressOf++;
6840         }
6841 
6842     Ldone:
6843         sc = sc.pop();
6844         return e;
6845     }
6846 
6847     // used from CallExp::semantic()
6848     Expression semantic(Scope* sc, Expressions* arguments)
6849     {
6850         if ((!type || type == Type.tvoid) && td && arguments && arguments.dim)
6851         {
6852             for (size_t k = 0; k < arguments.dim; k++)
6853             {
6854                 Expression checkarg = (*arguments)[k];
6855                 if (checkarg.op == TOKerror)
6856                     return checkarg;
6857             }
6858 
6859             genIdent(sc);
6860 
6861             assert(td.parameters && td.parameters.dim);
6862             td.semantic(sc);
6863 
6864             TypeFunction tfl = cast(TypeFunction)fd.type;
6865             size_t dim = Parameter.dim(tfl.parameters);
6866             if (arguments.dim < dim)
6867             {
6868                 // Default arguments are always typed, so they don't need inference.
6869                 Parameter p = Parameter.getNth(tfl.parameters, arguments.dim);
6870                 if (p.defaultArg)
6871                     dim = arguments.dim;
6872             }
6873 
6874             if ((!tfl.varargs && arguments.dim == dim) || (tfl.varargs && arguments.dim >= dim))
6875             {
6876                 auto tiargs = new Objects();
6877                 tiargs.reserve(td.parameters.dim);
6878 
6879                 for (size_t i = 0; i < td.parameters.dim; i++)
6880                 {
6881                     TemplateParameter tp = (*td.parameters)[i];
6882                     for (size_t u = 0; u < dim; u++)
6883                     {
6884                         Parameter p = Parameter.getNth(tfl.parameters, u);
6885                         if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident)
6886                         {
6887                             Expression e = (*arguments)[u];
6888                             tiargs.push(e.type);
6889                             u = dim; // break inner loop
6890                         }
6891                     }
6892                 }
6893 
6894                 auto ti = new TemplateInstance(loc, td, tiargs);
6895                 return (new ScopeExp(loc, ti)).semantic(sc);
6896             }
6897             error("cannot infer function literal type");
6898             return new ErrorExp();
6899         }
6900         return semantic(sc);
6901     }
6902 
6903     MATCH matchType(Type to, Scope* sc, FuncExp* presult, int flag = 0)
6904     {
6905         //printf("FuncExp::matchType('%s'), to=%s\n", type ? type->toChars() : "null", to->toChars());
6906         if (presult)
6907             *presult = null;
6908 
6909         TypeFunction tof = null;
6910         if (to.ty == Tdelegate)
6911         {
6912             if (tok == TOKfunction)
6913             {
6914                 if (!flag)
6915                     error("cannot match function literal to delegate type '%s'", to.toChars());
6916                 return MATCHnomatch;
6917             }
6918             tof = cast(TypeFunction)to.nextOf();
6919         }
6920         else if (to.ty == Tpointer && to.nextOf().ty == Tfunction)
6921         {
6922             if (tok == TOKdelegate)
6923             {
6924                 if (!flag)
6925                     error("cannot match delegate literal to function pointer type '%s'", to.toChars());
6926                 return MATCHnomatch;
6927             }
6928             tof = cast(TypeFunction)to.nextOf();
6929         }
6930 
6931         if (td)
6932         {
6933             if (!tof)
6934             {
6935             L1:
6936                 if (!flag)
6937                     error("cannot infer parameter types from %s", to.toChars());
6938                 return MATCHnomatch;
6939             }
6940 
6941             // Parameter types inference from 'tof'
6942             assert(td._scope);
6943             TypeFunction tf = cast(TypeFunction)fd.type;
6944             //printf("\ttof = %s\n", tof->toChars());
6945             //printf("\ttf  = %s\n", tf->toChars());
6946             size_t dim = Parameter.dim(tf.parameters);
6947 
6948             if (Parameter.dim(tof.parameters) != dim || tof.varargs != tf.varargs)
6949                 goto L1;
6950 
6951             auto tiargs = new Objects();
6952             tiargs.reserve(td.parameters.dim);
6953 
6954             for (size_t i = 0; i < td.parameters.dim; i++)
6955             {
6956                 TemplateParameter tp = (*td.parameters)[i];
6957                 size_t u = 0;
6958                 for (; u < dim; u++)
6959                 {
6960                     Parameter p = Parameter.getNth(tf.parameters, u);
6961                     if (p.type.ty == Tident && (cast(TypeIdentifier)p.type).ident == tp.ident)
6962                     {
6963                         break;
6964                     }
6965                 }
6966                 assert(u < dim);
6967                 Parameter pto = Parameter.getNth(tof.parameters, u);
6968                 Type t = pto.type;
6969                 if (t.ty == Terror)
6970                     goto L1;
6971                 tiargs.push(t);
6972             }
6973 
6974             // Set target of return type inference
6975             if (!tf.next && tof.next)
6976                 fd.treq = to;
6977 
6978             auto ti = new TemplateInstance(loc, td, tiargs);
6979             Expression ex = (new ScopeExp(loc, ti)).semantic(td._scope);
6980 
6981             // Reset inference target for the later re-semantic
6982             fd.treq = null;
6983 
6984             if (ex.op == TOKerror)
6985                 return MATCHnomatch;
6986             if (ex.op != TOKfunction)
6987                 goto L1;
6988             return (cast(FuncExp)ex).matchType(to, sc, presult, flag);
6989         }
6990 
6991         if (!tof || !tof.next)
6992             return MATCHnomatch;
6993 
6994         assert(type && type != Type.tvoid);
6995         TypeFunction tfx = cast(TypeFunction)fd.type;
6996         bool convertMatch = (type.ty != to.ty);
6997 
6998         if (fd.inferRetType && tfx.next.implicitConvTo(tof.next) == MATCHconvert)
6999         {
7000             /* If return type is inferred and covariant return,
7001              * tweak return statements to required return type.
7002              *
7003              * interface I {}
7004              * class C : Object, I{}
7005              *
7006              * I delegate() dg = delegate() { return new class C(); }
7007              */
7008             convertMatch = true;
7009 
7010             auto tfy = new TypeFunction(tfx.parameters, tof.next, tfx.varargs, tfx.linkage, STCundefined);
7011             tfy.mod = tfx.mod;
7012             tfy.isnothrow = tfx.isnothrow;
7013             tfy.isnogc = tfx.isnogc;
7014             tfy.purity = tfx.purity;
7015             tfy.isproperty = tfx.isproperty;
7016             tfy.isref = tfx.isref;
7017             tfy.iswild = tfx.iswild;
7018             tfy.deco = tfy.merge().deco;
7019 
7020             tfx = tfy;
7021         }
7022         Type tx;
7023         if (tok == TOKdelegate || tok == TOKreserved && (type.ty == Tdelegate || type.ty == Tpointer && to.ty == Tdelegate))
7024         {
7025             // Allow conversion from implicit function pointer to delegate
7026             tx = new TypeDelegate(tfx);
7027             tx.deco = tx.merge().deco;
7028         }
7029         else
7030         {
7031             assert(tok == TOKfunction || tok == TOKreserved && type.ty == Tpointer);
7032             tx = tfx.pointerTo();
7033         }
7034         //printf("\ttx = %s, to = %s\n", tx->toChars(), to->toChars());
7035 
7036         MATCH m = tx.implicitConvTo(to);
7037         if (m > MATCHnomatch)
7038         {
7039             // MATCHexact:      exact type match
7040             // MATCHconst:      covairiant type match (eg. attributes difference)
7041             // MATCHconvert:    context conversion
7042             m = convertMatch ? MATCHconvert : tx.equals(to) ? MATCHexact : MATCHconst;
7043 
7044             if (presult)
7045             {
7046                 (*presult) = cast(FuncExp)copy();
7047                 (*presult).type = to;
7048 
7049                 // Bugzilla 12508: Tweak function body for covariant returns.
7050                 (*presult).fd.modifyReturns(sc, tof.next);
7051             }
7052         }
7053         else if (!flag)
7054         {
7055             error("cannot implicitly convert expression (%s) of type %s to %s", toChars(), tx.toChars(), to.toChars());
7056         }
7057         return m;
7058     }
7059 
7060     override const(char)* toChars()
7061     {
7062         return fd.toChars();
7063     }
7064 
7065     override bool checkType()
7066     {
7067         if (td)
7068         {
7069             error("template lambda has no type");
7070             return true;
7071         }
7072         return false;
7073     }
7074 
7075     override bool checkValue()
7076     {
7077         if (td)
7078         {
7079             error("template lambda has no value");
7080             return true;
7081         }
7082         return false;
7083     }
7084 
7085     override void accept(Visitor v)
7086     {
7087         v.visit(this);
7088     }
7089 }
7090 
7091 /***********************************************************
7092  * Declaration of a symbol
7093  *
7094  * D grammar allows declarations only as statements. However in AST representation
7095  * it can be part of any expression. This is used, for example, during internal
7096  * syntax re-writes to inject hidden symbols.
7097  */
7098 extern (C++) final class DeclarationExp : Expression
7099 {
7100     Dsymbol declaration;
7101 
7102     extern (D) this(Loc loc, Dsymbol declaration)
7103     {
7104         super(loc, TOKdeclaration, __traits(classInstanceSize, DeclarationExp));
7105         this.declaration = declaration;
7106     }
7107 
7108     override Expression syntaxCopy()
7109     {
7110         return new DeclarationExp(loc, declaration.syntaxCopy(null));
7111     }
7112 
7113     override Expression semantic(Scope* sc)
7114     {
7115         if (type)
7116             return this;
7117         static if (LOGSEMANTIC)
7118         {
7119             printf("DeclarationExp::semantic() %s\n", toChars());
7120         }
7121 
7122         uint olderrors = global.errors;
7123 
7124         /* This is here to support extern(linkage) declaration,
7125          * where the extern(linkage) winds up being an AttribDeclaration
7126          * wrapper.
7127          */
7128         Dsymbol s = declaration;
7129 
7130         while (1)
7131         {
7132             AttribDeclaration ad = s.isAttribDeclaration();
7133             if (ad)
7134             {
7135                 if (ad.decl && ad.decl.dim == 1)
7136                 {
7137                     s = (*ad.decl)[0];
7138                     continue;
7139                 }
7140             }
7141             break;
7142         }
7143 
7144         VarDeclaration v = s.isVarDeclaration();
7145         if (v)
7146         {
7147             // Do semantic() on initializer first, so:
7148             //      int a = a;
7149             // will be illegal.
7150             declaration.semantic(sc);
7151             s.parent = sc.parent;
7152         }
7153 
7154         //printf("inserting '%s' %p into sc = %p\n", s->toChars(), s, sc);
7155         // Insert into both local scope and function scope.
7156         // Must be unique in both.
7157         if (s.ident)
7158         {
7159             if (!sc.insert(s))
7160             {
7161                 error("declaration %s is already defined", s.toPrettyChars());
7162                 return new ErrorExp();
7163             }
7164             else if (sc.func)
7165             {
7166                 // Bugzilla 11720 - include Dataseg variables
7167                 if ((s.isFuncDeclaration() ||
7168                      s.isAggregateDeclaration() ||
7169                      s.isEnumDeclaration() ||
7170                      v && v.isDataseg()) && !sc.func.localsymtab.insert(s))
7171                 {
7172                     error("declaration %s is already defined in another scope in %s", s.toPrettyChars(), sc.func.toChars());
7173                     return new ErrorExp();
7174                 }
7175                 else
7176                 {
7177                     // Disallow shadowing
7178                     for (Scope* scx = sc.enclosing; scx && scx.func == sc.func; scx = scx.enclosing)
7179                     {
7180                         Dsymbol s2;
7181                         if (scx.scopesym && scx.scopesym.symtab && (s2 = scx.scopesym.symtab.lookup(s.ident)) !is null && s != s2)
7182                         {
7183                             error("%s %s is shadowing %s %s", s.kind(), s.ident.toChars(), s2.kind(), s2.toPrettyChars());
7184                             return new ErrorExp();
7185                         }
7186                     }
7187                 }
7188             }
7189         }
7190         if (!s.isVarDeclaration())
7191         {
7192             Scope* sc2 = sc;
7193             if (sc2.stc & (STCpure | STCnothrow | STCnogc))
7194                 sc2 = sc.push();
7195             sc2.stc &= ~(STCpure | STCnothrow | STCnogc);
7196             declaration.semantic(sc2);
7197             if (sc2 != sc)
7198                 sc2.pop();
7199             s.parent = sc.parent;
7200         }
7201         if (global.errors == olderrors)
7202         {
7203             declaration.semantic2(sc);
7204             if (global.errors == olderrors)
7205             {
7206                 declaration.semantic3(sc);
7207             }
7208         }
7209         // todo: error in declaration should be propagated.
7210 
7211         type = Type.tvoid;
7212         return this;
7213     }
7214 
7215     override void accept(Visitor v)
7216     {
7217         v.visit(this);
7218     }
7219 }
7220 
7221 /***********************************************************
7222  * typeid(int)
7223  */
7224 extern (C++) final class TypeidExp : Expression
7225 {
7226     RootObject obj;
7227 
7228     extern (D) this(Loc loc, RootObject o)
7229     {
7230         super(loc, TOKtypeid, __traits(classInstanceSize, TypeidExp));
7231         this.obj = o;
7232     }
7233 
7234     override Expression syntaxCopy()
7235     {
7236         return new TypeidExp(loc, objectSyntaxCopy(obj));
7237     }
7238 
7239     override Expression semantic(Scope* sc)
7240     {
7241         static if (LOGSEMANTIC)
7242         {
7243             printf("TypeidExp::semantic() %s\n", toChars());
7244         }
7245         Type ta = isType(obj);
7246         Expression ea = isExpression(obj);
7247         Dsymbol sa = isDsymbol(obj);
7248         //printf("ta %p ea %p sa %p\n", ta, ea, sa);
7249 
7250         if (ta)
7251         {
7252             ta.resolve(loc, sc, &ea, &ta, &sa, true);
7253         }
7254 
7255         if (ea)
7256         {
7257             if (auto sym = getDsymbol(ea))
7258                 ea = DsymbolExp.resolve(loc, sc, sym, false);
7259             else
7260                 ea = ea.semantic(sc);
7261             ea = resolveProperties(sc, ea);
7262             ta = ea.type;
7263             if (ea.op == TOKtype)
7264                 ea = null;
7265         }
7266 
7267         if (!ta)
7268         {
7269             //printf("ta %p ea %p sa %p\n", ta, ea, sa);
7270             error("no type for typeid(%s)", ea ? ea.toChars() : (sa ? sa.toChars() : ""));
7271             return new ErrorExp();
7272         }
7273 
7274         if (global.params.vcomplex)
7275             ta.checkComplexTransition(loc);
7276 
7277         Expression e;
7278         if (ea && ta.toBasetype().ty == Tclass)
7279         {
7280             /* Get the dynamic type, which is .classinfo
7281              */
7282             ea = ea.semantic(sc);
7283             e = new TypeidExp(ea.loc, ea);
7284             e.type = Type.typeinfoclass.type;
7285         }
7286         else if (ta.ty == Terror)
7287         {
7288             e = new ErrorExp();
7289         }
7290         else
7291         {
7292             // Handle this in the glue layer
7293             e = new TypeidExp(loc, ta);
7294             e.type = getTypeInfoType(ta, sc);
7295 
7296             semanticTypeInfo(sc, ta);
7297 
7298             if (ea)
7299             {
7300                 e = new CommaExp(loc, ea, e); // execute ea
7301                 e = e.semantic(sc);
7302             }
7303         }
7304         return e;
7305     }
7306 
7307     override void accept(Visitor v)
7308     {
7309         v.visit(this);
7310     }
7311 }
7312 
7313 /***********************************************************
7314  * __traits(identifier, args...)
7315  */
7316 extern (C++) final class TraitsExp : Expression
7317 {
7318     Identifier ident;
7319     Objects* args;
7320 
7321     extern (D) this(Loc loc, Identifier ident, Objects* args)
7322     {
7323         super(loc, TOKtraits, __traits(classInstanceSize, TraitsExp));
7324         this.ident = ident;
7325         this.args = args;
7326     }
7327 
7328     override Expression syntaxCopy()
7329     {
7330         return new TraitsExp(loc, ident, TemplateInstance.arraySyntaxCopy(args));
7331     }
7332 
7333     override Expression semantic(Scope* sc)
7334     {
7335         return semanticTraits(this, sc);
7336     }
7337 
7338     override void accept(Visitor v)
7339     {
7340         v.visit(this);
7341     }
7342 }
7343 
7344 /***********************************************************
7345  */
7346 extern (C++) final class HaltExp : Expression
7347 {
7348     extern (D) this(Loc loc)
7349     {
7350         super(loc, TOKhalt, __traits(classInstanceSize, HaltExp));
7351     }
7352 
7353     override Expression semantic(Scope* sc)
7354     {
7355         static if (LOGSEMANTIC)
7356         {
7357             printf("HaltExp::semantic()\n");
7358         }
7359         type = Type.tvoid;
7360         return this;
7361     }
7362 
7363     override void accept(Visitor v)
7364     {
7365         v.visit(this);
7366     }
7367 }
7368 
7369 /***********************************************************
7370  * is(targ id tok tspec)
7371  * is(targ id == tok2)
7372  */
7373 extern (C++) final class IsExp : Expression
7374 {
7375     Type targ;
7376     Identifier id;      // can be null
7377     TOK tok;            // ':' or '=='
7378     Type tspec;         // can be null
7379     TOK tok2;           // 'struct', 'union', etc.
7380     TemplateParameters* parameters;
7381 
7382     extern (D) this(Loc loc, Type targ, Identifier id, TOK tok, Type tspec, TOK tok2, TemplateParameters* parameters)
7383     {
7384         super(loc, TOKis, __traits(classInstanceSize, IsExp));
7385         this.targ = targ;
7386         this.id = id;
7387         this.tok = tok;
7388         this.tspec = tspec;
7389         this.tok2 = tok2;
7390         this.parameters = parameters;
7391     }
7392 
7393     override Expression syntaxCopy()
7394     {
7395         // This section is identical to that in TemplateDeclaration::syntaxCopy()
7396         TemplateParameters* p = null;
7397         if (parameters)
7398         {
7399             p = new TemplateParameters();
7400             p.setDim(parameters.dim);
7401             for (size_t i = 0; i < p.dim; i++)
7402                 (*p)[i] = (*parameters)[i].syntaxCopy();
7403         }
7404         return new IsExp(loc, targ.syntaxCopy(), id, tok, tspec ? tspec.syntaxCopy() : null, tok2, p);
7405     }
7406 
7407     override Expression semantic(Scope* sc)
7408     {
7409         /* is(targ id tok tspec)
7410          * is(targ id :  tok2)
7411          * is(targ id == tok2)
7412          */
7413 
7414         //printf("IsExp::semantic(%s)\n", toChars());
7415         if (id && !(sc.flags & SCOPEcondition))
7416         {
7417             error("can only declare type aliases within static if conditionals or static asserts");
7418             return new ErrorExp();
7419         }
7420 
7421         Type tded = null;
7422         Scope* sc2 = sc.copy(); // keep sc->flags
7423         sc2.tinst = null;
7424         sc2.minst = null;
7425         sc2.flags |= SCOPEfullinst;
7426         Type t = targ.trySemantic(loc, sc2);
7427         sc2.pop();
7428         if (!t)
7429             goto Lno;
7430         // errors, so condition is false
7431         targ = t;
7432         if (tok2 != TOKreserved)
7433         {
7434             switch (tok2)
7435             {
7436             case TOKstruct:
7437                 if (targ.ty != Tstruct)
7438                     goto Lno;
7439                 if ((cast(TypeStruct)targ).sym.isUnionDeclaration())
7440                     goto Lno;
7441                 tded = targ;
7442                 break;
7443 
7444             case TOKunion:
7445                 if (targ.ty != Tstruct)
7446                     goto Lno;
7447                 if (!(cast(TypeStruct)targ).sym.isUnionDeclaration())
7448                     goto Lno;
7449                 tded = targ;
7450                 break;
7451 
7452             case TOKclass:
7453                 if (targ.ty != Tclass)
7454                     goto Lno;
7455                 if ((cast(TypeClass)targ).sym.isInterfaceDeclaration())
7456                     goto Lno;
7457                 tded = targ;
7458                 break;
7459 
7460             case TOKinterface:
7461                 if (targ.ty != Tclass)
7462                     goto Lno;
7463                 if (!(cast(TypeClass)targ).sym.isInterfaceDeclaration())
7464                     goto Lno;
7465                 tded = targ;
7466                 break;
7467 
7468             case TOKconst:
7469                 if (!targ.isConst())
7470                     goto Lno;
7471                 tded = targ;
7472                 break;
7473 
7474             case TOKimmutable:
7475                 if (!targ.isImmutable())
7476                     goto Lno;
7477                 tded = targ;
7478                 break;
7479 
7480             case TOKshared:
7481                 if (!targ.isShared())
7482                     goto Lno;
7483                 tded = targ;
7484                 break;
7485 
7486             case TOKwild:
7487                 if (!targ.isWild())
7488                     goto Lno;
7489                 tded = targ;
7490                 break;
7491 
7492             case TOKsuper:
7493                 // If class or interface, get the base class and interfaces
7494                 if (targ.ty != Tclass)
7495                     goto Lno;
7496                 else
7497                 {
7498                     ClassDeclaration cd = (cast(TypeClass)targ).sym;
7499                     auto args = new Parameters();
7500                     args.reserve(cd.baseclasses.dim);
7501                     if (cd._scope && !cd.symtab)
7502                         cd.semantic(cd._scope);
7503                     for (size_t i = 0; i < cd.baseclasses.dim; i++)
7504                     {
7505                         BaseClass* b = (*cd.baseclasses)[i];
7506                         args.push(new Parameter(STCin, b.type, null, null));
7507                     }
7508                     tded = new TypeTuple(args);
7509                 }
7510                 break;
7511 
7512             case TOKenum:
7513                 if (targ.ty != Tenum)
7514                     goto Lno;
7515                 if (id)
7516                     tded = (cast(TypeEnum)targ).sym.getMemtype(loc);
7517                 else
7518                     tded = targ;
7519                 if (tded.ty == Terror)
7520                     return new ErrorExp();
7521                 break;
7522 
7523             case TOKdelegate:
7524                 if (targ.ty != Tdelegate)
7525                     goto Lno;
7526                 tded = (cast(TypeDelegate)targ).next; // the underlying function type
7527                 break;
7528 
7529             case TOKfunction:
7530             case TOKparameters:
7531                 {
7532                     if (targ.ty != Tfunction)
7533                         goto Lno;
7534                     tded = targ;
7535 
7536                     /* Generate tuple from function parameter types.
7537                      */
7538                     assert(tded.ty == Tfunction);
7539                     Parameters* params = (cast(TypeFunction)tded).parameters;
7540                     size_t dim = Parameter.dim(params);
7541                     auto args = new Parameters();
7542                     args.reserve(dim);
7543                     for (size_t i = 0; i < dim; i++)
7544                     {
7545                         Parameter arg = Parameter.getNth(params, i);
7546                         assert(arg && arg.type);
7547                         /* If one of the default arguments was an error,
7548                            don't return an invalid tuple
7549                          */
7550                         if (tok2 == TOKparameters && arg.defaultArg && arg.defaultArg.op == TOKerror)
7551                             return new ErrorExp();
7552                         args.push(new Parameter(arg.storageClass, arg.type, (tok2 == TOKparameters) ? arg.ident : null, (tok2 == TOKparameters) ? arg.defaultArg : null));
7553                     }
7554                     tded = new TypeTuple(args);
7555                     break;
7556                 }
7557             case TOKreturn:
7558                 /* Get the 'return type' for the function,
7559                  * delegate, or pointer to function.
7560                  */
7561                 if (targ.ty == Tfunction)
7562                     tded = (cast(TypeFunction)targ).next;
7563                 else if (targ.ty == Tdelegate)
7564                 {
7565                     tded = (cast(TypeDelegate)targ).next;
7566                     tded = (cast(TypeFunction)tded).next;
7567                 }
7568                 else if (targ.ty == Tpointer && (cast(TypePointer)targ).next.ty == Tfunction)
7569                 {
7570                     tded = (cast(TypePointer)targ).next;
7571                     tded = (cast(TypeFunction)tded).next;
7572                 }
7573                 else
7574                     goto Lno;
7575                 break;
7576 
7577             case TOKargTypes:
7578                 /* Generate a type tuple of the equivalent types used to determine if a
7579                  * function argument of this type can be passed in registers.
7580                  * The results of this are highly platform dependent, and intended
7581                  * primarly for use in implementing va_arg().
7582                  */
7583                 tded = toArgTypes(targ);
7584                 if (!tded)
7585                     goto Lno;
7586                 // not valid for a parameter
7587                 break;
7588 
7589             default:
7590                 assert(0);
7591             }
7592             goto Lyes;
7593         }
7594         else if (tspec && !id && !(parameters && parameters.dim))
7595         {
7596             /* Evaluate to true if targ matches tspec
7597              * is(targ == tspec)
7598              * is(targ : tspec)
7599              */
7600             tspec = tspec.semantic(loc, sc);
7601             //printf("targ  = %s, %s\n", targ->toChars(), targ->deco);
7602             //printf("tspec = %s, %s\n", tspec->toChars(), tspec->deco);
7603 
7604             if (tok == TOKcolon)
7605             {
7606                 if (targ.implicitConvTo(tspec))
7607                     goto Lyes;
7608                 else
7609                     goto Lno;
7610             }
7611             else /* == */
7612             {
7613                 if (targ.equals(tspec))
7614                     goto Lyes;
7615                 else
7616                     goto Lno;
7617             }
7618         }
7619         else if (tspec)
7620         {
7621             /* Evaluate to true if targ matches tspec.
7622              * If true, declare id as an alias for the specialized type.
7623              * is(targ == tspec, tpl)
7624              * is(targ : tspec, tpl)
7625              * is(targ id == tspec)
7626              * is(targ id : tspec)
7627              * is(targ id == tspec, tpl)
7628              * is(targ id : tspec, tpl)
7629              */
7630             Identifier tid = id ? id : Identifier.generateId("__isexp_id");
7631             parameters.insert(0, new TemplateTypeParameter(loc, tid, null, null));
7632 
7633             Objects dedtypes;
7634             dedtypes.setDim(parameters.dim);
7635             dedtypes.zero();
7636 
7637             MATCH m = deduceType(targ, sc, tspec, parameters, &dedtypes);
7638             //printf("targ: %s\n", targ->toChars());
7639             //printf("tspec: %s\n", tspec->toChars());
7640             if (m <= MATCHnomatch || (m != MATCHexact && tok == TOKequal))
7641             {
7642                 goto Lno;
7643             }
7644             else
7645             {
7646                 tded = cast(Type)dedtypes[0];
7647                 if (!tded)
7648                     tded = targ;
7649                 Objects tiargs;
7650                 tiargs.setDim(1);
7651                 tiargs[0] = targ;
7652 
7653                 /* Declare trailing parameters
7654                  */
7655                 for (size_t i = 1; i < parameters.dim; i++)
7656                 {
7657                     TemplateParameter tp = (*parameters)[i];
7658                     Declaration s = null;
7659 
7660                     m = tp.matchArg(loc, sc, &tiargs, i, parameters, &dedtypes, &s);
7661                     if (m <= MATCHnomatch)
7662                         goto Lno;
7663                     s.semantic(sc);
7664                     if (sc.sds)
7665                         s.addMember(sc, sc.sds);
7666                     else if (!sc.insert(s))
7667                         error("declaration %s is already defined", s.toChars());
7668 
7669                     unSpeculative(sc, s);
7670                 }
7671                 goto Lyes;
7672             }
7673         }
7674         else if (id)
7675         {
7676             /* Declare id as an alias for type targ. Evaluate to true
7677              * is(targ id)
7678              */
7679             tded = targ;
7680             goto Lyes;
7681         }
7682 
7683     Lyes:
7684         if (id)
7685         {
7686             Dsymbol s;
7687             Tuple tup = isTuple(tded);
7688             if (tup)
7689                 s = new TupleDeclaration(loc, id, &tup.objects);
7690             else
7691                 s = new AliasDeclaration(loc, id, tded);
7692             s.semantic(sc);
7693 
7694             /* The reason for the !tup is unclear. It fails Phobos unittests if it is not there.
7695              * More investigation is needed.
7696              */
7697             if (!tup && !sc.insert(s))
7698                 error("declaration %s is already defined", s.toChars());
7699             if (sc.sds)
7700                 s.addMember(sc, sc.sds);
7701 
7702             unSpeculative(sc, s);
7703         }
7704         //printf("Lyes\n");
7705         return new IntegerExp(loc, 1, Type.tbool);
7706 
7707     Lno:
7708         //printf("Lno\n");
7709         return new IntegerExp(loc, 0, Type.tbool);
7710     }
7711 
7712     override void accept(Visitor v)
7713     {
7714         v.visit(this);
7715     }
7716 }
7717 
7718 /***********************************************************
7719  */
7720 extern (C++) class UnaExp : Expression
7721 {
7722     Expression e1;
7723     Type att1;      // Save alias this type to detect recursion
7724 
7725     final extern (D) this(Loc loc, TOK op, int size, Expression e1)
7726     {
7727         super(loc, op, size);
7728         this.e1 = e1;
7729     }
7730 
7731     override Expression syntaxCopy()
7732     {
7733         UnaExp e = cast(UnaExp)copy();
7734         e.type = null;
7735         e.e1 = e.e1.syntaxCopy();
7736         return e;
7737     }
7738 
7739     override abstract Expression semantic(Scope* sc);
7740 
7741     /**************************
7742      * Helper function for easy error propagation.
7743      * If error occurs, returns ErrorExp. Otherwise returns NULL.
7744      */
7745     final Expression unaSemantic(Scope* sc)
7746     {
7747         static if (LOGSEMANTIC)
7748         {
7749             printf("UnaExp::semantic('%s')\n", toChars());
7750         }
7751         Expression e1x = e1.semantic(sc);
7752         if (e1x.op == TOKerror)
7753             return e1x;
7754         e1 = e1x;
7755         return null;
7756     }
7757 
7758     /*********************
7759      * Mark the operand as will never be dereferenced,
7760      * which is useful info for @safe checks.
7761      * Do before semantic() on operands rewrites them.
7762      */
7763     final void setNoderefOperand()
7764     {
7765         if (e1.op == TOKdotid)
7766             (cast(DotIdExp)e1).noderef = true;
7767 
7768     }
7769 
7770     override final Expression resolveLoc(Loc loc, Scope* sc)
7771     {
7772         e1 = e1.resolveLoc(loc, sc);
7773         return this;
7774     }
7775 
7776     override void accept(Visitor v)
7777     {
7778         v.visit(this);
7779     }
7780 
7781     override void printAST(int indent)
7782     {
7783         Expression.printAST(indent);
7784         e1.printAST(indent + 2);
7785     }
7786 }
7787 
7788 extern (C++) alias fp_t = UnionExp function(Loc loc, Type, Expression, Expression);
7789 extern (C++) alias fp2_t = int function(Loc loc, TOK, Expression, Expression);
7790 
7791 /***********************************************************
7792  */
7793 extern (C++) abstract class BinExp : Expression
7794 {
7795     Expression e1;
7796     Expression e2;
7797     Type att1;      // Save alias this type to detect recursion
7798     Type att2;      // Save alias this type to detect recursion
7799 
7800     final extern (D) this(Loc loc, TOK op, int size, Expression e1, Expression e2)
7801     {
7802         super(loc, op, size);
7803         this.e1 = e1;
7804         this.e2 = e2;
7805     }
7806 
7807     override Expression syntaxCopy()
7808     {
7809         BinExp e = cast(BinExp)copy();
7810         e.type = null;
7811         e.e1 = e.e1.syntaxCopy();
7812         e.e2 = e.e2.syntaxCopy();
7813         return e;
7814     }
7815 
7816     override abstract Expression semantic(Scope* sc);
7817 
7818     /**************************
7819      * Helper function for easy error propagation.
7820      * If error occurs, returns ErrorExp. Otherwise returns NULL.
7821      */
7822     final Expression binSemantic(Scope* sc)
7823     {
7824         static if (LOGSEMANTIC)
7825         {
7826             printf("BinExp::semantic('%s')\n", toChars());
7827         }
7828         Expression e1x = e1.semantic(sc);
7829         Expression e2x = e2.semantic(sc);
7830         if (e1x.op == TOKerror)
7831             return e1x;
7832         if (e2x.op == TOKerror)
7833             return e2x;
7834         e1 = e1x;
7835         e2 = e2x;
7836         return null;
7837     }
7838 
7839     final Expression binSemanticProp(Scope* sc)
7840     {
7841         if (Expression ex = binSemantic(sc))
7842             return ex;
7843         Expression e1x = resolveProperties(sc, e1);
7844         Expression e2x = resolveProperties(sc, e2);
7845         if (e1x.op == TOKerror)
7846             return e1x;
7847         if (e2x.op == TOKerror)
7848             return e2x;
7849         e1 = e1x;
7850         e2 = e2x;
7851         return null;
7852     }
7853 
7854     final Expression incompatibleTypes()
7855     {
7856         if (e1.type.toBasetype() != Type.terror && e2.type.toBasetype() != Type.terror)
7857         {
7858             // CondExp uses 'a ? b : c' but we're comparing 'b : c'
7859             TOK thisOp = (op == TOKquestion) ? TOKcolon : op;
7860             if (e1.op == TOKtype || e2.op == TOKtype)
7861             {
7862                 error("incompatible types for ((%s) %s (%s)): cannot use '%s' with types", e1.toChars(), Token.toChars(thisOp), e2.toChars(), Token.toChars(op));
7863             }
7864             else
7865             {
7866                 error("incompatible types for ((%s) %s (%s)): '%s' and '%s'", e1.toChars(), Token.toChars(thisOp), e2.toChars(), e1.type.toChars(), e2.type.toChars());
7867             }
7868             return new ErrorExp();
7869         }
7870         return this;
7871     }
7872 
7873     final Expression checkOpAssignTypes(Scope* sc)
7874     {
7875         // At that point t1 and t2 are the merged types. type is the original type of the lhs.
7876         Type t1 = e1.type;
7877         Type t2 = e2.type;
7878 
7879         // T opAssign floating yields a floating. Prevent truncating conversions (float to int).
7880         // See issue 3841.
7881         // Should we also prevent double to float (type->isfloating() && type->size() < t2 ->size()) ?
7882         if (op == TOKaddass || op == TOKminass ||
7883             op == TOKmulass || op == TOKdivass || op == TOKmodass ||
7884             op == TOKpowass)
7885         {
7886             if ((type.isintegral() && t2.isfloating()))
7887             {
7888                 warning("%s %s %s is performing truncating conversion", type.toChars(), Token.toChars(op), t2.toChars());
7889             }
7890         }
7891 
7892         // generate an error if this is a nonsensical *=,/=, or %=, eg real *= imaginary
7893         if (op == TOKmulass || op == TOKdivass || op == TOKmodass)
7894         {
7895             // Any multiplication by an imaginary or complex number yields a complex result.
7896             // r *= c, i*=c, r*=i, i*=i are all forbidden operations.
7897             const(char)* opstr = Token.toChars(op);
7898             if (t1.isreal() && t2.iscomplex())
7899             {
7900                 error("%s %s %s is undefined. Did you mean %s %s %s.re ?", t1.toChars(), opstr, t2.toChars(), t1.toChars(), opstr, t2.toChars());
7901                 return new ErrorExp();
7902             }
7903             else if (t1.isimaginary() && t2.iscomplex())
7904             {
7905                 error("%s %s %s is undefined. Did you mean %s %s %s.im ?", t1.toChars(), opstr, t2.toChars(), t1.toChars(), opstr, t2.toChars());
7906                 return new ErrorExp();
7907             }
7908             else if ((t1.isreal() || t1.isimaginary()) && t2.isimaginary())
7909             {
7910                 error("%s %s %s is an undefined operation", t1.toChars(), opstr, t2.toChars());
7911                 return new ErrorExp();
7912             }
7913         }
7914 
7915         // generate an error if this is a nonsensical += or -=, eg real += imaginary
7916         if (op == TOKaddass || op == TOKminass)
7917         {
7918             // Addition or subtraction of a real and an imaginary is a complex result.
7919             // Thus, r+=i, r+=c, i+=r, i+=c are all forbidden operations.
7920             if ((t1.isreal() && (t2.isimaginary() || t2.iscomplex())) || (t1.isimaginary() && (t2.isreal() || t2.iscomplex())))
7921             {
7922                 error("%s %s %s is undefined (result is complex)", t1.toChars(), Token.toChars(op), t2.toChars());
7923                 return new ErrorExp();
7924             }
7925             if (type.isreal() || type.isimaginary())
7926             {
7927                 assert(global.errors || t2.isfloating());
7928                 e2 = e2.castTo(sc, t1);
7929             }
7930         }
7931         if (op == TOKmulass)
7932         {
7933             if (t2.isfloating())
7934             {
7935                 if (t1.isreal())
7936                 {
7937                     if (t2.isimaginary() || t2.iscomplex())
7938                     {
7939                         e2 = e2.castTo(sc, t1);
7940                     }
7941                 }
7942                 else if (t1.isimaginary())
7943                 {
7944                     if (t2.isimaginary() || t2.iscomplex())
7945                     {
7946                         switch (t1.ty)
7947                         {
7948                         case Timaginary32:
7949                             t2 = Type.tfloat32;
7950                             break;
7951 
7952                         case Timaginary64:
7953                             t2 = Type.tfloat64;
7954                             break;
7955 
7956                         case Timaginary80:
7957                             t2 = Type.tfloat80;
7958                             break;
7959 
7960                         default:
7961                             assert(0);
7962                         }
7963                         e2 = e2.castTo(sc, t2);
7964                     }
7965                 }
7966             }
7967         }
7968         else if (op == TOKdivass)
7969         {
7970             if (t2.isimaginary())
7971             {
7972                 if (t1.isreal())
7973                 {
7974                     // x/iv = i(-x/v)
7975                     // Therefore, the result is 0
7976                     e2 = new CommaExp(loc, e2, new RealExp(loc, CTFloat.zero, t1));
7977                     e2.type = t1;
7978                     Expression e = new AssignExp(loc, e1, e2);
7979                     e.type = t1;
7980                     return e;
7981                 }
7982                 else if (t1.isimaginary())
7983                 {
7984                     Type t3;
7985                     switch (t1.ty)
7986                     {
7987                     case Timaginary32:
7988                         t3 = Type.tfloat32;
7989                         break;
7990 
7991                     case Timaginary64:
7992                         t3 = Type.tfloat64;
7993                         break;
7994 
7995                     case Timaginary80:
7996                         t3 = Type.tfloat80;
7997                         break;
7998 
7999                     default:
8000                         assert(0);
8001                     }
8002                     e2 = e2.castTo(sc, t3);
8003                     Expression e = new AssignExp(loc, e1, e2);
8004                     e.type = t1;
8005                     return e;
8006                 }
8007             }
8008         }
8009         else if (op == TOKmodass)
8010         {
8011             if (t2.iscomplex())
8012             {
8013                 error("cannot perform modulo complex arithmetic");
8014                 return new ErrorExp();
8015             }
8016         }
8017         return this;
8018     }
8019 
8020     final bool checkIntegralBin()
8021     {
8022         bool r1 = e1.checkIntegral();
8023         bool r2 = e2.checkIntegral();
8024         return (r1 || r2);
8025     }
8026 
8027     final bool checkArithmeticBin()
8028     {
8029         bool r1 = e1.checkArithmetic();
8030         bool r2 = e2.checkArithmetic();
8031         return (r1 || r2);
8032     }
8033 
8034     /*********************
8035      * Mark the operands as will never be dereferenced,
8036      * which is useful info for @safe checks.
8037      * Do before semantic() on operands rewrites them.
8038      */
8039     final void setNoderefOperands()
8040     {
8041         if (e1.op == TOKdotid)
8042             (cast(DotIdExp)e1).noderef = true;
8043         if (e2.op == TOKdotid)
8044             (cast(DotIdExp)e2).noderef = true;
8045 
8046     }
8047 
8048     final Expression reorderSettingAAElem(Scope* sc)
8049     {
8050         BinExp be = this;
8051 
8052         if (be.e1.op != TOKindex)
8053             return be;
8054         auto ie = cast(IndexExp)be.e1;
8055         if (ie.e1.type.toBasetype().ty != Taarray)
8056             return be;
8057 
8058         /* Fix evaluation order of setting AA element. (Bugzilla 3825)
8059          * Rewrite:
8060          *     aa[k1][k2][k3] op= val;
8061          * as:
8062          *     auto ref __aatmp = aa;
8063          *     auto ref __aakey3 = k1, __aakey2 = k2, __aakey1 = k3;
8064          *     auto ref __aaval = val;
8065          *     __aatmp[__aakey3][__aakey2][__aakey1] op= __aaval;  // assignment
8066          */
8067 
8068         Expression e0;
8069         while (1)
8070         {
8071             Expression de;
8072             ie.e2 = extractSideEffect(sc, "__aakey", de, ie.e2);
8073             e0 = Expression.combine(de, e0);
8074 
8075             Expression ie1 = ie.e1;
8076             if (ie1.op != TOKindex ||
8077                 (cast(IndexExp)ie1).e1.type.toBasetype().ty != Taarray)
8078             {
8079                 break;
8080             }
8081             ie = cast(IndexExp)ie1;
8082         }
8083         assert(ie.e1.type.toBasetype().ty == Taarray);
8084 
8085         Expression de;
8086         ie.e1 = extractSideEffect(sc, "__aatmp", de, ie.e1);
8087         e0 = Expression.combine(de, e0);
8088 
8089         be.e2 = extractSideEffect(sc, "__aaval", e0, be.e2, true);
8090 
8091         //printf("-e0 = %s, be = %s\n", e0.toChars(), be.toChars());
8092         return Expression.combine(e0, be);
8093     }
8094 
8095     override void accept(Visitor v)
8096     {
8097         v.visit(this);
8098     }
8099 
8100     override void printAST(int indent)
8101     {
8102         Expression.printAST(indent);
8103         e1.printAST(indent + 2);
8104         e2.printAST(indent + 2);
8105     }
8106 }
8107 
8108 /***********************************************************
8109  */
8110 extern (C++) class BinAssignExp : BinExp
8111 {
8112     final extern (D) this(Loc loc, TOK op, int size, Expression e1, Expression e2)
8113     {
8114         super(loc, op, size, e1, e2);
8115     }
8116 
8117     override Expression semantic(Scope* sc)
8118     {
8119         if (type)
8120             return this;
8121 
8122         Expression e = op_overload(sc);
8123         if (e)
8124             return e;
8125 
8126         if (e1.checkReadModifyWrite(op, e2))
8127             return new ErrorExp();
8128 
8129         if (e1.op == TOKarraylength)
8130         {
8131             // arr.length op= e2;
8132             e = ArrayLengthExp.rewriteOpAssign(this);
8133             e = e.semantic(sc);
8134             return e;
8135         }
8136         if (e1.op == TOKslice || e1.type.ty == Tarray || e1.type.ty == Tsarray)
8137         {
8138             // T[] op= ...
8139             if (e2.implicitConvTo(e1.type.nextOf()))
8140             {
8141                 // T[] op= T
8142                 e2 = e2.castTo(sc, e1.type.nextOf());
8143             }
8144             else if (Expression ex = typeCombine(this, sc))
8145                 return ex;
8146             type = e1.type;
8147             return arrayOp(this, sc);
8148         }
8149 
8150         e1 = e1.semantic(sc);
8151         e1 = e1.optimize(WANTvalue);
8152         e1 = e1.modifiableLvalue(sc, e1);
8153         type = e1.type;
8154         if (checkScalar())
8155             return new ErrorExp();
8156 
8157         int arith = (op == TOKaddass || op == TOKminass || op == TOKmulass || op == TOKdivass || op == TOKmodass || op == TOKpowass);
8158         int bitwise = (op == TOKandass || op == TOKorass || op == TOKxorass);
8159         int shift = (op == TOKshlass || op == TOKshrass || op == TOKushrass);
8160 
8161         if (bitwise && type.toBasetype().ty == Tbool)
8162             e2 = e2.implicitCastTo(sc, type);
8163         else if (checkNoBool())
8164             return new ErrorExp();
8165 
8166         if ((op == TOKaddass || op == TOKminass) && e1.type.toBasetype().ty == Tpointer && e2.type.toBasetype().isintegral())
8167             return scaleFactor(this, sc);
8168 
8169         if (Expression ex = typeCombine(this, sc))
8170             return ex;
8171 
8172         if (arith && checkArithmeticBin())
8173             return new ErrorExp();
8174         if ((bitwise || shift) && checkIntegralBin())
8175             return new ErrorExp();
8176         if (shift)
8177         {
8178             e2 = e2.castTo(sc, Type.tshiftcnt);
8179         }
8180 
8181         // vectors
8182         if (shift && (e1.type.toBasetype().ty == Tvector || e2.type.toBasetype().ty == Tvector))
8183             return incompatibleTypes();
8184 
8185         int isvector = type.toBasetype().ty == Tvector;
8186 
8187         if (op == TOKmulass && isvector && !e2.type.isfloating() && (cast(TypeVector)type.toBasetype()).elementType().size(loc) != 2)
8188             return incompatibleTypes(); // Only short[8] and ushort[8] work with multiply
8189 
8190         if (op == TOKdivass && isvector && !e1.type.isfloating())
8191             return incompatibleTypes();
8192 
8193         if (op == TOKmodass && isvector)
8194             return incompatibleTypes();
8195 
8196         if (e1.op == TOKerror || e2.op == TOKerror)
8197             return new ErrorExp();
8198 
8199         e = checkOpAssignTypes(sc);
8200         if (e.op == TOKerror)
8201             return e;
8202 
8203         assert(e.op == TOKassign || e == this);
8204         return (cast(BinExp)e).reorderSettingAAElem(sc);
8205     }
8206 
8207     override final bool isLvalue()
8208     {
8209         return true;
8210     }
8211 
8212     override final Expression toLvalue(Scope* sc, Expression ex)
8213     {
8214         // Lvalue-ness will be handled in glue layer.
8215         return this;
8216     }
8217 
8218     override final Expression modifiableLvalue(Scope* sc, Expression e)
8219     {
8220         // should check e1->checkModifiable() ?
8221         return toLvalue(sc, this);
8222     }
8223 
8224     override void accept(Visitor v)
8225     {
8226         v.visit(this);
8227     }
8228 }
8229 
8230 /***********************************************************
8231  */
8232 extern (C++) final class CompileExp : UnaExp
8233 {
8234     extern (D) this(Loc loc, Expression e)
8235     {
8236         super(loc, TOKmixin, __traits(classInstanceSize, CompileExp), e);
8237     }
8238 
8239     override Expression semantic(Scope* sc)
8240     {
8241         static if (LOGSEMANTIC)
8242         {
8243             printf("CompileExp::semantic('%s')\n", toChars());
8244         }
8245 
8246         auto se = semanticString(sc, e1, "argument to mixin");
8247         if (!se)
8248             return new ErrorExp();
8249         se = se.toUTF8(sc);
8250 
8251         uint errors = global.errors;
8252         scope Parser p = new Parser(loc, sc._module, se.toStringz(), false);
8253         p.nextToken();
8254         //printf("p.loc.linnum = %d\n", p.loc.linnum);
8255 
8256         Expression e = p.parseExpression();
8257         if (p.errors)
8258         {
8259             assert(global.errors != errors); // should have caught all these cases
8260             return new ErrorExp();
8261         }
8262         if (p.token.value != TOKeof)
8263         {
8264             error("incomplete mixin expression (%s)", se.toChars());
8265             return new ErrorExp();
8266         }
8267 
8268         return e.semantic(sc);
8269     }
8270 
8271     override void accept(Visitor v)
8272     {
8273         v.visit(this);
8274     }
8275 }
8276 
8277 /***********************************************************
8278  */
8279 extern (C++) final class ImportExp : UnaExp
8280 {
8281     extern (D) this(Loc loc, Expression e)
8282     {
8283         super(loc, TOKimport, __traits(classInstanceSize, ImportExp), e);
8284     }
8285 
8286     override Expression semantic(Scope* sc)
8287     {
8288         static if (LOGSEMANTIC)
8289         {
8290             printf("ImportExp::semantic('%s')\n", toChars());
8291         }
8292 
8293         auto se = semanticString(sc, e1, "file name argument");
8294         if (!se)
8295             return new ErrorExp();
8296         se = se.toUTF8(sc);
8297 
8298         auto namez = se.toStringz().ptr;
8299         if (!global.params.fileImppath)
8300         {
8301             error("need -Jpath switch to import text file %s", namez);
8302             return new ErrorExp();
8303         }
8304 
8305         /* Be wary of CWE-22: Improper Limitation of a Pathname to a Restricted Directory
8306          * ('Path Traversal') attacks.
8307          * http://cwe.mitre.org/data/definitions/22.html
8308          */
8309 
8310         auto name = FileName.safeSearchPath(global.filePath, namez);
8311         if (!name)
8312         {
8313             error("file %s cannot be found or not in a path specified with -J", se.toChars());
8314             return new ErrorExp();
8315         }
8316 
8317         if (global.params.verbose)
8318             fprintf(global.stdmsg, "file      %.*s\t(%s)\n", cast(int)se.len, se..string, name);
8319         if (global.params.moduleDeps !is null)
8320         {
8321             OutBuffer* ob = global.params.moduleDeps;
8322             Module imod = sc.instantiatingModule();
8323 
8324             if (!global.params.moduleDepsFile)
8325                 ob.writestring("depsFile ");
8326             ob.writestring(imod.toPrettyChars());
8327             ob.writestring(" (");
8328             escapePath(ob, imod.srcfile.toChars());
8329             ob.writestring(") : ");
8330             if (global.params.moduleDepsFile)
8331                 ob.writestring("string : ");
8332             ob.write(se..string, se.len);
8333             ob.writestring(" (");
8334             escapePath(ob, name);
8335             ob.writestring(")");
8336             ob.writenl();
8337         }
8338 
8339         {
8340             auto f = File(name);
8341             if (f.read())
8342             {
8343                 error("cannot read file %s", f.toChars());
8344                 return new ErrorExp();
8345             }
8346             else
8347             {
8348                 f._ref = 1;
8349                 se = new StringExp(loc, f.buffer, f.len);
8350             }
8351         }
8352         return se.semantic(sc);
8353     }
8354 
8355     override void accept(Visitor v)
8356     {
8357         v.visit(this);
8358     }
8359 }
8360 
8361 /***********************************************************
8362  */
8363 extern (C++) final class AssertExp : UnaExp
8364 {
8365     Expression msg;
8366 
8367     extern (D) this(Loc loc, Expression e, Expression msg = null)
8368     {
8369         super(loc, TOKassert, __traits(classInstanceSize, AssertExp), e);
8370         this.msg = msg;
8371     }
8372 
8373     override Expression syntaxCopy()
8374     {
8375         return new AssertExp(loc, e1.syntaxCopy(), msg ? msg.syntaxCopy() : null);
8376     }
8377 
8378     override Expression semantic(Scope* sc)
8379     {
8380         static if (LOGSEMANTIC)
8381         {
8382             printf("AssertExp::semantic('%s')\n", toChars());
8383         }
8384 
8385         if (Expression ex = unaSemantic(sc))
8386             return ex;
8387         e1 = resolveProperties(sc, e1);
8388         // BUG: see if we can do compile time elimination of the Assert
8389         e1 = e1.optimize(WANTvalue);
8390         e1 = e1.toBoolean(sc);
8391 
8392         if (msg)
8393         {
8394             msg = msg.semantic(sc);
8395             msg = resolveProperties(sc, msg);
8396             msg = msg.implicitCastTo(sc, Type.tchar.constOf().arrayOf());
8397             msg = msg.optimize(WANTvalue);
8398         }
8399 
8400         if (e1.op == TOKerror)
8401             return e1;
8402         if (msg && msg.op == TOKerror)
8403             return msg;
8404 
8405         auto f1 = checkNonAssignmentArrayOp(e1);
8406         auto f2 = msg && checkNonAssignmentArrayOp(msg);
8407         if (f1 || f2)
8408             return new ErrorExp();
8409 
8410         if (e1.isBool(false))
8411         {
8412             FuncDeclaration fd = sc.parent.isFuncDeclaration();
8413             if (fd)
8414                 fd.hasReturnExp |= 4;
8415             sc.callSuper |= CSXhalt;
8416             if (sc.fieldinit)
8417             {
8418                 for (size_t i = 0; i < sc.fieldinit_dim; i++)
8419                     sc.fieldinit[i] |= CSXhalt;
8420             }
8421 
8422             if (!global.params.useAssert)
8423             {
8424                 Expression e = new HaltExp(loc);
8425                 e = e.semantic(sc);
8426                 return e;
8427             }
8428         }
8429         type = Type.tvoid;
8430         return this;
8431     }
8432 
8433     override void accept(Visitor v)
8434     {
8435         v.visit(this);
8436     }
8437 }
8438 
8439 /***********************************************************
8440  */
8441 extern (C++) final class DotIdExp : UnaExp
8442 {
8443     Identifier ident;
8444     bool noderef;       // true if the result of the expression will never be dereferenced
8445 
8446     extern (D) this(Loc loc, Expression e, Identifier ident)
8447     {
8448         super(loc, TOKdotid, __traits(classInstanceSize, DotIdExp), e);
8449         this.ident = ident;
8450     }
8451 
8452     static DotIdExp create(Loc loc, Expression e, Identifier ident)
8453     {
8454         return new DotIdExp(loc, e, ident);
8455     }
8456 
8457     override Expression semantic(Scope* sc)
8458     {
8459         static if (LOGSEMANTIC)
8460         {
8461             printf("DotIdExp::semantic(this = %p, '%s')\n", this, toChars());
8462             //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
8463         }
8464         Expression e = semanticY(sc, 1);
8465         if (e && isDotOpDispatch(e))
8466         {
8467             uint errors = global.startGagging();
8468             e = resolvePropertiesX(sc, e);
8469             if (global.endGagging(errors))
8470                 e = null; /* fall down to UFCS */
8471             else
8472                 return e;
8473         }
8474         if (!e) // if failed to find the property
8475         {
8476             /* If ident is not a valid property, rewrite:
8477              *   e1.ident
8478              * as:
8479              *   .ident(e1)
8480              */
8481             e = resolveUFCSProperties(sc, this);
8482         }
8483         return e;
8484     }
8485 
8486     // Run semantic in e1
8487     Expression semanticX(Scope* sc)
8488     {
8489         //printf("DotIdExp::semanticX(this = %p, '%s')\n", this, toChars());
8490         if (Expression ex = unaSemantic(sc))
8491             return ex;
8492 
8493         if (ident == Id._mangleof)
8494         {
8495             // symbol.mangleof
8496             Dsymbol ds;
8497             switch (e1.op)
8498             {
8499             case TOKscope:
8500                 ds = (cast(ScopeExp)e1).sds;
8501                 goto L1;
8502             case TOKvar:
8503                 ds = (cast(VarExp)e1).var;
8504                 goto L1;
8505             case TOKdotvar:
8506                 ds = (cast(DotVarExp)e1).var;
8507                 goto L1;
8508             case TOKoverloadset:
8509                 ds = (cast(OverExp)e1).vars;
8510                 goto L1;
8511             case TOKtemplate:
8512                 {
8513                     TemplateExp te = cast(TemplateExp)e1;
8514                     ds = te.fd ? cast(Dsymbol)te.fd : te.td;
8515                 }
8516             L1:
8517                 {
8518                     assert(ds);
8519                     if (auto f = ds.isFuncDeclaration())
8520                     {
8521                         if (f.checkForwardRef(loc))
8522                             return new ErrorExp();
8523                     }
8524                     OutBuffer buf;
8525                     mangleToBuffer(ds, &buf);
8526                     const s = buf.peekSlice();
8527                     Expression e = new StringExp(loc, buf.extractString(), s.length);
8528                     e = e.semantic(sc);
8529                     return e;
8530                 }
8531             default:
8532                 break;
8533             }
8534         }
8535 
8536         if (e1.op == TOKvar && e1.type.toBasetype().ty == Tsarray && ident == Id.length)
8537         {
8538             // bypass checkPurity
8539             return e1.type.dotExp(sc, e1, ident, noderef ? Type.DotExpFlag.noDeref : 0);
8540         }
8541 
8542         if (e1.op == TOKdot)
8543         {
8544         }
8545         else
8546         {
8547             e1 = resolvePropertiesX(sc, e1);
8548         }
8549         if (e1.op == TOKtuple && ident == Id.offsetof)
8550         {
8551             /* 'distribute' the .offsetof to each of the tuple elements.
8552              */
8553             TupleExp te = cast(TupleExp)e1;
8554             auto exps = new Expressions();
8555             exps.setDim(te.exps.dim);
8556             for (size_t i = 0; i < exps.dim; i++)
8557             {
8558                 Expression e = (*te.exps)[i];
8559                 e = e.semantic(sc);
8560                 e = new DotIdExp(e.loc, e, Id.offsetof);
8561                 (*exps)[i] = e;
8562             }
8563             // Don't evaluate te->e0 in runtime
8564             Expression e = new TupleExp(loc, null, exps);
8565             e = e.semantic(sc);
8566             return e;
8567         }
8568         if (e1.op == TOKtuple && ident == Id.length)
8569         {
8570             TupleExp te = cast(TupleExp)e1;
8571             // Don't evaluate te->e0 in runtime
8572             Expression e = new IntegerExp(loc, te.exps.dim, Type.tsize_t);
8573             return e;
8574         }
8575 
8576         // Bugzilla 14416: Template has no built-in properties except for 'stringof'.
8577         if ((e1.op == TOKdottd || e1.op == TOKtemplate) && ident != Id.stringof)
8578         {
8579             error("template %s does not have property '%s'", e1.toChars(), ident.toChars());
8580             return new ErrorExp();
8581         }
8582         if (!e1.type)
8583         {
8584             error("expression %s does not have property '%s'", e1.toChars(), ident.toChars());
8585             return new ErrorExp();
8586         }
8587 
8588         return this;
8589     }
8590 
8591     // Resolve e1.ident without seeing UFCS.
8592     // If flag == 1, stop "not a property" error and return NULL.
8593     Expression semanticY(Scope* sc, int flag)
8594     {
8595         //printf("DotIdExp::semanticY(this = %p, '%s')\n", this, toChars());
8596 
8597         //{ static int z; fflush(stdout); if (++z == 10) *(char*)0=0; }
8598 
8599         /* Special case: rewrite this.id and super.id
8600          * to be classtype.id and baseclasstype.id
8601          * if we have no this pointer.
8602          */
8603         if ((e1.op == TOKthis || e1.op == TOKsuper) && !hasThis(sc))
8604         {
8605             if (AggregateDeclaration ad = sc.getStructClassScope())
8606             {
8607                 if (e1.op == TOKthis)
8608                 {
8609                     e1 = new TypeExp(e1.loc, ad.type);
8610                 }
8611                 else
8612                 {
8613                     ClassDeclaration cd = ad.isClassDeclaration();
8614                     if (cd && cd.baseClass)
8615                         e1 = new TypeExp(e1.loc, cd.baseClass.type);
8616                 }
8617             }
8618         }
8619 
8620         Expression e = semanticX(sc);
8621         if (e != this)
8622             return e;
8623 
8624         Expression eleft;
8625         Expression eright;
8626         if (e1.op == TOKdot)
8627         {
8628             DotExp de = cast(DotExp)e1;
8629             eleft = de.e1;
8630             eright = de.e2;
8631         }
8632         else
8633         {
8634             eleft = null;
8635             eright = e1;
8636         }
8637 
8638         Type t1b = e1.type.toBasetype();
8639 
8640         if (eright.op == TOKscope) // also used for template alias's
8641         {
8642             ScopeExp ie = cast(ScopeExp)eright;
8643 
8644             /* Disable access to another module's private imports.
8645              * The check for 'is sds our current module' is because
8646              * the current module should have access to its own imports.
8647              */
8648             Dsymbol s = ie.sds.search(loc, ident,
8649                 (ie.sds.isModule() && ie.sds != sc._module) ? IgnorePrivateImports | SearchLocalsOnly : SearchLocalsOnly);
8650             /* Check for visibility before resolving aliases because public
8651              * aliases to private symbols are public.
8652              */
8653             if (s && !symbolIsVisible(sc._module, s))
8654             {
8655                 if (s.isDeclaration())
8656                     .error(loc, "%s is not visible from module %s", s.toPrettyChars(), sc._module.toChars());
8657                 else
8658                     .deprecation(loc, "%s is not visible from module %s", s.toPrettyChars(), sc._module.toChars());
8659                 // s = null;
8660             }
8661             if (s)
8662             {
8663                 if (auto p = s.isPackage())
8664                     checkAccess(loc, sc, p);
8665 
8666                 // if 's' is a tuple variable, the tuple is returned.
8667                 s = s.toAlias();
8668 
8669                 checkDeprecated(sc, s);
8670 
8671                 EnumMember em = s.isEnumMember();
8672                 if (em)
8673                 {
8674                     return em.getVarExp(loc, sc);
8675                 }
8676                 VarDeclaration v = s.isVarDeclaration();
8677                 if (v)
8678                 {
8679                     //printf("DotIdExp:: Identifier '%s' is a variable, type '%s'\n", toChars(), v->type->toChars());
8680                     if (!v.type ||
8681                         !v.type.deco && v.inuse)
8682                     {
8683                         if (v.inuse)
8684                             error("circular reference to %s '%s'", v.kind(), v.toPrettyChars());
8685                         else
8686                             error("forward reference to %s '%s'", v.kind(), v.toPrettyChars());
8687                         return new ErrorExp();
8688                     }
8689                     if (v.type.ty == Terror)
8690                         return new ErrorExp();
8691 
8692                     if ((v.storage_class & STCmanifest) && v._init)
8693                     {
8694                         if (v.inuse)
8695                         {
8696                             .error(loc, "circular initialization of %s '%s'", v.kind(), v.toPrettyChars());
8697                             return new ErrorExp();
8698                         }
8699                         e = v.expandInitializer(loc);
8700                         v.inuse++;
8701                         e = e.semantic(sc);
8702                         v.inuse--;
8703                         return e;
8704                     }
8705 
8706                     if (v.needThis())
8707                     {
8708                         if (!eleft)
8709                             eleft = new ThisExp(loc);
8710                         e = new DotVarExp(loc, eleft, v);
8711                         e = e.semantic(sc);
8712                     }
8713                     else
8714                     {
8715                         e = new VarExp(loc, v);
8716                         if (eleft)
8717                         {
8718                             e = new CommaExp(loc, eleft, e);
8719                             e.type = v.type;
8720                         }
8721                     }
8722                     e = e.deref();
8723                     return e.semantic(sc);
8724                 }
8725 
8726                 FuncDeclaration f = s.isFuncDeclaration();
8727                 if (f)
8728                 {
8729                     //printf("it's a function\n");
8730                     if (!f.functionSemantic())
8731                         return new ErrorExp();
8732                     if (f.needThis())
8733                     {
8734                         if (!eleft)
8735                             eleft = new ThisExp(loc);
8736                         e = new DotVarExp(loc, eleft, f, true);
8737                         e = e.semantic(sc);
8738                     }
8739                     else
8740                     {
8741                         e = new VarExp(loc, f, true);
8742                         if (eleft)
8743                         {
8744                             e = new CommaExp(loc, eleft, e);
8745                             e.type = f.type;
8746                         }
8747                     }
8748                     return e;
8749                 }
8750                 if (auto td = s.isTemplateDeclaration())
8751                 {
8752                     if (eleft)
8753                         e = new DotTemplateExp(loc, eleft, td);
8754                     else
8755                         e = new TemplateExp(loc, td);
8756                     e = e.semantic(sc);
8757                     return e;
8758                 }
8759                 if (OverDeclaration od = s.isOverDeclaration())
8760                 {
8761                     e = new VarExp(loc, od, true);
8762                     if (eleft)
8763                     {
8764                         e = new CommaExp(loc, eleft, e);
8765                         e.type = Type.tvoid; // ambiguous type?
8766                     }
8767                     return e;
8768                 }
8769                 OverloadSet o = s.isOverloadSet();
8770                 if (o)
8771                 {
8772                     //printf("'%s' is an overload set\n", o->toChars());
8773                     return new OverExp(loc, o);
8774                 }
8775 
8776                 if (auto t = s.getType())
8777                 {
8778                     return (new TypeExp(loc, t)).semantic(sc);
8779                 }
8780 
8781                 TupleDeclaration tup = s.isTupleDeclaration();
8782                 if (tup)
8783                 {
8784                     if (eleft)
8785                     {
8786                         e = new DotVarExp(loc, eleft, tup);
8787                         e = e.semantic(sc);
8788                         return e;
8789                     }
8790                     e = new TupleExp(loc, tup);
8791                     e = e.semantic(sc);
8792                     return e;
8793                 }
8794 
8795                 ScopeDsymbol sds = s.isScopeDsymbol();
8796                 if (sds)
8797                 {
8798                     //printf("it's a ScopeDsymbol %s\n", ident->toChars());
8799                     e = new ScopeExp(loc, sds);
8800                     e = e.semantic(sc);
8801                     if (eleft)
8802                         e = new DotExp(loc, eleft, e);
8803                     return e;
8804                 }
8805 
8806                 Import imp = s.isImport();
8807                 if (imp)
8808                 {
8809                     ie = new ScopeExp(loc, imp.pkg);
8810                     return ie.semantic(sc);
8811                 }
8812                 // BUG: handle other cases like in IdentifierExp::semantic()
8813                 debug
8814                 {
8815                     printf("s = '%s', kind = '%s'\n", s.toChars(), s.kind());
8816                 }
8817                 assert(0);
8818             }
8819             else if (ident == Id.stringof)
8820             {
8821                 const p = ie.toChars();
8822                 e = new StringExp(loc, cast(char*)p, strlen(p));
8823                 e = e.semantic(sc);
8824                 return e;
8825             }
8826             if (ie.sds.isPackage() || ie.sds.isImport() || ie.sds.isModule())
8827             {
8828                 flag = 0;
8829             }
8830             if (flag)
8831                 return null;
8832             s = ie.sds.search_correct(ident);
8833             if (s)
8834                 error("undefined identifier '%s' in %s '%s', did you mean %s '%s'?", ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars(), s.kind(), s.toChars());
8835             else
8836                 error("undefined identifier '%s' in %s '%s'", ident.toChars(), ie.sds.kind(), ie.sds.toPrettyChars());
8837             return new ErrorExp();
8838         }
8839         else if (t1b.ty == Tpointer && e1.type.ty != Tenum && ident != Id._init && ident != Id.__sizeof && ident != Id.__xalignof && ident != Id.offsetof && ident != Id._mangleof && ident != Id.stringof)
8840         {
8841             Type t1bn = t1b.nextOf();
8842             if (flag)
8843             {
8844                 AggregateDeclaration ad = isAggregate(t1bn);
8845                 if (ad && !ad.members) // Bugzilla 11312
8846                     return null;
8847             }
8848 
8849             /* Rewrite:
8850              *   p.ident
8851              * as:
8852              *   (*p).ident
8853              */
8854             if (flag && t1bn.ty == Tvoid)
8855                 return null;
8856             e = new PtrExp(loc, e1);
8857             e = e.semantic(sc);
8858             return e.type.dotExp(sc, e, ident, flag | (noderef ? Type.DotExpFlag.noDeref : 0));
8859         }
8860         else
8861         {
8862             if (e1.op == TOKtype || e1.op == TOKtemplate)
8863                 flag = 0;
8864             e = e1.type.dotExp(sc, e1, ident, flag | (noderef ? Type.DotExpFlag.noDeref : 0));
8865             if (!flag || e)
8866                 e = e.semantic(sc);
8867             return e;
8868         }
8869     }
8870 
8871     override void accept(Visitor v)
8872     {
8873         v.visit(this);
8874     }
8875 }
8876 
8877 /***********************************************************
8878  * Mainly just a placeholder
8879  */
8880 extern (C++) final class DotTemplateExp : UnaExp
8881 {
8882     TemplateDeclaration td;
8883 
8884     extern (D) this(Loc loc, Expression e, TemplateDeclaration td)
8885     {
8886         super(loc, TOKdottd, __traits(classInstanceSize, DotTemplateExp), e);
8887         this.td = td;
8888     }
8889 
8890     override Expression semantic(Scope* sc)
8891     {
8892         if (Expression ex = unaSemantic(sc))
8893             return ex;
8894         return this;
8895     }
8896 
8897     override void accept(Visitor v)
8898     {
8899         v.visit(this);
8900     }
8901 }
8902 
8903 /***********************************************************
8904  */
8905 extern (C++) final class DotVarExp : UnaExp
8906 {
8907     Declaration var;
8908     bool hasOverloads;
8909 
8910     extern (D) this(Loc loc, Expression e, Declaration var, bool hasOverloads = true)
8911     {
8912         if (var.isVarDeclaration())
8913             hasOverloads = false;
8914 
8915         super(loc, TOKdotvar, __traits(classInstanceSize, DotVarExp), e);
8916         //printf("DotVarExp()\n");
8917         this.var = var;
8918         this.hasOverloads = hasOverloads;
8919     }
8920 
8921     override Expression semantic(Scope* sc)
8922     {
8923         static if (LOGSEMANTIC)
8924         {
8925             printf("DotVarExp::semantic('%s')\n", toChars());
8926         }
8927         if (type)
8928             return this;
8929 
8930         var = var.toAlias().isDeclaration();
8931 
8932         e1 = e1.semantic(sc);
8933 
8934         if (auto tup = var.isTupleDeclaration())
8935         {
8936             /* Replace:
8937              *  e1.tuple(a, b, c)
8938              * with:
8939              *  tuple(e1.a, e1.b, e1.c)
8940              */
8941             Expression e0;
8942             Expression ev = extractSideEffect(sc, "__tup", e0, e1);
8943 
8944             auto exps = new Expressions();
8945             exps.reserve(tup.objects.dim);
8946             for (size_t i = 0; i < tup.objects.dim; i++)
8947             {
8948                 RootObject o = (*tup.objects)[i];
8949                 Expression e;
8950                 if (o.dyncast() == DYNCAST_EXPRESSION)
8951                 {
8952                     e = cast(Expression)o;
8953                     if (e.op == TOKdsymbol)
8954                     {
8955                         Dsymbol s = (cast(DsymbolExp)e).s;
8956                         e = new DotVarExp(loc, ev, s.isDeclaration());
8957                     }
8958                 }
8959                 else if (o.dyncast() == DYNCAST_DSYMBOL)
8960                 {
8961                     e = new DsymbolExp(loc, cast(Dsymbol)o);
8962                 }
8963                 else if (o.dyncast() == DYNCAST_TYPE)
8964                 {
8965                     e = new TypeExp(loc, cast(Type)o);
8966                 }
8967                 else
8968                 {
8969                     error("%s is not an expression", o.toChars());
8970                     return new ErrorExp();
8971                 }
8972                 exps.push(e);
8973             }
8974 
8975             Expression e = new TupleExp(loc, e0, exps);
8976             e = e.semantic(sc);
8977             return e;
8978         }
8979 
8980         e1 = e1.addDtorHook(sc);
8981 
8982         Type t1 = e1.type;
8983 
8984         if (FuncDeclaration fd = var.isFuncDeclaration())
8985         {
8986             // for functions, do checks after overload resolution
8987             if (!fd.functionSemantic())
8988                 return new ErrorExp();
8989 
8990             /* Bugzilla 13843: If fd obviously has no overloads, we should
8991              * normalize AST, and it will give a chance to wrap fd with FuncExp.
8992              */
8993             if (fd.isNested() || fd.isFuncLiteralDeclaration())
8994             {
8995                 // (e1, fd)
8996                 auto e = DsymbolExp.resolve(loc, sc, fd, false);
8997                 return Expression.combine(e1, e);
8998             }
8999 
9000             type = fd.type;
9001             assert(type);
9002         }
9003         else if (OverDeclaration od = var.isOverDeclaration())
9004         {
9005             type = Type.tvoid; // ambiguous type?
9006         }
9007         else
9008         {
9009             type = var.type;
9010             if (!type && global.errors)
9011             {
9012                 // var is goofed up, just return 0
9013                 return new ErrorExp();
9014             }
9015             assert(type);
9016 
9017             if (t1.ty == Tpointer)
9018                 t1 = t1.nextOf();
9019 
9020             type = type.addMod(t1.mod);
9021 
9022             Dsymbol vparent = var.toParent();
9023             AggregateDeclaration ad = vparent ? vparent.isAggregateDeclaration() : null;
9024             if (Expression e1x = getRightThis(loc, sc, ad, e1, var, 1))
9025                 e1 = e1x;
9026             else
9027             {
9028                 /* Later checkRightThis will report correct error for invalid field variable access.
9029                  */
9030                 Expression e = new VarExp(loc, var);
9031                 e = e.semantic(sc);
9032                 return e;
9033             }
9034             checkAccess(loc, sc, e1, var);
9035 
9036             VarDeclaration v = var.isVarDeclaration();
9037             if (v && (v.isDataseg() || (v.storage_class & STCmanifest)))
9038             {
9039                 Expression e = expandVar(WANTvalue, v);
9040                 if (e)
9041                     return e;
9042             }
9043 
9044             if (v && v.isDataseg()) // fix bugzilla 8238
9045             {
9046                 // (e1, v)
9047                 checkAccess(loc, sc, e1, v);
9048                 Expression e = new VarExp(loc, v);
9049                 e = new CommaExp(loc, e1, e);
9050                 e = e.semantic(sc);
9051                 return e;
9052             }
9053         }
9054         //printf("-DotVarExp::semantic('%s')\n", toChars());
9055         return this;
9056     }
9057 
9058     override int checkModifiable(Scope* sc, int flag)
9059     {
9060         //printf("DotVarExp::checkModifiable %s %s\n", toChars(), type.toChars());
9061         if (checkUnsafeAccess(sc, this, false, !flag))
9062             return 2;
9063 
9064         if (e1.op == TOKthis)
9065             return var.checkModify(loc, sc, type, e1, flag);
9066 
9067         //printf("\te1 = %s\n", e1.toChars());
9068         return e1.checkModifiable(sc, flag);
9069     }
9070 
9071     bool checkReadModifyWrite();
9072 
9073     override bool isLvalue()
9074     {
9075         return true;
9076     }
9077 
9078     override Expression toLvalue(Scope* sc, Expression e)
9079     {
9080         //printf("DotVarExp::toLvalue(%s)\n", toChars());
9081         return this;
9082     }
9083 
9084     override Expression modifiableLvalue(Scope* sc, Expression e)
9085     {
9086         version (none)
9087         {
9088             printf("DotVarExp::modifiableLvalue(%s)\n", toChars());
9089             printf("e1->type = %s\n", e1.type.toChars());
9090             printf("var->type = %s\n", var.type.toChars());
9091         }
9092 
9093         return Expression.modifiableLvalue(sc, e);
9094     }
9095 
9096     override void accept(Visitor v)
9097     {
9098         v.visit(this);
9099     }
9100 }
9101 
9102 /***********************************************************
9103  * foo.bar!(args)
9104  */
9105 extern (C++) final class DotTemplateInstanceExp : UnaExp
9106 {
9107     TemplateInstance ti;
9108 
9109     extern (D) this(Loc loc, Expression e, Identifier name, Objects* tiargs)
9110     {
9111         super(loc, TOKdotti, __traits(classInstanceSize, DotTemplateInstanceExp), e);
9112         //printf("DotTemplateInstanceExp()\n");
9113         this.ti = new TemplateInstance(loc, name, tiargs);
9114     }
9115 
9116     extern (D) this(Loc loc, Expression e, TemplateInstance ti)
9117     {
9118         super(loc, TOKdotti, __traits(classInstanceSize, DotTemplateInstanceExp), e);
9119         this.ti = ti;
9120     }
9121 
9122     override Expression syntaxCopy()
9123     {
9124         return new DotTemplateInstanceExp(loc, e1.syntaxCopy(), ti.name, TemplateInstance.arraySyntaxCopy(ti.tiargs));
9125     }
9126 
9127     bool findTempDecl(Scope* sc)
9128     {
9129         static if (LOGSEMANTIC)
9130         {
9131             printf("DotTemplateInstanceExp::findTempDecl('%s')\n", toChars());
9132         }
9133         if (ti.tempdecl)
9134             return true;
9135 
9136         Expression e = new DotIdExp(loc, e1, ti.name);
9137         e = e.semantic(sc);
9138         if (e.op == TOKdot)
9139             e = (cast(DotExp)e).e2;
9140 
9141         Dsymbol s = null;
9142         switch (e.op)
9143         {
9144         case TOKoverloadset:
9145             s = (cast(OverExp)e).vars;
9146             break;
9147 
9148         case TOKdottd:
9149             s = (cast(DotTemplateExp)e).td;
9150             break;
9151 
9152         case TOKscope:
9153             s = (cast(ScopeExp)e).sds;
9154             break;
9155 
9156         case TOKdotvar:
9157             s = (cast(DotVarExp)e).var;
9158             break;
9159 
9160         case TOKvar:
9161             s = (cast(VarExp)e).var;
9162             break;
9163 
9164         default:
9165             return false;
9166         }
9167         return ti.updateTempDecl(sc, s);
9168     }
9169 
9170     override Expression semantic(Scope* sc)
9171     {
9172         static if (LOGSEMANTIC)
9173         {
9174             printf("DotTemplateInstanceExp::semantic('%s')\n", toChars());
9175         }
9176         // Indicate we need to resolve by UFCS.
9177         Expression e = semanticY(sc, 1);
9178         if (!e)
9179             e = resolveUFCSProperties(sc, this);
9180         return e;
9181     }
9182 
9183     // Resolve e1.ident!tiargs without seeing UFCS.
9184     // If flag == 1, stop "not a property" error and return NULL.
9185     Expression semanticY(Scope* sc, int flag)
9186     {
9187         static if (LOGSEMANTIC)
9188         {
9189             printf("DotTemplateInstanceExpY::semantic('%s')\n", toChars());
9190         }
9191 
9192         auto die = new DotIdExp(loc, e1, ti.name);
9193 
9194         Expression e = die.semanticX(sc);
9195         if (e == die)
9196         {
9197             e1 = die.e1; // take back
9198             Type t1b = e1.type.toBasetype();
9199             if (t1b.ty == Tarray || t1b.ty == Tsarray || t1b.ty == Taarray || t1b.ty == Tnull || (t1b.isTypeBasic() && t1b.ty != Tvoid))
9200             {
9201                 /* No built-in type has templatized properties, so do shortcut.
9202                  * It is necessary in: 1024.max!"a < b"
9203                  */
9204                 if (flag)
9205                     return null;
9206             }
9207             e = die.semanticY(sc, flag);
9208             if (flag && e && isDotOpDispatch(e))
9209             {
9210                 /* opDispatch!tiargs would be a function template that needs IFTI,
9211                  * so it's not a template
9212                  */
9213                 e = null; /* fall down to UFCS */
9214             }
9215             if (flag && !e)
9216                 return null;
9217         }
9218         assert(e);
9219 
9220     L1:
9221         if (e.op == TOKerror)
9222             return e;
9223         if (e.op == TOKdotvar)
9224         {
9225             DotVarExp dve = cast(DotVarExp)e;
9226             if (FuncDeclaration fd = dve.var.isFuncDeclaration())
9227             {
9228                 TemplateDeclaration td = fd.findTemplateDeclRoot();
9229                 if (td)
9230                 {
9231                     e = new DotTemplateExp(dve.loc, dve.e1, td);
9232                     e = e.semantic(sc);
9233                 }
9234             }
9235             else if (OverDeclaration od = dve.var.isOverDeclaration())
9236             {
9237                 e1 = dve.e1; // pull semantic() result
9238 
9239                 if (!findTempDecl(sc))
9240                     goto Lerr;
9241                 if (ti.needsTypeInference(sc))
9242                     return this;
9243                 ti.semantic(sc);
9244                 if (!ti.inst || ti.errors) // if template failed to expand
9245                     return new ErrorExp();
9246 
9247                 Dsymbol s = ti.toAlias();
9248                 Declaration v = s.isDeclaration();
9249                 if (v)
9250                 {
9251                     if (v.type && !v.type.deco)
9252                         v.type = v.type.semantic(v.loc, sc);
9253                     e = new DotVarExp(loc, e1, v);
9254                     e = e.semantic(sc);
9255                     return e;
9256                 }
9257                 e = new ScopeExp(loc, ti);
9258                 e = new DotExp(loc, e1, e);
9259                 e = e.semantic(sc);
9260                 return e;
9261             }
9262         }
9263         else if (e.op == TOKvar)
9264         {
9265             VarExp ve = cast(VarExp)e;
9266             if (FuncDeclaration fd = ve.var.isFuncDeclaration())
9267             {
9268                 TemplateDeclaration td = fd.findTemplateDeclRoot();
9269                 if (td)
9270                 {
9271                     e = new TemplateExp(ve.loc, td);
9272                     e = e.semantic(sc);
9273                 }
9274             }
9275             else if (OverDeclaration od = ve.var.isOverDeclaration())
9276             {
9277                 ti.tempdecl = od;
9278                 e = new ScopeExp(loc, ti);
9279                 e = e.semantic(sc);
9280                 return e;
9281             }
9282         }
9283         if (e.op == TOKdottd)
9284         {
9285             DotTemplateExp dte = cast(DotTemplateExp)e;
9286             e1 = dte.e1; // pull semantic() result
9287 
9288             ti.tempdecl = dte.td;
9289             if (!ti.semanticTiargs(sc))
9290                 return new ErrorExp();
9291             if (ti.needsTypeInference(sc))
9292                 return this;
9293             ti.semantic(sc);
9294             if (!ti.inst || ti.errors) // if template failed to expand
9295                 return new ErrorExp();
9296 
9297             Dsymbol s = ti.toAlias();
9298             Declaration v = s.isDeclaration();
9299             if (v && (v.isFuncDeclaration() || v.isVarDeclaration()))
9300             {
9301                 e = new DotVarExp(loc, e1, v);
9302                 e = e.semantic(sc);
9303                 return e;
9304             }
9305             e = new ScopeExp(loc, ti);
9306             e = new DotExp(loc, e1, e);
9307             e = e.semantic(sc);
9308             return e;
9309         }
9310         else if (e.op == TOKtemplate)
9311         {
9312             ti.tempdecl = (cast(TemplateExp)e).td;
9313             e = new ScopeExp(loc, ti);
9314             e = e.semantic(sc);
9315             return e;
9316         }
9317         else if (e.op == TOKdot)
9318         {
9319             DotExp de = cast(DotExp)e;
9320 
9321             if (de.e2.op == TOKoverloadset)
9322             {
9323                 if (!findTempDecl(sc) || !ti.semanticTiargs(sc))
9324                 {
9325                     return new ErrorExp();
9326                 }
9327                 if (ti.needsTypeInference(sc))
9328                     return this;
9329                 ti.semantic(sc);
9330                 if (!ti.inst || ti.errors) // if template failed to expand
9331                     return new ErrorExp();
9332 
9333                 Dsymbol s = ti.toAlias();
9334                 Declaration v = s.isDeclaration();
9335                 if (v)
9336                 {
9337                     if (v.type && !v.type.deco)
9338                         v.type = v.type.semantic(v.loc, sc);
9339                     e = new DotVarExp(loc, e1, v);
9340                     e = e.semantic(sc);
9341                     return e;
9342                 }
9343                 e = new ScopeExp(loc, ti);
9344                 e = new DotExp(loc, e1, e);
9345                 e = e.semantic(sc);
9346                 return e;
9347             }
9348         }
9349         else if (e.op == TOKoverloadset)
9350         {
9351             OverExp oe = cast(OverExp)e;
9352             ti.tempdecl = oe.vars;
9353             e = new ScopeExp(loc, ti);
9354             e = e.semantic(sc);
9355             return e;
9356         }
9357 
9358     Lerr:
9359         error("%s isn't a template", e.toChars());
9360         return new ErrorExp();
9361     }
9362 
9363     override void accept(Visitor v)
9364     {
9365         v.visit(this);
9366     }
9367 }
9368 
9369 /***********************************************************
9370  */
9371 extern (C++) final class DelegateExp : UnaExp
9372 {
9373     FuncDeclaration func;
9374     bool hasOverloads;
9375 
9376     extern (D) this(Loc loc, Expression e, FuncDeclaration f, bool hasOverloads = true)
9377     {
9378         super(loc, TOKdelegate, __traits(classInstanceSize, DelegateExp), e);
9379         this.func = f;
9380         this.hasOverloads = hasOverloads;
9381     }
9382 
9383     override Expression semantic(Scope* sc)
9384     {
9385         static if (LOGSEMANTIC)
9386         {
9387             printf("DelegateExp::semantic('%s')\n", toChars());
9388         }
9389         if (type)
9390             return this;
9391 
9392         e1 = e1.semantic(sc);
9393 
9394         type = new TypeDelegate(func.type);
9395         type = type.semantic(loc, sc);
9396 
9397         FuncDeclaration f = func.toAliasFunc();
9398         AggregateDeclaration ad = f.toParent().isAggregateDeclaration();
9399         if (f.needThis())
9400             e1 = getRightThis(loc, sc, ad, e1, f);
9401         if (f.type.ty == Tfunction)
9402         {
9403             TypeFunction tf = cast(TypeFunction)f.type;
9404             if (!MODimplicitConv(e1.type.mod, f.type.mod))
9405             {
9406                 OutBuffer thisBuf, funcBuf;
9407                 MODMatchToBuffer(&thisBuf, e1.type.mod, tf.mod);
9408                 MODMatchToBuffer(&funcBuf, tf.mod, e1.type.mod);
9409                 error("%smethod %s is not callable using a %s%s",
9410                     funcBuf.peekString(), f.toPrettyChars(), thisBuf.peekString(), e1.toChars());
9411                 return new ErrorExp();
9412             }
9413         }
9414         if (ad && ad.isClassDeclaration() && ad.type != e1.type)
9415         {
9416             // A downcast is required for interfaces, see Bugzilla 3706
9417             e1 = new CastExp(loc, e1, ad.type);
9418             e1 = e1.semantic(sc);
9419         }
9420         return this;
9421     }
9422 
9423     override void accept(Visitor v)
9424     {
9425         v.visit(this);
9426     }
9427 
9428     override void printAST(int indent)
9429     {
9430         UnaExp.printAST(indent);
9431         foreach (i; 0 .. indent + 2)
9432             printf(" ");
9433         printf(".func: %s\n", func ? func.toChars() : "");
9434     }
9435 }
9436 
9437 /***********************************************************
9438  */
9439 extern (C++) final class DotTypeExp : UnaExp
9440 {
9441     Dsymbol sym;        // symbol that represents a type
9442 
9443     extern (D) this(Loc loc, Expression e, Dsymbol s)
9444     {
9445         super(loc, TOKdottype, __traits(classInstanceSize, DotTypeExp), e);
9446         this.sym = s;
9447     }
9448 
9449     override Expression semantic(Scope* sc)
9450     {
9451         static if (LOGSEMANTIC)
9452         {
9453             printf("DotTypeExp::semantic('%s')\n", toChars());
9454         }
9455         if (type)
9456             return this;
9457 
9458         if (auto e = unaSemantic(sc))
9459             return e;
9460 
9461         type = sym.getType().addMod(e1.type.mod);
9462         return this;
9463     }
9464 
9465     override void accept(Visitor v)
9466     {
9467         v.visit(this);
9468     }
9469 }
9470 
9471 /***********************************************************
9472  */
9473 extern (C++) final class CallExp : UnaExp
9474 {
9475     Expressions* arguments; // function arguments
9476     FuncDeclaration f;      // symbol to call
9477     bool directcall;        // true if a virtual call is devirtualized
9478 
9479     extern (D) this(Loc loc, Expression e, Expressions* exps)
9480     {
9481         super(loc, TOKcall, __traits(classInstanceSize, CallExp), e);
9482         this.arguments = exps;
9483     }
9484 
9485     extern (D) this(Loc loc, Expression e)
9486     {
9487         super(loc, TOKcall, __traits(classInstanceSize, CallExp), e);
9488     }
9489 
9490     extern (D) this(Loc loc, Expression e, Expression earg1)
9491     {
9492         super(loc, TOKcall, __traits(classInstanceSize, CallExp), e);
9493         auto arguments = new Expressions();
9494         if (earg1)
9495         {
9496             arguments.setDim(1);
9497             (*arguments)[0] = earg1;
9498         }
9499         this.arguments = arguments;
9500     }
9501 
9502     extern (D) this(Loc loc, Expression e, Expression earg1, Expression earg2)
9503     {
9504         super(loc, TOKcall, __traits(classInstanceSize, CallExp), e);
9505         auto arguments = new Expressions();
9506         arguments.setDim(2);
9507         (*arguments)[0] = earg1;
9508         (*arguments)[1] = earg2;
9509         this.arguments = arguments;
9510     }
9511 
9512     static CallExp create(Loc loc, Expression e, Expressions* exps)
9513     {
9514         return new CallExp(loc, e, exps);
9515     }
9516 
9517     static CallExp create(Loc loc, Expression e)
9518     {
9519         return new CallExp(loc, e);
9520     }
9521 
9522     static CallExp create(Loc loc, Expression e, Expression earg1)
9523     {
9524         return new CallExp(loc, e, earg1);
9525     }
9526 
9527     override Expression syntaxCopy()
9528     {
9529         return new CallExp(loc, e1.syntaxCopy(), arraySyntaxCopy(arguments));
9530     }
9531 
9532     override Expression semantic(Scope* sc)
9533     {
9534         static if (LOGSEMANTIC)
9535         {
9536             printf("CallExp::semantic() %s\n", toChars());
9537         }
9538         if (type)
9539             return this; // semantic() already run
9540         version (none)
9541         {
9542             if (arguments && arguments.dim)
9543             {
9544                 Expression earg = (*arguments)[0];
9545                 earg.print();
9546                 if (earg.type)
9547                     earg.type.print();
9548             }
9549         }
9550 
9551         Type t1;
9552         Objects* tiargs = null; // initial list of template arguments
9553         Expression ethis = null;
9554         Type tthis = null;
9555         Expression e1org = e1;
9556 
9557         if (e1.op == TOKcomma)
9558         {
9559             /* Rewrite (a,b)(args) as (a,(b(args)))
9560              */
9561             auto ce = cast(CommaExp)e1;
9562             e1 = ce.e2;
9563             ce.e2 = this;
9564             return ce.semantic(sc);
9565         }
9566         if (e1.op == TOKdelegate)
9567         {
9568             DelegateExp de = cast(DelegateExp)e1;
9569             e1 = new DotVarExp(de.loc, de.e1, de.func, de.hasOverloads);
9570             return semantic(sc);
9571         }
9572         if (e1.op == TOKfunction)
9573         {
9574             if (arrayExpressionSemantic(arguments, sc) || preFunctionParameters(loc, sc, arguments))
9575             {
9576                 return new ErrorExp();
9577             }
9578 
9579             // Run e1 semantic even if arguments have any errors
9580             FuncExp fe = cast(FuncExp)e1;
9581             e1 = fe.semantic(sc, arguments);
9582             if (e1.op == TOKerror)
9583                 return e1;
9584         }
9585 
9586         if (Expression ex = resolveUFCS(sc, this))
9587             return ex;
9588 
9589         /* This recognizes:
9590          *  foo!(tiargs)(funcargs)
9591          */
9592         if (e1.op == TOKscope)
9593         {
9594             ScopeExp se = cast(ScopeExp)e1;
9595             TemplateInstance ti = se.sds.isTemplateInstance();
9596             if (ti)
9597             {
9598                 /* Attempt to instantiate ti. If that works, go with it.
9599                  * If not, go with partial explicit specialization.
9600                  */
9601                 WithScopeSymbol withsym;
9602                 if (!ti.findTempDecl(sc, &withsym) || !ti.semanticTiargs(sc))
9603                 {
9604                     return new ErrorExp();
9605                 }
9606                 if (withsym && withsym.withstate.wthis)
9607                 {
9608                     e1 = new VarExp(e1.loc, withsym.withstate.wthis);
9609                     e1 = new DotTemplateInstanceExp(e1.loc, e1, ti);
9610                     goto Ldotti;
9611                 }
9612                 if (ti.needsTypeInference(sc, 1))
9613                 {
9614                     /* Go with partial explicit specialization
9615                      */
9616                     tiargs = ti.tiargs;
9617                     assert(ti.tempdecl);
9618                     if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
9619                         e1 = new TemplateExp(loc, td);
9620                     else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
9621                         e1 = new VarExp(loc, od);
9622                     else
9623                         e1 = new OverExp(loc, ti.tempdecl.isOverloadSet());
9624                 }
9625                 else
9626                 {
9627                     Expression e1x = e1.semantic(sc);
9628                     if (e1x.op == TOKerror)
9629                         return e1x;
9630                     e1 = e1x;
9631                 }
9632             }
9633         }
9634 
9635         /* This recognizes:
9636          *  expr.foo!(tiargs)(funcargs)
9637          */
9638     Ldotti:
9639         if (e1.op == TOKdotti && !e1.type)
9640         {
9641             DotTemplateInstanceExp se = cast(DotTemplateInstanceExp)e1;
9642             TemplateInstance ti = se.ti;
9643             {
9644                 /* Attempt to instantiate ti. If that works, go with it.
9645                  * If not, go with partial explicit specialization.
9646                  */
9647                 if (!se.findTempDecl(sc) || !ti.semanticTiargs(sc))
9648                 {
9649                     return new ErrorExp();
9650                 }
9651                 if (ti.needsTypeInference(sc, 1))
9652                 {
9653                     /* Go with partial explicit specialization
9654                      */
9655                     tiargs = ti.tiargs;
9656                     assert(ti.tempdecl);
9657                     if (TemplateDeclaration td = ti.tempdecl.isTemplateDeclaration())
9658                         e1 = new DotTemplateExp(loc, se.e1, td);
9659                     else if (OverDeclaration od = ti.tempdecl.isOverDeclaration())
9660                     {
9661                         e1 = new DotVarExp(loc, se.e1, od, true);
9662                     }
9663                     else
9664                         e1 = new DotExp(loc, se.e1, new OverExp(loc, ti.tempdecl.isOverloadSet()));
9665                 }
9666                 else
9667                 {
9668                     Expression e1x = e1.semantic(sc);
9669                     if (e1x.op == TOKerror)
9670                         return e1x;
9671                     e1 = e1x;
9672                 }
9673             }
9674         }
9675 
9676     Lagain:
9677         //printf("Lagain: %s\n", toChars());
9678         f = null;
9679         if (e1.op == TOKthis || e1.op == TOKsuper)
9680         {
9681             // semantic() run later for these
9682         }
9683         else
9684         {
9685             if (e1.op == TOKdotid)
9686             {
9687                 DotIdExp die = cast(DotIdExp)e1;
9688                 e1 = die.semantic(sc);
9689                 /* Look for e1 having been rewritten to expr.opDispatch!(string)
9690                  * We handle such earlier, so go back.
9691                  * Note that in the rewrite, we carefully did not run semantic() on e1
9692                  */
9693                 if (e1.op == TOKdotti && !e1.type)
9694                 {
9695                     goto Ldotti;
9696                 }
9697             }
9698             else
9699             {
9700                 static __gshared int nest;
9701                 if (++nest > 500)
9702                 {
9703                     error("recursive evaluation of %s", toChars());
9704                     --nest;
9705                     return new ErrorExp();
9706                 }
9707                 Expression ex = unaSemantic(sc);
9708                 --nest;
9709                 if (ex)
9710                     return ex;
9711             }
9712 
9713             /* Look for e1 being a lazy parameter
9714              */
9715             if (e1.op == TOKvar)
9716             {
9717                 VarExp ve = cast(VarExp)e1;
9718                 if (ve.var.storage_class & STClazy)
9719                 {
9720                     // lazy paramaters can be called without violating purity and safety
9721                     Type tw = ve.var.type;
9722                     Type tc = ve.var.type.substWildTo(MODconst);
9723                     auto tf = new TypeFunction(null, tc, 0, LINKd, STCsafe | STCpure);
9724                     (tf = cast(TypeFunction)tf.semantic(loc, sc)).next = tw; // hack for bug7757
9725                     auto t = new TypeDelegate(tf);
9726                     ve.type = t.semantic(loc, sc);
9727                 }
9728                 VarDeclaration v = ve.var.isVarDeclaration();
9729                 if (v && ve.checkPurity(sc, v))
9730                     return new ErrorExp();
9731             }
9732 
9733             if (e1.op == TOKsymoff && (cast(SymOffExp)e1).hasOverloads)
9734             {
9735                 SymOffExp se = cast(SymOffExp)e1;
9736                 e1 = new VarExp(se.loc, se.var, true);
9737                 e1 = e1.semantic(sc);
9738             }
9739             else if (e1.op == TOKdot)
9740             {
9741                 DotExp de = cast(DotExp)e1;
9742 
9743                 if (de.e2.op == TOKoverloadset)
9744                 {
9745                     ethis = de.e1;
9746                     tthis = de.e1.type;
9747                     e1 = de.e2;
9748                 }
9749             }
9750             else if (e1.op == TOKstar && e1.type.ty == Tfunction)
9751             {
9752                 // Rewrite (*fp)(arguments) to fp(arguments)
9753                 e1 = (cast(PtrExp)e1).e1;
9754             }
9755         }
9756 
9757         t1 = e1.type ? e1.type.toBasetype() : null;
9758 
9759         if (e1.op == TOKerror)
9760             return e1;
9761         if (arrayExpressionSemantic(arguments, sc) || preFunctionParameters(loc, sc, arguments))
9762         {
9763             return new ErrorExp();
9764         }
9765 
9766         // Check for call operator overload
9767         if (t1)
9768         {
9769             if (t1.ty == Tstruct)
9770             {
9771                 auto sd = (cast(TypeStruct)t1).sym;
9772                 sd.size(loc); // Resolve forward references to construct object
9773                 if (sd.sizeok != SIZEOKdone)
9774                     return new ErrorExp();
9775                 if (!sd.ctor)
9776                     sd.ctor = sd.searchCtor();
9777 
9778                 // First look for constructor
9779                 if (e1.op == TOKtype && sd.ctor)
9780                 {
9781                     if (!sd.noDefaultCtor && !(arguments && arguments.dim))
9782                         goto Lx;
9783 
9784                     auto sle = new StructLiteralExp(loc, sd, null, e1.type);
9785                     if (!sd.fill(loc, sle.elements, true))
9786                         return new ErrorExp();
9787                     if (checkFrameAccess(loc, sc, sd, sle.elements.dim))
9788                         return new ErrorExp();
9789 
9790                     // Bugzilla 14556: Set concrete type to avoid further redundant semantic().
9791                     sle.type = e1.type;
9792 
9793                     /* Constructor takes a mutable object, so don't use
9794                      * the immutable initializer symbol.
9795                      */
9796                     sle.useStaticInit = false;
9797 
9798                     Expression e = sle;
9799                     if (auto cf = sd.ctor.isCtorDeclaration())
9800                     {
9801                         e = new DotVarExp(loc, e, cf, true);
9802                     }
9803                     else if (auto td = sd.ctor.isTemplateDeclaration())
9804                     {
9805                         e = new DotTemplateExp(loc, e, td);
9806                     }
9807                     else if (auto os = sd.ctor.isOverloadSet())
9808                     {
9809                         e = new DotExp(loc, e, new OverExp(loc, os));
9810                     }
9811                     else
9812                         assert(0);
9813                     e = new CallExp(loc, e, arguments);
9814                     e = e.semantic(sc);
9815                     return e;
9816                 }
9817                 // No constructor, look for overload of opCall
9818                 if (search_function(sd, Id.call))
9819                     goto L1;
9820                 // overload of opCall, therefore it's a call
9821                 if (e1.op != TOKtype)
9822                 {
9823                     if (sd.aliasthis && e1.type != att1)
9824                     {
9825                         if (!att1 && e1.type.checkAliasThisRec())
9826                             att1 = e1.type;
9827                         e1 = resolveAliasThis(sc, e1);
9828                         goto Lagain;
9829                     }
9830                     error("%s %s does not overload ()", sd.kind(), sd.toChars());
9831                     return new ErrorExp();
9832                 }
9833 
9834                 /* It's a struct literal
9835                  */
9836             Lx:
9837                 Expression e = new StructLiteralExp(loc, sd, arguments, e1.type);
9838                 e = e.semantic(sc);
9839                 return e;
9840             }
9841             else if (t1.ty == Tclass)
9842             {
9843             L1:
9844                 // Rewrite as e1.call(arguments)
9845                 Expression e = new DotIdExp(loc, e1, Id.call);
9846                 e = new CallExp(loc, e, arguments);
9847                 e = e.semantic(sc);
9848                 return e;
9849             }
9850             else if (e1.op == TOKtype && t1.isscalar())
9851             {
9852                 Expression e;
9853                 if (!arguments || arguments.dim == 0)
9854                 {
9855                     e = t1.defaultInitLiteral(loc);
9856                 }
9857                 else if (arguments.dim == 1)
9858                 {
9859                     e = (*arguments)[0];
9860                     e = e.implicitCastTo(sc, t1);
9861                     e = new CastExp(loc, e, t1);
9862                 }
9863                 else
9864                 {
9865                     error("more than one argument for construction of %s", t1.toChars());
9866                     e = new ErrorExp();
9867                 }
9868                 e = e.semantic(sc);
9869                 return e;
9870             }
9871         }
9872 
9873         static FuncDeclaration resolveOverloadSet(Loc loc, Scope* sc,
9874             OverloadSet os, Objects* tiargs, Type tthis, Expressions* arguments)
9875         {
9876             FuncDeclaration f = null;
9877             foreach (s; os.a)
9878             {
9879                 if (tiargs && s.isFuncDeclaration())
9880                     continue;
9881                 if (auto f2 = resolveFuncCall(loc, sc, s, tiargs, tthis, arguments, 1))
9882                 {
9883                     if (f2.errors)
9884                         return null;
9885                     if (f)
9886                     {
9887                         /* Error if match in more than one overload set,
9888                          * even if one is a 'better' match than the other.
9889                          */
9890                         ScopeDsymbol.multiplyDefined(loc, f, f2);
9891                     }
9892                     else
9893                         f = f2;
9894                 }
9895             }
9896             if (!f)
9897                 .error(loc, "no overload matches for %s", os.toChars());
9898             else if (f.errors)
9899                 f = null;
9900             return f;
9901         }
9902 
9903         if (e1.op == TOKdotvar && t1.ty == Tfunction || e1.op == TOKdottd)
9904         {
9905             UnaExp ue = cast(UnaExp)e1;
9906 
9907             Expression ue1 = ue.e1;
9908             Expression ue1old = ue1; // need for 'right this' check
9909             VarDeclaration v;
9910             if (ue1.op == TOKvar && (v = (cast(VarExp)ue1).var.isVarDeclaration()) !is null && v.needThis())
9911             {
9912                 ue.e1 = new TypeExp(ue1.loc, ue1.type);
9913                 ue1 = null;
9914             }
9915 
9916             DotVarExp dve;
9917             DotTemplateExp dte;
9918             Dsymbol s;
9919             if (e1.op == TOKdotvar)
9920             {
9921                 dve = cast(DotVarExp)e1;
9922                 dte = null;
9923                 s = dve.var;
9924                 tiargs = null;
9925             }
9926             else
9927             {
9928                 dve = null;
9929                 dte = cast(DotTemplateExp)e1;
9930                 s = dte.td;
9931             }
9932 
9933             // Do overload resolution
9934             f = resolveFuncCall(loc, sc, s, tiargs, ue1 ? ue1.type : null, arguments);
9935             if (!f || f.errors || f.type.ty == Terror)
9936                 return new ErrorExp();
9937 
9938             if (f.interfaceVirtual)
9939             {
9940                 /* Cast 'this' to the type of the interface, and replace f with the interface's equivalent
9941                  */
9942                 auto b = f.interfaceVirtual;
9943                 auto ad2 = b.sym;
9944                 ue.e1 = ue.e1.castTo(sc, ad2.type.addMod(ue.e1.type.mod));
9945                 ue.e1 = ue.e1.semantic(sc);
9946                 ue1 = ue.e1;
9947                 auto vi = f.findVtblIndex(&ad2.vtbl, cast(int)ad2.vtbl.dim);
9948                 assert(vi >= 0);
9949                 f = ad2.vtbl[vi].isFuncDeclaration();
9950                 assert(f);
9951             }
9952             if (f.needThis())
9953             {
9954                 AggregateDeclaration ad = f.toParent2().isAggregateDeclaration();
9955                 ue.e1 = getRightThis(loc, sc, ad, ue.e1, f);
9956                 if (ue.e1.op == TOKerror)
9957                     return ue.e1;
9958                 ethis = ue.e1;
9959                 tthis = ue.e1.type;
9960             }
9961 
9962             /* Cannot call public functions from inside invariant
9963              * (because then the invariant would have infinite recursion)
9964              */
9965             if (sc.func && sc.func.isInvariantDeclaration() && ue.e1.op == TOKthis && f.addPostInvariant())
9966             {
9967                 error("cannot call public/export function %s from invariant", f.toChars());
9968                 return new ErrorExp();
9969             }
9970 
9971             checkDeprecated(sc, f);
9972             checkPurity(sc, f);
9973             checkSafety(sc, f);
9974             checkNogc(sc, f);
9975             checkAccess(loc, sc, ue.e1, f);
9976             if (!f.needThis())
9977             {
9978                 e1 = Expression.combine(ue.e1, new VarExp(loc, f, false));
9979             }
9980             else
9981             {
9982                 if (ue1old.checkRightThis(sc))
9983                     return new ErrorExp();
9984                 if (e1.op == TOKdotvar)
9985                 {
9986                     dve.var = f;
9987                     e1.type = f.type;
9988                 }
9989                 else
9990                 {
9991                     e1 = new DotVarExp(loc, dte.e1, f, false);
9992                     e1 = e1.semantic(sc);
9993                     if (e1.op == TOKerror)
9994                         return new ErrorExp();
9995                     ue = cast(UnaExp)e1;
9996                 }
9997                 version (none)
9998                 {
9999                     printf("ue->e1 = %s\n", ue.e1.toChars());
10000                     printf("f = %s\n", f.toChars());
10001                     printf("t = %s\n", t.toChars());
10002                     printf("e1 = %s\n", e1.toChars());
10003                     printf("e1->type = %s\n", e1.type.toChars());
10004                 }
10005 
10006                 // See if we need to adjust the 'this' pointer
10007                 AggregateDeclaration ad = f.isThis();
10008                 ClassDeclaration cd = ue.e1.type.isClassHandle();
10009                 if (ad && cd && ad.isClassDeclaration())
10010                 {
10011                     if (ue.e1.op == TOKdottype)
10012                     {
10013                         ue.e1 = (cast(DotTypeExp)ue.e1).e1;
10014                         directcall = true;
10015                     }
10016                     else if (ue.e1.op == TOKsuper)
10017                         directcall = true;
10018                     else if ((cd.storage_class & STCfinal) != 0) // Bugzilla 14211
10019                         directcall = true;
10020 
10021                     if (ad != cd)
10022                     {
10023                         ue.e1 = ue.e1.castTo(sc, ad.type.addMod(ue.e1.type.mod));
10024                         ue.e1 = ue.e1.semantic(sc);
10025                     }
10026                 }
10027             }
10028             t1 = e1.type;
10029         }
10030         else if (e1.op == TOKsuper)
10031         {
10032             // Base class constructor call
10033             auto ad = sc.func ? sc.func.isThis() : null;
10034             auto cd = ad ? ad.isClassDeclaration() : null;
10035             if (!cd || !cd.baseClass || !sc.func.isCtorDeclaration())
10036             {
10037                 error("super class constructor call must be in a constructor");
10038                 return new ErrorExp();
10039             }
10040             if (!cd.baseClass.ctor)
10041             {
10042                 error("no super class constructor for %s", cd.baseClass.toChars());
10043                 return new ErrorExp();
10044             }
10045 
10046             if (!sc.intypeof && !(sc.callSuper & CSXhalt))
10047             {
10048                 if (sc.noctor || sc.callSuper & CSXlabel)
10049                     error("constructor calls not allowed in loops or after labels");
10050                 if (sc.callSuper & (CSXsuper_ctor | CSXthis_ctor))
10051                     error("multiple constructor calls");
10052                 if ((sc.callSuper & CSXreturn) && !(sc.callSuper & CSXany_ctor))
10053                     error("an earlier return statement skips constructor");
10054                 sc.callSuper |= CSXany_ctor | CSXsuper_ctor;
10055             }
10056 
10057             tthis = cd.type.addMod(sc.func.type.mod);
10058             if (auto os = cd.baseClass.ctor.isOverloadSet())
10059                 f = resolveOverloadSet(loc, sc, os, null, tthis, arguments);
10060             else
10061                 f = resolveFuncCall(loc, sc, cd.baseClass.ctor, null, tthis, arguments, 0);
10062             if (!f || f.errors)
10063                 return new ErrorExp();
10064             checkDeprecated(sc, f);
10065             checkPurity(sc, f);
10066             checkSafety(sc, f);
10067             checkNogc(sc, f);
10068             checkAccess(loc, sc, null, f);
10069 
10070             e1 = new DotVarExp(e1.loc, e1, f, false);
10071             e1 = e1.semantic(sc);
10072             t1 = e1.type;
10073         }
10074         else if (e1.op == TOKthis)
10075         {
10076             // same class constructor call
10077             auto ad = sc.func ? sc.func.isThis() : null;
10078             if (!ad || !sc.func.isCtorDeclaration())
10079             {
10080                 error("constructor call must be in a constructor");
10081                 return new ErrorExp();
10082             }
10083 
10084             if (!sc.intypeof && !(sc.callSuper & CSXhalt))
10085             {
10086                 if (sc.noctor || sc.callSuper & CSXlabel)
10087                     error("constructor calls not allowed in loops or after labels");
10088                 if (sc.callSuper & (CSXsuper_ctor | CSXthis_ctor))
10089                     error("multiple constructor calls");
10090                 if ((sc.callSuper & CSXreturn) && !(sc.callSuper & CSXany_ctor))
10091                     error("an earlier return statement skips constructor");
10092                 sc.callSuper |= CSXany_ctor | CSXthis_ctor;
10093             }
10094 
10095             tthis = ad.type.addMod(sc.func.type.mod);
10096             if (auto os = ad.ctor.isOverloadSet())
10097                 f = resolveOverloadSet(loc, sc, os, null, tthis, arguments);
10098             else
10099                 f = resolveFuncCall(loc, sc, ad.ctor, null, tthis, arguments, 0);
10100             if (!f || f.errors)
10101                 return new ErrorExp();
10102             checkDeprecated(sc, f);
10103             checkPurity(sc, f);
10104             checkSafety(sc, f);
10105             checkNogc(sc, f);
10106             //checkAccess(loc, sc, NULL, f);    // necessary?
10107 
10108             e1 = new DotVarExp(e1.loc, e1, f, false);
10109             e1 = e1.semantic(sc);
10110             t1 = e1.type;
10111 
10112             // BUG: this should really be done by checking the static
10113             // call graph
10114             if (f == sc.func)
10115             {
10116                 error("cyclic constructor call");
10117                 return new ErrorExp();
10118             }
10119         }
10120         else if (e1.op == TOKoverloadset)
10121         {
10122             auto os = (cast(OverExp)e1).vars;
10123             f = resolveOverloadSet(loc, sc, os, tiargs, tthis, arguments);
10124             if (!f)
10125                 return new ErrorExp();
10126             if (ethis)
10127                 e1 = new DotVarExp(loc, ethis, f, false);
10128             else
10129                 e1 = new VarExp(loc, f, false);
10130             goto Lagain;
10131         }
10132         else if (!t1)
10133         {
10134             error("function expected before (), not '%s'", e1.toChars());
10135             return new ErrorExp();
10136         }
10137         else if (t1.ty == Terror)
10138         {
10139             return new ErrorExp();
10140         }
10141         else if (t1.ty != Tfunction)
10142         {
10143             TypeFunction tf;
10144             const(char)* p;
10145             Dsymbol s;
10146             f = null;
10147             if (e1.op == TOKfunction)
10148             {
10149                 // function literal that direct called is always inferred.
10150                 assert((cast(FuncExp)e1).fd);
10151                 f = (cast(FuncExp)e1).fd;
10152                 tf = cast(TypeFunction)f.type;
10153                 p = "function literal";
10154             }
10155             else if (t1.ty == Tdelegate)
10156             {
10157                 TypeDelegate td = cast(TypeDelegate)t1;
10158                 assert(td.next.ty == Tfunction);
10159                 tf = cast(TypeFunction)td.next;
10160                 p = "delegate";
10161             }
10162             else if (t1.ty == Tpointer && (cast(TypePointer)t1).next.ty == Tfunction)
10163             {
10164                 tf = cast(TypeFunction)(cast(TypePointer)t1).next;
10165                 p = "function pointer";
10166             }
10167             else if (e1.op == TOKdotvar && (cast(DotVarExp)e1).var.isOverDeclaration())
10168             {
10169                 DotVarExp dve = cast(DotVarExp)e1;
10170                 f = resolveFuncCall(loc, sc, dve.var, tiargs, dve.e1.type, arguments, 2);
10171                 if (!f)
10172                     return new ErrorExp();
10173                 if (f.needThis())
10174                 {
10175                     dve.var = f;
10176                     dve.type = f.type;
10177                     dve.hasOverloads = false;
10178                     goto Lagain;
10179                 }
10180                 e1 = new VarExp(dve.loc, f, false);
10181                 Expression e = new CommaExp(loc, dve.e1, this);
10182                 return e.semantic(sc);
10183             }
10184             else if (e1.op == TOKvar && (cast(VarExp)e1).var.isOverDeclaration())
10185             {
10186                 s = (cast(VarExp)e1).var;
10187                 goto L2;
10188             }
10189             else if (e1.op == TOKtemplate)
10190             {
10191                 s = (cast(TemplateExp)e1).td;
10192             L2:
10193                 f = resolveFuncCall(loc, sc, s, tiargs, null, arguments);
10194                 if (!f || f.errors)
10195                     return new ErrorExp();
10196                 if (f.needThis())
10197                 {
10198                     if (hasThis(sc))
10199                     {
10200                         // Supply an implicit 'this', as in
10201                         //    this.ident
10202                         e1 = new DotVarExp(loc, (new ThisExp(loc)).semantic(sc), f, false);
10203                         goto Lagain;
10204                     }
10205                     else if (isNeedThisScope(sc, f))
10206                     {
10207                         error("need 'this' for '%s' of type '%s'", f.toChars(), f.type.toChars());
10208                         return new ErrorExp();
10209                     }
10210                 }
10211                 e1 = new VarExp(e1.loc, f, false);
10212                 goto Lagain;
10213             }
10214             else
10215             {
10216                 error("function expected before (), not %s of type %s", e1.toChars(), e1.type.toChars());
10217                 return new ErrorExp();
10218             }
10219 
10220             if (!tf.callMatch(null, arguments))
10221             {
10222                 OutBuffer buf;
10223                 buf.writeByte('(');
10224                 argExpTypesToCBuffer(&buf, arguments);
10225                 buf.writeByte(')');
10226                 if (tthis)
10227                     tthis.modToBuffer(&buf);
10228 
10229                 //printf("tf = %s, args = %s\n", tf->deco, (*arguments)[0]->type->deco);
10230                 .error(loc, "%s %s %s is not callable using argument types %s", p, e1.toChars(), parametersTypeToChars(tf.parameters, tf.varargs), buf.peekString());
10231 
10232                 return new ErrorExp();
10233             }
10234             // Purity and safety check should run after testing arguments matching
10235             if (f)
10236             {
10237                 checkPurity(sc, f);
10238                 checkSafety(sc, f);
10239                 checkNogc(sc, f);
10240                 if (f.checkNestedReference(sc, loc))
10241                     return new ErrorExp();
10242             }
10243             else if (sc.func && sc.intypeof != 1 && !(sc.flags & SCOPEctfe))
10244             {
10245                 bool err = false;
10246                 if (!tf.purity && !(sc.flags & SCOPEdebug) && sc.func.setImpure())
10247                 {
10248                     error("pure %s '%s' cannot call impure %s '%s'",
10249                         sc.func.kind(), sc.func.toPrettyChars(), p, e1.toChars());
10250                     err = true;
10251                 }
10252                 if (!tf.isnogc && sc.func.setGC())
10253                 {
10254                     error("@nogc %s '%s' cannot call non-@nogc %s '%s'",
10255                         sc.func.kind(), sc.func.toPrettyChars(), p, e1.toChars());
10256                     err = true;
10257                 }
10258                 if (tf.trust <= TRUSTsystem && sc.func.setUnsafe())
10259                 {
10260                     error("@safe %s '%s' cannot call @system %s '%s'",
10261                         sc.func.kind(), sc.func.toPrettyChars(), p, e1.toChars());
10262                     err = true;
10263                 }
10264                 if (err)
10265                     return new ErrorExp();
10266             }
10267 
10268             if (t1.ty == Tpointer)
10269             {
10270                 Expression e = new PtrExp(loc, e1);
10271                 e.type = tf;
10272                 e1 = e;
10273             }
10274             t1 = tf;
10275         }
10276         else if (e1.op == TOKvar)
10277         {
10278             // Do overload resolution
10279             VarExp ve = cast(VarExp)e1;
10280 
10281             f = ve.var.isFuncDeclaration();
10282             assert(f);
10283             tiargs = null;
10284 
10285             if (ve.hasOverloads)
10286                 f = resolveFuncCall(loc, sc, f, tiargs, null, arguments, 2);
10287             else
10288             {
10289                 f = f.toAliasFunc();
10290                 TypeFunction tf = cast(TypeFunction)f.type;
10291                 if (!tf.callMatch(null, arguments))
10292                 {
10293                     OutBuffer buf;
10294                     buf.writeByte('(');
10295                     argExpTypesToCBuffer(&buf, arguments);
10296                     buf.writeByte(')');
10297 
10298                     //printf("tf = %s, args = %s\n", tf->deco, (*arguments)[0]->type->deco);
10299                     .error(loc, "%s %s is not callable using argument types %s", e1.toChars(), parametersTypeToChars(tf.parameters, tf.varargs), buf.peekString());
10300 
10301                     f = null;
10302                 }
10303             }
10304             if (!f || f.errors)
10305                 return new ErrorExp();
10306 
10307             if (f.needThis())
10308             {
10309                 // Change the ancestor lambdas to delegate before hasThis(sc) call.
10310                 if (f.checkNestedReference(sc, loc))
10311                     return new ErrorExp();
10312 
10313                 if (hasThis(sc))
10314                 {
10315                     // Supply an implicit 'this', as in
10316                     //    this.ident
10317                     e1 = new DotVarExp(loc, (new ThisExp(loc)).semantic(sc), ve.var);
10318                     // Note: we cannot use f directly, because further overload resolution
10319                     // through the supplied 'this' may cause different result.
10320                     goto Lagain;
10321                 }
10322                 else if (isNeedThisScope(sc, f))
10323                 {
10324                     error("need 'this' for '%s' of type '%s'", f.toChars(), f.type.toChars());
10325                     return new ErrorExp();
10326                 }
10327             }
10328 
10329             checkDeprecated(sc, f);
10330             checkPurity(sc, f);
10331             checkSafety(sc, f);
10332             checkNogc(sc, f);
10333             checkAccess(loc, sc, null, f);
10334             if (f.checkNestedReference(sc, loc))
10335                 return new ErrorExp();
10336 
10337             ethis = null;
10338             tthis = null;
10339 
10340             if (ve.hasOverloads)
10341             {
10342                 e1 = new VarExp(ve.loc, f, false);
10343                 e1.type = f.type;
10344             }
10345             t1 = f.type;
10346         }
10347         assert(t1.ty == Tfunction);
10348 
10349         Expression argprefix;
10350         if (!arguments)
10351             arguments = new Expressions();
10352         if (functionParameters(loc, sc, cast(TypeFunction)t1, tthis, arguments, f, &type, &argprefix))
10353             return new ErrorExp();
10354 
10355         if (!type)
10356         {
10357             e1 = e1org; // Bugzilla 10922, avoid recursive expression printing
10358             error("forward reference to inferred return type of function call '%s'", toChars());
10359             return new ErrorExp();
10360         }
10361 
10362         if (f && f.tintro)
10363         {
10364             Type t = type;
10365             int offset = 0;
10366             TypeFunction tf = cast(TypeFunction)f.tintro;
10367             if (tf.next.isBaseOf(t, &offset) && offset)
10368             {
10369                 type = tf.next;
10370                 return combine(argprefix, castTo(sc, t));
10371             }
10372         }
10373 
10374         // Handle the case of a direct lambda call
10375         if (f && f.isFuncLiteralDeclaration() && sc.func && !sc.intypeof)
10376         {
10377             f.tookAddressOf = 0;
10378         }
10379 
10380         return combine(argprefix, this);
10381     }
10382 
10383     override bool isLvalue()
10384     {
10385         Type tb = e1.type.toBasetype();
10386         if (tb.ty == Tdelegate || tb.ty == Tpointer)
10387             tb = tb.nextOf();
10388         if (tb.ty == Tfunction && (cast(TypeFunction)tb).isref)
10389         {
10390             if (e1.op == TOKdotvar)
10391                 if ((cast(DotVarExp)e1).var.isCtorDeclaration())
10392                     return false;
10393             return true; // function returns a reference
10394         }
10395         return false;
10396     }
10397 
10398     override Expression toLvalue(Scope* sc, Expression e)
10399     {
10400         if (isLvalue())
10401             return this;
10402         return Expression.toLvalue(sc, e);
10403     }
10404 
10405     override Expression addDtorHook(Scope* sc)
10406     {
10407         /* Only need to add dtor hook if it's a type that needs destruction.
10408          * Use same logic as VarDeclaration::callScopeDtor()
10409          */
10410 
10411         if (e1.type && e1.type.ty == Tfunction)
10412         {
10413             TypeFunction tf = cast(TypeFunction)e1.type;
10414             if (tf.isref)
10415                 return this;
10416         }
10417 
10418         Type tv = type.baseElemOf();
10419         if (tv.ty == Tstruct)
10420         {
10421             TypeStruct ts = cast(TypeStruct)tv;
10422             StructDeclaration sd = ts.sym;
10423             if (sd.dtor)
10424             {
10425                 /* Type needs destruction, so declare a tmp
10426                  * which the back end will recognize and call dtor on
10427                  */
10428                 auto tmp = copyToTemp(0, "__tmpfordtor", this);
10429                 auto de = new DeclarationExp(loc, tmp);
10430                 auto ve = new VarExp(loc, tmp);
10431                 Expression e = new CommaExp(loc, de, new VarExp(loc, tmp));
10432                 e = e.semantic(sc);
10433                 return e;
10434             }
10435         }
10436         return this;
10437     }
10438 
10439     override void accept(Visitor v)
10440     {
10441         v.visit(this);
10442     }
10443 }
10444 
10445 FuncDeclaration isFuncAddress(Expression e, bool* hasOverloads = null)
10446 {
10447     if (e.op == TOKaddress)
10448     {
10449         auto ae1 = (cast(AddrExp)e).e1;
10450         if (ae1.op == TOKvar)
10451         {
10452             auto ve = cast(VarExp)ae1;
10453             if (hasOverloads)
10454                 *hasOverloads = ve.hasOverloads;
10455             return ve.var.isFuncDeclaration();
10456         }
10457         if (ae1.op == TOKdotvar)
10458         {
10459             auto dve = cast(DotVarExp)ae1;
10460             if (hasOverloads)
10461                 *hasOverloads = dve.hasOverloads;
10462             return dve.var.isFuncDeclaration();
10463         }
10464     }
10465     else
10466     {
10467         if (e.op == TOKsymoff)
10468         {
10469             auto soe = cast(SymOffExp)e;
10470             if (hasOverloads)
10471                 *hasOverloads = soe.hasOverloads;
10472             return soe.var.isFuncDeclaration();
10473         }
10474         if (e.op == TOKdelegate)
10475         {
10476             auto dge = cast(DelegateExp)e;
10477             if (hasOverloads)
10478                 *hasOverloads = dge.hasOverloads;
10479             return dge.func.isFuncDeclaration();
10480         }
10481     }
10482     return null;
10483 }
10484 
10485 /***********************************************************
10486  */
10487 extern (C++) final class AddrExp : UnaExp
10488 {
10489     extern (D) this(Loc loc, Expression e)
10490     {
10491         super(loc, TOKaddress, __traits(classInstanceSize, AddrExp), e);
10492     }
10493 
10494     override Expression semantic(Scope* sc)
10495     {
10496         static if (LOGSEMANTIC)
10497         {
10498             printf("AddrExp::semantic('%s')\n", toChars());
10499         }
10500         if (type)
10501             return this;
10502 
10503         if (Expression ex = unaSemantic(sc))
10504             return ex;
10505 
10506         int wasCond = e1.op == TOKquestion;
10507 
10508         if (e1.op == TOKdotti)
10509         {
10510             DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)e1;
10511             TemplateInstance ti = dti.ti;
10512             {
10513                 //assert(ti.needsTypeInference(sc));
10514                 ti.semantic(sc);
10515                 if (!ti.inst || ti.errors) // if template failed to expand
10516                     return new ErrorExp();
10517                 Dsymbol s = ti.toAlias();
10518                 FuncDeclaration f = s.isFuncDeclaration();
10519                 if (f)
10520                 {
10521                     e1 = new DotVarExp(e1.loc, dti.e1, f);
10522                     e1 = e1.semantic(sc);
10523                 }
10524             }
10525         }
10526         else if (e1.op == TOKscope)
10527         {
10528             TemplateInstance ti = (cast(ScopeExp)e1).sds.isTemplateInstance();
10529             if (ti)
10530             {
10531                 //assert(ti.needsTypeInference(sc));
10532                 ti.semantic(sc);
10533                 if (!ti.inst || ti.errors) // if template failed to expand
10534                     return new ErrorExp();
10535                 Dsymbol s = ti.toAlias();
10536                 FuncDeclaration f = s.isFuncDeclaration();
10537                 if (f)
10538                 {
10539                     e1 = new VarExp(e1.loc, f);
10540                     e1 = e1.semantic(sc);
10541                 }
10542             }
10543         }
10544         e1 = e1.toLvalue(sc, null);
10545         if (e1.op == TOKerror)
10546             return e1;
10547         if (checkNonAssignmentArrayOp(e1))
10548             return new ErrorExp();
10549 
10550         if (!e1.type)
10551         {
10552             error("cannot take address of %s", e1.toChars());
10553             return new ErrorExp();
10554         }
10555 
10556         bool hasOverloads;
10557         if (auto f = isFuncAddress(this, &hasOverloads))
10558         {
10559             if (!hasOverloads && f.checkForwardRef(loc))
10560                 return new ErrorExp();
10561         }
10562         else if (!e1.type.deco)
10563         {
10564             if (e1.op == TOKvar)
10565             {
10566                 VarExp ve = cast(VarExp)e1;
10567                 Declaration d = ve.var;
10568                 error("forward reference to %s %s", d.kind(), d.toChars());
10569             }
10570             else
10571                 error("forward reference to %s", e1.toChars());
10572             return new ErrorExp();
10573         }
10574 
10575         type = e1.type.pointerTo();
10576 
10577         // See if this should really be a delegate
10578         if (e1.op == TOKdotvar)
10579         {
10580             DotVarExp dve = cast(DotVarExp)e1;
10581             FuncDeclaration f = dve.var.isFuncDeclaration();
10582             if (f)
10583             {
10584                 f = f.toAliasFunc(); // FIXME, should see overloads - Bugzilla 1983
10585                 if (!dve.hasOverloads)
10586                     f.tookAddressOf++;
10587 
10588                 Expression e;
10589                 if (f.needThis())
10590                     e = new DelegateExp(loc, dve.e1, f, dve.hasOverloads);
10591                 else // It is a function pointer. Convert &v.f() --> (v, &V.f())
10592                     e = new CommaExp(loc, dve.e1, new AddrExp(loc, new VarExp(loc, f, dve.hasOverloads)));
10593                 e = e.semantic(sc);
10594                 return e;
10595             }
10596 
10597             // Look for misaligned pointer in @safe mode
10598             if (checkUnsafeAccess(sc, dve, !type.isMutable(), true))
10599                 return new ErrorExp();
10600         }
10601         else if (e1.op == TOKvar)
10602         {
10603             VarExp ve = cast(VarExp)e1;
10604             VarDeclaration v = ve.var.isVarDeclaration();
10605             if (v)
10606             {
10607                 if (!v.canTakeAddressOf())
10608                 {
10609                     error("cannot take address of %s", e1.toChars());
10610                     return new ErrorExp();
10611                 }
10612                 if (sc.func && !sc.intypeof && !v.isDataseg())
10613                 {
10614                     if (sc.func.setUnsafe())
10615                     {
10616                         const(char)* p = v.isParameter() ? "parameter" : "local";
10617                         error("cannot take address of %s %s in @safe function %s", p, v.toChars(), sc.func.toChars());
10618                     }
10619                 }
10620 
10621                 ve.checkPurity(sc, v);
10622             }
10623             FuncDeclaration f = ve.var.isFuncDeclaration();
10624             if (f)
10625             {
10626                 /* Because nested functions cannot be overloaded,
10627                  * mark here that we took its address because castTo()
10628                  * may not be called with an exact match.
10629                  */
10630                 if (!ve.hasOverloads || f.isNested())
10631                     f.tookAddressOf++;
10632                 if (f.isNested())
10633                 {
10634                     if (f.isFuncLiteralDeclaration())
10635                     {
10636                         if (!f.FuncDeclaration.isNested())
10637                         {
10638                             /* Supply a 'null' for a this pointer if no this is available
10639                              */
10640                             Expression e = new DelegateExp(loc, new NullExp(loc, Type.tnull), f, ve.hasOverloads);
10641                             e = e.semantic(sc);
10642                             return e;
10643                         }
10644                     }
10645                     Expression e = new DelegateExp(loc, e1, f, ve.hasOverloads);
10646                     e = e.semantic(sc);
10647                     return e;
10648                 }
10649                 if (f.needThis())
10650                 {
10651                     if (hasThis(sc))
10652                     {
10653                         /* Should probably supply 'this' after overload resolution,
10654                          * not before.
10655                          */
10656                         Expression ethis = new ThisExp(loc);
10657                         Expression e = new DelegateExp(loc, ethis, f, ve.hasOverloads);
10658                         e = e.semantic(sc);
10659                         return e;
10660                     }
10661                     if (sc.func && !sc.intypeof)
10662                     {
10663                         if (sc.func.setUnsafe())
10664                         {
10665                             error("'this' reference necessary to take address of member %s in @safe function %s", f.toChars(), sc.func.toChars());
10666                         }
10667                     }
10668                 }
10669             }
10670         }
10671         else if (e1.op == TOKcall)
10672         {
10673             CallExp ce = cast(CallExp)e1;
10674             if (ce.e1.type.ty == Tfunction)
10675             {
10676                 TypeFunction tf = cast(TypeFunction)ce.e1.type;
10677                 if (tf.isref && sc.func && !sc.intypeof && sc.func.setUnsafe())
10678                 {
10679                     error("cannot take address of ref return of %s() in @safe function %s",
10680                         ce.e1.toChars(), sc.func.toChars());
10681                 }
10682             }
10683         }
10684         else if (wasCond)
10685         {
10686             /* a ? b : c was transformed to *(a ? &b : &c), but we still
10687              * need to do safety checks
10688              */
10689             assert(e1.op == TOKstar);
10690             PtrExp pe = cast(PtrExp)e1;
10691             assert(pe.e1.op == TOKquestion);
10692             CondExp ce = cast(CondExp)pe.e1;
10693             assert(ce.e1.op == TOKaddress);
10694             assert(ce.e2.op == TOKaddress);
10695 
10696             // Re-run semantic on the address expressions only
10697             ce.e1.type = null;
10698             ce.e1 = ce.e1.semantic(sc);
10699             ce.e2.type = null;
10700             ce.e2 = ce.e2.semantic(sc);
10701         }
10702         return optimize(WANTvalue);
10703     }
10704 
10705     override void accept(Visitor v)
10706     {
10707         v.visit(this);
10708     }
10709 }
10710 
10711 /***********************************************************
10712  */
10713 extern (C++) final class PtrExp : UnaExp
10714 {
10715     extern (D) this(Loc loc, Expression e)
10716     {
10717         super(loc, TOKstar, __traits(classInstanceSize, PtrExp), e);
10718         //if (e->type)
10719         //  type = ((TypePointer *)e->type)->next;
10720     }
10721 
10722     extern (D) this(Loc loc, Expression e, Type t)
10723     {
10724         super(loc, TOKstar, __traits(classInstanceSize, PtrExp), e);
10725         type = t;
10726     }
10727 
10728     override Expression semantic(Scope* sc)
10729     {
10730         static if (LOGSEMANTIC)
10731         {
10732             printf("PtrExp::semantic('%s')\n", toChars());
10733         }
10734         if (type)
10735             return this;
10736 
10737         Expression e = op_overload(sc);
10738         if (e)
10739             return e;
10740 
10741         Type tb = e1.type.toBasetype();
10742         switch (tb.ty)
10743         {
10744         case Tpointer:
10745             type = (cast(TypePointer)tb).next;
10746             break;
10747 
10748         case Tsarray:
10749         case Tarray:
10750             if (isNonAssignmentArrayOp(e1))
10751                 goto default;
10752             error("using * on an array is no longer supported; use *(%s).ptr instead", e1.toChars());
10753             type = (cast(TypeArray)tb).next;
10754             e1 = e1.castTo(sc, type.pointerTo());
10755             break;
10756 
10757         default:
10758             error("can only * a pointer, not a '%s'", e1.type.toChars());
10759             goto case Terror;
10760         case Terror:
10761             return new ErrorExp();
10762         }
10763         if (checkValue())
10764             return new ErrorExp();
10765 
10766         return this;
10767     }
10768 
10769     override int checkModifiable(Scope* sc, int flag)
10770     {
10771         if (e1.op == TOKsymoff)
10772         {
10773             SymOffExp se = cast(SymOffExp)e1;
10774             return se.var.checkModify(loc, sc, type, null, flag);
10775         }
10776         else if (e1.op == TOKaddress)
10777         {
10778             AddrExp ae = cast(AddrExp)e1;
10779             return ae.e1.checkModifiable(sc, flag);
10780         }
10781         return 1;
10782     }
10783 
10784     override bool isLvalue()
10785     {
10786         return true;
10787     }
10788 
10789     override Expression toLvalue(Scope* sc, Expression e)
10790     {
10791         return this;
10792     }
10793 
10794     override Expression modifiableLvalue(Scope* sc, Expression e)
10795     {
10796         //printf("PtrExp::modifiableLvalue() %s, type %s\n", toChars(), type->toChars());
10797         return Expression.modifiableLvalue(sc, e);
10798     }
10799 
10800     override void accept(Visitor v)
10801     {
10802         v.visit(this);
10803     }
10804 }
10805 
10806 /***********************************************************
10807  */
10808 extern (C++) final class NegExp : UnaExp
10809 {
10810     extern (D) this(Loc loc, Expression e)
10811     {
10812         super(loc, TOKneg, __traits(classInstanceSize, NegExp), e);
10813     }
10814 
10815     override Expression semantic(Scope* sc)
10816     {
10817         static if (LOGSEMANTIC)
10818         {
10819             printf("NegExp::semantic('%s')\n", toChars());
10820         }
10821         if (type)
10822             return this;
10823 
10824         Expression e = op_overload(sc);
10825         if (e)
10826             return e;
10827 
10828         type = e1.type;
10829         Type tb = type.toBasetype();
10830         if (tb.ty == Tarray || tb.ty == Tsarray)
10831         {
10832             if (!isArrayOpValid(e1))
10833             {
10834                 error("invalid array operation %s (possible missing [])", toChars());
10835                 return new ErrorExp();
10836             }
10837             return this;
10838         }
10839 
10840         if (e1.checkNoBool())
10841             return new ErrorExp();
10842         if (e1.checkArithmetic())
10843             return new ErrorExp();
10844 
10845         return this;
10846     }
10847 
10848     override void accept(Visitor v)
10849     {
10850         v.visit(this);
10851     }
10852 }
10853 
10854 /***********************************************************
10855  */
10856 extern (C++) final class UAddExp : UnaExp
10857 {
10858     extern (D) this(Loc loc, Expression e)
10859     {
10860         super(loc, TOKuadd, __traits(classInstanceSize, UAddExp), e);
10861     }
10862 
10863     override Expression semantic(Scope* sc)
10864     {
10865         static if (LOGSEMANTIC)
10866         {
10867             printf("UAddExp::semantic('%s')\n", toChars());
10868         }
10869         assert(!type);
10870 
10871         Expression e = op_overload(sc);
10872         if (e)
10873             return e;
10874 
10875         if (e1.checkNoBool())
10876             return new ErrorExp();
10877         if (e1.checkArithmetic())
10878             return new ErrorExp();
10879 
10880         return e1;
10881     }
10882 
10883     override void accept(Visitor v)
10884     {
10885         v.visit(this);
10886     }
10887 }
10888 
10889 /***********************************************************
10890  */
10891 extern (C++) final class ComExp : UnaExp
10892 {
10893     extern (D) this(Loc loc, Expression e)
10894     {
10895         super(loc, TOKtilde, __traits(classInstanceSize, ComExp), e);
10896     }
10897 
10898     override Expression semantic(Scope* sc)
10899     {
10900         if (type)
10901             return this;
10902 
10903         Expression e = op_overload(sc);
10904         if (e)
10905             return e;
10906 
10907         type = e1.type;
10908         Type tb = type.toBasetype();
10909         if (tb.ty == Tarray || tb.ty == Tsarray)
10910         {
10911             if (!isArrayOpValid(e1))
10912             {
10913                 error("invalid array operation %s (possible missing [])", toChars());
10914                 return new ErrorExp();
10915             }
10916             return this;
10917         }
10918 
10919         if (e1.checkNoBool())
10920             return new ErrorExp();
10921         if (e1.checkIntegral())
10922             return new ErrorExp();
10923 
10924         return this;
10925     }
10926 
10927     override void accept(Visitor v)
10928     {
10929         v.visit(this);
10930     }
10931 }
10932 
10933 /***********************************************************
10934  */
10935 extern (C++) final class NotExp : UnaExp
10936 {
10937     extern (D) this(Loc loc, Expression e)
10938     {
10939         super(loc, TOKnot, __traits(classInstanceSize, NotExp), e);
10940     }
10941 
10942     override Expression semantic(Scope* sc)
10943     {
10944         if (type)
10945             return this;
10946 
10947         setNoderefOperand();
10948 
10949         // Note there is no operator overload
10950         if (Expression ex = unaSemantic(sc))
10951             return ex;
10952         e1 = resolveProperties(sc, e1);
10953         e1 = e1.toBoolean(sc);
10954         if (e1.type == Type.terror)
10955             return e1;
10956 
10957         // Bugzilla 13910: Today NotExp can take an array as its operand.
10958         if (checkNonAssignmentArrayOp(e1))
10959             return new ErrorExp();
10960 
10961         type = Type.tbool;
10962         return this;
10963     }
10964 
10965     override void accept(Visitor v)
10966     {
10967         v.visit(this);
10968     }
10969 }
10970 
10971 /***********************************************************
10972  */
10973 extern (C++) final class DeleteExp : UnaExp
10974 {
10975     extern (D) this(Loc loc, Expression e)
10976     {
10977         super(loc, TOKdelete, __traits(classInstanceSize, DeleteExp), e);
10978     }
10979 
10980     override Expression semantic(Scope* sc)
10981     {
10982         if (Expression ex = unaSemantic(sc))
10983             return ex;
10984         e1 = resolveProperties(sc, e1);
10985         e1 = e1.modifiableLvalue(sc, null);
10986         if (e1.op == TOKerror)
10987             return e1;
10988         type = Type.tvoid;
10989 
10990         AggregateDeclaration ad = null;
10991         Type tb = e1.type.toBasetype();
10992         switch (tb.ty)
10993         {
10994         case Tclass:
10995             {
10996                 auto cd = (cast(TypeClass)tb).sym;
10997                 if (cd.isCOMinterface())
10998                 {
10999                     /* Because COM classes are deleted by IUnknown.Release()
11000                      */
11001                     error("cannot delete instance of COM interface %s", cd.toChars());
11002                     return new ErrorExp();
11003                 }
11004 
11005                 ad = cd;
11006                 break;
11007             }
11008         case Tpointer:
11009             tb = (cast(TypePointer)tb).next.toBasetype();
11010             if (tb.ty == Tstruct)
11011             {
11012                 ad = (cast(TypeStruct)tb).sym;
11013                 auto f = ad.aggDelete;
11014                 auto fd = ad.dtor;
11015                 if (!f)
11016                 {
11017                     semanticTypeInfo(sc, tb);
11018                     break;
11019                 }
11020 
11021                 /* Construct:
11022                  *      ea = copy e1 to a tmp to do side effects only once
11023                  *      eb = call destructor
11024                  *      ec = call deallocator
11025                  */
11026                 Expression ea = null;
11027                 Expression eb = null;
11028                 Expression ec = null;
11029                 VarDeclaration v = null;
11030                 if (fd && f)
11031                 {
11032                     v = copyToTemp(0, "__tmpea", e1);
11033                     v.semantic(sc);
11034                     ea = new DeclarationExp(loc, v);
11035                     ea.type = v.type;
11036                 }
11037                 if (fd)
11038                 {
11039                     Expression e = ea ? new VarExp(loc, v) : e1;
11040                     e = new DotVarExp(Loc(), e, fd, false);
11041                     eb = new CallExp(loc, e);
11042                     eb = eb.semantic(sc);
11043                 }
11044                 if (f)
11045                 {
11046                     Type tpv = Type.tvoid.pointerTo();
11047                     Expression e = ea ? new VarExp(loc, v) : e1.castTo(sc, tpv);
11048                     e = new CallExp(loc, new VarExp(loc, f, false), e);
11049                     ec = e.semantic(sc);
11050                 }
11051                 ea = combine(ea, eb);
11052                 ea = combine(ea, ec);
11053                 assert(ea);
11054                 return ea;
11055             }
11056             break;
11057 
11058         case Tarray:
11059             {
11060                 Type tv = tb.nextOf().baseElemOf();
11061                 if (tv.ty == Tstruct)
11062                 {
11063                     ad = (cast(TypeStruct)tv).sym;
11064                     if (ad.dtor)
11065                         semanticTypeInfo(sc, ad.type);
11066                 }
11067                 break;
11068             }
11069         default:
11070             error("cannot delete type %s", e1.type.toChars());
11071             return new ErrorExp();
11072         }
11073 
11074         bool err = false;
11075         if (ad)
11076         {
11077             if (ad.dtor)
11078             {
11079                 err |= checkPurity(sc, ad.dtor);
11080                 err |= checkSafety(sc, ad.dtor);
11081                 err |= checkNogc(sc, ad.dtor);
11082             }
11083             if (ad.aggDelete && tb.ty != Tarray)
11084             {
11085                 err |= checkPurity(sc, ad.aggDelete);
11086                 err |= checkSafety(sc, ad.aggDelete);
11087                 err |= checkNogc(sc, ad.aggDelete);
11088             }
11089             if (err)
11090                 return new ErrorExp();
11091         }
11092 
11093         // unsafe
11094         if (!sc.intypeof && sc.func && sc.func.setUnsafe())
11095         {
11096             error("%s is not @safe but is used in @safe function %s", toChars(), sc.func.toChars());
11097             err = true;
11098         }
11099         if (err)
11100             return new ErrorExp();
11101 
11102         return this;
11103     }
11104 
11105     override Expression toBoolean(Scope* sc)
11106     {
11107         error("delete does not give a boolean result");
11108         return new ErrorExp();
11109     }
11110 
11111     override void accept(Visitor v)
11112     {
11113         v.visit(this);
11114     }
11115 }
11116 
11117 /***********************************************************
11118  * Possible to cast to one type while painting to another type
11119  */
11120 extern (C++) final class CastExp : UnaExp
11121 {
11122     Type to;                    // type to cast to
11123     ubyte mod = cast(ubyte)~0;  // MODxxxxx
11124 
11125     extern (D) this(Loc loc, Expression e, Type t)
11126     {
11127         super(loc, TOKcast, __traits(classInstanceSize, CastExp), e);
11128         this.to = t;
11129     }
11130 
11131     /* For cast(const) and cast(immutable)
11132      */
11133     extern (D) this(Loc loc, Expression e, ubyte mod)
11134     {
11135         super(loc, TOKcast, __traits(classInstanceSize, CastExp), e);
11136         this.mod = mod;
11137     }
11138 
11139     override Expression syntaxCopy()
11140     {
11141         return to ? new CastExp(loc, e1.syntaxCopy(), to.syntaxCopy()) : new CastExp(loc, e1.syntaxCopy(), mod);
11142     }
11143 
11144     override Expression semantic(Scope* sc)
11145     {
11146         static if (LOGSEMANTIC)
11147         {
11148             printf("CastExp::semantic('%s')\n", toChars());
11149         }
11150         //static int x; assert(++x < 10);
11151         if (type)
11152             return this;
11153 
11154         if (to)
11155         {
11156             to = to.semantic(loc, sc);
11157             if (to == Type.terror)
11158                 return new ErrorExp();
11159 
11160             if (!to.hasPointers())
11161                 setNoderefOperand();
11162 
11163             // When e1 is a template lambda, this cast may instantiate it with
11164             // the type 'to'.
11165             e1 = inferType(e1, to);
11166         }
11167 
11168         if (auto e = unaSemantic(sc))
11169             return e;
11170         auto e1x = resolveProperties(sc, e1);
11171         if (e1x.op == TOKerror)
11172             return e1x;
11173         if (e1x.checkType())
11174             return new ErrorExp();
11175         e1 = e1x;
11176 
11177         if (!e1.type)
11178         {
11179             error("cannot cast %s", e1.toChars());
11180             return new ErrorExp();
11181         }
11182 
11183         if (!to) // Handle cast(const) and cast(immutable), etc.
11184         {
11185             to = e1.type.castMod(mod);
11186             to = to.semantic(loc, sc);
11187             if (to == Type.terror)
11188                 return new ErrorExp();
11189         }
11190 
11191         if (to.ty == Ttuple)
11192         {
11193             error("cannot cast %s to tuple type %s", e1.toChars(), to.toChars());
11194             return new ErrorExp();
11195         }
11196 
11197         // cast(void) is used to mark e1 as unused, so it is safe
11198         if (to.ty == Tvoid)
11199         {
11200             type = to;
11201             return this;
11202         }
11203 
11204         if (!to.equals(e1.type) && mod == cast(ubyte)~0)
11205         {
11206             if (Expression e = op_overload(sc))
11207                 return e.implicitCastTo(sc, to);
11208         }
11209 
11210         Type t1b = e1.type.toBasetype();
11211         Type tob = to.toBasetype();
11212 
11213         if (tob.ty == Tstruct && !tob.equals(t1b))
11214         {
11215             /* Look to replace:
11216              *  cast(S)t
11217              * with:
11218              *  S(t)
11219              */
11220 
11221             // Rewrite as to.call(e1)
11222             Expression e = new TypeExp(loc, to);
11223             e = new CallExp(loc, e, e1);
11224             e = e.trySemantic(sc);
11225             if (e)
11226                 return e;
11227         }
11228 
11229         if (!t1b.equals(tob) && (t1b.ty == Tarray || t1b.ty == Tsarray))
11230         {
11231             if (checkNonAssignmentArrayOp(e1))
11232                 return new ErrorExp();
11233         }
11234 
11235         // Look for casting to a vector type
11236         if (tob.ty == Tvector && t1b.ty != Tvector)
11237         {
11238             return new VectorExp(loc, e1, to);
11239         }
11240 
11241         Expression ex = e1.castTo(sc, to);
11242         if (ex.op == TOKerror)
11243             return ex;
11244 
11245         // Check for unsafe casts
11246         if (sc.func && !sc.intypeof &&
11247             !isSafeCast(ex, t1b, tob) &&
11248             sc.func.setUnsafe())
11249         {
11250             error("cast from %s to %s not allowed in safe code", e1.type.toChars(), to.toChars());
11251             return new ErrorExp();
11252         }
11253 
11254         return ex;
11255     }
11256 
11257     override void accept(Visitor v)
11258     {
11259         v.visit(this);
11260     }
11261 }
11262 
11263 /***********************************************************
11264  */
11265 extern (C++) final class VectorExp : UnaExp
11266 {
11267     TypeVector to;      // the target vector type before semantic()
11268     uint dim = ~0;      // number of elements in the vector
11269 
11270     extern (D) this(Loc loc, Expression e, Type t)
11271     {
11272         super(loc, TOKvector, __traits(classInstanceSize, VectorExp), e);
11273         assert(t.ty == Tvector);
11274         to = cast(TypeVector)t;
11275     }
11276 
11277     override Expression syntaxCopy()
11278     {
11279         return new VectorExp(loc, e1.syntaxCopy(), to.syntaxCopy());
11280     }
11281 
11282     override Expression semantic(Scope* sc)
11283     {
11284         static if (LOGSEMANTIC)
11285         {
11286             printf("VectorExp::semantic('%s')\n", toChars());
11287         }
11288         if (type)
11289             return this;
11290 
11291         e1 = e1.semantic(sc);
11292         type = to.semantic(loc, sc);
11293         if (e1.op == TOKerror || type.ty == Terror)
11294             return e1;
11295 
11296         Type tb = type.toBasetype();
11297         assert(tb.ty == Tvector);
11298         TypeVector tv = cast(TypeVector)tb;
11299         Type te = tv.elementType();
11300         dim = cast(int)(tv.size(loc) / te.size(loc));
11301 
11302         bool checkElem(Expression elem)
11303         {
11304             if (elem.isConst() == 1)
11305                 return false;
11306 
11307              error("constant expression expected, not %s", elem.toChars());
11308              return true;
11309         }
11310 
11311         e1 = e1.optimize(WANTvalue);
11312         bool result;
11313         if (e1.op == TOKarrayliteral)
11314         {
11315             foreach (i; 0 .. dim)
11316             {
11317                 // Do not stop on first error - check all AST nodes even if error found
11318                 result |= checkElem((cast(ArrayLiteralExp)e1).getElement(i));
11319             }
11320         }
11321         else
11322             result = checkElem(e1);
11323 
11324         return result ? new ErrorExp() : this;
11325     }
11326 
11327     override void accept(Visitor v)
11328     {
11329         v.visit(this);
11330     }
11331 }
11332 
11333 /***********************************************************
11334  */
11335 extern (C++) final class SliceExp : UnaExp
11336 {
11337     Expression upr;             // null if implicit 0
11338     Expression lwr;             // null if implicit [length - 1]
11339     VarDeclaration lengthVar;
11340     bool upperIsInBounds;       // true if upr <= e1.length
11341     bool lowerIsLessThanUpper;  // true if lwr <= upr
11342 
11343     /************************************************************/
11344     extern (D) this(Loc loc, Expression e1, IntervalExp ie)
11345     {
11346         super(loc, TOKslice, __traits(classInstanceSize, SliceExp), e1);
11347         this.upr = ie ? ie.upr : null;
11348         this.lwr = ie ? ie.lwr : null;
11349     }
11350 
11351     extern (D) this(Loc loc, Expression e1, Expression lwr, Expression upr)
11352     {
11353         super(loc, TOKslice, __traits(classInstanceSize, SliceExp), e1);
11354         this.upr = upr;
11355         this.lwr = lwr;
11356     }
11357 
11358     override Expression syntaxCopy()
11359     {
11360         auto se = new SliceExp(loc, e1.syntaxCopy(), lwr ? lwr.syntaxCopy() : null, upr ? upr.syntaxCopy() : null);
11361         se.lengthVar = this.lengthVar; // bug7871
11362         return se;
11363     }
11364 
11365     override Expression semantic(Scope* sc)
11366     {
11367         static if (LOGSEMANTIC)
11368         {
11369             printf("SliceExp::semantic('%s')\n", toChars());
11370         }
11371         if (type)
11372             return this;
11373 
11374         // operator overloading should be handled in ArrayExp already.
11375         if (Expression ex = unaSemantic(sc))
11376             return ex;
11377         e1 = resolveProperties(sc, e1);
11378         if (e1.op == TOKtype && e1.type.ty != Ttuple)
11379         {
11380             if (lwr || upr)
11381             {
11382                 error("cannot slice type '%s'", e1.toChars());
11383                 return new ErrorExp();
11384             }
11385             Expression e = new TypeExp(loc, e1.type.arrayOf());
11386             return e.semantic(sc);
11387         }
11388         if (!lwr && !upr)
11389         {
11390             if (e1.op == TOKarrayliteral)
11391             {
11392                 // Convert [a,b,c][] to [a,b,c]
11393                 Type t1b = e1.type.toBasetype();
11394                 Expression e = e1;
11395                 if (t1b.ty == Tsarray)
11396                 {
11397                     e = e.copy();
11398                     e.type = t1b.nextOf().arrayOf();
11399                 }
11400                 return e;
11401             }
11402             if (e1.op == TOKslice)
11403             {
11404                 // Convert e[][] to e[]
11405                 SliceExp se = cast(SliceExp)e1;
11406                 if (!se.lwr && !se.upr)
11407                     return se;
11408             }
11409             if (isArrayOpOperand(e1))
11410             {
11411                 // Convert (a[]+b[])[] to a[]+b[]
11412                 return e1;
11413             }
11414         }
11415         if (e1.op == TOKerror)
11416             return e1;
11417         if (e1.type.ty == Terror)
11418             return new ErrorExp();
11419 
11420         Type t1b = e1.type.toBasetype();
11421         if (t1b.ty == Tpointer)
11422         {
11423             if ((cast(TypePointer)t1b).next.ty == Tfunction)
11424             {
11425                 error("cannot slice function pointer %s", e1.toChars());
11426                 return new ErrorExp();
11427             }
11428             if (!lwr || !upr)
11429             {
11430                 error("need upper and lower bound to slice pointer");
11431                 return new ErrorExp();
11432             }
11433             if (sc.func && !sc.intypeof && sc.func.setUnsafe())
11434             {
11435                 error("pointer slicing not allowed in safe functions");
11436                 return new ErrorExp();
11437             }
11438         }
11439         else if (t1b.ty == Tarray)
11440         {
11441         }
11442         else if (t1b.ty == Tsarray)
11443         {
11444         }
11445         else if (t1b.ty == Ttuple)
11446         {
11447             if (!lwr && !upr)
11448                 return e1;
11449             if (!lwr || !upr)
11450             {
11451                 error("need upper and lower bound to slice tuple");
11452                 return new ErrorExp();
11453             }
11454         }
11455         else
11456         {
11457             error("%s cannot be sliced with []", t1b.ty == Tvoid ? e1.toChars() : t1b.toChars());
11458             return new ErrorExp();
11459         }
11460 
11461         /* Run semantic on lwr and upr.
11462          */
11463         Scope* scx = sc;
11464         if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
11465         {
11466             // Create scope for 'length' variable
11467             ScopeDsymbol sym = new ArrayScopeSymbol(sc, this);
11468             sym.loc = loc;
11469             sym.parent = sc.scopesym;
11470             sc = sc.push(sym);
11471         }
11472         if (lwr)
11473         {
11474             if (t1b.ty == Ttuple)
11475                 sc = sc.startCTFE();
11476             lwr = lwr.semantic(sc);
11477             lwr = resolveProperties(sc, lwr);
11478             if (t1b.ty == Ttuple)
11479                 sc = sc.endCTFE();
11480             lwr = lwr.implicitCastTo(sc, Type.tsize_t);
11481         }
11482         if (upr)
11483         {
11484             if (t1b.ty == Ttuple)
11485                 sc = sc.startCTFE();
11486             upr = upr.semantic(sc);
11487             upr = resolveProperties(sc, upr);
11488             if (t1b.ty == Ttuple)
11489                 sc = sc.endCTFE();
11490             upr = upr.implicitCastTo(sc, Type.tsize_t);
11491         }
11492         if (sc != scx)
11493             sc = sc.pop();
11494         if (lwr && lwr.type == Type.terror || upr && upr.type == Type.terror)
11495         {
11496             return new ErrorExp();
11497         }
11498 
11499         if (t1b.ty == Ttuple)
11500         {
11501             lwr = lwr.ctfeInterpret();
11502             upr = upr.ctfeInterpret();
11503             uinteger_t i1 = lwr.toUInteger();
11504             uinteger_t i2 = upr.toUInteger();
11505 
11506             TupleExp te;
11507             TypeTuple tup;
11508             size_t length;
11509             if (e1.op == TOKtuple) // slicing an expression tuple
11510             {
11511                 te = cast(TupleExp)e1;
11512                 tup = null;
11513                 length = te.exps.dim;
11514             }
11515             else if (e1.op == TOKtype) // slicing a type tuple
11516             {
11517                 te = null;
11518                 tup = cast(TypeTuple)t1b;
11519                 length = Parameter.dim(tup.arguments);
11520             }
11521             else
11522                 assert(0);
11523 
11524             if (i2 < i1 || length < i2)
11525             {
11526                 error("string slice [%llu .. %llu] is out of bounds", i1, i2);
11527                 return new ErrorExp();
11528             }
11529 
11530             size_t j1 = cast(size_t)i1;
11531             size_t j2 = cast(size_t)i2;
11532             Expression e;
11533             if (e1.op == TOKtuple)
11534             {
11535                 auto exps = new Expressions();
11536                 exps.setDim(j2 - j1);
11537                 for (size_t i = 0; i < j2 - j1; i++)
11538                 {
11539                     (*exps)[i] = (*te.exps)[j1 + i];
11540                 }
11541                 e = new TupleExp(loc, te.e0, exps);
11542             }
11543             else
11544             {
11545                 auto args = new Parameters();
11546                 args.reserve(j2 - j1);
11547                 for (size_t i = j1; i < j2; i++)
11548                 {
11549                     Parameter arg = Parameter.getNth(tup.arguments, i);
11550                     args.push(arg);
11551                 }
11552                 e = new TypeExp(e1.loc, new TypeTuple(args));
11553             }
11554             e = e.semantic(sc);
11555             return e;
11556         }
11557 
11558         type = t1b.nextOf().arrayOf();
11559         // Allow typedef[] -> typedef[]
11560         if (type.equals(t1b))
11561             type = e1.type;
11562 
11563         if (lwr && upr)
11564         {
11565             lwr = lwr.optimize(WANTvalue);
11566             upr = upr.optimize(WANTvalue);
11567 
11568             IntRange lwrRange = getIntRange(lwr);
11569             IntRange uprRange = getIntRange(upr);
11570 
11571             if (t1b.ty == Tsarray || t1b.ty == Tarray)
11572             {
11573                 Expression el = new ArrayLengthExp(loc, e1);
11574                 el = el.semantic(sc);
11575                 el = el.optimize(WANTvalue);
11576                 if (el.op == TOKint64)
11577                 {
11578                     dinteger_t length = el.toInteger();
11579                     auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length));
11580                     this.upperIsInBounds = bounds.contains(uprRange);
11581                 }
11582             }
11583             else if (t1b.ty == Tpointer)
11584             {
11585                 this.upperIsInBounds = true;
11586             }
11587             else
11588                 assert(0);
11589 
11590             this.lowerIsLessThanUpper = (lwrRange.imax <= uprRange.imin);
11591 
11592             //printf("upperIsInBounds = %d lowerIsLessThanUpper = %d\n", upperIsInBounds, lowerIsLessThanUpper);
11593         }
11594 
11595         return this;
11596     }
11597 
11598     override int checkModifiable(Scope* sc, int flag)
11599     {
11600         //printf("SliceExp::checkModifiable %s\n", toChars());
11601         if (e1.type.ty == Tsarray || (e1.op == TOKindex && e1.type.ty != Tarray) || e1.op == TOKslice)
11602         {
11603             return e1.checkModifiable(sc, flag);
11604         }
11605         return 1;
11606     }
11607 
11608     override bool isLvalue()
11609     {
11610         /* slice expression is rvalue in default, but
11611          * conversion to reference of static array is only allowed.
11612          */
11613         return (type && type.toBasetype().ty == Tsarray);
11614     }
11615 
11616     override Expression toLvalue(Scope* sc, Expression e)
11617     {
11618         //printf("SliceExp::toLvalue(%s) type = %s\n", toChars(), type ? type->toChars() : NULL);
11619         return (type && type.toBasetype().ty == Tsarray) ? this : Expression.toLvalue(sc, e);
11620     }
11621 
11622     override Expression modifiableLvalue(Scope* sc, Expression e)
11623     {
11624         error("slice expression %s is not a modifiable lvalue", toChars());
11625         return this;
11626     }
11627 
11628     override bool isBool(bool result)
11629     {
11630         return e1.isBool(result);
11631     }
11632 
11633     override void accept(Visitor v)
11634     {
11635         v.visit(this);
11636     }
11637 }
11638 
11639 /***********************************************************
11640  */
11641 extern (C++) final class ArrayLengthExp : UnaExp
11642 {
11643     extern (D) this(Loc loc, Expression e1)
11644     {
11645         super(loc, TOKarraylength, __traits(classInstanceSize, ArrayLengthExp), e1);
11646     }
11647 
11648     override Expression semantic(Scope* sc)
11649     {
11650         static if (LOGSEMANTIC)
11651         {
11652             printf("ArrayLengthExp::semantic('%s')\n", toChars());
11653         }
11654         if (type)
11655             return this;
11656 
11657         if (Expression ex = unaSemantic(sc))
11658             return ex;
11659         e1 = resolveProperties(sc, e1);
11660 
11661         type = Type.tsize_t;
11662         return this;
11663     }
11664 
11665     /*********************
11666      * Rewrite:
11667      *    array.length op= e2
11668      * as:
11669      *    array.length = array.length op e2
11670      * or:
11671      *    auto tmp = &array;
11672      *    (*tmp).length = (*tmp).length op e2
11673      */
11674     static Expression rewriteOpAssign(BinExp exp)
11675     {
11676         Expression e;
11677 
11678         assert(exp.e1.op == TOKarraylength);
11679         ArrayLengthExp ale = cast(ArrayLengthExp)exp.e1;
11680         if (ale.e1.op == TOKvar)
11681         {
11682             e = opAssignToOp(exp.loc, exp.op, ale, exp.e2);
11683             e = new AssignExp(exp.loc, ale.syntaxCopy(), e);
11684         }
11685         else
11686         {
11687             /*    auto tmp = &array;
11688              *    (*tmp).length = (*tmp).length op e2
11689              */
11690             auto tmp = copyToTemp(0, "__arraylength", new AddrExp(ale.loc, ale.e1));
11691 
11692             Expression e1 = new ArrayLengthExp(ale.loc, new PtrExp(ale.loc, new VarExp(ale.loc, tmp)));
11693             Expression elvalue = e1.syntaxCopy();
11694             e = opAssignToOp(exp.loc, exp.op, e1, exp.e2);
11695             e = new AssignExp(exp.loc, elvalue, e);
11696             e = new CommaExp(exp.loc, new DeclarationExp(ale.loc, tmp), e);
11697         }
11698         return e;
11699     }
11700 
11701     override void accept(Visitor v)
11702     {
11703         v.visit(this);
11704     }
11705 }
11706 
11707 /***********************************************************
11708  * e1 [ a0, a1, a2, a3 ,... ]
11709  */
11710 extern (C++) final class ArrayExp : UnaExp
11711 {
11712     Expressions* arguments;     // Array of Expression's
11713     size_t currentDimension;    // for opDollar
11714     VarDeclaration lengthVar;
11715 
11716     extern (D) this(Loc loc, Expression e1, Expression index = null)
11717     {
11718         super(loc, TOKarray, __traits(classInstanceSize, ArrayExp), e1);
11719         arguments = new Expressions();
11720         if (index)
11721             arguments.push(index);
11722     }
11723 
11724     extern (D) this(Loc loc, Expression e1, Expressions* args)
11725     {
11726         super(loc, TOKarray, __traits(classInstanceSize, ArrayExp), e1);
11727         arguments = args;
11728     }
11729 
11730     override Expression syntaxCopy()
11731     {
11732         auto ae = new ArrayExp(loc, e1.syntaxCopy(), arraySyntaxCopy(arguments));
11733         ae.lengthVar = this.lengthVar; // bug7871
11734         return ae;
11735     }
11736 
11737     override Expression semantic(Scope* sc)
11738     {
11739         static if (LOGSEMANTIC)
11740         {
11741             printf("ArrayExp::semantic('%s')\n", toChars());
11742         }
11743         assert(!type);
11744         Expression e = op_overload(sc);
11745         if (e)
11746             return e;
11747 
11748         if (isAggregate(e1.type))
11749             error("no [] operator overload for type %s", e1.type.toChars());
11750         else
11751             error("only one index allowed to index %s", e1.type.toChars());
11752         return new ErrorExp();
11753     }
11754 
11755     override bool isLvalue()
11756     {
11757         if (type && type.toBasetype().ty == Tvoid)
11758             return false;
11759         return true;
11760     }
11761 
11762     override Expression toLvalue(Scope* sc, Expression e)
11763     {
11764         if (type && type.toBasetype().ty == Tvoid)
11765             error("voids have no value");
11766         return this;
11767     }
11768 
11769     override void accept(Visitor v)
11770     {
11771         v.visit(this);
11772     }
11773 }
11774 
11775 /***********************************************************
11776  */
11777 extern (C++) final class DotExp : BinExp
11778 {
11779     extern (D) this(Loc loc, Expression e1, Expression e2)
11780     {
11781         super(loc, TOKdot, __traits(classInstanceSize, DotExp), e1, e2);
11782     }
11783 
11784     override Expression semantic(Scope* sc)
11785     {
11786         static if (LOGSEMANTIC)
11787         {
11788             printf("DotExp::semantic('%s')\n", toChars());
11789             if (type)
11790                 printf("\ttype = %s\n", type.toChars());
11791         }
11792         e1 = e1.semantic(sc);
11793         e2 = e2.semantic(sc);
11794 
11795         if (e1.op == TOKtype)
11796             return e2;
11797         if (e2.op == TOKtype)
11798             return e2;
11799 
11800         if (e2.op == TOKtemplate)
11801         {
11802             auto td = (cast(TemplateExp)e2).td;
11803             Expression e = new DotTemplateExp(loc, e1, td);
11804             return e.semantic(sc);
11805         }
11806         if (!type)
11807             type = e2.type;
11808         return this;
11809     }
11810 
11811     override void accept(Visitor v)
11812     {
11813         v.visit(this);
11814     }
11815 }
11816 
11817 /***********************************************************
11818  */
11819 extern (C++) final class CommaExp : BinExp
11820 {
11821     /// This is needed because AssignExp rewrites CommaExp, hence it needs
11822     /// to trigger the deprecation.
11823     const bool isGenerated;
11824 
11825     /// Temporary variable to enable / disable deprecation of comma expression
11826     /// depending on the context.
11827     /// Since most constructor calls are rewritting, the only place where
11828     /// false will be passed will be from the parser.
11829     bool allowCommaExp;
11830 
11831 
11832     extern (D) this(Loc loc, Expression e1, Expression e2, bool generated = true)
11833     {
11834         super(loc, TOKcomma, __traits(classInstanceSize, CommaExp), e1, e2);
11835         allowCommaExp = isGenerated = generated;
11836     }
11837 
11838     override Expression semantic(Scope* sc)
11839     {
11840         if (type)
11841             return this;
11842 
11843         // Allow `((a,b),(x,y))`
11844         if (allowCommaExp)
11845         {
11846             CommaExp.allow(e1);
11847             CommaExp.allow(e2);
11848         }
11849 
11850         if (Expression ex = binSemanticProp(sc))
11851             return ex;
11852         e1 = e1.addDtorHook(sc);
11853 
11854         if (checkNonAssignmentArrayOp(e1))
11855             return new ErrorExp();
11856 
11857         type = e2.type;
11858         if (type !is Type.tvoid && !allowCommaExp && !isGenerated)
11859             deprecation("Using the result of a comma expression is deprecated");
11860         return this;
11861     }
11862 
11863     override int checkModifiable(Scope* sc, int flag)
11864     {
11865         return e2.checkModifiable(sc, flag);
11866     }
11867 
11868     override bool isLvalue()
11869     {
11870         return e2.isLvalue();
11871     }
11872 
11873     override Expression toLvalue(Scope* sc, Expression e)
11874     {
11875         e2 = e2.toLvalue(sc, null);
11876         return this;
11877     }
11878 
11879     override Expression modifiableLvalue(Scope* sc, Expression e)
11880     {
11881         e2 = e2.modifiableLvalue(sc, e);
11882         return this;
11883     }
11884 
11885     override bool isBool(bool result)
11886     {
11887         return e2.isBool(result);
11888     }
11889 
11890     override Expression toBoolean(Scope* sc)
11891     {
11892         auto ex2 = e2.toBoolean(sc);
11893         if (ex2.op == TOKerror)
11894             return ex2;
11895         e2 = ex2;
11896         return this;
11897     }
11898 
11899     override Expression addDtorHook(Scope* sc)
11900     {
11901         e2 = e2.addDtorHook(sc);
11902         return this;
11903     }
11904 
11905     override void accept(Visitor v)
11906     {
11907         v.visit(this);
11908     }
11909 
11910     /**
11911      * If the argument is a CommaExp, set a flag to prevent deprecation messages
11912      *
11913      * It's impossible to know from CommaExp.semantic if the result will
11914      * be used, hence when there is a result (type != void), a deprecation
11915      * message is always emitted.
11916      * However, some construct can produce a result but won't use it
11917      * (ExpStatement and for loop increment).  Those should call this function
11918      * to prevent unwanted deprecations to be emitted.
11919      *
11920      * Params:
11921      *   exp = An expression that discards its result.
11922      *         If the argument is null or not a CommaExp, nothing happens.
11923      */
11924     static void allow(Expression exp)
11925     {
11926         if (exp && exp.op == TOK.TOKcomma)
11927             (cast(CommaExp)exp).allowCommaExp = true;
11928     }
11929 }
11930 
11931 /***********************************************************
11932  * Mainly just a placeholder
11933  */
11934 extern (C++) final class IntervalExp : Expression
11935 {
11936     Expression lwr;
11937     Expression upr;
11938 
11939     extern (D) this(Loc loc, Expression lwr, Expression upr)
11940     {
11941         super(loc, TOKinterval, __traits(classInstanceSize, IntervalExp));
11942         this.lwr = lwr;
11943         this.upr = upr;
11944     }
11945 
11946     override Expression syntaxCopy()
11947     {
11948         return new IntervalExp(loc, lwr.syntaxCopy(), upr.syntaxCopy());
11949     }
11950 
11951     override Expression semantic(Scope* sc)
11952     {
11953         static if (LOGSEMANTIC)
11954         {
11955             printf("IntervalExp::semantic('%s')\n", toChars());
11956         }
11957         if (type)
11958             return this;
11959 
11960         Expression le = lwr;
11961         le = le.semantic(sc);
11962         le = resolveProperties(sc, le);
11963 
11964         Expression ue = upr;
11965         ue = ue.semantic(sc);
11966         ue = resolveProperties(sc, ue);
11967 
11968         if (le.op == TOKerror)
11969             return le;
11970         if (ue.op == TOKerror)
11971             return ue;
11972 
11973         lwr = le;
11974         upr = ue;
11975 
11976         type = Type.tvoid;
11977         return this;
11978     }
11979 
11980     override Expression modifiableLvalue(Scope* sc, Expression e)
11981     {
11982         if (sc.func.setUnsafe())
11983         {
11984             error("cannot modify delegate pointer in @safe code %s", toChars());
11985             return new ErrorExp();
11986         }
11987         return Expression.modifiableLvalue(sc, e);
11988     }
11989 
11990     override void accept(Visitor v)
11991     {
11992         v.visit(this);
11993     }
11994 }
11995 
11996 extern (C++) final class DelegatePtrExp : UnaExp
11997 {
11998     extern (D) this(Loc loc, Expression e1)
11999     {
12000         super(loc, TOKdelegateptr, __traits(classInstanceSize, DelegatePtrExp), e1);
12001     }
12002 
12003     override Expression semantic(Scope* sc)
12004     {
12005         static if (LOGSEMANTIC)
12006         {
12007             printf("DelegatePtrExp::semantic('%s')\n", toChars());
12008         }
12009         if (!type)
12010         {
12011             unaSemantic(sc);
12012             e1 = resolveProperties(sc, e1);
12013 
12014             if (e1.op == TOKerror)
12015                 return e1;
12016             type = Type.tvoidptr;
12017         }
12018         return this;
12019     }
12020 
12021     override bool isLvalue()
12022     {
12023         return e1.isLvalue();
12024     }
12025 
12026     override Expression toLvalue(Scope* sc, Expression e)
12027     {
12028         e1 = e1.toLvalue(sc, e);
12029         return this;
12030     }
12031 
12032     override Expression modifiableLvalue(Scope* sc, Expression e)
12033     {
12034         if (sc.func.setUnsafe())
12035         {
12036             error("cannot modify delegate pointer in @safe code %s", toChars());
12037             return new ErrorExp();
12038         }
12039         return Expression.modifiableLvalue(sc, e);
12040     }
12041 
12042     override void accept(Visitor v)
12043     {
12044         v.visit(this);
12045     }
12046 }
12047 
12048 /***********************************************************
12049  */
12050 extern (C++) final class DelegateFuncptrExp : UnaExp
12051 {
12052     extern (D) this(Loc loc, Expression e1)
12053     {
12054         super(loc, TOKdelegatefuncptr, __traits(classInstanceSize, DelegateFuncptrExp), e1);
12055     }
12056 
12057     override Expression semantic(Scope* sc)
12058     {
12059         static if (LOGSEMANTIC)
12060         {
12061             printf("DelegateFuncptrExp::semantic('%s')\n", toChars());
12062         }
12063         if (!type)
12064         {
12065             unaSemantic(sc);
12066             e1 = resolveProperties(sc, e1);
12067             if (e1.op == TOKerror)
12068                 return e1;
12069             type = e1.type.nextOf().pointerTo();
12070         }
12071         return this;
12072     }
12073 
12074     override bool isLvalue()
12075     {
12076         return e1.isLvalue();
12077     }
12078 
12079     override Expression toLvalue(Scope* sc, Expression e)
12080     {
12081         e1 = e1.toLvalue(sc, e);
12082         return this;
12083     }
12084 
12085     override Expression modifiableLvalue(Scope* sc, Expression e)
12086     {
12087         if (sc.func.setUnsafe())
12088         {
12089             error("cannot modify delegate function pointer in @safe code %s", toChars());
12090             return new ErrorExp();
12091         }
12092         return Expression.modifiableLvalue(sc, e);
12093     }
12094 
12095     override void accept(Visitor v)
12096     {
12097         v.visit(this);
12098     }
12099 }
12100 
12101 /***********************************************************
12102  * e1 [ e2 ]
12103  */
12104 extern (C++) final class IndexExp : BinExp
12105 {
12106     VarDeclaration lengthVar;
12107     bool modifiable = false;    // assume it is an rvalue
12108     bool indexIsInBounds;       // true if 0 <= e2 && e2 <= e1.length - 1
12109 
12110     extern (D) this(Loc loc, Expression e1, Expression e2)
12111     {
12112         super(loc, TOKindex, __traits(classInstanceSize, IndexExp), e1, e2);
12113         //printf("IndexExp::IndexExp('%s')\n", toChars());
12114     }
12115 
12116     override Expression syntaxCopy()
12117     {
12118         auto ie = new IndexExp(loc, e1.syntaxCopy(), e2.syntaxCopy());
12119         ie.lengthVar = this.lengthVar; // bug7871
12120         return ie;
12121     }
12122 
12123     override Expression semantic(Scope* sc)
12124     {
12125         static if (LOGSEMANTIC)
12126         {
12127             printf("IndexExp::semantic('%s')\n", toChars());
12128         }
12129         if (type)
12130             return this;
12131 
12132         // operator overloading should be handled in ArrayExp already.
12133         if (!e1.type)
12134             e1 = e1.semantic(sc);
12135         assert(e1.type); // semantic() should already be run on it
12136         if (e1.op == TOKtype && e1.type.ty != Ttuple)
12137         {
12138             e2 = e2.semantic(sc);
12139             e2 = resolveProperties(sc, e2);
12140             Type nt;
12141             if (e2.op == TOKtype)
12142                 nt = new TypeAArray(e1.type, e2.type);
12143             else
12144                 nt = new TypeSArray(e1.type, e2);
12145             Expression e = new TypeExp(loc, nt);
12146             return e.semantic(sc);
12147         }
12148         if (e1.op == TOKerror)
12149             return e1;
12150         if (e1.type.ty == Terror)
12151             return new ErrorExp();
12152 
12153         // Note that unlike C we do not implement the int[ptr]
12154 
12155         Type t1b = e1.type.toBasetype();
12156 
12157         /* Run semantic on e2
12158          */
12159         Scope* scx = sc;
12160         if (t1b.ty == Tsarray || t1b.ty == Tarray || t1b.ty == Ttuple)
12161         {
12162             // Create scope for 'length' variable
12163             ScopeDsymbol sym = new ArrayScopeSymbol(sc, this);
12164             sym.loc = loc;
12165             sym.parent = sc.scopesym;
12166             sc = sc.push(sym);
12167         }
12168         if (t1b.ty == Ttuple)
12169             sc = sc.startCTFE();
12170         e2 = e2.semantic(sc);
12171         e2 = resolveProperties(sc, e2);
12172         if (t1b.ty == Ttuple)
12173             sc = sc.endCTFE();
12174         if (e2.op == TOKtuple)
12175         {
12176             TupleExp te = cast(TupleExp)e2;
12177             if (te.exps && te.exps.dim == 1)
12178                 e2 = Expression.combine(te.e0, (*te.exps)[0]); // bug 4444 fix
12179         }
12180         if (sc != scx)
12181             sc = sc.pop();
12182         if (e2.type == Type.terror)
12183             return new ErrorExp();
12184 
12185         if (checkNonAssignmentArrayOp(e1))
12186             return new ErrorExp();
12187 
12188         switch (t1b.ty)
12189         {
12190         case Tpointer:
12191             if ((cast(TypePointer)t1b).next.ty == Tfunction)
12192             {
12193                 error("cannot index function pointer %s", e1.toChars());
12194                 return new ErrorExp();
12195             }
12196             e2 = e2.implicitCastTo(sc, Type.tsize_t);
12197             if (e2.type == Type.terror)
12198                 return new ErrorExp();
12199             e2 = e2.optimize(WANTvalue);
12200             if (e2.op == TOKint64 && e2.toInteger() == 0)
12201             {
12202             }
12203             else if (sc.func && sc.func.setUnsafe())
12204             {
12205                 error("safe function '%s' cannot index pointer '%s'", sc.func.toPrettyChars(), e1.toChars());
12206                 return new ErrorExp();
12207             }
12208             type = (cast(TypeNext)t1b).next;
12209             break;
12210 
12211         case Tarray:
12212             e2 = e2.implicitCastTo(sc, Type.tsize_t);
12213             if (e2.type == Type.terror)
12214                 return new ErrorExp();
12215             type = (cast(TypeNext)t1b).next;
12216             break;
12217 
12218         case Tsarray:
12219             {
12220                 e2 = e2.implicitCastTo(sc, Type.tsize_t);
12221                 if (e2.type == Type.terror)
12222                     return new ErrorExp();
12223                 type = t1b.nextOf();
12224                 break;
12225             }
12226         case Taarray:
12227             {
12228                 TypeAArray taa = cast(TypeAArray)t1b;
12229                 /* We can skip the implicit conversion if they differ only by
12230                  * constness (Bugzilla 2684, see also bug 2954b)
12231                  */
12232                 if (!arrayTypeCompatibleWithoutCasting(e2.loc, e2.type, taa.index))
12233                 {
12234                     e2 = e2.implicitCastTo(sc, taa.index); // type checking
12235                     if (e2.type == Type.terror)
12236                         return new ErrorExp();
12237                 }
12238 
12239                 semanticTypeInfo(sc, taa);
12240 
12241                 type = taa.next;
12242                 break;
12243             }
12244         case Ttuple:
12245             {
12246                 e2 = e2.implicitCastTo(sc, Type.tsize_t);
12247                 if (e2.type == Type.terror)
12248                     return new ErrorExp();
12249                 e2 = e2.ctfeInterpret();
12250                 uinteger_t index = e2.toUInteger();
12251 
12252                 TupleExp te;
12253                 TypeTuple tup;
12254                 size_t length;
12255                 if (e1.op == TOKtuple)
12256                 {
12257                     te = cast(TupleExp)e1;
12258                     tup = null;
12259                     length = te.exps.dim;
12260                 }
12261                 else if (e1.op == TOKtype)
12262                 {
12263                     te = null;
12264                     tup = cast(TypeTuple)t1b;
12265                     length = Parameter.dim(tup.arguments);
12266                 }
12267                 else
12268                     assert(0);
12269 
12270                 if (length <= index)
12271                 {
12272                     error("array index [%llu] is outside array bounds [0 .. %llu]", index, cast(ulong)length);
12273                     return new ErrorExp();
12274                 }
12275                 Expression e;
12276                 if (e1.op == TOKtuple)
12277                 {
12278                     e = (*te.exps)[cast(size_t)index];
12279                     e = combine(te.e0, e);
12280                 }
12281                 else
12282                     e = new TypeExp(e1.loc, Parameter.getNth(tup.arguments, cast(size_t)index).type);
12283                 return e;
12284             }
12285         default:
12286             error("%s must be an array or pointer type, not %s", e1.toChars(), e1.type.toChars());
12287             return new ErrorExp();
12288         }
12289 
12290         if (t1b.ty == Tsarray || t1b.ty == Tarray)
12291         {
12292             Expression el = new ArrayLengthExp(loc, e1);
12293             el = el.semantic(sc);
12294             el = el.optimize(WANTvalue);
12295             if (el.op == TOKint64)
12296             {
12297                 e2 = e2.optimize(WANTvalue);
12298                 dinteger_t length = el.toInteger();
12299                 if (length)
12300                 {
12301                     auto bounds = IntRange(SignExtendedNumber(0), SignExtendedNumber(length - 1));
12302                     indexIsInBounds = bounds.contains(getIntRange(e2));
12303                 }
12304             }
12305         }
12306 
12307         return this;
12308     }
12309 
12310     override int checkModifiable(Scope* sc, int flag)
12311     {
12312         if (e1.type.ty == Tsarray || e1.type.ty == Taarray || (e1.op == TOKindex && e1.type.ty != Tarray) || e1.op == TOKslice)
12313         {
12314             return e1.checkModifiable(sc, flag);
12315         }
12316         return 1;
12317     }
12318 
12319     override bool isLvalue()
12320     {
12321         return true;
12322     }
12323 
12324     override Expression toLvalue(Scope* sc, Expression e)
12325     {
12326         return this;
12327     }
12328 
12329     override Expression modifiableLvalue(Scope* sc, Expression e)
12330     {
12331         //printf("IndexExp::modifiableLvalue(%s)\n", toChars());
12332         Expression ex = markSettingAAElem();
12333         if (ex.op == TOKerror)
12334             return ex;
12335 
12336         return Expression.modifiableLvalue(sc, e);
12337     }
12338 
12339     Expression markSettingAAElem()
12340     {
12341         if (e1.type.toBasetype().ty == Taarray)
12342         {
12343             Type t2b = e2.type.toBasetype();
12344             if (t2b.ty == Tarray && t2b.nextOf().isMutable())
12345             {
12346                 error("associative arrays can only be assigned values with immutable keys, not %s", e2.type.toChars());
12347                 return new ErrorExp();
12348             }
12349             modifiable = true;
12350 
12351             if (e1.op == TOKindex)
12352             {
12353                 Expression ex = (cast(IndexExp)e1).markSettingAAElem();
12354                 if (ex.op == TOKerror)
12355                     return ex;
12356                 assert(ex == e1);
12357             }
12358         }
12359         return this;
12360     }
12361 
12362     override void accept(Visitor v)
12363     {
12364         v.visit(this);
12365     }
12366 }
12367 
12368 /***********************************************************
12369  * For both i++ and i--
12370  */
12371 extern (C++) final class PostExp : BinExp
12372 {
12373     extern (D) this(TOK op, Loc loc, Expression e)
12374     {
12375         super(loc, op, __traits(classInstanceSize, PostExp), e, new IntegerExp(loc, 1, Type.tint32));
12376     }
12377 
12378     override Expression semantic(Scope* sc)
12379     {
12380         static if (LOGSEMANTIC)
12381         {
12382             printf("PostExp::semantic('%s')\n", toChars());
12383         }
12384         if (type)
12385             return this;
12386 
12387         if (Expression ex = binSemantic(sc))
12388             return ex;
12389         Expression e1x = resolveProperties(sc, e1);
12390         if (e1x.op == TOKerror)
12391             return e1x;
12392         e1 = e1x;
12393 
12394         Expression e = op_overload(sc);
12395         if (e)
12396             return e;
12397 
12398         if (e1.checkReadModifyWrite(op))
12399             return new ErrorExp();
12400         if (e1.op == TOKslice)
12401         {
12402             const(char)* s = op == TOKplusplus ? "increment" : "decrement";
12403             error("cannot post-%s array slice '%s', use pre-%s instead", s, e1.toChars(), s);
12404             return new ErrorExp();
12405         }
12406 
12407         e1 = e1.optimize(WANTvalue);
12408 
12409         Type t1 = e1.type.toBasetype();
12410         if (t1.ty == Tclass || t1.ty == Tstruct || e1.op == TOKarraylength)
12411         {
12412             /* Check for operator overloading,
12413              * but rewrite in terms of ++e instead of e++
12414              */
12415 
12416             /* If e1 is not trivial, take a reference to it
12417              */
12418             Expression de = null;
12419             if (e1.op != TOKvar && e1.op != TOKarraylength)
12420             {
12421                 // ref v = e1;
12422                 auto v = copyToTemp(STCref, "__postref", e1);
12423                 de = new DeclarationExp(loc, v);
12424                 e1 = new VarExp(e1.loc, v);
12425             }
12426 
12427             /* Rewrite as:
12428              * auto tmp = e1; ++e1; tmp
12429              */
12430             auto tmp = copyToTemp(0, "__pitmp", e1);
12431             Expression ea = new DeclarationExp(loc, tmp);
12432 
12433             Expression eb = e1.syntaxCopy();
12434             eb = new PreExp(op == TOKplusplus ? TOKpreplusplus : TOKpreminusminus, loc, eb);
12435 
12436             Expression ec = new VarExp(loc, tmp);
12437 
12438             // Combine de,ea,eb,ec
12439             if (de)
12440                 ea = new CommaExp(loc, de, ea);
12441             e = new CommaExp(loc, ea, eb);
12442             e = new CommaExp(loc, e, ec);
12443             e = e.semantic(sc);
12444             return e;
12445         }
12446 
12447         e1 = e1.modifiableLvalue(sc, e1);
12448 
12449         e = this;
12450         if (e1.checkScalar())
12451             return new ErrorExp();
12452         if (e1.checkNoBool())
12453             return new ErrorExp();
12454 
12455         if (e1.type.ty == Tpointer)
12456             e = scaleFactor(this, sc);
12457         else
12458             e2 = e2.castTo(sc, e1.type);
12459         e.type = e1.type;
12460         return e;
12461     }
12462 
12463     override void accept(Visitor v)
12464     {
12465         v.visit(this);
12466     }
12467 }
12468 
12469 /***********************************************************
12470  * For both ++i and --i
12471  */
12472 extern (C++) final class PreExp : UnaExp
12473 {
12474     extern (D) this(TOK op, Loc loc, Expression e)
12475     {
12476         super(loc, op, __traits(classInstanceSize, PreExp), e);
12477     }
12478 
12479     override Expression semantic(Scope* sc)
12480     {
12481         Expression e = op_overload(sc);
12482         // printf("PreExp::semantic('%s')\n", toChars());
12483         if (e)
12484             return e;
12485 
12486         // Rewrite as e1+=1 or e1-=1
12487         if (op == TOKpreplusplus)
12488             e = new AddAssignExp(loc, e1, new IntegerExp(loc, 1, Type.tint32));
12489         else
12490             e = new MinAssignExp(loc, e1, new IntegerExp(loc, 1, Type.tint32));
12491         return e.semantic(sc);
12492     }
12493 
12494     override void accept(Visitor v)
12495     {
12496         v.visit(this);
12497     }
12498 }
12499 
12500 enum MemorySet
12501 {
12502     blockAssign     = 1,    // setting the contents of an array
12503     referenceInit   = 2,    // setting the reference of STCref variable
12504 }
12505 
12506 /***********************************************************
12507  */
12508 extern (C++) class AssignExp : BinExp
12509 {
12510     int memset;         // combination of MemorySet flags
12511 
12512     /************************************************************/
12513     /* op can be TOKassign, TOKconstruct, or TOKblit */
12514     final extern (D) this(Loc loc, Expression e1, Expression e2)
12515     {
12516         super(loc, TOKassign, __traits(classInstanceSize, AssignExp), e1, e2);
12517     }
12518 
12519     override final Expression semantic(Scope* sc)
12520     {
12521         static if (LOGSEMANTIC)
12522         {
12523             printf("AssignExp::semantic('%s')\n", toChars());
12524         }
12525         //printf("e1->op = %d, '%s'\n", e1->op, Token::toChars(e1->op));
12526         //printf("e2->op = %d, '%s'\n", e2->op, Token::toChars(e2->op));
12527         if (type)
12528             return this;
12529 
12530         Expression e1old = e1;
12531 
12532         if (e2.op == TOKcomma)
12533         {
12534             /* Rewrite to get rid of the comma from rvalue
12535              */
12536             if (!(cast(CommaExp)e2).isGenerated)
12537                 deprecation("Using the result of a comma expression is deprecated");
12538             Expression e0;
12539             e2 = Expression.extractLast(e2, &e0);
12540             Expression e = Expression.combine(e0, this);
12541             return e.semantic(sc);
12542         }
12543 
12544         /* Look for operator overloading of a[arguments] = e2.
12545          * Do it before e1->semantic() otherwise the ArrayExp will have been
12546          * converted to unary operator overloading already.
12547          */
12548         if (e1.op == TOKarray)
12549         {
12550             Expression result;
12551 
12552             ArrayExp ae = cast(ArrayExp)e1;
12553             ae.e1 = ae.e1.semantic(sc);
12554             ae.e1 = resolveProperties(sc, ae.e1);
12555             Expression ae1old = ae.e1;
12556 
12557             const(bool) maybeSlice =
12558                 (ae.arguments.dim == 0 ||
12559                  ae.arguments.dim == 1 && (*ae.arguments)[0].op == TOKinterval);
12560 
12561             IntervalExp ie = null;
12562             if (maybeSlice && ae.arguments.dim)
12563             {
12564                 assert((*ae.arguments)[0].op == TOKinterval);
12565                 ie = cast(IntervalExp)(*ae.arguments)[0];
12566             }
12567             while (true)
12568             {
12569                 if (ae.e1.op == TOKerror)
12570                     return ae.e1;
12571                 Expression e0 = null;
12572                 Expression ae1save = ae.e1;
12573                 ae.lengthVar = null;
12574 
12575                 Type t1b = ae.e1.type.toBasetype();
12576                 AggregateDeclaration ad = isAggregate(t1b);
12577                 if (!ad)
12578                     break;
12579                 if (search_function(ad, Id.indexass))
12580                 {
12581                     // Deal with $
12582                     result = resolveOpDollar(sc, ae, &e0);
12583                     if (!result) // a[i..j] = e2 might be: a.opSliceAssign(e2, i, j)
12584                         goto Lfallback;
12585                     if (result.op == TOKerror)
12586                         return result;
12587 
12588                     result = e2.semantic(sc);
12589                     if (result.op == TOKerror)
12590                         return result;
12591                     e2 = result;
12592 
12593                     /* Rewrite (a[arguments] = e2) as:
12594                      *      a.opIndexAssign(e2, arguments)
12595                      */
12596                     Expressions* a = ae.arguments.copy();
12597                     a.insert(0, e2);
12598                     result = new DotIdExp(loc, ae.e1, Id.indexass);
12599                     result = new CallExp(loc, result, a);
12600                     if (maybeSlice) // a[] = e2 might be: a.opSliceAssign(e2)
12601                         result = result.trySemantic(sc);
12602                     else
12603                         result = result.semantic(sc);
12604                     if (result)
12605                     {
12606                         result = Expression.combine(e0, result);
12607                         return result;
12608                     }
12609                 }
12610 
12611             Lfallback:
12612                 if (maybeSlice && search_function(ad, Id.sliceass))
12613                 {
12614                     // Deal with $
12615                     result = resolveOpDollar(sc, ae, ie, &e0);
12616                     if (result.op == TOKerror)
12617                         return result;
12618 
12619                     result = e2.semantic(sc);
12620                     if (result.op == TOKerror)
12621                         return result;
12622                     e2 = result;
12623 
12624                     /* Rewrite (a[i..j] = e2) as:
12625                      *      a.opSliceAssign(e2, i, j)
12626                      */
12627                     auto a = new Expressions();
12628                     a.push(e2);
12629                     if (ie)
12630                     {
12631                         a.push(ie.lwr);
12632                         a.push(ie.upr);
12633                     }
12634                     result = new DotIdExp(loc, ae.e1, Id.sliceass);
12635                     result = new CallExp(loc, result, a);
12636                     result = result.semantic(sc);
12637                     result = Expression.combine(e0, result);
12638                     return result;
12639                 }
12640 
12641                 // No operator overloading member function found yet, but
12642                 // there might be an alias this to try.
12643                 if (ad.aliasthis && t1b != ae.att1)
12644                 {
12645                     if (!ae.att1 && t1b.checkAliasThisRec())
12646                         ae.att1 = t1b;
12647 
12648                     /* Rewrite (a[arguments] op e2) as:
12649                      *      a.aliasthis[arguments] op e2
12650                      */
12651                     ae.e1 = resolveAliasThis(sc, ae1save, true);
12652                     if (ae.e1)
12653                         continue;
12654                 }
12655                 break;
12656             }
12657             ae.e1 = ae1old; // recovery
12658             ae.lengthVar = null;
12659         }
12660 
12661         /* Run this->e1 semantic.
12662          */
12663         {
12664             Expression e1x = e1;
12665 
12666             /* With UFCS, e.f = value
12667              * Could mean:
12668              *      .f(e, value)
12669              * or:
12670              *      .f(e) = value
12671              */
12672             if (e1x.op == TOKdotti)
12673             {
12674                 DotTemplateInstanceExp dti = cast(DotTemplateInstanceExp)e1x;
12675                 Expression e = dti.semanticY(sc, 1);
12676                 if (!e)
12677                     return resolveUFCSProperties(sc, e1x, e2);
12678                 e1x = e;
12679             }
12680             else if (e1x.op == TOKdotid)
12681             {
12682                 DotIdExp die = cast(DotIdExp)e1x;
12683                 Expression e = die.semanticY(sc, 1);
12684                 if (e && isDotOpDispatch(e))
12685                 {
12686                     uint errors = global.startGagging();
12687                     e = resolvePropertiesX(sc, e, e2);
12688                     if (global.endGagging(errors))
12689                         e = null; /* fall down to UFCS */
12690                     else
12691                         return e;
12692                 }
12693                 if (!e)
12694                     return resolveUFCSProperties(sc, e1x, e2);
12695                 e1x = e;
12696             }
12697             else
12698                 e1x = e1x.semantic(sc);
12699 
12700             /* We have f = value.
12701              * Could mean:
12702              *      f(value)
12703              * or:
12704              *      f() = value
12705              */
12706             if (Expression e = resolvePropertiesX(sc, e1x, e2))
12707                 return e;
12708             if (e1x.checkRightThis(sc))
12709                 return new ErrorExp();
12710             e1 = e1x;
12711             assert(e1.type);
12712         }
12713         Type t1 = e1.type.toBasetype();
12714 
12715         /* Run this->e2 semantic.
12716          * Different from other binary expressions, the analysis of e2
12717          * depends on the result of e1 in assignments.
12718          */
12719         {
12720             Expression e2x = inferType(e2, t1.baseElemOf());
12721             e2x = e2x.semantic(sc);
12722             e2x = resolveProperties(sc, e2x);
12723             if (e2x.op == TOKerror)
12724                 return e2x;
12725             if (e2x.checkValue())
12726                 return new ErrorExp();
12727             e2 = e2x;
12728         }
12729 
12730         /* Rewrite tuple assignment as a tuple of assignments.
12731          */
12732         {
12733             Expression e2x = e2;
12734 
12735         Ltupleassign:
12736             if (e1.op == TOKtuple && e2x.op == TOKtuple)
12737             {
12738                 TupleExp tup1 = cast(TupleExp)e1;
12739                 TupleExp tup2 = cast(TupleExp)e2x;
12740                 size_t dim = tup1.exps.dim;
12741                 Expression e = null;
12742                 if (dim != tup2.exps.dim)
12743                 {
12744                     error("mismatched tuple lengths, %d and %d", cast(int)dim, cast(int)tup2.exps.dim);
12745                     return new ErrorExp();
12746                 }
12747                 if (dim == 0)
12748                 {
12749                     e = new IntegerExp(loc, 0, Type.tint32);
12750                     e = new CastExp(loc, e, Type.tvoid); // avoid "has no effect" error
12751                     e = combine(combine(tup1.e0, tup2.e0), e);
12752                 }
12753                 else
12754                 {
12755                     auto exps = new Expressions();
12756                     exps.setDim(dim);
12757                     for (size_t i = 0; i < dim; i++)
12758                     {
12759                         Expression ex1 = (*tup1.exps)[i];
12760                         Expression ex2 = (*tup2.exps)[i];
12761                         (*exps)[i] = new AssignExp(loc, ex1, ex2);
12762                     }
12763                     e = new TupleExp(loc, combine(tup1.e0, tup2.e0), exps);
12764                 }
12765                 return e.semantic(sc);
12766             }
12767 
12768             /* Look for form: e1 = e2->aliasthis.
12769              */
12770             if (e1.op == TOKtuple)
12771             {
12772                 TupleDeclaration td = isAliasThisTuple(e2x);
12773                 if (!td)
12774                     goto Lnomatch;
12775 
12776                 assert(e1.type.ty == Ttuple);
12777                 TypeTuple tt = cast(TypeTuple)e1.type;
12778 
12779                 Expression e0;
12780                 Expression ev = extractSideEffect(sc, "__tup", e0, e2x);
12781 
12782                 auto iexps = new Expressions();
12783                 iexps.push(ev);
12784                 for (size_t u = 0; u < iexps.dim; u++)
12785                 {
12786                 Lexpand:
12787                     Expression e = (*iexps)[u];
12788 
12789                     Parameter arg = Parameter.getNth(tt.arguments, u);
12790                     //printf("[%d] iexps->dim = %d, ", u, iexps->dim);
12791                     //printf("e = (%s %s, %s), ", Token::tochars[e->op], e->toChars(), e->type->toChars());
12792                     //printf("arg = (%s, %s)\n", arg->toChars(), arg->type->toChars());
12793 
12794                     if (!arg || !e.type.implicitConvTo(arg.type))
12795                     {
12796                         // expand initializer to tuple
12797                         if (expandAliasThisTuples(iexps, u) != -1)
12798                         {
12799                             if (iexps.dim <= u)
12800                                 break;
12801                             goto Lexpand;
12802                         }
12803                         goto Lnomatch;
12804                     }
12805                 }
12806                 e2x = new TupleExp(e2x.loc, e0, iexps);
12807                 e2x = e2x.semantic(sc);
12808                 if (e2x.op == TOKerror)
12809                     return e2x;
12810                 // Do not need to overwrite this->e2
12811                 goto Ltupleassign;
12812             }
12813         Lnomatch:
12814         }
12815 
12816         /* Inside constructor, if this is the first assignment of object field,
12817          * rewrite this to initializing the field.
12818          */
12819         if (op == TOKassign && e1.checkModifiable(sc) == 2)
12820         {
12821             //printf("[%s] change to init - %s\n", loc.toChars(), toChars());
12822             op = TOKconstruct;
12823 
12824             // Bugzilla 13515: set Index::modifiable flag for complex AA element initialization
12825             if (e1.op == TOKindex)
12826             {
12827                 Expression e1x = (cast(IndexExp)e1).markSettingAAElem();
12828                 if (e1x.op == TOKerror)
12829                     return e1x;
12830             }
12831         }
12832         else if (op == TOKconstruct && e1.op == TOKvar &&
12833                  (cast(VarExp)e1).var.storage_class & (STCout | STCref))
12834         {
12835             memset |= MemorySet.referenceInit;
12836         }
12837 
12838         /* If it is an assignment from a 'foreign' type,
12839          * check for operator overloading.
12840          */
12841         if (memset & MemorySet.referenceInit)
12842         {
12843             // If this is an initialization of a reference,
12844             // do nothing
12845         }
12846         else if (t1.ty == Tstruct)
12847         {
12848             auto e1x = e1;
12849             auto e2x = e2;
12850             auto sd = (cast(TypeStruct)t1).sym;
12851 
12852             if (op == TOKconstruct)
12853             {
12854                 Type t2 = e2x.type.toBasetype();
12855                 if (t2.ty == Tstruct && sd == (cast(TypeStruct)t2).sym)
12856                 {
12857                     sd.size(loc);
12858                     if (sd.sizeok != SIZEOKdone)
12859                         return new ErrorExp();
12860                     if (!sd.ctor)
12861                         sd.ctor = sd.searchCtor();
12862 
12863                     // Bugzilla 15661: Look for the form from last of comma chain.
12864                     auto e2y = e2x;
12865                     while (e2y.op == TOKcomma)
12866                         e2y = (cast(CommaExp)e2y).e2;
12867 
12868                     CallExp ce = (e2y.op == TOKcall) ? cast(CallExp)e2y : null;
12869                     DotVarExp dve = (ce && ce.e1.op == TOKdotvar)
12870                         ? cast(DotVarExp)ce.e1 : null;
12871                     if (sd.ctor && ce && dve && dve.var.isCtorDeclaration() &&
12872                         e2y.type.implicitConvTo(t1))
12873                     {
12874                         /* Look for form of constructor call which is:
12875                          *    __ctmp.ctor(arguments...)
12876                          */
12877 
12878                         /* Before calling the constructor, initialize
12879                          * variable with a bit copy of the default
12880                          * initializer
12881                          */
12882                         Expression einit;
12883                         if (sd.zeroInit == 1 && !sd.isNested())
12884                         {
12885                             // Bugzilla 14606: Always use BlitExp for the special expression: (struct = 0)
12886                             einit = new IntegerExp(loc, 0, Type.tint32);
12887                         }
12888                         else if (sd.isNested())
12889                         {
12890                             auto sle = new StructLiteralExp(loc, sd, null, t1);
12891                             if (!sd.fill(loc, sle.elements, true))
12892                                 return new ErrorExp();
12893                             if (checkFrameAccess(loc, sc, sd, sle.elements.dim))
12894                                 return new ErrorExp();
12895                             sle.type = t1;
12896 
12897                             einit = sle;
12898                         }
12899                         else
12900                         {
12901                             einit = t1.defaultInit(loc);
12902                         }
12903                         auto ae = new BlitExp(loc, e1, einit);
12904                         ae.type = e1x.type;
12905 
12906                         /* Replace __ctmp being constructed with e1.
12907                          * We need to copy constructor call expression,
12908                          * because it may be used in other place.
12909                          */
12910                         auto dvx = cast(DotVarExp)dve.copy();
12911                         dvx.e1 = e1x;
12912                         auto cx = cast(CallExp)ce.copy();
12913                         cx.e1 = dvx;
12914 
12915                         Expression e0;
12916                         extractLast(e2x, &e0);
12917 
12918                         auto e = combine(ae, cx);
12919                         e = combine(e0, e);
12920                         e = e.semantic(sc);
12921                         return e;
12922                     }
12923                     if (sd.postblit)
12924                     {
12925                         /* We have a copy constructor for this
12926                          */
12927                         if (e2x.op == TOKquestion)
12928                         {
12929                             /* Rewrite as:
12930                              *  a ? e1 = b : e1 = c;
12931                              */
12932                             CondExp econd = cast(CondExp)e2x;
12933                             Expression ea1 = new ConstructExp(econd.e1.loc, e1x, econd.e1);
12934                             Expression ea2 = new ConstructExp(econd.e1.loc, e1x, econd.e2);
12935                             Expression e = new CondExp(loc, econd.econd, ea1, ea2);
12936                             return e.semantic(sc);
12937                         }
12938 
12939                         if (e2x.isLvalue())
12940                         {
12941                             if (!e2x.type.implicitConvTo(e1x.type))
12942                             {
12943                                 error("conversion error from %s to %s",
12944                                     e2x.type.toChars(), e1x.type.toChars());
12945                                 return new ErrorExp();
12946                             }
12947 
12948                             /* Rewrite as:
12949                              *  (e1 = e2).postblit();
12950                              *
12951                              * Blit assignment e1 = e2 returns a reference to the original e1,
12952                              * then call the postblit on it.
12953                              */
12954                             Expression e = e1x.copy();
12955                             e.type = e.type.mutableOf();
12956                             e = new BlitExp(loc, e, e2x);
12957                             e = new DotVarExp(loc, e, sd.postblit, false);
12958                             e = new CallExp(loc, e);
12959                             return e.semantic(sc);
12960                         }
12961                         else
12962                         {
12963                             /* The struct value returned from the function is transferred
12964                              * so should not call the destructor on it.
12965                              */
12966                             e2x = valueNoDtor(e2x);
12967                         }
12968                     }
12969                 }
12970                 else if (!e2x.implicitConvTo(t1))
12971                 {
12972                     sd.size(loc);
12973                     if (sd.sizeok != SIZEOKdone)
12974                         return new ErrorExp();
12975                     if (!sd.ctor)
12976                         sd.ctor = sd.searchCtor();
12977 
12978                     if (sd.ctor)
12979                     {
12980                         /* Look for implicit constructor call
12981                          * Rewrite as:
12982                          *  e1 = init, e1.ctor(e2)
12983                          */
12984                         Expression einit;
12985                         einit = new BlitExp(loc, e1x, e1x.type.defaultInit(loc));
12986                         einit.type = e1x.type;
12987 
12988                         Expression e;
12989                         e = new DotIdExp(loc, e1x, Id.ctor);
12990                         e = new CallExp(loc, e, e2x);
12991                         e = new CommaExp(loc, einit, e);
12992                         e = e.semantic(sc);
12993                         return e;
12994                     }
12995                     if (search_function(sd, Id.call))
12996                     {
12997                         /* Look for static opCall
12998                          * (See bugzilla 2702 for more discussion)
12999                          * Rewrite as:
13000                          *  e1 = typeof(e1).opCall(arguments)
13001                          */
13002                         e2x = typeDotIdExp(e2x.loc, e1x.type, Id.call);
13003                         e2x = new CallExp(loc, e2x, this.e2);
13004 
13005                         e2x = e2x.semantic(sc);
13006                         e2x = resolveProperties(sc, e2x);
13007                         if (e2x.op == TOKerror)
13008                             return e2x;
13009                         if (e2x.checkValue())
13010                             return new ErrorExp();
13011                     }
13012                 }
13013                 else // Bugzilla 11355
13014                 {
13015                     AggregateDeclaration ad2 = isAggregate(e2x.type);
13016                     if (ad2 && ad2.aliasthis && !(att2 && e2x.type == att2))
13017                     {
13018                         if (!att2 && e2.type.checkAliasThisRec())
13019                             att2 = e2.type;
13020                         /* Rewrite (e1 op e2) as:
13021                          *      (e1 op e2.aliasthis)
13022                          */
13023                         e2 = new DotIdExp(e2.loc, e2, ad2.aliasthis.ident);
13024                         return semantic(sc);
13025                     }
13026                 }
13027             }
13028             else if (op == TOKassign)
13029             {
13030                 if (e1x.op == TOKindex && (cast(IndexExp)e1x).e1.type.toBasetype().ty == Taarray)
13031                 {
13032                     /*
13033                      * Rewrite:
13034                      *      aa[key] = e2;
13035                      * as:
13036                      *      ref __aatmp = aa;
13037                      *      ref __aakey = key;
13038                      *      ref __aaval = e2;
13039                      *      (__aakey in __aatmp
13040                      *          ? __aatmp[__aakey].opAssign(__aaval)
13041                      *          : ConstructExp(__aatmp[__aakey], __aaval));
13042                      */
13043                     IndexExp ie = cast(IndexExp)e1x;
13044                     Type t2 = e2x.type.toBasetype();
13045 
13046                     Expression e0 = null;
13047                     Expression ea = extractSideEffect(sc, "__aatmp", e0, ie.e1);
13048                     Expression ek = extractSideEffect(sc, "__aakey", e0, ie.e2);
13049                     Expression ev = extractSideEffect(sc, "__aaval", e0, e2x);
13050 
13051                     AssignExp ae = cast(AssignExp)copy();
13052                     ae.e1 = new IndexExp(loc, ea, ek);
13053                     ae.e1 = ae.e1.semantic(sc);
13054                     ae.e1 = ae.e1.optimize(WANTvalue);
13055                     ae.e2 = ev;
13056                     Expression e = ae.op_overload(sc);
13057                     if (e)
13058                     {
13059                         Expression ey = null;
13060                         if (t2.ty == Tstruct && sd == t2.toDsymbol(sc))
13061                         {
13062                             ey = ev;
13063                         }
13064                         else if (!ev.implicitConvTo(ie.type) && sd.ctor)
13065                         {
13066                             // Look for implicit constructor call
13067                             // Rewrite as S().ctor(e2)
13068                             ey = new StructLiteralExp(loc, sd, null);
13069                             ey = new DotIdExp(loc, ey, Id.ctor);
13070                             ey = new CallExp(loc, ey, ev);
13071                             ey = ey.trySemantic(sc);
13072                         }
13073                         if (ey)
13074                         {
13075                             Expression ex;
13076                             ex = new IndexExp(loc, ea, ek);
13077                             ex = ex.semantic(sc);
13078                             ex = ex.optimize(WANTvalue);
13079                             ex = ex.modifiableLvalue(sc, ex); // allocate new slot
13080 
13081                             ey = new ConstructExp(loc, ex, ey);
13082                             ey = ey.semantic(sc);
13083                             if (ey.op == TOKerror)
13084                                 return ey;
13085                             ex = e;
13086 
13087                             // Bugzilla 14144: The whole expression should have the common type
13088                             // of opAssign() return and assigned AA entry.
13089                             // Even if there's no common type, expression should be typed as void.
13090                             Type t = null;
13091                             if (!typeMerge(sc, TOKquestion, &t, &ex, &ey))
13092                             {
13093                                 ex = new CastExp(ex.loc, ex, Type.tvoid);
13094                                 ey = new CastExp(ey.loc, ey, Type.tvoid);
13095                             }
13096                             e = new CondExp(loc, new InExp(loc, ek, ea), ex, ey);
13097                         }
13098                         e = combine(e0, e);
13099                         e = e.semantic(sc);
13100                         return e;
13101                     }
13102                 }
13103                 else
13104                 {
13105                     Expression e = op_overload(sc);
13106                     if (e)
13107                         return e;
13108                 }
13109             }
13110             else
13111                 assert(op == TOKblit);
13112 
13113             e1 = e1x;
13114             e2 = e2x;
13115         }
13116         else if (t1.ty == Tclass)
13117         {
13118             // Disallow assignment operator overloads for same type
13119             if (op == TOKassign && !e2.implicitConvTo(e1.type))
13120             {
13121                 Expression e = op_overload(sc);
13122                 if (e)
13123                     return e;
13124             }
13125         }
13126         else if (t1.ty == Tsarray)
13127         {
13128             // SliceExp cannot have static array type without context inference.
13129             assert(e1.op != TOKslice);
13130             Expression e1x = e1;
13131             Expression e2x = e2;
13132 
13133             if (e2x.implicitConvTo(e1x.type))
13134             {
13135                 if (op != TOKblit && (e2x.op == TOKslice && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op == TOKcast && (cast(UnaExp)e2x).e1.isLvalue() || e2x.op != TOKslice && e2x.isLvalue()))
13136                 {
13137                     if (e1x.checkPostblit(sc, t1))
13138                         return new ErrorExp();
13139                 }
13140 
13141                 // e2 matches to t1 because of the implicit length match, so
13142                 if (isUnaArrayOp(e2x.op) || isBinArrayOp(e2x.op))
13143                 {
13144                     // convert e1 to e1[]
13145                     // e.g. e1[] = a[] + b[];
13146                     e1x = new SliceExp(e1x.loc, e1x, null, null);
13147                     e1x = e1x.semantic(sc);
13148                 }
13149                 else
13150                 {
13151                     // convert e2 to t1 later
13152                     // e.g. e1 = [1, 2, 3];
13153                 }
13154             }
13155             else
13156             {
13157                 if (e2x.implicitConvTo(t1.nextOf().arrayOf()) > MATCHnomatch)
13158                 {
13159                     uinteger_t dim1 = (cast(TypeSArray)t1).dim.toInteger();
13160                     uinteger_t dim2 = dim1;
13161                     if (e2x.op == TOKarrayliteral)
13162                     {
13163                         ArrayLiteralExp ale = cast(ArrayLiteralExp)e2x;
13164                         dim2 = ale.elements ? ale.elements.dim : 0;
13165                     }
13166                     else if (e2x.op == TOKslice)
13167                     {
13168                         Type tx = toStaticArrayType(cast(SliceExp)e2x);
13169                         if (tx)
13170                             dim2 = (cast(TypeSArray)tx).dim.toInteger();
13171                     }
13172                     if (dim1 != dim2)
13173                     {
13174                         error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
13175                         return new ErrorExp();
13176                     }
13177                 }
13178 
13179                 // May be block or element-wise assignment, so
13180                 // convert e1 to e1[]
13181                 if (op != TOKassign)
13182                 {
13183                     // If multidimensional static array, treat as one large array
13184                     dinteger_t dim = (cast(TypeSArray)t1).dim.toInteger();
13185                     Type t = t1;
13186                     while (1)
13187                     {
13188                         t = t.nextOf().toBasetype();
13189                         if (t.ty != Tsarray)
13190                             break;
13191                         dim *= (cast(TypeSArray)t).dim.toInteger();
13192                         e1x.type = t.nextOf().sarrayOf(dim);
13193                     }
13194                 }
13195                 e1x = new SliceExp(e1x.loc, e1x, null, null);
13196                 e1x = e1x.semantic(sc);
13197             }
13198             if (e1x.op == TOKerror)
13199                 return e1x;
13200             if (e2x.op == TOKerror)
13201                 return e2x;
13202 
13203             e1 = e1x;
13204             e2 = e2x;
13205             t1 = e1x.type.toBasetype();
13206         }
13207         /* Check the mutability of e1.
13208          */
13209         if (e1.op == TOKarraylength)
13210         {
13211             // e1 is not an lvalue, but we let code generator handle it
13212             ArrayLengthExp ale = cast(ArrayLengthExp)e1;
13213 
13214             Expression ale1x = ale.e1;
13215             ale1x = ale1x.modifiableLvalue(sc, e1);
13216             if (ale1x.op == TOKerror)
13217                 return ale1x;
13218             ale.e1 = ale1x;
13219 
13220             Type tn = ale.e1.type.toBasetype().nextOf();
13221             checkDefCtor(ale.loc, tn);
13222             semanticTypeInfo(sc, tn);
13223         }
13224         else if (e1.op == TOKslice)
13225         {
13226             Type tn = e1.type.nextOf();
13227             if (op == TOKassign && !tn.isMutable())
13228             {
13229                 error("slice %s is not mutable", e1.toChars());
13230                 return new ErrorExp();
13231             }
13232 
13233             // For conditional operator, both branches need conversion.
13234             SliceExp se = cast(SliceExp)e1;
13235             while (se.e1.op == TOKslice)
13236                 se = cast(SliceExp)se.e1;
13237             if (se.e1.op == TOKquestion && se.e1.type.toBasetype().ty == Tsarray)
13238             {
13239                 se.e1 = se.e1.modifiableLvalue(sc, e1);
13240                 if (se.e1.op == TOKerror)
13241                     return se.e1;
13242             }
13243         }
13244         else
13245         {
13246             Expression e1x = e1;
13247 
13248             // Try to do a decent error message with the expression
13249             // before it got constant folded
13250 
13251             if (e1x.op != TOKvar)
13252                 e1x = e1x.optimize(WANTvalue);
13253 
13254             if (op == TOKassign)
13255                 e1x = e1x.modifiableLvalue(sc, e1old);
13256 
13257             if (e1x.op == TOKerror)
13258                 return e1x;
13259             e1 = e1x;
13260         }
13261 
13262         /* Tweak e2 based on the type of e1.
13263          */
13264         Expression e2x = e2;
13265         Type t2 = e2x.type.toBasetype();
13266 
13267         // If it is a array, get the element type. Note that it may be
13268         // multi-dimensional.
13269         Type telem = t1;
13270         while (telem.ty == Tarray)
13271             telem = telem.nextOf();
13272 
13273         if (e1.op == TOKslice && t1.nextOf() &&
13274             (telem.ty != Tvoid || e2x.op == TOKnull) &&
13275             e2x.implicitConvTo(t1.nextOf()))
13276         {
13277             // Check for block assignment. If it is of type void[], void[][], etc,
13278             // '= null' is the only allowable block assignment (Bug 7493)
13279             memset |= MemorySet.blockAssign;    // make it easy for back end to tell what this is
13280             e2x = e2x.implicitCastTo(sc, t1.nextOf());
13281             if (op != TOKblit && e2x.isLvalue() && e1.checkPostblit(sc, t1.nextOf()))
13282             {
13283                 return new ErrorExp();
13284             }
13285         }
13286         else if (e1.op == TOKslice &&
13287                  (t2.ty == Tarray || t2.ty == Tsarray) &&
13288                  t2.nextOf().implicitConvTo(t1.nextOf()))
13289         {
13290             // Check element-wise assignment.
13291 
13292             /* If assigned elements number is known at compile time,
13293              * check the mismatch.
13294              */
13295             SliceExp se1 = cast(SliceExp)e1;
13296             TypeSArray tsa1 = cast(TypeSArray)toStaticArrayType(se1);
13297             TypeSArray tsa2 = null;
13298             if (e2x.op == TOKarrayliteral)
13299                 tsa2 = cast(TypeSArray)t2.nextOf().sarrayOf((cast(ArrayLiteralExp)e2x).elements.dim);
13300             else if (e2x.op == TOKslice)
13301                 tsa2 = cast(TypeSArray)toStaticArrayType(cast(SliceExp)e2x);
13302             else if (t2.ty == Tsarray)
13303                 tsa2 = cast(TypeSArray)t2;
13304             if (tsa1 && tsa2)
13305             {
13306                 uinteger_t dim1 = tsa1.dim.toInteger();
13307                 uinteger_t dim2 = tsa2.dim.toInteger();
13308                 if (dim1 != dim2)
13309                 {
13310                     error("mismatched array lengths, %d and %d", cast(int)dim1, cast(int)dim2);
13311                     return new ErrorExp();
13312                 }
13313             }
13314 
13315             if (op != TOKblit &&
13316                 (e2x.op == TOKslice && (cast(UnaExp)e2x).e1.isLvalue() ||
13317                  e2x.op == TOKcast && (cast(UnaExp)e2x).e1.isLvalue() ||
13318                  e2x.op != TOKslice && e2x.isLvalue()))
13319             {
13320                 if (e1.checkPostblit(sc, t1.nextOf()))
13321                     return new ErrorExp();
13322             }
13323 
13324             if (0 && global.params.warnings && !global.gag && op == TOKassign &&
13325                 e2x.op != TOKslice && e2x.op != TOKassign &&
13326                 e2x.op != TOKarrayliteral && e2x.op != TOKstring &&
13327                 !(e2x.op == TOKadd || e2x.op == TOKmin ||
13328                   e2x.op == TOKmul || e2x.op == TOKdiv ||
13329                   e2x.op == TOKmod || e2x.op == TOKxor ||
13330                   e2x.op == TOKand || e2x.op == TOKor ||
13331                   e2x.op == TOKpow ||
13332                   e2x.op == TOKtilde || e2x.op == TOKneg))
13333             {
13334                 const(char)* e1str = e1.toChars();
13335                 const(char)* e2str = e2x.toChars();
13336                 warning("explicit element-wise assignment %s = (%s)[] is better than %s = %s", e1str, e2str, e1str, e2str);
13337             }
13338 
13339             Type t2n = t2.nextOf();
13340             Type t1n = t1.nextOf();
13341             int offset;
13342             if (t2n.equivalent(t1n) ||
13343                 t1n.isBaseOf(t2n, &offset) && offset == 0)
13344             {
13345                 /* Allow copy of distinct qualifier elements.
13346                  * eg.
13347                  *  char[] dst;  const(char)[] src;
13348                  *  dst[] = src;
13349                  *
13350                  *  class C {}   class D : C {}
13351                  *  C[2] ca;  D[] da;
13352                  *  ca[] = da;
13353                  */
13354                 if (isArrayOpValid(e2x))
13355                 {
13356                     // Don't add CastExp to keep AST for array operations
13357                     e2x = e2x.copy();
13358                     e2x.type = e1.type.constOf();
13359                 }
13360                 else
13361                     e2x = e2x.castTo(sc, e1.type.constOf());
13362             }
13363             else
13364             {
13365                 /* Bugzilla 15778: A string literal has an array type of immutable
13366                  * elements by default, and normally it cannot be convertible to
13367                  * array type of mutable elements. But for element-wise assignment,
13368                  * elements need to be const at best. So we should give a chance
13369                  * to change code unit size for polysemous string literal.
13370                  */
13371                 if (e2x.op == TOKstring)
13372                     e2x = e2x.implicitCastTo(sc, e1.type.constOf());
13373                 else
13374                     e2x = e2x.implicitCastTo(sc, e1.type);
13375             }
13376             if (t1n.toBasetype.ty == Tvoid && t2n.toBasetype.ty == Tvoid)
13377             {
13378                 if (!sc.intypeof && sc.func && sc.func.setUnsafe())
13379                 {
13380                     error("cannot copy void[] to void[] in @safe code");
13381                     return new ErrorExp();
13382                 }
13383             }
13384         }
13385         else
13386         {
13387             if (0 && global.params.warnings && !global.gag && op == TOKassign &&
13388                 t1.ty == Tarray && t2.ty == Tsarray &&
13389                 e2x.op != TOKslice &&
13390                 t2.implicitConvTo(t1))
13391             {
13392                 // Disallow ar[] = sa (Converted to ar[] = sa[])
13393                 // Disallow da   = sa (Converted to da   = sa[])
13394                 const(char)* e1str = e1.toChars();
13395                 const(char)* e2str = e2x.toChars();
13396                 const(char)* atypestr = e1.op == TOKslice ? "element-wise" : "slice";
13397                 warning("explicit %s assignment %s = (%s)[] is better than %s = %s", atypestr, e1str, e2str, e1str, e2str);
13398             }
13399             if (op == TOKblit)
13400                 e2x = e2x.castTo(sc, e1.type);
13401             else
13402                 e2x = e2x.implicitCastTo(sc, e1.type);
13403         }
13404         if (e2x.op == TOKerror)
13405             return e2x;
13406         e2 = e2x;
13407         t2 = e2.type.toBasetype();
13408 
13409         /* Look for array operations
13410          */
13411         if ((t2.ty == Tarray || t2.ty == Tsarray) && isArrayOpValid(e2))
13412         {
13413             // Look for valid array operations
13414             if (!(memset & MemorySet.blockAssign) &&
13415                 e1.op == TOKslice &&
13416                 (isUnaArrayOp(e2.op) || isBinArrayOp(e2.op)))
13417             {
13418                 type = e1.type;
13419                 if (op == TOKconstruct) // Bugzilla 10282: tweak mutability of e1 element
13420                     e1.type = e1.type.nextOf().mutableOf().arrayOf();
13421                 return arrayOp(this, sc);
13422             }
13423 
13424             // Drop invalid array operations in e2
13425             //  d = a[] + b[], d = (a[] + b[])[0..2], etc
13426             if (checkNonAssignmentArrayOp(e2, !(memset & MemorySet.blockAssign) && op == TOKassign))
13427                 return new ErrorExp();
13428 
13429             // Remains valid array assignments
13430             //  d = d[], d = [1,2,3], etc
13431         }
13432 
13433         /* Don't allow assignment to classes that were allocated on the stack with:
13434          *      scope Class c = new Class();
13435          */
13436         if (e1.op == TOKvar && op == TOKassign)
13437         {
13438             VarExp ve = cast(VarExp)e1;
13439             VarDeclaration vd = ve.var.isVarDeclaration();
13440             if (vd && (vd.onstack || vd.mynew))
13441             {
13442                 assert(t1.ty == Tclass);
13443                 error("cannot rebind scope variables");
13444             }
13445         }
13446 
13447         if (e1.op == TOKvar && (cast(VarExp)e1).var.ident == Id.ctfe)
13448         {
13449             error("cannot modify compiler-generated variable __ctfe");
13450         }
13451 
13452         type = e1.type;
13453         assert(type);
13454         return op == TOKassign ? reorderSettingAAElem(sc) : this;
13455     }
13456 
13457     override final bool isLvalue()
13458     {
13459         // Array-op 'x[] = y[]' should make an rvalue.
13460         // Setting array length 'x.length = v' should make an rvalue.
13461         if (e1.op == TOKslice || e1.op == TOKarraylength)
13462         {
13463             return false;
13464         }
13465         return true;
13466     }
13467 
13468     override final Expression toLvalue(Scope* sc, Expression ex)
13469     {
13470         if (e1.op == TOKslice || e1.op == TOKarraylength)
13471         {
13472             return Expression.toLvalue(sc, ex);
13473         }
13474 
13475         /* In front-end level, AssignExp should make an lvalue of e1.
13476          * Taking the address of e1 will be handled in low level layer,
13477          * so this function does nothing.
13478          */
13479         return this;
13480     }
13481 
13482     override final Expression toBoolean(Scope* sc)
13483     {
13484         // Things like:
13485         //  if (a = b) ...
13486         // are usually mistakes.
13487 
13488         error("assignment cannot be used as a condition, perhaps == was meant?");
13489         return new ErrorExp();
13490     }
13491 
13492     override void accept(Visitor v)
13493     {
13494         v.visit(this);
13495     }
13496 }
13497 
13498 /***********************************************************
13499  */
13500 extern (C++) final class ConstructExp : AssignExp
13501 {
13502     extern (D) this(Loc loc, Expression e1, Expression e2)
13503     {
13504         super(loc, e1, e2);
13505         op = TOKconstruct;
13506     }
13507 
13508     // Internal use only. If `v` is a reference variable, the assinment
13509     // will become a reference initialization automatically.
13510     extern (D) this(Loc loc, VarDeclaration v, Expression e2)
13511     {
13512         auto ve = new VarExp(loc, v);
13513         assert(v.type && ve.type);
13514 
13515         super(loc, ve, e2);
13516         op = TOKconstruct;
13517 
13518         if (v.storage_class & (STCref | STCout))
13519             memset |= MemorySet.referenceInit;
13520     }
13521 
13522     override void accept(Visitor v)
13523     {
13524         v.visit(this);
13525     }
13526 }
13527 
13528 /***********************************************************
13529  */
13530 extern (C++) final class BlitExp : AssignExp
13531 {
13532     extern (D) this(Loc loc, Expression e1, Expression e2)
13533     {
13534         super(loc, e1, e2);
13535         op = TOKblit;
13536     }
13537 
13538     // Internal use only. If `v` is a reference variable, the assinment
13539     // will become a reference rebinding automatically.
13540     extern (D) this(Loc loc, VarDeclaration v, Expression e2)
13541     {
13542         auto ve = new VarExp(loc, v);
13543         assert(v.type && ve.type);
13544 
13545         super(loc, ve, e2);
13546         op = TOKblit;
13547 
13548         if (v.storage_class & (STCref | STCout))
13549             memset |= MemorySet.referenceInit;
13550     }
13551 
13552     override void accept(Visitor v)
13553     {
13554         v.visit(this);
13555     }
13556 }
13557 
13558 /***********************************************************
13559  */
13560 extern (C++) final class AddAssignExp : BinAssignExp
13561 {
13562     extern (D) this(Loc loc, Expression e1, Expression e2)
13563     {
13564         super(loc, TOKaddass, __traits(classInstanceSize, AddAssignExp), e1, e2);
13565     }
13566 
13567     override void accept(Visitor v)
13568     {
13569         v.visit(this);
13570     }
13571 }
13572 
13573 /***********************************************************
13574  */
13575 extern (C++) final class MinAssignExp : BinAssignExp
13576 {
13577     extern (D) this(Loc loc, Expression e1, Expression e2)
13578     {
13579         super(loc, TOKminass, __traits(classInstanceSize, MinAssignExp), e1, e2);
13580     }
13581 
13582     override void accept(Visitor v)
13583     {
13584         v.visit(this);
13585     }
13586 }
13587 
13588 /***********************************************************
13589  */
13590 extern (C++) final class MulAssignExp : BinAssignExp
13591 {
13592     extern (D) this(Loc loc, Expression e1, Expression e2)
13593     {
13594         super(loc, TOKmulass, __traits(classInstanceSize, MulAssignExp), e1, e2);
13595     }
13596 
13597     override void accept(Visitor v)
13598     {
13599         v.visit(this);
13600     }
13601 }
13602 
13603 /***********************************************************
13604  */
13605 extern (C++) final class DivAssignExp : BinAssignExp
13606 {
13607     extern (D) this(Loc loc, Expression e1, Expression e2)
13608     {
13609         super(loc, TOKdivass, __traits(classInstanceSize, DivAssignExp), e1, e2);
13610     }
13611 
13612     override void accept(Visitor v)
13613     {
13614         v.visit(this);
13615     }
13616 }
13617 
13618 /***********************************************************
13619  */
13620 extern (C++) final class ModAssignExp : BinAssignExp
13621 {
13622     extern (D) this(Loc loc, Expression e1, Expression e2)
13623     {
13624         super(loc, TOKmodass, __traits(classInstanceSize, ModAssignExp), e1, e2);
13625     }
13626 
13627     override void accept(Visitor v)
13628     {
13629         v.visit(this);
13630     }
13631 }
13632 
13633 /***********************************************************
13634  */
13635 extern (C++) final class AndAssignExp : BinAssignExp
13636 {
13637     extern (D) this(Loc loc, Expression e1, Expression e2)
13638     {
13639         super(loc, TOKandass, __traits(classInstanceSize, AndAssignExp), e1, e2);
13640     }
13641 
13642     override void accept(Visitor v)
13643     {
13644         v.visit(this);
13645     }
13646 }
13647 
13648 /***********************************************************
13649  */
13650 extern (C++) final class OrAssignExp : BinAssignExp
13651 {
13652     extern (D) this(Loc loc, Expression e1, Expression e2)
13653     {
13654         super(loc, TOKorass, __traits(classInstanceSize, OrAssignExp), e1, e2);
13655     }
13656 
13657     override void accept(Visitor v)
13658     {
13659         v.visit(this);
13660     }
13661 }
13662 
13663 /***********************************************************
13664  */
13665 extern (C++) final class XorAssignExp : BinAssignExp
13666 {
13667     extern (D) this(Loc loc, Expression e1, Expression e2)
13668     {
13669         super(loc, TOKxorass, __traits(classInstanceSize, XorAssignExp), e1, e2);
13670     }
13671 
13672     override void accept(Visitor v)
13673     {
13674         v.visit(this);
13675     }
13676 }
13677 
13678 /***********************************************************
13679  */
13680 extern (C++) final class PowAssignExp : BinAssignExp
13681 {
13682     extern (D) this(Loc loc, Expression e1, Expression e2)
13683     {
13684         super(loc, TOKpowass, __traits(classInstanceSize, PowAssignExp), e1, e2);
13685     }
13686 
13687     override Expression semantic(Scope* sc)
13688     {
13689         if (type)
13690             return this;
13691 
13692         Expression e = op_overload(sc);
13693         if (e)
13694             return e;
13695 
13696         if (e1.checkReadModifyWrite(op, e2))
13697             return new ErrorExp();
13698 
13699         assert(e1.type && e2.type);
13700         if (e1.op == TOKslice || e1.type.ty == Tarray || e1.type.ty == Tsarray)
13701         {
13702             // T[] ^^= ...
13703             if (e2.implicitConvTo(e1.type.nextOf()))
13704             {
13705                 // T[] ^^= T
13706                 e2 = e2.castTo(sc, e1.type.nextOf());
13707             }
13708             else if (Expression ex = typeCombine(this, sc))
13709                 return ex;
13710 
13711             // Check element types are arithmetic
13712             Type tb1 = e1.type.nextOf().toBasetype();
13713             Type tb2 = e2.type.toBasetype();
13714             if (tb2.ty == Tarray || tb2.ty == Tsarray)
13715                 tb2 = tb2.nextOf().toBasetype();
13716             if ((tb1.isintegral() || tb1.isfloating()) && (tb2.isintegral() || tb2.isfloating()))
13717             {
13718                 type = e1.type;
13719                 return arrayOp(this, sc);
13720             }
13721         }
13722         else
13723         {
13724             e1 = e1.modifiableLvalue(sc, e1);
13725         }
13726 
13727         if ((e1.type.isintegral() || e1.type.isfloating()) && (e2.type.isintegral() || e2.type.isfloating()))
13728         {
13729             Expression e0 = null;
13730             e = reorderSettingAAElem(sc);
13731             e = extractLast(e, &e0);
13732             assert(e == this);
13733 
13734             if (e1.op == TOKvar)
13735             {
13736                 // Rewrite: e1 = e1 ^^ e2
13737                 e = new PowExp(loc, e1.syntaxCopy(), e2);
13738                 e = new AssignExp(loc, e1, e);
13739             }
13740             else
13741             {
13742                 // Rewrite: ref tmp = e1; tmp = tmp ^^ e2
13743                 auto v = copyToTemp(STCref, "__powtmp", e1);
13744                 auto de = new DeclarationExp(e1.loc, v);
13745                 auto ve = new VarExp(e1.loc, v);
13746                 e = new PowExp(loc, ve, e2);
13747                 e = new AssignExp(loc, new VarExp(e1.loc, v), e);
13748                 e = new CommaExp(loc, de, e);
13749             }
13750             e = Expression.combine(e0, e);
13751             e = e.semantic(sc);
13752             if (e.type.toBasetype().ty == Tvector)
13753                 return incompatibleTypes();
13754             return e;
13755         }
13756         return incompatibleTypes();
13757     }
13758 
13759     override void accept(Visitor v)
13760     {
13761         v.visit(this);
13762     }
13763 }
13764 
13765 /***********************************************************
13766  */
13767 extern (C++) final class ShlAssignExp : BinAssignExp
13768 {
13769     extern (D) this(Loc loc, Expression e1, Expression e2)
13770     {
13771         super(loc, TOKshlass, __traits(classInstanceSize, ShlAssignExp), e1, e2);
13772     }
13773 
13774     override void accept(Visitor v)
13775     {
13776         v.visit(this);
13777     }
13778 }
13779 
13780 /***********************************************************
13781  */
13782 extern (C++) final class ShrAssignExp : BinAssignExp
13783 {
13784     extern (D) this(Loc loc, Expression e1, Expression e2)
13785     {
13786         super(loc, TOKshrass, __traits(classInstanceSize, ShrAssignExp), e1, e2);
13787     }
13788 
13789     override void accept(Visitor v)
13790     {
13791         v.visit(this);
13792     }
13793 }
13794 
13795 /***********************************************************
13796  */
13797 extern (C++) final class UshrAssignExp : BinAssignExp
13798 {
13799     extern (D) this(Loc loc, Expression e1, Expression e2)
13800     {
13801         super(loc, TOKushrass, __traits(classInstanceSize, UshrAssignExp), e1, e2);
13802     }
13803 
13804     override void accept(Visitor v)
13805     {
13806         v.visit(this);
13807     }
13808 }
13809 
13810 /***********************************************************
13811  */
13812 extern (C++) final class CatAssignExp : BinAssignExp
13813 {
13814     extern (D) this(Loc loc, Expression e1, Expression e2)
13815     {
13816         super(loc, TOKcatass, __traits(classInstanceSize, CatAssignExp), e1, e2);
13817     }
13818 
13819     override Expression semantic(Scope* sc)
13820     {
13821         if (type)
13822             return this;
13823 
13824         //printf("CatAssignExp::semantic() %s\n", toChars());
13825         Expression e = op_overload(sc);
13826         if (e)
13827             return e;
13828 
13829         if (e1.op == TOKslice)
13830         {
13831             SliceExp se = cast(SliceExp)e1;
13832             if (se.e1.type.toBasetype().ty == Tsarray)
13833             {
13834                 error("cannot append to static array %s", se.e1.type.toChars());
13835                 return new ErrorExp();
13836             }
13837         }
13838 
13839         e1 = e1.modifiableLvalue(sc, e1);
13840         if (e1.op == TOKerror)
13841             return e1;
13842         if (e2.op == TOKerror)
13843             return e2;
13844 
13845         if (checkNonAssignmentArrayOp(e2))
13846             return new ErrorExp();
13847 
13848         Type tb1 = e1.type.toBasetype();
13849         Type tb1next = tb1.nextOf();
13850         Type tb2 = e2.type.toBasetype();
13851 
13852         if ((tb1.ty == Tarray) &&
13853             (tb2.ty == Tarray || tb2.ty == Tsarray) &&
13854             (e2.implicitConvTo(e1.type) ||
13855              (tb2.nextOf().implicitConvTo(tb1next) &&
13856               (tb2.nextOf().size(Loc()) == tb1next.size(Loc())))))
13857         {
13858             // Append array
13859             if (e1.checkPostblit(sc, tb1next))
13860                 return new ErrorExp();
13861             e2 = e2.castTo(sc, e1.type);
13862         }
13863         else if ((tb1.ty == Tarray) && e2.implicitConvTo(tb1next))
13864         {
13865             // Append element
13866             if (e2.checkPostblit(sc, tb2))
13867                 return new ErrorExp();
13868             e2 = e2.castTo(sc, tb1next);
13869             e2 = doCopyOrMove(sc, e2);
13870         }
13871         else if (tb1.ty == Tarray &&
13872                  (tb1next.ty == Tchar || tb1next.ty == Twchar) &&
13873                  e2.type.ty != tb1next.ty &&
13874                  e2.implicitConvTo(Type.tdchar))
13875         {
13876             // Append dchar to char[] or wchar[]
13877             e2 = e2.castTo(sc, Type.tdchar);
13878 
13879             /* Do not allow appending wchar to char[] because if wchar happens
13880              * to be a surrogate pair, nothing good can result.
13881              */
13882         }
13883         else
13884         {
13885             error("cannot append type %s to type %s", tb2.toChars(), tb1.toChars());
13886             return new ErrorExp();
13887         }
13888         if (e2.checkValue())
13889             return new ErrorExp();
13890 
13891         type = e1.type;
13892         return reorderSettingAAElem(sc);
13893     }
13894 
13895     override void accept(Visitor v)
13896     {
13897         v.visit(this);
13898     }
13899 }
13900 
13901 /***********************************************************
13902  */
13903 extern (C++) final class AddExp : BinExp
13904 {
13905     extern (D) this(Loc loc, Expression e1, Expression e2)
13906     {
13907         super(loc, TOKadd, __traits(classInstanceSize, AddExp), e1, e2);
13908     }
13909 
13910     override Expression semantic(Scope* sc)
13911     {
13912         static if (LOGSEMANTIC)
13913         {
13914             printf("AddExp::semantic('%s')\n", toChars());
13915         }
13916         if (type)
13917             return this;
13918 
13919         if (Expression ex = binSemanticProp(sc))
13920             return ex;
13921         Expression e = op_overload(sc);
13922         if (e)
13923             return e;
13924 
13925         Type tb1 = e1.type.toBasetype();
13926         Type tb2 = e2.type.toBasetype();
13927 
13928         bool err = false;
13929         if (tb1.ty == Tdelegate || tb1.ty == Tpointer && tb1.nextOf().ty == Tfunction)
13930         {
13931             err |= e1.checkArithmetic();
13932         }
13933         if (tb2.ty == Tdelegate || tb2.ty == Tpointer && tb2.nextOf().ty == Tfunction)
13934         {
13935             err |= e2.checkArithmetic();
13936         }
13937         if (err)
13938             return new ErrorExp();
13939 
13940         if (tb1.ty == Tpointer && e2.type.isintegral() || tb2.ty == Tpointer && e1.type.isintegral())
13941         {
13942             return scaleFactor(this, sc);
13943         }
13944 
13945         if (tb1.ty == Tpointer && tb2.ty == Tpointer)
13946         {
13947             return incompatibleTypes();
13948         }
13949 
13950         if (Expression ex = typeCombine(this, sc))
13951             return ex;
13952 
13953         Type tb = type.toBasetype();
13954         if (tb.ty == Tarray || tb.ty == Tsarray)
13955         {
13956             if (!isArrayOpValid(this))
13957             {
13958                 error("invalid array operation %s (possible missing [])", toChars());
13959                 return new ErrorExp();
13960             }
13961             return this;
13962         }
13963 
13964         tb1 = e1.type.toBasetype();
13965         if (tb1.ty == Tvector && !tb1.isscalar())
13966         {
13967             return incompatibleTypes();
13968         }
13969         if ((tb1.isreal() && e2.type.isimaginary()) || (tb1.isimaginary() && e2.type.isreal()))
13970         {
13971             switch (type.toBasetype().ty)
13972             {
13973             case Tfloat32:
13974             case Timaginary32:
13975                 type = Type.tcomplex32;
13976                 break;
13977 
13978             case Tfloat64:
13979             case Timaginary64:
13980                 type = Type.tcomplex64;
13981                 break;
13982 
13983             case Tfloat80:
13984             case Timaginary80:
13985                 type = Type.tcomplex80;
13986                 break;
13987 
13988             default:
13989                 assert(0);
13990             }
13991         }
13992         return this;
13993     }
13994 
13995     override void accept(Visitor v)
13996     {
13997         v.visit(this);
13998     }
13999 }
14000 
14001 /***********************************************************
14002  */
14003 extern (C++) final class MinExp : BinExp
14004 {
14005     extern (D) this(Loc loc, Expression e1, Expression e2)
14006     {
14007         super(loc, TOKmin, __traits(classInstanceSize, MinExp), e1, e2);
14008     }
14009 
14010     override Expression semantic(Scope* sc)
14011     {
14012         static if (LOGSEMANTIC)
14013         {
14014             printf("MinExp::semantic('%s')\n", toChars());
14015         }
14016         if (type)
14017             return this;
14018 
14019         if (Expression ex = binSemanticProp(sc))
14020             return ex;
14021         Expression e = op_overload(sc);
14022         if (e)
14023             return e;
14024 
14025         Type t1 = e1.type.toBasetype();
14026         Type t2 = e2.type.toBasetype();
14027 
14028         bool err = false;
14029         if (t1.ty == Tdelegate || t1.ty == Tpointer && t1.nextOf().ty == Tfunction)
14030         {
14031             err |= e1.checkArithmetic();
14032         }
14033         if (t2.ty == Tdelegate || t2.ty == Tpointer && t2.nextOf().ty == Tfunction)
14034         {
14035             err |= e2.checkArithmetic();
14036         }
14037         if (err)
14038             return new ErrorExp();
14039 
14040         if (t1.ty == Tpointer)
14041         {
14042             if (t2.ty == Tpointer)
14043             {
14044                 // Need to divide the result by the stride
14045                 // Replace (ptr - ptr) with (ptr - ptr) / stride
14046                 d_int64 stride;
14047 
14048                 // make sure pointer types are compatible
14049                 if (Expression ex = typeCombine(this, sc))
14050                     return ex;
14051 
14052                 type = Type.tptrdiff_t;
14053                 stride = t2.nextOf().size();
14054                 if (stride == 0)
14055                 {
14056                     e = new IntegerExp(loc, 0, Type.tptrdiff_t);
14057                 }
14058                 else
14059                 {
14060                     e = new DivExp(loc, this, new IntegerExp(Loc(), stride, Type.tptrdiff_t));
14061                     e.type = Type.tptrdiff_t;
14062                 }
14063             }
14064             else if (t2.isintegral())
14065                 e = scaleFactor(this, sc);
14066             else
14067             {
14068                 error("can't subtract %s from pointer", t2.toChars());
14069                 e = new ErrorExp();
14070             }
14071             return e;
14072         }
14073         if (t2.ty == Tpointer)
14074         {
14075             type = e2.type;
14076             error("can't subtract pointer from %s", e1.type.toChars());
14077             return new ErrorExp();
14078         }
14079 
14080         if (Expression ex = typeCombine(this, sc))
14081             return ex;
14082 
14083         Type tb = type.toBasetype();
14084         if (tb.ty == Tarray || tb.ty == Tsarray)
14085         {
14086             if (!isArrayOpValid(this))
14087             {
14088                 error("invalid array operation %s (possible missing [])", toChars());
14089                 return new ErrorExp();
14090             }
14091             return this;
14092         }
14093 
14094         t1 = e1.type.toBasetype();
14095         t2 = e2.type.toBasetype();
14096         if (t1.ty == Tvector && !t1.isscalar())
14097         {
14098             return incompatibleTypes();
14099         }
14100         if ((t1.isreal() && t2.isimaginary()) || (t1.isimaginary() && t2.isreal()))
14101         {
14102             switch (type.ty)
14103             {
14104             case Tfloat32:
14105             case Timaginary32:
14106                 type = Type.tcomplex32;
14107                 break;
14108 
14109             case Tfloat64:
14110             case Timaginary64:
14111                 type = Type.tcomplex64;
14112                 break;
14113 
14114             case Tfloat80:
14115             case Timaginary80:
14116                 type = Type.tcomplex80;
14117                 break;
14118 
14119             default:
14120                 assert(0);
14121             }
14122         }
14123         return this;
14124     }
14125 
14126     override void accept(Visitor v)
14127     {
14128         v.visit(this);
14129     }
14130 }
14131 
14132 /***********************************************************
14133  */
14134 extern (C++) final class CatExp : BinExp
14135 {
14136     extern (D) this(Loc loc, Expression e1, Expression e2)
14137     {
14138         super(loc, TOKcat, __traits(classInstanceSize, CatExp), e1, e2);
14139     }
14140 
14141     override Expression semantic(Scope* sc)
14142     {
14143         //printf("CatExp::semantic() %s\n", toChars());
14144         if (type)
14145             return this;
14146 
14147         if (Expression ex = binSemanticProp(sc))
14148             return ex;
14149         Expression e = op_overload(sc);
14150         if (e)
14151             return e;
14152 
14153         Type tb1 = e1.type.toBasetype();
14154         Type tb2 = e2.type.toBasetype();
14155 
14156         auto f1 = checkNonAssignmentArrayOp(e1);
14157         auto f2 = checkNonAssignmentArrayOp(e2);
14158         if (f1 || f2)
14159             return new ErrorExp();
14160 
14161         /* BUG: Should handle things like:
14162          *      char c;
14163          *      c ~ ' '
14164          *      ' ' ~ c;
14165          */
14166 
14167         version (none)
14168         {
14169             e1.type.print();
14170             e2.type.print();
14171         }
14172         Type tb1next = tb1.nextOf();
14173         Type tb2next = tb2.nextOf();
14174 
14175         // Check for: array ~ array
14176         if (tb1next && tb2next && (tb1next.implicitConvTo(tb2next) >= MATCHconst || tb2next.implicitConvTo(tb1next) >= MATCHconst || e1.op == TOKarrayliteral && e1.implicitConvTo(tb2) || e2.op == TOKarrayliteral && e2.implicitConvTo(tb1)))
14177         {
14178             /* Bugzilla 9248: Here to avoid the case of:
14179              *    void*[] a = [cast(void*)1];
14180              *    void*[] b = [cast(void*)2];
14181              *    a ~ b;
14182              * becoming:
14183              *    a ~ [cast(void*)b];
14184              */
14185 
14186             /* Bugzilla 14682: Also to avoid the case of:
14187              *    int[][] a;
14188              *    a ~ [];
14189              * becoming:
14190              *    a ~ cast(int[])[];
14191              */
14192             goto Lpeer;
14193         }
14194 
14195         // Check for: array ~ element
14196         if ((tb1.ty == Tsarray || tb1.ty == Tarray) && tb2.ty != Tvoid)
14197         {
14198             if (e1.op == TOKarrayliteral)
14199             {
14200                 e2 = doCopyOrMove(sc, e2);
14201                 // Bugzilla 14686: Postblit call appears in AST, and this is
14202                 // finally translated  to an ArrayLiteralExp in below optimize().
14203             }
14204             else if (e1.op == TOKstring)
14205             {
14206                 // No postblit call exists on character (integer) value.
14207             }
14208             else
14209             {
14210                 if (e2.checkPostblit(sc, tb2))
14211                     return new ErrorExp();
14212                 // Postblit call will be done in runtime helper function
14213             }
14214 
14215             if (e1.op == TOKarrayliteral && e1.implicitConvTo(tb2.arrayOf()))
14216             {
14217                 e1 = e1.implicitCastTo(sc, tb2.arrayOf());
14218                 type = tb2.arrayOf();
14219                 goto L2elem;
14220             }
14221             if (e2.implicitConvTo(tb1next) >= MATCHconvert)
14222             {
14223                 e2 = e2.implicitCastTo(sc, tb1next);
14224                 type = tb1next.arrayOf();
14225             L2elem:
14226                 if (tb2.ty == Tarray || tb2.ty == Tsarray)
14227                 {
14228                     // Make e2 into [e2]
14229                     e2 = new ArrayLiteralExp(e2.loc, e2);
14230                     e2.type = type;
14231                 }
14232                 return optimize(WANTvalue);
14233             }
14234         }
14235         // Check for: element ~ array
14236         if ((tb2.ty == Tsarray || tb2.ty == Tarray) && tb1.ty != Tvoid)
14237         {
14238             if (e2.op == TOKarrayliteral)
14239             {
14240                 e1 = doCopyOrMove(sc, e1);
14241             }
14242             else if (e2.op == TOKstring)
14243             {
14244             }
14245             else
14246             {
14247                 if (e1.checkPostblit(sc, tb1))
14248                     return new ErrorExp();
14249             }
14250 
14251             if (e2.op == TOKarrayliteral && e2.implicitConvTo(tb1.arrayOf()))
14252             {
14253                 e2 = e2.implicitCastTo(sc, tb1.arrayOf());
14254                 type = tb1.arrayOf();
14255                 goto L1elem;
14256             }
14257             if (e1.implicitConvTo(tb2next) >= MATCHconvert)
14258             {
14259                 e1 = e1.implicitCastTo(sc, tb2next);
14260                 type = tb2next.arrayOf();
14261             L1elem:
14262                 if (tb1.ty == Tarray || tb1.ty == Tsarray)
14263                 {
14264                     // Make e1 into [e1]
14265                     e1 = new ArrayLiteralExp(e1.loc, e1);
14266                     e1.type = type;
14267                 }
14268                 return optimize(WANTvalue);
14269             }
14270         }
14271 
14272     Lpeer:
14273         if ((tb1.ty == Tsarray || tb1.ty == Tarray) && (tb2.ty == Tsarray || tb2.ty == Tarray) && (tb1next.mod || tb2next.mod) && (tb1next.mod != tb2next.mod))
14274         {
14275             Type t1 = tb1next.mutableOf().constOf().arrayOf();
14276             Type t2 = tb2next.mutableOf().constOf().arrayOf();
14277             if (e1.op == TOKstring && !(cast(StringExp)e1).committed)
14278                 e1.type = t1;
14279             else
14280                 e1 = e1.castTo(sc, t1);
14281             if (e2.op == TOKstring && !(cast(StringExp)e2).committed)
14282                 e2.type = t2;
14283             else
14284                 e2 = e2.castTo(sc, t2);
14285         }
14286 
14287         if (Expression ex = typeCombine(this, sc))
14288             return ex;
14289         type = type.toHeadMutable();
14290 
14291         Type tb = type.toBasetype();
14292         if (tb.ty == Tsarray)
14293             type = tb.nextOf().arrayOf();
14294         if (type.ty == Tarray && tb1next && tb2next && tb1next.mod != tb2next.mod)
14295         {
14296             type = type.nextOf().toHeadMutable().arrayOf();
14297         }
14298         if (Type tbn = tb.nextOf())
14299         {
14300             if (checkPostblit(sc, tbn))
14301                 return new ErrorExp();
14302         }
14303         version (none)
14304         {
14305             e1.type.print();
14306             e2.type.print();
14307             type.print();
14308             print();
14309         }
14310         Type t1 = e1.type.toBasetype();
14311         Type t2 = e2.type.toBasetype();
14312         if ((t1.ty == Tarray || t1.ty == Tsarray) &&
14313             (t2.ty == Tarray || t2.ty == Tsarray))
14314         {
14315             // Normalize to ArrayLiteralExp or StringExp as far as possible
14316             e = optimize(WANTvalue);
14317         }
14318         else
14319         {
14320             //printf("(%s) ~ (%s)\n", e1->toChars(), e2->toChars());
14321             return incompatibleTypes();
14322         }
14323 
14324         return e;
14325     }
14326 
14327     override void accept(Visitor v)
14328     {
14329         v.visit(this);
14330     }
14331 }
14332 
14333 /***********************************************************
14334  */
14335 extern (C++) final class MulExp : BinExp
14336 {
14337     extern (D) this(Loc loc, Expression e1, Expression e2)
14338     {
14339         super(loc, TOKmul, __traits(classInstanceSize, MulExp), e1, e2);
14340     }
14341 
14342     override Expression semantic(Scope* sc)
14343     {
14344         version (none)
14345         {
14346             printf("MulExp::semantic() %s\n", toChars());
14347         }
14348         if (type)
14349             return this;
14350 
14351         if (Expression ex = binSemanticProp(sc))
14352             return ex;
14353         Expression e = op_overload(sc);
14354         if (e)
14355             return e;
14356 
14357         if (Expression ex = typeCombine(this, sc))
14358             return ex;
14359 
14360         Type tb = type.toBasetype();
14361         if (tb.ty == Tarray || tb.ty == Tsarray)
14362         {
14363             if (!isArrayOpValid(this))
14364             {
14365                 error("invalid array operation %s (possible missing [])", toChars());
14366                 return new ErrorExp();
14367             }
14368             return this;
14369         }
14370 
14371         if (checkArithmeticBin())
14372             return new ErrorExp();
14373 
14374         if (type.isfloating())
14375         {
14376             Type t1 = e1.type;
14377             Type t2 = e2.type;
14378 
14379             if (t1.isreal())
14380             {
14381                 type = t2;
14382             }
14383             else if (t2.isreal())
14384             {
14385                 type = t1;
14386             }
14387             else if (t1.isimaginary())
14388             {
14389                 if (t2.isimaginary())
14390                 {
14391                     switch (t1.toBasetype().ty)
14392                     {
14393                     case Timaginary32:
14394                         type = Type.tfloat32;
14395                         break;
14396 
14397                     case Timaginary64:
14398                         type = Type.tfloat64;
14399                         break;
14400 
14401                     case Timaginary80:
14402                         type = Type.tfloat80;
14403                         break;
14404 
14405                     default:
14406                         assert(0);
14407                     }
14408 
14409                     // iy * iv = -yv
14410                     e1.type = type;
14411                     e2.type = type;
14412                     e = new NegExp(loc, this);
14413                     e = e.semantic(sc);
14414                     return e;
14415                 }
14416                 else
14417                     type = t2; // t2 is complex
14418             }
14419             else if (t2.isimaginary())
14420             {
14421                 type = t1; // t1 is complex
14422             }
14423         }
14424         else if (tb.ty == Tvector && (cast(TypeVector)tb).elementType().size(loc) != 2)
14425         {
14426             // Only short[8] and ushort[8] work with multiply
14427             return incompatibleTypes();
14428         }
14429         return this;
14430     }
14431 
14432     override void accept(Visitor v)
14433     {
14434         v.visit(this);
14435     }
14436 }
14437 
14438 /***********************************************************
14439  */
14440 extern (C++) final class DivExp : BinExp
14441 {
14442     extern (D) this(Loc loc, Expression e1, Expression e2)
14443     {
14444         super(loc, TOKdiv, __traits(classInstanceSize, DivExp), e1, e2);
14445     }
14446 
14447     override Expression semantic(Scope* sc)
14448     {
14449         if (type)
14450             return this;
14451 
14452         if (Expression ex = binSemanticProp(sc))
14453             return ex;
14454         Expression e = op_overload(sc);
14455         if (e)
14456             return e;
14457 
14458         if (Expression ex = typeCombine(this, sc))
14459             return ex;
14460 
14461         Type tb = type.toBasetype();
14462         if (tb.ty == Tarray || tb.ty == Tsarray)
14463         {
14464             if (!isArrayOpValid(this))
14465             {
14466                 error("invalid array operation %s (possible missing [])", toChars());
14467                 return new ErrorExp();
14468             }
14469             return this;
14470         }
14471 
14472         if (checkArithmeticBin())
14473             return new ErrorExp();
14474 
14475         if (type.isfloating())
14476         {
14477             Type t1 = e1.type;
14478             Type t2 = e2.type;
14479 
14480             if (t1.isreal())
14481             {
14482                 type = t2;
14483                 if (t2.isimaginary())
14484                 {
14485                     // x/iv = i(-x/v)
14486                     e2.type = t1;
14487                     e = new NegExp(loc, this);
14488                     e = e.semantic(sc);
14489                     return e;
14490                 }
14491             }
14492             else if (t2.isreal())
14493             {
14494                 type = t1;
14495             }
14496             else if (t1.isimaginary())
14497             {
14498                 if (t2.isimaginary())
14499                 {
14500                     switch (t1.toBasetype().ty)
14501                     {
14502                     case Timaginary32:
14503                         type = Type.tfloat32;
14504                         break;
14505 
14506                     case Timaginary64:
14507                         type = Type.tfloat64;
14508                         break;
14509 
14510                     case Timaginary80:
14511                         type = Type.tfloat80;
14512                         break;
14513 
14514                     default:
14515                         assert(0);
14516                     }
14517                 }
14518                 else
14519                     type = t2; // t2 is complex
14520             }
14521             else if (t2.isimaginary())
14522             {
14523                 type = t1; // t1 is complex
14524             }
14525         }
14526         else if (tb.ty == Tvector)
14527         {
14528             return incompatibleTypes();
14529         }
14530         return this;
14531     }
14532 
14533     override void accept(Visitor v)
14534     {
14535         v.visit(this);
14536     }
14537 }
14538 
14539 /***********************************************************
14540  */
14541 extern (C++) final class ModExp : BinExp
14542 {
14543     extern (D) this(Loc loc, Expression e1, Expression e2)
14544     {
14545         super(loc, TOKmod, __traits(classInstanceSize, ModExp), e1, e2);
14546     }
14547 
14548     override Expression semantic(Scope* sc)
14549     {
14550         if (type)
14551             return this;
14552 
14553         if (Expression ex = binSemanticProp(sc))
14554             return ex;
14555         Expression e = op_overload(sc);
14556         if (e)
14557             return e;
14558 
14559         if (Expression ex = typeCombine(this, sc))
14560             return ex;
14561 
14562         Type tb = type.toBasetype();
14563         if (tb.ty == Tarray || tb.ty == Tsarray)
14564         {
14565             if (!isArrayOpValid(this))
14566             {
14567                 error("invalid array operation %s (possible missing [])", toChars());
14568                 return new ErrorExp();
14569             }
14570             return this;
14571         }
14572         if (tb.ty == Tvector)
14573         {
14574             return incompatibleTypes();
14575         }
14576 
14577         if (checkArithmeticBin())
14578             return new ErrorExp();
14579 
14580         if (type.isfloating())
14581         {
14582             type = e1.type;
14583             if (e2.type.iscomplex())
14584             {
14585                 error("cannot perform modulo complex arithmetic");
14586                 return new ErrorExp();
14587             }
14588         }
14589         return this;
14590     }
14591 
14592     override void accept(Visitor v)
14593     {
14594         v.visit(this);
14595     }
14596 }
14597 
14598 /***********************************************************
14599  */
14600 extern (C++) final class PowExp : BinExp
14601 {
14602     extern (D) this(Loc loc, Expression e1, Expression e2)
14603     {
14604         super(loc, TOKpow, __traits(classInstanceSize, PowExp), e1, e2);
14605     }
14606 
14607     override Expression semantic(Scope* sc)
14608     {
14609         if (type)
14610             return this;
14611 
14612         //printf("PowExp::semantic() %s\n", toChars());
14613         if (Expression ex = binSemanticProp(sc))
14614             return ex;
14615         Expression e = op_overload(sc);
14616         if (e)
14617             return e;
14618 
14619         if (Expression ex = typeCombine(this, sc))
14620             return ex;
14621 
14622         Type tb = type.toBasetype();
14623         if (tb.ty == Tarray || tb.ty == Tsarray)
14624         {
14625             if (!isArrayOpValid(this))
14626             {
14627                 error("invalid array operation %s (possible missing [])", toChars());
14628                 return new ErrorExp();
14629             }
14630             return this;
14631         }
14632 
14633         if (checkArithmeticBin())
14634             return new ErrorExp();
14635 
14636         // For built-in numeric types, there are several cases.
14637         // TODO: backend support, especially for  e1 ^^ 2.
14638 
14639         // First, attempt to fold the expression.
14640         e = optimize(WANTvalue);
14641         if (e.op != TOKpow)
14642         {
14643             e = e.semantic(sc);
14644             return e;
14645         }
14646 
14647         // Determine if we're raising to an integer power.
14648         sinteger_t intpow = 0;
14649         if (e2.op == TOKint64 && (cast(sinteger_t)e2.toInteger() == 2 || cast(sinteger_t)e2.toInteger() == 3))
14650             intpow = e2.toInteger();
14651         else if (e2.op == TOKfloat64 && (e2.toReal() == real_t(cast(sinteger_t)e2.toReal())))
14652             intpow = cast(sinteger_t)e2.toReal();
14653 
14654         // Deal with x^^2, x^^3 immediately, since they are of practical importance.
14655         if (intpow == 2 || intpow == 3)
14656         {
14657             // Replace x^^2 with (tmp = x, tmp*tmp)
14658             // Replace x^^3 with (tmp = x, tmp*tmp*tmp)
14659             auto tmp = copyToTemp(0, "__powtmp", e1);
14660             Expression de = new DeclarationExp(loc, tmp);
14661             Expression ve = new VarExp(loc, tmp);
14662 
14663             /* Note that we're reusing ve. This should be ok.
14664              */
14665             Expression me = new MulExp(loc, ve, ve);
14666             if (intpow == 3)
14667                 me = new MulExp(loc, me, ve);
14668             e = new CommaExp(loc, de, me);
14669             e = e.semantic(sc);
14670             return e;
14671         }
14672 
14673         Module mmath = loadStdMath();
14674         if (!mmath)
14675         {
14676             //error("requires std.math for ^^ operators");
14677             //fatal();
14678             // Leave handling of PowExp to the backend, or throw
14679             // an error gracefully if no backend support exists.
14680             if (Expression ex = typeCombine(this, sc))
14681                 return ex;
14682             return this;
14683         }
14684         e = new ScopeExp(loc, mmath);
14685 
14686         if (e2.op == TOKfloat64 && e2.toReal() == CTFloat.half)
14687         {
14688             // Replace e1 ^^ 0.5 with .std.math.sqrt(x)
14689             e = new CallExp(loc, new DotIdExp(loc, e, Id._sqrt), e1);
14690         }
14691         else
14692         {
14693             // Replace e1 ^^ e2 with .std.math.pow(e1, e2)
14694             e = new CallExp(loc, new DotIdExp(loc, e, Id._pow), e1, e2);
14695         }
14696         e = e.semantic(sc);
14697         return e;
14698     }
14699 
14700     override void accept(Visitor v)
14701     {
14702         v.visit(this);
14703     }
14704 }
14705 
14706 extern (C++) Module loadStdMath()
14707 {
14708     static __gshared Import impStdMath = null;
14709     if (!impStdMath)
14710     {
14711         auto a = new Identifiers();
14712         a.push(Id.std);
14713         auto s = new Import(Loc(), a, Id.math, null, false);
14714         s.load(null);
14715         if (s.mod)
14716         {
14717             s.mod.importAll(null);
14718             s.mod.semantic(null);
14719         }
14720         impStdMath = s;
14721     }
14722     return impStdMath.mod;
14723 }
14724 
14725 /***********************************************************
14726  */
14727 extern (C++) final class ShlExp : BinExp
14728 {
14729     extern (D) this(Loc loc, Expression e1, Expression e2)
14730     {
14731         super(loc, TOKshl, __traits(classInstanceSize, ShlExp), e1, e2);
14732     }
14733 
14734     override Expression semantic(Scope* sc)
14735     {
14736         //printf("ShlExp::semantic(), type = %p\n", type);
14737         if (type)
14738             return this;
14739 
14740         if (Expression ex = binSemanticProp(sc))
14741             return ex;
14742         Expression e = op_overload(sc);
14743         if (e)
14744             return e;
14745 
14746         if (checkIntegralBin())
14747             return new ErrorExp();
14748         if (e1.type.toBasetype().ty == Tvector || e2.type.toBasetype().ty == Tvector)
14749         {
14750             return incompatibleTypes();
14751         }
14752         e1 = integralPromotions(e1, sc);
14753         e2 = e2.castTo(sc, Type.tshiftcnt);
14754 
14755         type = e1.type;
14756         return this;
14757     }
14758 
14759     override void accept(Visitor v)
14760     {
14761         v.visit(this);
14762     }
14763 }
14764 
14765 /***********************************************************
14766  */
14767 extern (C++) final class ShrExp : BinExp
14768 {
14769     extern (D) this(Loc loc, Expression e1, Expression e2)
14770     {
14771         super(loc, TOKshr, __traits(classInstanceSize, ShrExp), e1, e2);
14772     }
14773 
14774     override Expression semantic(Scope* sc)
14775     {
14776         if (type)
14777             return this;
14778 
14779         if (Expression ex = binSemanticProp(sc))
14780             return ex;
14781         Expression e = op_overload(sc);
14782         if (e)
14783             return e;
14784 
14785         if (checkIntegralBin())
14786             return new ErrorExp();
14787         if (e1.type.toBasetype().ty == Tvector || e2.type.toBasetype().ty == Tvector)
14788         {
14789             return incompatibleTypes();
14790         }
14791         e1 = integralPromotions(e1, sc);
14792         e2 = e2.castTo(sc, Type.tshiftcnt);
14793 
14794         type = e1.type;
14795         return this;
14796     }
14797 
14798     override void accept(Visitor v)
14799     {
14800         v.visit(this);
14801     }
14802 }
14803 
14804 /***********************************************************
14805  */
14806 extern (C++) final class UshrExp : BinExp
14807 {
14808     extern (D) this(Loc loc, Expression e1, Expression e2)
14809     {
14810         super(loc, TOKushr, __traits(classInstanceSize, UshrExp), e1, e2);
14811     }
14812 
14813     override Expression semantic(Scope* sc)
14814     {
14815         if (type)
14816             return this;
14817 
14818         if (Expression ex = binSemanticProp(sc))
14819             return ex;
14820         Expression e = op_overload(sc);
14821         if (e)
14822             return e;
14823 
14824         if (checkIntegralBin())
14825             return new ErrorExp();
14826         if (e1.type.toBasetype().ty == Tvector || e2.type.toBasetype().ty == Tvector)
14827         {
14828             return incompatibleTypes();
14829         }
14830 
14831         e1 = integralPromotions(e1, sc);
14832         e2 = e2.castTo(sc, Type.tshiftcnt);
14833 
14834         type = e1.type;
14835         return this;
14836     }
14837 
14838     override void accept(Visitor v)
14839     {
14840         v.visit(this);
14841     }
14842 }
14843 
14844 /***********************************************************
14845  */
14846 extern (C++) final class AndExp : BinExp
14847 {
14848     extern (D) this(Loc loc, Expression e1, Expression e2)
14849     {
14850         super(loc, TOKand, __traits(classInstanceSize, AndExp), e1, e2);
14851     }
14852 
14853     override Expression semantic(Scope* sc)
14854     {
14855         if (type)
14856             return this;
14857 
14858         if (Expression ex = binSemanticProp(sc))
14859             return ex;
14860         Expression e = op_overload(sc);
14861         if (e)
14862             return e;
14863 
14864         if (e1.type.toBasetype().ty == Tbool && e2.type.toBasetype().ty == Tbool)
14865         {
14866             type = e1.type;
14867             return this;
14868         }
14869 
14870         if (Expression ex = typeCombine(this, sc))
14871             return ex;
14872 
14873         Type tb = type.toBasetype();
14874         if (tb.ty == Tarray || tb.ty == Tsarray)
14875         {
14876             if (!isArrayOpValid(this))
14877             {
14878                 error("invalid array operation %s (possible missing [])", toChars());
14879                 return new ErrorExp();
14880             }
14881             return this;
14882         }
14883 
14884         if (checkIntegralBin())
14885             return new ErrorExp();
14886 
14887         return this;
14888     }
14889 
14890     override void accept(Visitor v)
14891     {
14892         v.visit(this);
14893     }
14894 }
14895 
14896 /***********************************************************
14897  */
14898 extern (C++) final class OrExp : BinExp
14899 {
14900     extern (D) this(Loc loc, Expression e1, Expression e2)
14901     {
14902         super(loc, TOKor, __traits(classInstanceSize, OrExp), e1, e2);
14903     }
14904 
14905     override Expression semantic(Scope* sc)
14906     {
14907         if (type)
14908             return this;
14909 
14910         if (Expression ex = binSemanticProp(sc))
14911             return ex;
14912         Expression e = op_overload(sc);
14913         if (e)
14914             return e;
14915 
14916         if (e1.type.toBasetype().ty == Tbool && e2.type.toBasetype().ty == Tbool)
14917         {
14918             type = e1.type;
14919             return this;
14920         }
14921 
14922         if (Expression ex = typeCombine(this, sc))
14923             return ex;
14924 
14925         Type tb = type.toBasetype();
14926         if (tb.ty == Tarray || tb.ty == Tsarray)
14927         {
14928             if (!isArrayOpValid(this))
14929             {
14930                 error("invalid array operation %s (possible missing [])", toChars());
14931                 return new ErrorExp();
14932             }
14933             return this;
14934         }
14935 
14936         if (checkIntegralBin())
14937             return new ErrorExp();
14938 
14939         return this;
14940     }
14941 
14942     override void accept(Visitor v)
14943     {
14944         v.visit(this);
14945     }
14946 }
14947 
14948 /***********************************************************
14949  */
14950 extern (C++) final class XorExp : BinExp
14951 {
14952     extern (D) this(Loc loc, Expression e1, Expression e2)
14953     {
14954         super(loc, TOKxor, __traits(classInstanceSize, XorExp), e1, e2);
14955     }
14956 
14957     override Expression semantic(Scope* sc)
14958     {
14959         if (type)
14960             return this;
14961 
14962         if (Expression ex = binSemanticProp(sc))
14963             return ex;
14964         Expression e = op_overload(sc);
14965         if (e)
14966             return e;
14967 
14968         if (e1.type.toBasetype().ty == Tbool && e2.type.toBasetype().ty == Tbool)
14969         {
14970             type = e1.type;
14971             return this;
14972         }
14973 
14974         if (Expression ex = typeCombine(this, sc))
14975             return ex;
14976 
14977         Type tb = type.toBasetype();
14978         if (tb.ty == Tarray || tb.ty == Tsarray)
14979         {
14980             if (!isArrayOpValid(this))
14981             {
14982                 error("invalid array operation %s (possible missing [])", toChars());
14983                 return new ErrorExp();
14984             }
14985             return this;
14986         }
14987 
14988         if (checkIntegralBin())
14989             return new ErrorExp();
14990 
14991         return this;
14992     }
14993 
14994     override void accept(Visitor v)
14995     {
14996         v.visit(this);
14997     }
14998 }
14999 
15000 /***********************************************************
15001  */
15002 extern (C++) final class OrOrExp : BinExp
15003 {
15004     extern (D) this(Loc loc, Expression e1, Expression e2)
15005     {
15006         super(loc, TOKoror, __traits(classInstanceSize, OrOrExp), e1, e2);
15007     }
15008 
15009     override Expression semantic(Scope* sc)
15010     {
15011         if (type)
15012             return this;
15013 
15014         setNoderefOperands();
15015 
15016         // same as for AndAnd
15017         e1 = e1.semantic(sc);
15018         e1 = resolveProperties(sc, e1);
15019         e1 = e1.toBoolean(sc);
15020         uint cs1 = sc.callSuper;
15021 
15022         if (sc.flags & SCOPEcondition)
15023         {
15024             /* If in static if, don't evaluate e2 if we don't have to.
15025              */
15026             e1 = e1.optimize(WANTvalue);
15027             if (e1.isBool(true))
15028             {
15029                 return new IntegerExp(loc, 1, Type.tbool);
15030             }
15031         }
15032 
15033         e2 = e2.semantic(sc);
15034         sc.mergeCallSuper(loc, cs1);
15035         e2 = resolveProperties(sc, e2);
15036 
15037         auto f1 = checkNonAssignmentArrayOp(e1);
15038         auto f2 = checkNonAssignmentArrayOp(e2);
15039         if (f1 || f2)
15040             return new ErrorExp();
15041 
15042         if (e2.type.ty == Tvoid)
15043             type = Type.tvoid;
15044         else
15045         {
15046             e2 = e2.toBoolean(sc);
15047             type = Type.tbool;
15048         }
15049         if (e2.op == TOKtype || e2.op == TOKscope)
15050         {
15051             error("%s is not an expression", e2.toChars());
15052             return new ErrorExp();
15053         }
15054         if (e1.op == TOKerror)
15055             return e1;
15056         if (e2.op == TOKerror)
15057             return e2;
15058 
15059         return this;
15060     }
15061 
15062     override Expression toBoolean(Scope* sc)
15063     {
15064         auto ex2 = e2.toBoolean(sc);
15065         if (ex2.op == TOKerror)
15066             return ex2;
15067         e2 = ex2;
15068         return this;
15069     }
15070 
15071     override void accept(Visitor v)
15072     {
15073         v.visit(this);
15074     }
15075 }
15076 
15077 /***********************************************************
15078  */
15079 extern (C++) final class AndAndExp : BinExp
15080 {
15081     extern (D) this(Loc loc, Expression e1, Expression e2)
15082     {
15083         super(loc, TOKandand, __traits(classInstanceSize, AndAndExp), e1, e2);
15084     }
15085 
15086     override Expression semantic(Scope* sc)
15087     {
15088         if (type)
15089             return this;
15090 
15091         setNoderefOperands();
15092 
15093         // same as for OrOr
15094         e1 = e1.semantic(sc);
15095         e1 = resolveProperties(sc, e1);
15096         e1 = e1.toBoolean(sc);
15097         uint cs1 = sc.callSuper;
15098 
15099         if (sc.flags & SCOPEcondition)
15100         {
15101             /* If in static if, don't evaluate e2 if we don't have to.
15102              */
15103             e1 = e1.optimize(WANTvalue);
15104             if (e1.isBool(false))
15105             {
15106                 return new IntegerExp(loc, 0, Type.tbool);
15107             }
15108         }
15109 
15110         e2 = e2.semantic(sc);
15111         sc.mergeCallSuper(loc, cs1);
15112         e2 = resolveProperties(sc, e2);
15113 
15114         auto f1 = checkNonAssignmentArrayOp(e1);
15115         auto f2 = checkNonAssignmentArrayOp(e2);
15116         if (f1 || f2)
15117             return new ErrorExp();
15118 
15119         if (e2.type.ty == Tvoid)
15120             type = Type.tvoid;
15121         else
15122         {
15123             e2 = e2.toBoolean(sc);
15124             type = Type.tbool;
15125         }
15126         if (e2.op == TOKtype || e2.op == TOKscope)
15127         {
15128             error("%s is not an expression", e2.toChars());
15129             return new ErrorExp();
15130         }
15131         if (e1.op == TOKerror)
15132             return e1;
15133         if (e2.op == TOKerror)
15134             return e2;
15135 
15136         return this;
15137     }
15138 
15139     override Expression toBoolean(Scope* sc)
15140     {
15141         auto ex2 = e2.toBoolean(sc);
15142         if (ex2.op == TOKerror)
15143             return ex2;
15144         e2 = ex2;
15145         return this;
15146     }
15147 
15148     override void accept(Visitor v)
15149     {
15150         v.visit(this);
15151     }
15152 }
15153 
15154 /***********************************************************
15155  */
15156 extern (C++) final class CmpExp : BinExp
15157 {
15158     extern (D) this(TOK op, Loc loc, Expression e1, Expression e2)
15159     {
15160         super(loc, op, __traits(classInstanceSize, CmpExp), e1, e2);
15161     }
15162 
15163     override Expression semantic(Scope* sc)
15164     {
15165         static if (LOGSEMANTIC)
15166         {
15167             printf("CmpExp::semantic('%s')\n", toChars());
15168         }
15169         if (type)
15170             return this;
15171 
15172         setNoderefOperands();
15173 
15174         if (Expression ex = binSemanticProp(sc))
15175             return ex;
15176         Type t1 = e1.type.toBasetype();
15177         Type t2 = e2.type.toBasetype();
15178         if (t1.ty == Tclass && e2.op == TOKnull || t2.ty == Tclass && e1.op == TOKnull)
15179         {
15180             error("do not use null when comparing class types");
15181             return new ErrorExp();
15182         }
15183 
15184         Expression e = op_overload(sc);
15185         if (e)
15186         {
15187             if (!e.type.isscalar() && e.type.equals(e1.type))
15188             {
15189                 error("recursive opCmp expansion");
15190                 return new ErrorExp();
15191             }
15192             if (e.op == TOKcall)
15193             {
15194                 e = new CmpExp(op, loc, e, new IntegerExp(loc, 0, Type.tint32));
15195                 e = e.semantic(sc);
15196             }
15197             return e;
15198         }
15199 
15200         if (Expression ex = typeCombine(this, sc))
15201             return ex;
15202 
15203         auto f1 = checkNonAssignmentArrayOp(e1);
15204         auto f2 = checkNonAssignmentArrayOp(e2);
15205         if (f1 || f2)
15206             return new ErrorExp();
15207 
15208         type = Type.tbool;
15209 
15210         // Special handling for array comparisons
15211         t1 = e1.type.toBasetype();
15212         t2 = e2.type.toBasetype();
15213         if ((t1.ty == Tarray || t1.ty == Tsarray || t1.ty == Tpointer) && (t2.ty == Tarray || t2.ty == Tsarray || t2.ty == Tpointer))
15214         {
15215             Type t1next = t1.nextOf();
15216             Type t2next = t2.nextOf();
15217             if (t1next.implicitConvTo(t2next) < MATCHconst && t2next.implicitConvTo(t1next) < MATCHconst && (t1next.ty != Tvoid && t2next.ty != Tvoid))
15218             {
15219                 error("array comparison type mismatch, %s vs %s", t1next.toChars(), t2next.toChars());
15220                 return new ErrorExp();
15221             }
15222             if ((t1.ty == Tarray || t1.ty == Tsarray) && (t2.ty == Tarray || t2.ty == Tsarray))
15223             {
15224                 semanticTypeInfo(sc, t1.nextOf());
15225             }
15226         }
15227         else if (t1.ty == Tstruct || t2.ty == Tstruct || (t1.ty == Tclass && t2.ty == Tclass))
15228         {
15229             if (t2.ty == Tstruct)
15230                 error("need member function opCmp() for %s %s to compare", t2.toDsymbol(sc).kind(), t2.toChars());
15231             else
15232                 error("need member function opCmp() for %s %s to compare", t1.toDsymbol(sc).kind(), t1.toChars());
15233             return new ErrorExp();
15234         }
15235         else if (t1.iscomplex() || t2.iscomplex())
15236         {
15237             error("compare not defined for complex operands");
15238             return new ErrorExp();
15239         }
15240         else if (t1.ty == Taarray || t2.ty == Taarray)
15241         {
15242             error("%s is not defined for associative arrays", Token.toChars(op));
15243             return new ErrorExp();
15244         }
15245         else if (t1.ty == Tvector)
15246         {
15247             return incompatibleTypes();
15248         }
15249         else
15250         {
15251             bool r1 = e1.checkValue();
15252             bool r2 = e2.checkValue();
15253             if (r1 || r2)
15254                 return new ErrorExp();
15255         }
15256 
15257         TOK altop;
15258         switch (op)
15259         {
15260             // Refer rel_integral[] table
15261         case TOKunord:
15262             altop = TOKerror;
15263             break;
15264 
15265         case TOKlg:
15266             altop = TOKnotequal;
15267             break;
15268 
15269         case TOKleg:
15270             altop = TOKerror;
15271             break;
15272 
15273         case TOKule:
15274             altop = TOKle;
15275             break;
15276 
15277         case TOKul:
15278             altop = TOKlt;
15279             break;
15280 
15281         case TOKuge:
15282             altop = TOKge;
15283             break;
15284 
15285         case TOKug:
15286             altop = TOKgt;
15287             break;
15288 
15289         case TOKue:
15290             altop = TOKequal;
15291             break;
15292 
15293         default:
15294             altop = TOKreserved;
15295             break;
15296         }
15297         if (altop == TOKerror && (t1.ty == Tarray || t1.ty == Tsarray || t2.ty == Tarray || t2.ty == Tsarray))
15298         {
15299             error("'%s' is not defined for array comparisons", Token.toChars(op));
15300             return new ErrorExp();
15301         }
15302         if (altop != TOKreserved)
15303         {
15304             if (!t1.isfloating())
15305             {
15306                 if (altop == TOKerror)
15307                 {
15308                     const(char)* s = op == TOKunord ? "false" : "true";
15309                     error("floating point operator '%s' always returns %s for non-floating comparisons", Token.toChars(op), s);
15310                 }
15311                 else
15312                 {
15313                     error("use '%s' for non-floating comparisons rather than floating point operator '%s'", Token.toChars(altop), Token.toChars(op));
15314                 }
15315             }
15316             else
15317             {
15318                 error("use std.math.isNaN to deal with NaN operands rather than floating point operator '%s'", Token.toChars(op));
15319             }
15320             return new ErrorExp();
15321         }
15322 
15323         //printf("CmpExp: %s, type = %s\n", e->toChars(), e->type->toChars());
15324         return this;
15325     }
15326 
15327     override void accept(Visitor v)
15328     {
15329         v.visit(this);
15330     }
15331 }
15332 
15333 /***********************************************************
15334  */
15335 extern (C++) final class InExp : BinExp
15336 {
15337     extern (D) this(Loc loc, Expression e1, Expression e2)
15338     {
15339         super(loc, TOKin, __traits(classInstanceSize, InExp), e1, e2);
15340     }
15341 
15342     override Expression semantic(Scope* sc)
15343     {
15344         if (type)
15345             return this;
15346 
15347         if (Expression ex = binSemanticProp(sc))
15348             return ex;
15349         Expression e = op_overload(sc);
15350         if (e)
15351             return e;
15352 
15353         Type t2b = e2.type.toBasetype();
15354         switch (t2b.ty)
15355         {
15356         case Taarray:
15357             {
15358                 TypeAArray ta = cast(TypeAArray)t2b;
15359 
15360                 // Special handling for array keys
15361                 if (!arrayTypeCompatible(e1.loc, e1.type, ta.index))
15362                 {
15363                     // Convert key to type of key
15364                     e1 = e1.implicitCastTo(sc, ta.index);
15365                 }
15366 
15367                 semanticTypeInfo(sc, ta.index);
15368 
15369                 // Return type is pointer to value
15370                 type = ta.nextOf().pointerTo();
15371                 break;
15372             }
15373         default:
15374             error("rvalue of in expression must be an associative array, not %s", e2.type.toChars());
15375             goto case Terror;
15376         case Terror:
15377             return new ErrorExp();
15378         }
15379         return this;
15380     }
15381 
15382     override void accept(Visitor v)
15383     {
15384         v.visit(this);
15385     }
15386 }
15387 
15388 /***********************************************************
15389  * This deletes the key e1 from the associative array e2
15390  */
15391 extern (C++) final class RemoveExp : BinExp
15392 {
15393     extern (D) this(Loc loc, Expression e1, Expression e2)
15394     {
15395         super(loc, TOKremove, __traits(classInstanceSize, RemoveExp), e1, e2);
15396         type = Type.tbool;
15397     }
15398 
15399     override Expression semantic(Scope* sc)
15400     {
15401         if (Expression ex = binSemantic(sc))
15402             return ex;
15403         return this;
15404     }
15405 
15406     override void accept(Visitor v)
15407     {
15408         v.visit(this);
15409     }
15410 }
15411 
15412 /***********************************************************
15413  * == and !=
15414  */
15415 extern (C++) final class EqualExp : BinExp
15416 {
15417     extern (D) this(TOK op, Loc loc, Expression e1, Expression e2)
15418     {
15419         super(loc, op, __traits(classInstanceSize, EqualExp), e1, e2);
15420         assert(op == TOKequal || op == TOKnotequal);
15421     }
15422 
15423     override Expression semantic(Scope* sc)
15424     {
15425         //printf("EqualExp::semantic('%s')\n", toChars());
15426         if (type)
15427             return this;
15428 
15429         setNoderefOperands();
15430 
15431         if (auto e = binSemanticProp(sc))
15432             return e;
15433         if (e1.op == TOKtype || e2.op == TOKtype)
15434             return incompatibleTypes();
15435 
15436         /* Before checking for operator overloading, check to see if we're
15437          * comparing the addresses of two statics. If so, we can just see
15438          * if they are the same symbol.
15439          */
15440         if (e1.op == TOKaddress && e2.op == TOKaddress)
15441         {
15442             AddrExp ae1 = cast(AddrExp)e1;
15443             AddrExp ae2 = cast(AddrExp)e2;
15444             if (ae1.e1.op == TOKvar && ae2.e1.op == TOKvar)
15445             {
15446                 VarExp ve1 = cast(VarExp)ae1.e1;
15447                 VarExp ve2 = cast(VarExp)ae2.e1;
15448                 if (ve1.var == ve2.var)
15449                 {
15450                     // They are the same, result is 'true' for ==, 'false' for !=
15451                     return new IntegerExp(loc, (op == TOKequal), Type.tbool);
15452                 }
15453             }
15454         }
15455 
15456         if (auto e = op_overload(sc))
15457             return e;
15458 
15459         if (auto e = typeCombine(this, sc))
15460             return e;
15461 
15462         auto f1 = checkNonAssignmentArrayOp(e1);
15463         auto f2 = checkNonAssignmentArrayOp(e2);
15464         if (f1 || f2)
15465             return new ErrorExp();
15466 
15467         type = Type.tbool;
15468 
15469         // Special handling for array comparisons
15470         if (!arrayTypeCompatible(loc, e1.type, e2.type))
15471         {
15472             if (e1.type != e2.type && e1.type.isfloating() && e2.type.isfloating())
15473             {
15474                 // Cast both to complex
15475                 e1 = e1.castTo(sc, Type.tcomplex80);
15476                 e2 = e2.castTo(sc, Type.tcomplex80);
15477             }
15478         }
15479         if (e1.type.toBasetype().ty == Taarray)
15480             semanticTypeInfo(sc, e1.type.toBasetype());
15481 
15482         if (e1.type.toBasetype().ty == Tvector)
15483             return incompatibleTypes();
15484 
15485         return this;
15486     }
15487 
15488     override void accept(Visitor v)
15489     {
15490         v.visit(this);
15491     }
15492 }
15493 
15494 /***********************************************************
15495  * is and !is
15496  */
15497 extern (C++) final class IdentityExp : BinExp
15498 {
15499     extern (D) this(TOK op, Loc loc, Expression e1, Expression e2)
15500     {
15501         super(loc, op, __traits(classInstanceSize, IdentityExp), e1, e2);
15502     }
15503 
15504     override Expression semantic(Scope* sc)
15505     {
15506         if (type)
15507             return this;
15508 
15509         setNoderefOperands();
15510 
15511         if (auto e = binSemanticProp(sc))
15512             return e;
15513 
15514         if (auto e = typeCombine(this, sc))
15515             return e;
15516 
15517         auto f1 = checkNonAssignmentArrayOp(e1);
15518         auto f2 = checkNonAssignmentArrayOp(e2);
15519         if (f1 || f2)
15520             return new ErrorExp();
15521 
15522         type = Type.tbool;
15523 
15524         if (e1.type != e2.type && e1.type.isfloating() && e2.type.isfloating())
15525         {
15526             // Cast both to complex
15527             e1 = e1.castTo(sc, Type.tcomplex80);
15528             e2 = e2.castTo(sc, Type.tcomplex80);
15529         }
15530 
15531         if (e1.type.toBasetype().ty == Tvector)
15532             return incompatibleTypes();
15533 
15534         if (e1.type.toBasetype().ty == Tsarray ||
15535             e2.type.toBasetype().ty == Tsarray)
15536             deprecation("identity comparison of static arrays "
15537                 "implicitly coerces them to slices, "
15538                 "which are compared by reference");
15539 
15540         return this;
15541     }
15542 
15543     override void accept(Visitor v)
15544     {
15545         v.visit(this);
15546     }
15547 }
15548 
15549 /***********************************************************
15550  */
15551 extern (C++) final class CondExp : BinExp
15552 {
15553     Expression econd;
15554 
15555     extern (D) this(Loc loc, Expression econd, Expression e1, Expression e2)
15556     {
15557         super(loc, TOKquestion, __traits(classInstanceSize, CondExp), e1, e2);
15558         this.econd = econd;
15559     }
15560 
15561     override Expression syntaxCopy()
15562     {
15563         return new CondExp(loc, econd.syntaxCopy(), e1.syntaxCopy(), e2.syntaxCopy());
15564     }
15565 
15566     override Expression semantic(Scope* sc)
15567     {
15568         static if (LOGSEMANTIC)
15569         {
15570             printf("CondExp::semantic('%s')\n", toChars());
15571         }
15572         if (type)
15573             return this;
15574 
15575         if (econd.op == TOKdotid)
15576             (cast(DotIdExp)econd).noderef = true;
15577 
15578         Expression ec = econd.semantic(sc);
15579         ec = resolveProperties(sc, ec);
15580         ec = ec.toBoolean(sc);
15581 
15582         uint cs0 = sc.callSuper;
15583         uint* fi0 = sc.saveFieldInit();
15584         Expression e1x = e1.semantic(sc);
15585         e1x = resolveProperties(sc, e1x);
15586 
15587         uint cs1 = sc.callSuper;
15588         uint* fi1 = sc.fieldinit;
15589         sc.callSuper = cs0;
15590         sc.fieldinit = fi0;
15591         Expression e2x = e2.semantic(sc);
15592         e2x = resolveProperties(sc, e2x);
15593 
15594         sc.mergeCallSuper(loc, cs1);
15595         sc.mergeFieldInit(loc, fi1);
15596 
15597         if (ec.op == TOKerror)
15598             return ec;
15599         if (ec.type == Type.terror)
15600             return new ErrorExp();
15601         econd = ec;
15602 
15603         if (e1x.op == TOKerror)
15604             return e1x;
15605         if (e1x.type == Type.terror)
15606             return new ErrorExp();
15607         e1 = e1x;
15608 
15609         if (e2x.op == TOKerror)
15610             return e2x;
15611         if (e2x.type == Type.terror)
15612             return new ErrorExp();
15613         e2 = e2x;
15614 
15615         auto f0 = checkNonAssignmentArrayOp(econd);
15616         auto f1 = checkNonAssignmentArrayOp(e1);
15617         auto f2 = checkNonAssignmentArrayOp(e2);
15618         if (f0 || f1 || f2)
15619             return new ErrorExp();
15620 
15621         // If either operand is void, the result is void
15622         Type t1 = e1.type;
15623         Type t2 = e2.type;
15624         if (t1.ty == Tvoid || t2.ty == Tvoid)
15625             type = Type.tvoid;
15626         else if (t1 == t2)
15627             type = t1;
15628         else
15629         {
15630             if (Expression ex = typeCombine(this, sc))
15631                 return ex;
15632 
15633             switch (e1.type.toBasetype().ty)
15634             {
15635             case Tcomplex32:
15636             case Tcomplex64:
15637             case Tcomplex80:
15638                 e2 = e2.castTo(sc, e1.type);
15639                 break;
15640             default:
15641                 break;
15642             }
15643             switch (e2.type.toBasetype().ty)
15644             {
15645             case Tcomplex32:
15646             case Tcomplex64:
15647             case Tcomplex80:
15648                 e1 = e1.castTo(sc, e2.type);
15649                 break;
15650             default:
15651                 break;
15652             }
15653             if (type.toBasetype().ty == Tarray)
15654             {
15655                 e1 = e1.castTo(sc, type);
15656                 e2 = e2.castTo(sc, type);
15657             }
15658         }
15659         type = type.merge2();
15660         version (none)
15661         {
15662             printf("res: %s\n", type.toChars());
15663             printf("e1 : %s\n", e1.type.toChars());
15664             printf("e2 : %s\n", e2.type.toChars());
15665         }
15666 
15667         /* Bugzilla 14696: If either e1 or e2 contain temporaries which need dtor,
15668          * make them conditional.
15669          * Rewrite:
15670          *      cond ? (__tmp1 = ..., __tmp1) : (__tmp2 = ..., __tmp2)
15671          * to:
15672          *      (auto __cond = cond) ? (... __tmp1) : (... __tmp2)
15673          * and replace edtors of __tmp1 and __tmp2 with:
15674          *      __tmp1->edtor --> __cond && __tmp1.dtor()
15675          *      __tmp2->edtor --> __cond || __tmp2.dtor()
15676          */
15677         hookDtors(sc);
15678 
15679         return this;
15680     }
15681 
15682     override int checkModifiable(Scope* sc, int flag)
15683     {
15684         return e1.checkModifiable(sc, flag) && e2.checkModifiable(sc, flag);
15685     }
15686 
15687     override bool isLvalue()
15688     {
15689         return e1.isLvalue() && e2.isLvalue();
15690     }
15691 
15692     override Expression toLvalue(Scope* sc, Expression ex)
15693     {
15694         // convert (econd ? e1 : e2) to *(econd ? &e1 : &e2)
15695         CondExp e = cast(CondExp)copy();
15696         e.e1 = e1.toLvalue(sc, null).addressOf();
15697         e.e2 = e2.toLvalue(sc, null).addressOf();
15698         e.type = type.pointerTo();
15699         return new PtrExp(loc, e, type);
15700     }
15701 
15702     override Expression modifiableLvalue(Scope* sc, Expression e)
15703     {
15704         //error("conditional expression %s is not a modifiable lvalue", toChars());
15705         e1 = e1.modifiableLvalue(sc, e1);
15706         e2 = e2.modifiableLvalue(sc, e2);
15707         return toLvalue(sc, this);
15708     }
15709 
15710     override Expression toBoolean(Scope* sc)
15711     {
15712         auto ex1 = e1.toBoolean(sc);
15713         auto ex2 = e2.toBoolean(sc);
15714         if (ex1.op == TOKerror)
15715             return ex1;
15716         if (ex2.op == TOKerror)
15717             return ex2;
15718         e1 = ex1;
15719         e2 = ex2;
15720         return this;
15721     }
15722 
15723     void hookDtors(Scope* sc)
15724     {
15725         extern (C++) final class DtorVisitor : StoppableVisitor
15726         {
15727             alias visit = super.visit;
15728         public:
15729             Scope* sc;
15730             CondExp ce;
15731             VarDeclaration vcond;
15732             bool isThen;
15733 
15734             extern (D) this(Scope* sc, CondExp ce)
15735             {
15736                 this.sc = sc;
15737                 this.ce = ce;
15738             }
15739 
15740             override void visit(Expression e)
15741             {
15742                 //printf("(e = %s)\n", e->toChars());
15743             }
15744 
15745             override void visit(DeclarationExp e)
15746             {
15747                 auto v = e.declaration.isVarDeclaration();
15748                 if (v && !v.isDataseg())
15749                 {
15750                     if (v._init)
15751                     {
15752                         if (auto ei = v._init.isExpInitializer())
15753                             ei.exp.accept(this);
15754                     }
15755 
15756                     if (v.needsScopeDtor())
15757                     {
15758                         if (!vcond)
15759                         {
15760                             vcond = copyToTemp(STCvolatile, "__cond", ce.econd);
15761                             vcond.semantic(sc);
15762 
15763                             Expression de = new DeclarationExp(ce.econd.loc, vcond);
15764                             de = de.semantic(sc);
15765 
15766                             Expression ve = new VarExp(ce.econd.loc, vcond);
15767                             ce.econd = Expression.combine(de, ve);
15768                         }
15769 
15770                         //printf("\t++v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
15771                         Expression ve = new VarExp(vcond.loc, vcond);
15772                         if (isThen)
15773                             v.edtor = new AndAndExp(v.edtor.loc, ve, v.edtor);
15774                         else
15775                             v.edtor = new OrOrExp(v.edtor.loc, ve, v.edtor);
15776                         v.edtor = v.edtor.semantic(sc);
15777                         //printf("\t--v = %s, v->edtor = %s\n", v->toChars(), v->edtor->toChars());
15778                     }
15779                 }
15780             }
15781         }
15782 
15783         scope DtorVisitor v = new DtorVisitor(sc, this);
15784         //printf("+%s\n", toChars());
15785         v.isThen = true;
15786         walkPostorder(e1, v);
15787         v.isThen = false;
15788         walkPostorder(e2, v);
15789         //printf("-%s\n", toChars());
15790     }
15791 
15792     override void accept(Visitor v)
15793     {
15794         v.visit(this);
15795     }
15796 }
15797 
15798 /***********************************************************
15799  */
15800 extern (C++) class DefaultInitExp : Expression
15801 {
15802     TOK subop;      // which of the derived classes this is
15803 
15804     final extern (D) this(Loc loc, TOK subop, int size)
15805     {
15806         super(loc, TOKdefault, size);
15807         this.subop = subop;
15808     }
15809 
15810     override void accept(Visitor v)
15811     {
15812         v.visit(this);
15813     }
15814 }
15815 
15816 /***********************************************************
15817  */
15818 extern (C++) final class FileInitExp : DefaultInitExp
15819 {
15820     extern (D) this(Loc loc, TOK tok)
15821     {
15822         super(loc, tok, __traits(classInstanceSize, FileInitExp));
15823     }
15824 
15825     override Expression semantic(Scope* sc)
15826     {
15827         //printf("FileInitExp::semantic()\n");
15828         type = Type.tstring;
15829         return this;
15830     }
15831 
15832     override Expression resolveLoc(Loc loc, Scope* sc)
15833     {
15834         //printf("FileInitExp::resolve() %s\n", toChars());
15835         const(char)* s = loc.filename ? loc.filename : sc._module.ident.toChars();
15836         Expression e = new StringExp(loc, cast(char*)s);
15837         e = e.semantic(sc);
15838         e = e.castTo(sc, type);
15839         return e;
15840     }
15841 
15842     override void accept(Visitor v)
15843     {
15844         v.visit(this);
15845     }
15846 }
15847 
15848 /***********************************************************
15849  */
15850 extern (C++) final class LineInitExp : DefaultInitExp
15851 {
15852     extern (D) this(Loc loc)
15853     {
15854         super(loc, TOKline, __traits(classInstanceSize, LineInitExp));
15855     }
15856 
15857     override Expression semantic(Scope* sc)
15858     {
15859         type = Type.tint32;
15860         return this;
15861     }
15862 
15863     override Expression resolveLoc(Loc loc, Scope* sc)
15864     {
15865         Expression e = new IntegerExp(loc, loc.linnum, Type.tint32);
15866         e = e.castTo(sc, type);
15867         return e;
15868     }
15869 
15870     override void accept(Visitor v)
15871     {
15872         v.visit(this);
15873     }
15874 }
15875 
15876 /***********************************************************
15877  */
15878 extern (C++) final class ModuleInitExp : DefaultInitExp
15879 {
15880     extern (D) this(Loc loc)
15881     {
15882         super(loc, TOKmodulestring, __traits(classInstanceSize, ModuleInitExp));
15883     }
15884 
15885     override Expression semantic(Scope* sc)
15886     {
15887         //printf("ModuleInitExp::semantic()\n");
15888         type = Type.tstring;
15889         return this;
15890     }
15891 
15892     override Expression resolveLoc(Loc loc, Scope* sc)
15893     {
15894         const(char)* s;
15895         if (sc.callsc)
15896             s = sc.callsc._module.toPrettyChars();
15897         else
15898             s = sc._module.toPrettyChars();
15899         Expression e = new StringExp(loc, cast(char*)s);
15900         e = e.semantic(sc);
15901         e = e.castTo(sc, type);
15902         return e;
15903     }
15904 
15905     override void accept(Visitor v)
15906     {
15907         v.visit(this);
15908     }
15909 }
15910 
15911 /***********************************************************
15912  */
15913 extern (C++) final class FuncInitExp : DefaultInitExp
15914 {
15915     extern (D) this(Loc loc)
15916     {
15917         super(loc, TOKfuncstring, __traits(classInstanceSize, FuncInitExp));
15918     }
15919 
15920     override Expression semantic(Scope* sc)
15921     {
15922         //printf("FuncInitExp::semantic()\n");
15923         type = Type.tstring;
15924         if (sc.func)
15925             return this.resolveLoc(Loc(), sc);
15926         return this;
15927     }
15928 
15929     override Expression resolveLoc(Loc loc, Scope* sc)
15930     {
15931         const(char)* s;
15932         if (sc.callsc && sc.callsc.func)
15933             s = sc.callsc.func.Dsymbol.toPrettyChars();
15934         else if (sc.func)
15935             s = sc.func.Dsymbol.toPrettyChars();
15936         else
15937             s = "";
15938         Expression e = new StringExp(loc, cast(char*)s);
15939         e = e.semantic(sc);
15940         e = e.castTo(sc, type);
15941         return e;
15942     }
15943 
15944     override void accept(Visitor v)
15945     {
15946         v.visit(this);
15947     }
15948 }
15949 
15950 /***********************************************************
15951  */
15952 extern (C++) final class PrettyFuncInitExp : DefaultInitExp
15953 {
15954     extern (D) this(Loc loc)
15955     {
15956         super(loc, TOKprettyfunc, __traits(classInstanceSize, PrettyFuncInitExp));
15957     }
15958 
15959     override Expression semantic(Scope* sc)
15960     {
15961         //printf("PrettyFuncInitExp::semantic()\n");
15962         type = Type.tstring;
15963         if (sc.func)
15964             return this.resolveLoc(Loc(), sc);
15965         return this;
15966     }
15967 
15968     override Expression resolveLoc(Loc loc, Scope* sc)
15969     {
15970         FuncDeclaration fd;
15971         if (sc.callsc && sc.callsc.func)
15972             fd = sc.callsc.func;
15973         else
15974             fd = sc.func;
15975 
15976         const(char)* s;
15977         if (fd)
15978         {
15979             const(char)* funcStr = fd.Dsymbol.toPrettyChars();
15980             OutBuffer buf;
15981             functionToBufferWithIdent(cast(TypeFunction)fd.type, &buf, funcStr);
15982             s = buf.extractString();
15983         }
15984         else
15985         {
15986             s = "";
15987         }
15988 
15989         Expression e = new StringExp(loc, cast(char*)s);
15990         e = e.semantic(sc);
15991         e = e.castTo(sc, type);
15992         return e;
15993     }
15994 
15995     override void accept(Visitor v)
15996     {
15997         v.visit(this);
15998     }
15999 }